Commit aa2a7dad authored by Fatih Acet's avatar Fatih Acet

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into #15643

# Conflicts:
#	app/assets/stylesheets/pages/issuable.scss
parents b99471ca c002a560
...@@ -21,6 +21,7 @@ AllCops: ...@@ -21,6 +21,7 @@ AllCops:
- 'lib/email_validator.rb' - 'lib/email_validator.rb'
- 'lib/gitlab/upgrader.rb' - 'lib/gitlab/upgrader.rb'
- 'lib/gitlab/seeder.rb' - 'lib/gitlab/seeder.rb'
- 'generator_templates/**/*'
##################### Style ################################## ##################### Style ##################################
...@@ -151,7 +152,7 @@ Style/ConstantName: ...@@ -151,7 +152,7 @@ Style/ConstantName:
# Use def with parentheses when there are arguments. # Use def with parentheses when there are arguments.
Style/DefWithParentheses: Style/DefWithParentheses:
Enabled: false Enabled: true
# Checks for use of deprecated Hash methods. # Checks for use of deprecated Hash methods.
Style/DeprecatedHashMethods: Style/DeprecatedHashMethods:
...@@ -276,7 +277,7 @@ Style/IdenticalConditionalBranches: ...@@ -276,7 +277,7 @@ Style/IdenticalConditionalBranches:
Enabled: false Enabled: false
# Checks the indentation of the first line of the right-hand-side of a # Checks the indentation of the first line of the right-hand-side of a
# multi-line assignment. # multi-line assignment.
Style/IndentAssignment: Style/IndentAssignment:
Enabled: false Enabled: false
...@@ -298,7 +299,7 @@ Style/IndentHash: ...@@ -298,7 +299,7 @@ Style/IndentHash:
# Use Kernel#loop for infinite loops. # Use Kernel#loop for infinite loops.
Style/InfiniteLoop: Style/InfiniteLoop:
Enabled: false Enabled: true
# Use the new lambda literal syntax for single-line blocks. # Use the new lambda literal syntax for single-line blocks.
Style/Lambda: Style/Lambda:
...@@ -332,6 +333,12 @@ Style/MethodName: ...@@ -332,6 +333,12 @@ Style/MethodName:
Style/ModuleFunction: Style/ModuleFunction:
Enabled: false Enabled: false
# Checks that the closing brace in an array literal is either on the same line
# as the last array element, or a new line.
Style/MultilineArrayBraceLayout:
Enabled: false
EnforcedStyle: symmetrical
# Avoid multi-line chains of blocks. # Avoid multi-line chains of blocks.
Style/MultilineBlockChain: Style/MultilineBlockChain:
Enabled: false Enabled: false
...@@ -340,10 +347,22 @@ Style/MultilineBlockChain: ...@@ -340,10 +347,22 @@ Style/MultilineBlockChain:
Style/MultilineBlockLayout: Style/MultilineBlockLayout:
Enabled: true Enabled: true
# Checks that the closing brace in a hash literal is either on the same line as
# the last hash element, or a new line.
Style/MultilineHashBraceLayout:
Enabled: false
EnforcedStyle: symmetrical
# Do not use then for multi-line if/unless. # Do not use then for multi-line if/unless.
Style/MultilineIfThen: Style/MultilineIfThen:
Enabled: false Enabled: false
# Checks that the closing brace in a method call is either on the same line as
# the last method argument, or a new line.
Style/MultilineMethodCallBraceLayout:
Enabled: false
EnforcedStyle: symmetrical
# Checks indentation of method calls with the dot operator that span more than # Checks indentation of method calls with the dot operator that span more than
# one line. # one line.
Style/MultilineMethodCallIndentation: Style/MultilineMethodCallIndentation:
...@@ -524,14 +543,13 @@ Style/SpaceAfterSemicolon: ...@@ -524,14 +543,13 @@ Style/SpaceAfterSemicolon:
Style/SpaceAroundEqualsInParameterDefault: Style/SpaceAroundEqualsInParameterDefault:
Enabled: false Enabled: false
# TODO: Enable SpaceAroundKeyword Cop.
# Use a space around keywords if appropriate. # Use a space around keywords if appropriate.
Style/SpaceAroundKeyword: Style/SpaceAroundKeyword:
Enabled: false Enabled: true
# Use a single space around operators. # Use a single space around operators.
Style/SpaceAroundOperators: Style/SpaceAroundOperators:
Enabled: false Enabled: true
# Checks that the left block brace has or doesn't have space before it. # Checks that the left block brace has or doesn't have space before it.
Style/SpaceBeforeBlockBraces: Style/SpaceBeforeBlockBraces:
...@@ -754,23 +772,23 @@ Lint/BlockAlignment: ...@@ -754,23 +772,23 @@ Lint/BlockAlignment:
# Default values in optional keyword arguments and optional ordinal arguments # Default values in optional keyword arguments and optional ordinal arguments
# should not refer back to the name of the argument. # should not refer back to the name of the argument.
Lint/CircularArgumentReference: Lint/CircularArgumentReference:
Enabled: false Enabled: true
# Checks for condition placed in a confusing position relative to the keyword. # Checks for condition placed in a confusing position relative to the keyword.
Lint/ConditionPosition: Lint/ConditionPosition:
Enabled: false Enabled: true
# Check for debugger calls. # Check for debugger calls.
Lint/Debugger: Lint/Debugger:
Enabled: false Enabled: true
# Align ends corresponding to defs correctly. # Align ends corresponding to defs correctly.
Lint/DefEndAlignment: Lint/DefEndAlignment:
Enabled: false Enabled: true
# Check for deprecated class method calls. # Check for deprecated class method calls.
Lint/DeprecatedClassMethods: Lint/DeprecatedClassMethods:
Enabled: false Enabled: true
# Check for duplicate method definitions. # Check for duplicate method definitions.
Lint/DuplicateMethods: Lint/DuplicateMethods:
...@@ -782,15 +800,15 @@ Lint/DuplicatedKey: ...@@ -782,15 +800,15 @@ Lint/DuplicatedKey:
# Check for immutable argument given to each_with_object. # Check for immutable argument given to each_with_object.
Lint/EachWithObjectArgument: Lint/EachWithObjectArgument:
Enabled: false Enabled: true
# Check for odd code arrangement in an else block. # Check for odd code arrangement in an else block.
Lint/ElseLayout: Lint/ElseLayout:
Enabled: false Enabled: true
# Checks for empty ensure block. # Checks for empty ensure block.
Lint/EmptyEnsure: Lint/EmptyEnsure:
Enabled: false Enabled: true
# Checks for empty string interpolation. # Checks for empty string interpolation.
Lint/EmptyInterpolation: Lint/EmptyInterpolation:
...@@ -798,37 +816,36 @@ Lint/EmptyInterpolation: ...@@ -798,37 +816,36 @@ Lint/EmptyInterpolation:
# Align ends correctly. # Align ends correctly.
Lint/EndAlignment: Lint/EndAlignment:
Enabled: false Enabled: true
# END blocks should not be placed inside method definitions. # END blocks should not be placed inside method definitions.
Lint/EndInMethod: Lint/EndInMethod:
Enabled: false Enabled: true
# Do not use return in an ensure block. # Do not use return in an ensure block.
Lint/EnsureReturn: Lint/EnsureReturn:
Enabled: false Enabled: true
# The use of eval represents a serious security risk. # The use of eval represents a serious security risk.
Lint/Eval: Lint/Eval:
Enabled: false Enabled: true
# Catches floating-point literals too large or small for Ruby to represent. # Catches floating-point literals too large or small for Ruby to represent.
Lint/FloatOutOfRange: Lint/FloatOutOfRange:
Enabled: false Enabled: true
# The number of parameters to format/sprint must match the fields. # The number of parameters to format/sprint must match the fields.
Lint/FormatParameterMismatch: Lint/FormatParameterMismatch:
Enabled: false Enabled: true
# Don't suppress exception. # Don't suppress exception.
Lint/HandleExceptions: Lint/HandleExceptions:
Enabled: false Enabled: false
# TODO: Enable ImplicitStringConcatenation Cop.
# Checks for adjacent string literals on the same line, which could better be # Checks for adjacent string literals on the same line, which could better be
# represented as a single string literal. # represented as a single string literal.
Lint/ImplicitStringConcatenation: Lint/ImplicitStringConcatenation:
Enabled: false Enabled: true
# TODO: Enable IneffectiveAccessModifier Cop. # TODO: Enable IneffectiveAccessModifier Cop.
# Checks for attempts to use `private` or `protected` to set the visibility # Checks for attempts to use `private` or `protected` to set the visibility
...@@ -839,7 +856,7 @@ Lint/IneffectiveAccessModifier: ...@@ -839,7 +856,7 @@ Lint/IneffectiveAccessModifier:
# Checks for invalid character literals with a non-escaped whitespace # Checks for invalid character literals with a non-escaped whitespace
# character. # character.
Lint/InvalidCharacterLiteral: Lint/InvalidCharacterLiteral:
Enabled: false Enabled: true
# Checks of literals used in conditions. # Checks of literals used in conditions.
Lint/LiteralInCondition: Lint/LiteralInCondition:
...@@ -847,7 +864,7 @@ Lint/LiteralInCondition: ...@@ -847,7 +864,7 @@ Lint/LiteralInCondition:
# Checks for literals used in interpolation. # Checks for literals used in interpolation.
Lint/LiteralInInterpolation: Lint/LiteralInInterpolation:
Enabled: false Enabled: true
# Use Kernel#loop with break rather than begin/end/until or begin/end/while # Use Kernel#loop with break rather than begin/end/until or begin/end/while
# for post-loop tests. # for post-loop tests.
...@@ -856,11 +873,11 @@ Lint/Loop: ...@@ -856,11 +873,11 @@ Lint/Loop:
# Do not use nested method definitions. # Do not use nested method definitions.
Lint/NestedMethodDefinition: Lint/NestedMethodDefinition:
Enabled: false Enabled: true
# Do not omit the accumulator when calling `next` in a `reduce`/`inject` block. # Do not omit the accumulator when calling `next` in a `reduce`/`inject` block.
Lint/NextWithoutAccumulator: Lint/NextWithoutAccumulator:
Enabled: false Enabled: true
# Checks for method calls with a space before the opening parenthesis. # Checks for method calls with a space before the opening parenthesis.
Lint/ParenthesesAsGroupedExpression: Lint/ParenthesesAsGroupedExpression:
...@@ -869,11 +886,11 @@ Lint/ParenthesesAsGroupedExpression: ...@@ -869,11 +886,11 @@ Lint/ParenthesesAsGroupedExpression:
# Checks for `rand(1)` calls. Such calls always return `0` and most likely # Checks for `rand(1)` calls. Such calls always return `0` and most likely
# a mistake. # a mistake.
Lint/RandOne: Lint/RandOne:
Enabled: false Enabled: true
# Use parentheses in the method call to avoid confusion about precedence. # Use parentheses in the method call to avoid confusion about precedence.
Lint/RequireParentheses: Lint/RequireParentheses:
Enabled: false Enabled: true
# Avoid rescuing the Exception class. # Avoid rescuing the Exception class.
Lint/RescueException: Lint/RescueException:
...@@ -908,7 +925,7 @@ Lint/UnusedMethodArgument: ...@@ -908,7 +925,7 @@ Lint/UnusedMethodArgument:
# Unreachable code. # Unreachable code.
Lint/UnreachableCode: Lint/UnreachableCode:
Enabled: false Enabled: true
# Checks for useless access modifiers. # Checks for useless access modifiers.
Lint/UselessAccessModifier: Lint/UselessAccessModifier:
...@@ -920,19 +937,19 @@ Lint/UselessAssignment: ...@@ -920,19 +937,19 @@ Lint/UselessAssignment:
# Checks for comparison of something with itself. # Checks for comparison of something with itself.
Lint/UselessComparison: Lint/UselessComparison:
Enabled: false Enabled: true
# Checks for useless `else` in `begin..end` without `rescue`. # Checks for useless `else` in `begin..end` without `rescue`.
Lint/UselessElseWithoutRescue: Lint/UselessElseWithoutRescue:
Enabled: false Enabled: true
# Checks for useless setter call to a local variable. # Checks for useless setter call to a local variable.
Lint/UselessSetterCall: Lint/UselessSetterCall:
Enabled: false Enabled: true
# Possible use of operator/literal/variable in void context. # Possible use of operator/literal/variable in void context.
Lint/Void: Lint/Void:
Enabled: false Enabled: true
##################### Performance ############################ ##################### Performance ############################
...@@ -941,11 +958,10 @@ Lint/Void: ...@@ -941,11 +958,10 @@ Lint/Void:
Performance/Casecmp: Performance/Casecmp:
Enabled: true Enabled: true
# TODO: Enable DoubleStartEndWith Cop.
# Use `str.{start,end}_with?(x, ..., y, ...)` instead of # Use `str.{start,end}_with?(x, ..., y, ...)` instead of
# `str.{start,end}_with?(x, ...) || str.{start,end}_with?(y, ...)`. # `str.{start,end}_with?(x, ...) || str.{start,end}_with?(y, ...)`.
Performance/DoubleStartEndWith: Performance/DoubleStartEndWith:
Enabled: false Enabled: true
# TODO: Enable EndWith Cop. # TODO: Enable EndWith Cop.
# Use `end_with?` instead of a regex match anchored to the end of a string. # Use `end_with?` instead of a regex match anchored to the end of a string.
...@@ -956,10 +972,9 @@ Performance/EndWith: ...@@ -956,10 +972,9 @@ Performance/EndWith:
Performance/LstripRstrip: Performance/LstripRstrip:
Enabled: true Enabled: true
# TODO: Enable RangeInclude Cop.
# Use `Range#cover?` instead of `Range#include?`. # Use `Range#cover?` instead of `Range#include?`.
Performance/RangeInclude: Performance/RangeInclude:
Enabled: false Enabled: true
# TODO: Enable RedundantBlockCall Cop. # TODO: Enable RedundantBlockCall Cop.
# Use `yield` instead of `block.call`. # Use `yield` instead of `block.call`.
...@@ -979,16 +994,14 @@ Performance/RedundantMerge: ...@@ -979,16 +994,14 @@ Performance/RedundantMerge:
MaxKeyValuePairs: 2 MaxKeyValuePairs: 2
Enabled: false Enabled: false
# TODO: Enable RedundantSortBy Cop.
# Use `sort` instead of `sort_by { |x| x }`. # Use `sort` instead of `sort_by { |x| x }`.
Performance/RedundantSortBy: Performance/RedundantSortBy:
Enabled: false Enabled: true
# TODO: Enable StartWith Cop.
# Use `start_with?` instead of a regex match anchored to the beginning of a # Use `start_with?` instead of a regex match anchored to the beginning of a
# string. # string.
Performance/StartWith: Performance/StartWith:
Enabled: false Enabled: true
# Use `tr` instead of `gsub` when you are replacing the same number of # Use `tr` instead of `gsub` when you are replacing the same number of
# characters. Use `delete` instead of `gsub` when you are deleting # characters. Use `delete` instead of `gsub` when you are deleting
...@@ -1024,11 +1037,11 @@ Rails/Delegate: ...@@ -1024,11 +1037,11 @@ Rails/Delegate:
# Prefer `find_by` over `where.first`. # Prefer `find_by` over `where.first`.
Rails/FindBy: Rails/FindBy:
Enabled: false Enabled: true
# Prefer `all.find_each` over `all.find`. # Prefer `all.find_each` over `all.find`.
Rails/FindEach: Rails/FindEach:
Enabled: false Enabled: true
# Prefer has_many :through to has_and_belongs_to_many. # Prefer has_many :through to has_and_belongs_to_many.
Rails/HasAndBelongsToMany: Rails/HasAndBelongsToMany:
...@@ -1040,7 +1053,7 @@ Rails/Output: ...@@ -1040,7 +1053,7 @@ Rails/Output:
# Checks for incorrect grammar when using methods like `3.day.ago`. # Checks for incorrect grammar when using methods like `3.day.ago`.
Rails/PluralizationGrammar: Rails/PluralizationGrammar:
Enabled: false Enabled: true
# Checks for `read_attribute(:attr)` and `write_attribute(:attr, val)`. # Checks for `read_attribute(:attr)` and `write_attribute(:attr, val)`.
Rails/ReadWriteAttribute: Rails/ReadWriteAttribute:
...@@ -1048,7 +1061,7 @@ Rails/ReadWriteAttribute: ...@@ -1048,7 +1061,7 @@ Rails/ReadWriteAttribute:
# Checks the arguments of ActiveRecord scopes. # Checks the arguments of ActiveRecord scopes.
Rails/ScopeArgs: Rails/ScopeArgs:
Enabled: false Enabled: true
# Checks the correct usage of time zone aware methods. # Checks the correct usage of time zone aware methods.
# http://danilenko.org/2012/7/6/rails_timezones # http://danilenko.org/2012/7/6/rails_timezones
......
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.8.0 (unreleased) v 8.8.2 (unreleased)
- Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources
- Fix Error 500 in CI charts by gracefully handling commits with no durations
v 8.8.1
- Add documentation for the "Health Check" feature
- Allow anonymous users to access a public project's pipelines
- Fix MySQL compatibility in zero downtime migrations helpers
- Fix the CI login to Container Registry (the gitlab-ci-token user)
v 8.8.0
- Implement GFM references for milestones (Alejandro Rodríguez)
- Snippets tab under user profile. !4001 (Long Nguyen)
- Fix error when using link to uploads in global snippets - Fix error when using link to uploads in global snippets
- Fix Error 500 when attempting to retrieve project license when HEAD points to non-existent ref
- Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen) - Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen)
- Use a case-insensitive comparison in sanitizing URI schemes - Use a case-insensitive comparison in sanitizing URI schemes
- Toggle sign-up confirmation emails in application settings
- Make it possible to prevent tagged runner from picking untagged jobs
- Added `InlineDiffFilter` to the markdown parser. (Adam Butler)
- Added inline diff styling for `change_title` system notes. (Adam Butler)
- Project#open_branches has been cleaned up and no longer loads entire records into memory. - Project#open_branches has been cleaned up and no longer loads entire records into memory.
- Escape HTML in commit titles in system note messages - Escape HTML in commit titles in system note messages
- Fix scope used when accessing container registry
- Fix creation of Ci::Commit object which can lead to pending, failed in some scenarios
- Improve multiple branch push performance by memoizing permission checking - Improve multiple branch push performance by memoizing permission checking
- Log to application.log when an admin starts and stops impersonating a user - Log to application.log when an admin starts and stops impersonating a user
- Changing the confidentiality of an issue now creates a new system note (Alex Moore-Niemi)
- Updated gitlab_git to 10.1.0 - Updated gitlab_git to 10.1.0
- GitAccess#protected_tag? no longer loads all tags just to check if a single one exists - GitAccess#protected_tag? no longer loads all tags just to check if a single one exists
- Reduce delay in destroying a project from 1-minute to immediately - Reduce delay in destroying a project from 1-minute to immediately
- Make build status canceled if any of the jobs was canceled and none failed - Make build status canceled if any of the jobs was canceled and none failed
- Upgrade Sidekiq to 4.1.2 - Upgrade Sidekiq to 4.1.2
- Added /health_check endpoint for checking service status
- Make 'upcoming' filter for milestones work better across projects
- Sanitize repo paths in new project error message - Sanitize repo paths in new project error message
- Bump mail_room to 0.7.0 to fix stuck IDLE connections - Bump mail_room to 0.7.0 to fix stuck IDLE connections
- Remove future dates from contribution calendar graph. - Remove future dates from contribution calendar graph.
- Support e-mail notifications for comments on project snippets - Support e-mail notifications for comments on project snippets
- Fix API leak of notes of unauthorized issues, snippets and merge requests
- Use ActionDispatch Remote IP for Akismet checking - Use ActionDispatch Remote IP for Akismet checking
- Fix error when visiting commit builds page before build was updated - Fix error when visiting commit builds page before build was updated
- Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project - Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project
- Update SVG sanitizer to conform to SVG 1.1 - Update SVG sanitizer to conform to SVG 1.1
- Speed up push emails with multiple recipients by only generating the email once
- Updated search UI - Updated search UI
- Added authentication service for Container Registry
- Display informative message when new milestone is created - Display informative message when new milestone is created
- Sanitize milestones and labels titles - Sanitize milestones and labels titles
- Support multi-line tag messages. !3833 (Calin Seciu) - Support multi-line tag messages. !3833 (Calin Seciu)
- Force users to reset their password after an admin changes it
- Allow "NEWS" and "CHANGES" as alternative names for CHANGELOG. !3768 (Connor Shea) - Allow "NEWS" and "CHANGES" as alternative names for CHANGELOG. !3768 (Connor Shea)
- Added button to toggle whitespaces changes on diff view - Added button to toggle whitespaces changes on diff view
- Backport GitHub Enterprise import support from EE - Backport GitHub Enterprise import support from EE
- Create tags using Rugged for performance reasons. !3745 - Create tags using Rugged for performance reasons. !3745
- Allow guests to set notification level in projects
- API: Expose Issue#user_notes_count. !3126 (Anton Popov) - API: Expose Issue#user_notes_count. !3126 (Anton Popov)
- Don't show forks button when user can't view forks
- Fix atom feed links and rendering
- Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718 - Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718
- Add support for supressing text diffs using .gitattributes on the default branch (Matt Oakes) - Add support for supressing text diffs using .gitattributes on the default branch (Matt Oakes)
- Add eager load paths to help prevent dependency load issues in Sidekiq workers. !3724 - Add eager load paths to help prevent dependency load issues in Sidekiq workers. !3724
- Added multiple colors for labels in dropdowns when dups happen. - Added multiple colors for labels in dropdowns when dups happen.
- Show commits in the same order as `git log`
- Improve description for the Two-factor Authentication sign-in screen. (Connor Shea) - Improve description for the Two-factor Authentication sign-in screen. (Connor Shea)
- API support for the 'since' and 'until' operators on commit requests (Paco Guzman) - API support for the 'since' and 'until' operators on commit requests (Paco Guzman)
- Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko) - Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko)
- Expire repository exists? and has_visible_content? caches after a push if necessary - Expire repository exists? and has_visible_content? caches after a push if necessary
- Fix unintentional filtering bug in issues sorted by milestone due (Takuya Noguchi) - Fix unintentional filtering bug in Issue/MR sorted by milestone due (Takuya Noguchi)
- Fix adding a todo for private group members (Ahmad Sherif) - Fix adding a todo for private group members (Ahmad Sherif)
- Bump ace-rails-ap gem version from 2.0.1 to 4.0.2 which upgrades Ace Editor from 1.1.2 to 1.2.3 - Bump ace-rails-ap gem version from 2.0.1 to 4.0.2 which upgrades Ace Editor from 1.1.2 to 1.2.3
- Total method execution timings are no longer tracked
- Allow Admins to remove the Login with buttons for OAuth services and still be able to import !4034. (Andrei Gliga)
- Add API endpoints for un/subscribing from/to a label. !4051 (Ahmad Sherif)
- Hide left sidebar on phone screens to give more space for content
- Redesign navigation for profile and group pages
- Add counter metrics for rails cache
- Import pull requests from GitHub where the source or target branches were removed
- All Grape API helpers are now instrumented
- Improve Issue formatting for the Slack Service (Jeroen van Baarsen)
- Fixed advice on invalid permissions on upload path !2948 (Ludovic Perrine)
- Allows MR authors to have the source branch removed when merging the MR. !2801 (Jeroen Jacobs)
- When creating a .gitignore file a dropdown with templates will be provided
v 8.7.6
- Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko)
- Fix import from GitLab.com to a private instance failure. !4181
- Fix external imports not finding the import data. !4106
v 8.7.5
- Fix relative links in wiki pages. !4050
- Fix always showing build notification message when switching between merge requests !4086
- Fix an issue when filtering merge requests with more than one label. !3886
- Fix short note for the default scope on build page (Takuya Noguchi)
v 8.7.4 v 8.7.4
- Fix always showing build notification message when switching between merge requests - Links for Redmine issue references are generated correctly again !4048 (Benedikt Huss)
- Links for Redmine issue references are generated correctly again (Benedikt Huss) - Fix setting trusted proxies !3970
- Fix an issue when filtering merge requests with more than one label. !3886 - Fix BitBucket importer bug when throwing exceptions !3941
- Use sign out path only if not empty !3989
- Running rake gitlab:db:drop_tables now drops tables with cascade !4020
- Running rake gitlab:db:drop_tables uses "IF EXISTS" as a precaution !4100
- Use a case-insensitive comparison in sanitizing URI schemes
v 8.7.3 v 8.7.3
- Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented
- Merge request widget displays TeamCity build state and code coverage correctly again. - Merge request widget displays TeamCity build state and code coverage correctly again.
- Fix the line code when importing PR review comments from GitHub. !4010 - Fix the line code when importing PR review comments from GitHub. !4010
- Wikis are now initialized on legacy projects when checking repositories - Wikis are now initialized on legacy projects when checking repositories
- Remove animate.css in favor of a smaller subset of animations. !3937 (Connor Shea)
v 8.7.2 v 8.7.2
- The "New Branch" button is now loaded asynchronously - The "New Branch" button is now loaded asynchronously
...@@ -860,7 +918,7 @@ v 8.1.3 ...@@ -860,7 +918,7 @@ v 8.1.3
- Use issue editor as cross reference comment author when issue is edited with a new mention - Use issue editor as cross reference comment author when issue is edited with a new mention
- Add Facebook authentication - Add Facebook authentication
v 8.1.2 v 8.1.1
- Fix cloning Wiki repositories via HTTP (Stan Hu) - Fix cloning Wiki repositories via HTTP (Stan Hu)
- Add migration to remove satellites directory - Add migration to remove satellites directory
- Fix specific runners visibility - Fix specific runners visibility
...@@ -1485,20 +1543,17 @@ v 7.10.0 ...@@ -1485,20 +1543,17 @@ v 7.10.0
- Fix stuck Merge Request merging events from old installations (Ben Bodenmiller) - Fix stuck Merge Request merging events from old installations (Ben Bodenmiller)
- Fix merge request comments on files with multiple commits - Fix merge request comments on files with multiple commits
- Fix Resource Owner Password Authentication Flow - Fix Resource Owner Password Authentication Flow
v 7.9.4
- Security: Fix project import URL regex to prevent arbitary local repos from being imported
- Fixed issue where only 25 commits would load in file listings
- Fix LDAP identities after config update
v 7.9.3
- Contains no changes
- Add icons to Add dropdown items. - Add icons to Add dropdown items.
- Allow admin to create public deploy keys that are accessible to any project. - Allow admin to create public deploy keys that are accessible to any project.
- Warn when gitlab-shell version doesn't match requirement. - Warn when gitlab-shell version doesn't match requirement.
- Skip email confirmation when set by admin or via LDAP. - Skip email confirmation when set by admin or via LDAP.
- Only allow users to reference groups, projects, issues, MRs, commits they have access to. - Only allow users to reference groups, projects, issues, MRs, commits they have access to.
v 7.9.4
- Security: Fix project import URL regex to prevent arbitary local repos from being imported
- Fixed issue where only 25 commits would load in file listings
- Fix LDAP identities after config update
v 7.9.3 v 7.9.3
- Contains no changes - Contains no changes
......
...@@ -36,6 +36,7 @@ gem 'omniauth-shibboleth', '~> 1.2.0' ...@@ -36,6 +36,7 @@ gem 'omniauth-shibboleth', '~> 1.2.0'
gem 'omniauth-twitter', '~> 1.2.0' gem 'omniauth-twitter', '~> 1.2.0'
gem 'omniauth_crowd', '~> 2.2.0' gem 'omniauth_crowd', '~> 2.2.0'
gem 'rack-oauth2', '~> 1.2.1' gem 'rack-oauth2', '~> 1.2.1'
gem 'jwt'
# Spam and anti-bot protection # Spam and anti-bot protection
gem 'recaptcha', require: 'recaptcha/rails' gem 'recaptcha', require: 'recaptcha/rails'
...@@ -224,6 +225,7 @@ gem 'request_store', '~> 1.3.0' ...@@ -224,6 +225,7 @@ gem 'request_store', '~> 1.3.0'
gem 'select2-rails', '~> 3.5.9' gem 'select2-rails', '~> 3.5.9'
gem 'virtus', '~> 1.0.1' gem 'virtus', '~> 1.0.1'
gem 'net-ssh', '~> 3.0.1' gem 'net-ssh', '~> 3.0.1'
gem 'base32', '~> 0.3.0'
# Sentry integration # Sentry integration
gem 'sentry-raven', '~> 0.15' gem 'sentry-raven', '~> 0.15'
...@@ -291,9 +293,9 @@ group :development, :test do ...@@ -291,9 +293,9 @@ 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.38.0', require: false gem 'rubocop', '~> 0.40.0', require: false
gem 'scss_lint', '~> 0.47.0', require: false gem 'scss_lint', '~> 0.47.0', require: false
gem 'coveralls', '~> 0.8.2', require: false gem 'coveralls', '~> 0.8.2', require: false
gem 'simplecov', '~> 0.11.0', require: false gem 'simplecov', '~> 0.11.0', require: false
gem 'flog', require: false gem 'flog', require: false
gem 'flay', require: false gem 'flay', require: false
...@@ -323,8 +325,7 @@ gem "mail_room", "~> 0.7" ...@@ -323,8 +325,7 @@ gem "mail_room", "~> 0.7"
gem 'email_reply_parser', '~> 0.5.8' gem 'email_reply_parser', '~> 0.5.8'
## CI ## CI
gem 'activerecord-deprecated_finders', '~> 1.0.3' gem 'activerecord-session_store', '~> 1.0.0'
gem 'activerecord-session_store', '~> 0.1.0'
gem "nested_form", '~> 0.3.2' gem "nested_form", '~> 0.3.2'
# OAuth # OAuth
...@@ -332,3 +333,6 @@ gem 'oauth2', '~> 1.0.0' ...@@ -332,3 +333,6 @@ gem 'oauth2', '~> 1.0.0'
# Soft deletion # Soft deletion
gem "paranoia", "~> 2.0" gem "paranoia", "~> 2.0"
# Health check
gem 'health_check', '~> 1.5.1'
...@@ -33,11 +33,12 @@ GEM ...@@ -33,11 +33,12 @@ GEM
activemodel (= 4.2.6) activemodel (= 4.2.6)
activesupport (= 4.2.6) activesupport (= 4.2.6)
arel (~> 6.0) arel (~> 6.0)
activerecord-deprecated_finders (1.0.4) activerecord-session_store (1.0.0)
activerecord-session_store (0.1.2) actionpack (>= 4.0, < 5.1)
actionpack (>= 4.0.0, < 5) activerecord (>= 4.0, < 5.1)
activerecord (>= 4.0.0, < 5) multi_json (~> 1.11, >= 1.11.2)
railties (>= 4.0.0, < 5) rack (>= 1.5.2, < 3)
railties (>= 4.0, < 5.1)
activesupport (4.2.6) activesupport (4.2.6)
i18n (~> 0.7) i18n (~> 0.7)
json (~> 1.7, >= 1.7.7) json (~> 1.7, >= 1.7.7)
...@@ -71,6 +72,7 @@ GEM ...@@ -71,6 +72,7 @@ GEM
ice_nine (~> 0.11.0) ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
babosa (1.0.2) babosa (1.0.2)
base32 (0.3.2)
bcrypt (3.1.10) bcrypt (3.1.10)
benchmark-ips (2.3.0) benchmark-ips (2.3.0)
better_errors (1.0.1) better_errors (1.0.1)
...@@ -402,6 +404,8 @@ GEM ...@@ -402,6 +404,8 @@ GEM
html2haml (>= 1.0.1) html2haml (>= 1.0.1)
railties (>= 4.0.1) railties (>= 4.0.1)
hashie (3.4.3) hashie (3.4.3)
health_check (1.5.1)
rails (>= 2.3.0)
highline (1.7.8) highline (1.7.8)
hipchat (1.5.2) hipchat (1.5.2)
httparty httparty
...@@ -547,7 +551,7 @@ GEM ...@@ -547,7 +551,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.0.6) parser (2.3.1.0)
ast (~> 2.2) ast (~> 2.2)
pg (0.18.4) pg (0.18.4)
poltergeist (1.9.0) poltergeist (1.9.0)
...@@ -682,15 +686,15 @@ GEM ...@@ -682,15 +686,15 @@ GEM
rspec-retry (0.4.5) rspec-retry (0.4.5)
rspec-core rspec-core
rspec-support (3.4.1) rspec-support (3.4.1)
rubocop (0.38.0) rubocop (0.40.0)
parser (>= 2.3.0.6, < 3.0) parser (>= 2.3.1.0, < 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)
unicode-display_width (~> 1.0, >= 1.0.1) unicode-display_width (~> 1.0, >= 1.0.1)
ruby-fogbugz (0.2.1) ruby-fogbugz (0.2.1)
crack (~> 0.4) crack (~> 0.4)
ruby-progressbar (1.7.5) ruby-progressbar (1.8.1)
ruby-saml (1.1.2) ruby-saml (1.1.2)
nokogiri (>= 1.5.10) nokogiri (>= 1.5.10)
uuid (~> 2.3) uuid (~> 2.3)
...@@ -837,7 +841,7 @@ GEM ...@@ -837,7 +841,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.2) unicode-display_width (1.0.5)
unicorn (4.9.0) unicorn (4.9.0)
kgio (~> 2.6) kgio (~> 2.6)
rack rack
...@@ -881,8 +885,7 @@ PLATFORMS ...@@ -881,8 +885,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
RedCloth (~> 4.2.9) RedCloth (~> 4.2.9)
ace-rails-ap (~> 4.0.2) ace-rails-ap (~> 4.0.2)
activerecord-deprecated_finders (~> 1.0.3) activerecord-session_store (~> 1.0.0)
activerecord-session_store (~> 0.1.0)
acts-as-taggable-on (~> 3.4) acts-as-taggable-on (~> 3.4)
addressable (~> 2.3.8) addressable (~> 2.3.8)
after_commit_queue after_commit_queue
...@@ -893,6 +896,7 @@ DEPENDENCIES ...@@ -893,6 +896,7 @@ DEPENDENCIES
attr_encrypted (~> 1.3.4) attr_encrypted (~> 1.3.4)
awesome_print (~> 1.2.0) awesome_print (~> 1.2.0)
babosa (~> 1.0.2) babosa (~> 1.0.2)
base32 (~> 0.3.0)
benchmark-ips benchmark-ips
better_errors (~> 1.0.1) better_errors (~> 1.0.1)
binding_of_caller (~> 0.7.2) binding_of_caller (~> 0.7.2)
...@@ -945,6 +949,7 @@ DEPENDENCIES ...@@ -945,6 +949,7 @@ DEPENDENCIES
grape (~> 0.13.0) grape (~> 0.13.0)
grape-entity (~> 0.4.2) grape-entity (~> 0.4.2)
haml-rails (~> 0.9.0) haml-rails (~> 0.9.0)
health_check (~> 1.5.1)
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)
...@@ -953,6 +958,7 @@ DEPENDENCIES ...@@ -953,6 +958,7 @@ DEPENDENCIES
jquery-rails (~> 4.1.0) jquery-rails (~> 4.1.0)
jquery-turbolinks (~> 2.1.0) jquery-turbolinks (~> 2.1.0)
jquery-ui-rails (~> 5.0.0) jquery-ui-rails (~> 5.0.0)
jwt
kaminari (~> 0.16.3) kaminari (~> 0.16.3)
letter_opener_web (~> 1.3.0) letter_opener_web (~> 1.3.0)
licensee (~> 8.0.0) licensee (~> 8.0.0)
...@@ -1009,7 +1015,7 @@ DEPENDENCIES ...@@ -1009,7 +1015,7 @@ DEPENDENCIES
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.4.0) rspec-rails (~> 3.4.0)
rspec-retry rspec-retry
rubocop (~> 0.38.0) rubocop (~> 0.40.0)
ruby-fogbugz (~> 0.2.1) ruby-fogbugz (~> 0.2.1)
sanitize (~> 2.0) sanitize (~> 2.0)
sass-rails (~> 5.0.0) sass-rails (~> 5.0.0)
...@@ -1054,4 +1060,4 @@ DEPENDENCIES ...@@ -1054,4 +1060,4 @@ DEPENDENCIES
wikicloth (= 0.8.1) wikicloth (= 0.8.1)
BUNDLED WITH BUNDLED WITH
1.12.3 1.12.4
@Api = @Api =
groups_path: "/api/:version/groups.json" groupsPath: "/api/:version/groups.json"
group_path: "/api/:version/groups/:id.json" groupPath: "/api/:version/groups/:id.json"
namespaces_path: "/api/:version/namespaces.json" namespacesPath: "/api/:version/namespaces.json"
group_projects_path: "/api/:version/groups/:id/projects.json" groupProjectsPath: "/api/:version/groups/:id/projects.json"
projects_path: "/api/:version/projects.json" projectsPath: "/api/:version/projects.json"
labels_path: "/api/:version/projects/:id/labels" labelsPath: "/api/:version/projects/:id/labels"
license_path: "/api/:version/licenses/:key" licensePath: "/api/:version/licenses/:key"
gitignorePath: "/api/:version/gitignores/:key"
group: (group_id, callback) -> group: (group_id, callback) ->
url = Api.buildUrl(Api.group_path) url = Api.buildUrl(Api.groupPath)
url = url.replace(':id', group_id) url = url.replace(':id', group_id)
$.ajax( $.ajax(
...@@ -22,7 +23,7 @@ ...@@ -22,7 +23,7 @@
# Return groups list. Filtered by query # Return groups list. Filtered by query
# Only active groups retrieved # Only active groups retrieved
groups: (query, skip_ldap, callback) -> groups: (query, skip_ldap, callback) ->
url = Api.buildUrl(Api.groups_path) url = Api.buildUrl(Api.groupsPath)
$.ajax( $.ajax(
url: url url: url
...@@ -36,7 +37,7 @@ ...@@ -36,7 +37,7 @@
# Return namespaces list. Filtered by query # Return namespaces list. Filtered by query
namespaces: (query, callback) -> namespaces: (query, callback) ->
url = Api.buildUrl(Api.namespaces_path) url = Api.buildUrl(Api.namespacesPath)
$.ajax( $.ajax(
url: url url: url
...@@ -50,7 +51,7 @@ ...@@ -50,7 +51,7 @@
# Return projects list. Filtered by query # Return projects list. Filtered by query
projects: (query, order, callback) -> projects: (query, order, callback) ->
url = Api.buildUrl(Api.projects_path) url = Api.buildUrl(Api.projectsPath)
$.ajax( $.ajax(
url: url url: url
...@@ -64,7 +65,7 @@ ...@@ -64,7 +65,7 @@
callback(projects) callback(projects)
newLabel: (project_id, data, callback) -> newLabel: (project_id, data, callback) ->
url = Api.buildUrl(Api.labels_path) url = Api.buildUrl(Api.labelsPath)
url = url.replace(':id', project_id) url = url.replace(':id', project_id)
data.private_token = gon.api_token data.private_token = gon.api_token
...@@ -80,7 +81,7 @@ ...@@ -80,7 +81,7 @@
# Return group projects list. Filtered by query # Return group projects list. Filtered by query
groupProjects: (group_id, query, callback) -> groupProjects: (group_id, query, callback) ->
url = Api.buildUrl(Api.group_projects_path) url = Api.buildUrl(Api.groupProjectsPath)
url = url.replace(':id', group_id) url = url.replace(':id', group_id)
$.ajax( $.ajax(
...@@ -95,7 +96,7 @@ ...@@ -95,7 +96,7 @@
# Return text for a specific license # Return text for a specific license
licenseText: (key, data, callback) -> licenseText: (key, data, callback) ->
url = Api.buildUrl(Api.license_path).replace(':key', key) url = Api.buildUrl(Api.licensePath).replace(':key', key)
$.ajax( $.ajax(
url: url url: url
...@@ -103,6 +104,12 @@ ...@@ -103,6 +104,12 @@
).done (license) -> ).done (license) ->
callback(license) callback(license)
gitignoreText: (key, callback) ->
url = Api.buildUrl(Api.gitignorePath).replace(':key', key)
$.get url, (gitignore) ->
callback(gitignore)
buildUrl: (url) -> buildUrl: (url) ->
url = gon.relative_url_root + url if gon.relative_url_root? url = gon.relative_url_root + url if gon.relative_url_root?
return url.replace(':version', gon.api_version) return url.replace(':version', gon.api_version)
class @BlobGitignoreSelector
constructor: (opts) ->
{
@dropdown
@editor
@$wrapper = @dropdown.closest('.gitignore-selector')
@$filenameInput = $('#file_name')
@data = @dropdown.data('filenames')
} = opts
@dropdown.glDropdown(
data: @data,
filterable: true,
selectable: true,
search:
fields: ['name']
clicked: @onClick
text: (gitignore) ->
gitignore.name
)
@toggleGitignoreSelector()
@bindEvents()
bindEvents: ->
@$filenameInput
.on 'keyup blur', (e) =>
@toggleGitignoreSelector()
toggleGitignoreSelector: ->
filename = @$filenameInput.val() or $('.editor-file-name').text().trim()
@$wrapper.toggleClass 'hidden', filename isnt '.gitignore'
onClick: (item, el, e) =>
e.preventDefault()
@requestIgnoreFile(item.name)
requestIgnoreFile: (name) ->
Api.gitignoreText name, @requestIgnoreFileSuccess.bind(@)
requestIgnoreFileSuccess: (gitignore) ->
@editor.setValue(gitignore.content, 1)
@editor.focus()
class @BlobGitignoreSelectors
constructor: (opts) ->
{
@$dropdowns = $('.js-gitignore-selector')
@editor
} = opts
@$dropdowns.each (i, dropdown) =>
$dropdown = $(dropdown)
new BlobGitignoreSelector(
dropdown: $dropdown,
editor: @editor
)
...@@ -13,6 +13,7 @@ class @EditBlob ...@@ -13,6 +13,7 @@ class @EditBlob
@initModePanesAndLinks() @initModePanesAndLinks()
new BlobLicenseSelector(@editor) new BlobLicenseSelector(@editor)
new BlobGitignoreSelectors(editor: @editor)
initModePanesAndLinks: -> initModePanesAndLinks: ->
@$editModePanes = $(".js-edit-mode-pane") @$editModePanes = $(".js-edit-mode-pane")
......
class CiBuild class CiBuild
@interval: null @interval: null
@state: null
constructor: (build_url, build_status) -> constructor: (build_url, build_status, build_state) ->
clearInterval(CiBuild.interval) clearInterval(CiBuild.interval)
@state = build_state
@initScrollButtonAffix() @initScrollButtonAffix()
if build_status == "running" || build_status == "pending" if build_status == "running" || build_status == "pending"
...@@ -26,14 +29,18 @@ class CiBuild ...@@ -26,14 +29,18 @@ class CiBuild
CiBuild.interval = setInterval => CiBuild.interval = setInterval =>
if window.location.href.split("#").first() is build_url if window.location.href.split("#").first() is build_url
$.ajax $.ajax
url: build_url url: build_url + "/trace.json?state=" + encodeURIComponent(@state)
dataType: "json" dataType: "json"
success: (build) => success: (log) =>
if build.status == "running" @state = log.state
$('#build-trace code').html build.trace_html if log.status is "running"
$('#build-trace code').append '<i class="fa fa-refresh fa-spin"/>' if log.append
$('.fa-refresh').before log.html
else
$('#build-trace code').html log.html
$('#build-trace code').append '<i class="fa fa-refresh fa-spin"/>'
@checkAutoscroll() @checkAutoscroll()
else if build.status != build_status else if log.status isnt build_status
Turbolinks.visit build_url Turbolinks.visit build_url
, 4000 , 4000
......
...@@ -11,6 +11,7 @@ class @DueDateSelect ...@@ -11,6 +11,7 @@ class @DueDateSelect
$block = $dropdown.closest('.block') $block = $dropdown.closest('.block')
$selectbox = $dropdown.closest('.selectbox') $selectbox = $dropdown.closest('.selectbox')
$value = $block.find('.value') $value = $block.find('.value')
$valueContent = $block.find('.value-content')
$sidebarValue = $('.js-due-date-sidebar-value', $block) $sidebarValue = $('.js-due-date-sidebar-value', $block)
fieldName = $dropdown.data('field-name') fieldName = $dropdown.data('field-name')
...@@ -23,11 +24,15 @@ class @DueDateSelect ...@@ -23,11 +24,15 @@ class @DueDateSelect
$value.removeAttr('style') $value.removeAttr('style')
) )
addDueDate = -> addDueDate = (isDropdown) ->
# Create the post date # Create the post date
value = $("input[name='#{fieldName}']").val() value = $("input[name='#{fieldName}']").val()
date = new Date value.replace(new RegExp('-', 'g'), ',')
mediumDate = $.datepicker.formatDate 'M d, yy', date if value isnt ''
date = new Date value.replace(new RegExp('-', 'g'), ',')
mediumDate = $.datepicker.formatDate 'M d, yy', date
else
mediumDate = 'None'
data = {} data = {}
data[abilityName] = {} data[abilityName] = {}
...@@ -39,23 +44,35 @@ class @DueDateSelect ...@@ -39,23 +44,35 @@ class @DueDateSelect
data: data data: data
beforeSend: -> beforeSend: ->
$loading.fadeIn() $loading.fadeIn()
$dropdown.trigger('loading.gl.dropdown') if isDropdown
$selectbox.hide() $dropdown.trigger('loading.gl.dropdown')
$selectbox.hide()
$value.removeAttr('style') $value.removeAttr('style')
$value.html(mediumDate) $valueContent.html(mediumDate)
$sidebarValue.html(mediumDate) $sidebarValue.html(mediumDate)
if value isnt ''
$('.js-remove-due-date-holder').removeClass 'hidden'
else
$('.js-remove-due-date-holder').addClass 'hidden'
).done (data) -> ).done (data) ->
$dropdown.trigger('loaded.gl.dropdown') if isDropdown
$dropdown.dropdown('toggle') $dropdown.trigger('loaded.gl.dropdown')
$dropdown.dropdown('toggle')
$loading.fadeOut() $loading.fadeOut()
$block.on 'click', '.js-remove-due-date', (e) ->
e.preventDefault()
$("input[name='#{fieldName}']").val ''
addDueDate(false)
$datePicker.datepicker( $datePicker.datepicker(
dateFormat: 'yy-mm-dd', dateFormat: 'yy-mm-dd',
defaultDate: $("input[name='#{fieldName}']").val() defaultDate: $("input[name='#{fieldName}']").val()
altField: "input[name='#{fieldName}']" altField: "input[name='#{fieldName}']"
onSelect: -> onSelect: ->
addDueDate() addDueDate(true)
) )
$(document) $(document)
......
...@@ -18,6 +18,10 @@ GitLab.GfmAutoComplete = ...@@ -18,6 +18,10 @@ GitLab.GfmAutoComplete =
Issues: Issues:
template: '<li><small>${id}</small> ${title}</li>' template: '<li><small>${id}</small> ${title}</li>'
# Milestones
Milestones:
template: '<li>${title}</li>'
# Add GFM auto-completion to all input fields, that accept GFM input. # Add GFM auto-completion to all input fields, that accept GFM input.
setup: (wrap) -> setup: (wrap) ->
@input = $('.js-gfm-input') @input = $('.js-gfm-input')
...@@ -81,6 +85,19 @@ GitLab.GfmAutoComplete = ...@@ -81,6 +85,19 @@ GitLab.GfmAutoComplete =
title: sanitize(i.title) title: sanitize(i.title)
search: "#{i.iid} #{i.title}" search: "#{i.iid} #{i.title}"
@input.atwho
at: '%'
alias: 'milestones'
searchKey: 'search'
displayTpl: @Milestones.template
insertTpl: '${atwho-at}"${title}"'
callbacks:
beforeSave: (milestones) ->
$.map milestones, (m) ->
id: m.iid
title: sanitize(m.title)
search: "#{m.title}"
@input.atwho @input.atwho
at: '!' at: '!'
alias: 'mergerequests' alias: 'mergerequests'
...@@ -105,6 +122,8 @@ GitLab.GfmAutoComplete = ...@@ -105,6 +122,8 @@ GitLab.GfmAutoComplete =
@input.atwho 'load', '@', data.members @input.atwho 'load', '@', data.members
# load issues # load issues
@input.atwho 'load', 'issues', data.issues @input.atwho 'load', 'issues', data.issues
# load milestones
@input.atwho 'load', 'milestones', data.milestones
# load merge requests # load merge requests
@input.atwho 'load', 'mergerequests', data.mergerequests @input.atwho 'load', 'mergerequests', data.mergerequests
# load emojis # load emojis
......
...@@ -60,9 +60,36 @@ class GitLabDropdownFilter ...@@ -60,9 +60,36 @@ class GitLabDropdownFilter
results = data results = data
if search_text isnt '' if search_text isnt ''
results = fuzzaldrinPlus.filter(data, search_text, # When data is an array of objects therefore [object Array] e.g.
key: @options.keys # [
) # { prop: 'foo' },
# { prop: 'baz' }
# ]
if _.isArray(data)
results = fuzzaldrinPlus.filter(data, search_text,
key: @options.keys
)
else
# If data is grouped therefore an [object Object]. e.g.
# {
# groupName1: [
# { prop: 'foo' },
# { prop: 'baz' }
# ],
# groupName2: [
# { prop: 'abc' },
# { prop: 'def' }
# ]
# }
if gl.utils.isObject data
results = {}
for key, group of data
tmp = fuzzaldrinPlus.filter(group, search_text,
key: @options.keys
)
if tmp.length
results[key] = tmp.map (item) -> item
@options.callback results @options.callback results
else else
...@@ -141,8 +168,9 @@ class GitLabDropdown ...@@ -141,8 +168,9 @@ class GitLabDropdown
searchFields = if @options.search then @options.search.fields else []; searchFields = if @options.search then @options.search.fields else [];
if @options.data if @options.data
# If data is an array # If we provided data
if _.isArray @options.data # data could be an array of objects or a group of arrays
if _.isObject(@options.data) and not _.isFunction(@options.data)
@fullData = @options.data @fullData = @options.data
@parseData @options.data @parseData @options.data
else else
...@@ -230,19 +258,33 @@ class GitLabDropdown ...@@ -230,19 +258,33 @@ class GitLabDropdown
parseData: (data) -> parseData: (data) ->
@renderedData = data @renderedData = data
# Render each row
html = $.map data, (obj) =>
return @renderItem(obj)
if @options.filterable and data.length is 0 if @options.filterable and data.length is 0
# render no matching results # render no matching results
html = [@noResults()] html = [@noResults()]
else
# Handle array groups
if gl.utils.isObject data
html = []
for name, groupData of data
# Add header for each group
html.push(@renderItem(header: name, name))
@renderData(groupData, name)
.map (item) ->
html.push item
else
# Render each row
html = @renderData(data)
# Render the full menu # Render the full menu
full_html = @renderMenu(html.join("")) full_html = @renderMenu(html.join(""))
@appendMenu(full_html) @appendMenu(full_html)
renderData: (data, group = false) ->
data.map (obj, index) =>
return @renderItem(obj, group, index)
shouldPropagate: (e) => shouldPropagate: (e) =>
if @options.multiSelect if @options.multiSelect
$target = $(e.target) $target = $(e.target)
...@@ -299,11 +341,10 @@ class GitLabDropdown ...@@ -299,11 +341,10 @@ class GitLabDropdown
selector = '.dropdown-content' selector = '.dropdown-content'
if @dropdown.find(".dropdown-toggle-page").length if @dropdown.find(".dropdown-toggle-page").length
selector = ".dropdown-page-one .dropdown-content" selector = ".dropdown-page-one .dropdown-content"
$(selector, @dropdown).html html $(selector, @dropdown).html html
# Render the row # Render the row
renderItem: (data) -> renderItem: (data, group = false, index = false) ->
html = "" html = ""
# Divider # Divider
...@@ -346,8 +387,13 @@ class GitLabDropdown ...@@ -346,8 +387,13 @@ class GitLabDropdown
if @highlight if @highlight
text = @highlightTextMatches(text, @filterInput.val()) text = @highlightTextMatches(text, @filterInput.val())
if group
groupAttrs = "data-group='#{group}' data-index='#{index}'"
else
groupAttrs = ''
html = "<li> html = "<li>
<a href='#{url}' class='#{cssClass}'> <a href='#{url}' #{groupAttrs} class='#{cssClass}'>
#{text} #{text}
</a> </a>
</li>" </li>"
...@@ -377,9 +423,15 @@ class GitLabDropdown ...@@ -377,9 +423,15 @@ class GitLabDropdown
rowClicked: (el) -> rowClicked: (el) ->
fieldName = @options.fieldName fieldName = @options.fieldName
selectedIndex = el.parent().index()
if @renderedData if @renderedData
selectedObject = @renderedData[selectedIndex] groupName = el.data('group')
if groupName
selectedIndex = el.data('index')
selectedObject = @renderedData[groupName][selectedIndex]
else
selectedIndex = el.closest('li').index()
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}']") field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']")
if el.hasClass(ACTIVE_CLASS) if el.hasClass(ACTIVE_CLASS)
...@@ -460,7 +512,7 @@ class GitLabDropdown ...@@ -460,7 +512,7 @@ class GitLabDropdown
return false return false
if currentKeyCode is 13 if currentKeyCode is 13
@selectRowAtIndex currentIndex @selectRowAtIndex if currentIndex < 0 then 0 else currentIndex
removeArrayKeyEvent: -> removeArrayKeyEvent: ->
$('body').off 'keydown' $('body').off 'keydown'
......
...@@ -20,6 +20,15 @@ class @IssuableForm ...@@ -20,6 +20,15 @@ class @IssuableForm
@initWip() @initWip()
$issuableDueDate = $('#issuable-due-date')
if $issuableDueDate.length
$('.datepicker').datepicker(
dateFormat: 'yy-mm-dd',
onSelect: (dateText, inst) ->
$issuableDueDate.val dateText
).datepicker 'setDate', $.datepicker.parseDate('yy-mm-dd', $issuableDueDate.val())
initAutosave: -> initAutosave: ->
new Autosave @titleField, [ new Autosave @titleField, [
document.location.pathname, document.location.pathname,
......
((w) ->
w.gl ?= {}
w.gl.utils ?= {}
w.gl.utils.isObject = (obj) ->
obj? and (obj.constructor is Object)
) window
...@@ -113,7 +113,7 @@ class @MergeRequestWidget ...@@ -113,7 +113,7 @@ class @MergeRequestWidget
switch state switch state
when "failed", "canceled", "not_found" when "failed", "canceled", "not_found"
@setMergeButtonClass('btn-danger') @setMergeButtonClass('btn-danger')
when "running", "pending" when "running"
@setMergeButtonClass('btn-warning') @setMergeButtonClass('btn-warning')
when "success" when "success"
@setMergeButtonClass('btn-create') @setMergeButtonClass('btn-create')
...@@ -126,6 +126,6 @@ class @MergeRequestWidget ...@@ -126,6 +126,6 @@ class @MergeRequestWidget
$('.ci_widget:visible .ci-coverage').text(text) $('.ci_widget:visible .ci-coverage').text(text)
setMergeButtonClass: (css_class) -> setMergeButtonClass: (css_class) ->
$('.accept_merge_request') $('.js-merge-button')
.removeClass('btn-danger btn-warning btn-create') .removeClass('btn-danger btn-warning btn-create')
.addClass(css_class) .addClass(css_class)
...@@ -285,6 +285,7 @@ class @Notes ...@@ -285,6 +285,7 @@ class @Notes
form.addClass "js-main-target-form" form.addClass "js-main-target-form"
form.find("#note_line_code").remove() form.find("#note_line_code").remove()
form.find("#note_type").remove()
### ###
General note form setup. General note form setup.
...@@ -472,6 +473,7 @@ class @Notes ...@@ -472,6 +473,7 @@ class @Notes
setupDiscussionNoteForm: (dataHolder, form) => setupDiscussionNoteForm: (dataHolder, form) =>
# setup note target # setup note target
form.attr 'id', "new-discussion-note-form-#{dataHolder.data("discussionId")}" form.attr 'id', "new-discussion-note-form-#{dataHolder.data("discussionId")}"
form.find("#note_type").val dataHolder.data("noteType")
form.find("#line_type").val dataHolder.data("lineType") form.find("#line_type").val dataHolder.data("lineType")
form.find("#note_commit_id").val dataHolder.data("commitId") form.find("#note_commit_id").val dataHolder.data("commitId")
form.find("#note_line_code").val dataHolder.data("lineCode") form.find("#note_line_code").val dataHolder.data("lineCode")
......
...@@ -26,6 +26,10 @@ ...@@ -26,6 +26,10 @@
# Personal projects # Personal projects
# </a> # </a>
# </li> # </li>
# <li class="snippets-tab">
# <a data-action="snippets" data-target="#snippets" data-toggle="tab" href="/u/username/snippets">
# </a>
# </li>
# </ul> # </ul>
# #
# <div class="tab-content"> # <div class="tab-content">
...@@ -41,6 +45,9 @@ ...@@ -41,6 +45,9 @@
# <div class="tab-pane" id="projects"> # <div class="tab-pane" id="projects">
# Projects content # Projects content
# </div> # </div>
# <div class="tab-pane" id="snippets">
# Snippets content
# </div>
# </div> # </div>
# #
# <div class="loading-status"> # <div class="loading-status">
...@@ -100,7 +107,7 @@ class @UserTabs ...@@ -100,7 +107,7 @@ class @UserTabs
if action is 'activity' if action is 'activity'
@loadActivities(source) @loadActivities(source)
if action in ['groups', 'contributed', 'projects'] if action in ['groups', 'contributed', 'projects', 'snippets']
@loadTab(source, action) @loadTab(source, action)
loadTab: (source, action) -> loadTab: (source, action) ->
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
*= require dropzone/basic *= require dropzone/basic
*= require cal-heatmap *= require cal-heatmap
*= require cropper.css *= require cropper.css
*= require animate
*/ */
/* /*
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
@import 'framework/tw_bootstrap'; @import 'framework/tw_bootstrap';
@import "framework/layout"; @import "framework/layout";
@import "framework/animations.scss";
@import "framework/avatar.scss"; @import "framework/avatar.scss";
@import "framework/blocks.scss"; @import "framework/blocks.scss";
@import "framework/buttons.scss"; @import "framework/buttons.scss";
......
// This file is based off animate.css 3.5.1, available here:
// https://github.com/daneden/animate.css/blob/3.5.1/animate.css
//
// animate.css - http://daneden.me/animate
// Version - 3.5.1
// Licensed under the MIT license - http://opensource.org/licenses/MIT
//
// Copyright (c) 2016 Daniel Eden
.animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.animated.infinite {
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.animated.hinge {
-webkit-animation-duration: 2s;
animation-duration: 2s;
}
.animated.flipOutX,
.animated.flipOutY,
.animated.bounceIn,
.animated.bounceOut {
-webkit-animation-duration: .75s;
animation-duration: .75s;
}
@-webkit-keyframes pulse {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
50% {
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes pulse {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
50% {
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
.pulse {
-webkit-animation-name: pulse;
animation-name: pulse;
}
...@@ -289,7 +289,7 @@ table { ...@@ -289,7 +289,7 @@ table {
text-shadow: none; text-shadow: none;
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
margin-top: 11px; margin-top: 8px;
} }
} }
......
...@@ -36,22 +36,6 @@ ...@@ -36,22 +36,6 @@
} }
} }
.filename {
&.old {
display: inline-block;
span.idiff {
background-color: #f8cbcb;
}
}
&.new {
display: inline-block;
span.idiff {
background-color: #a6f3a6;
}
}
}
a:not(.btn) { a:not(.btn) {
color: $gl-dark-link-color; color: $gl-dark-link-color;
} }
......
...@@ -28,10 +28,6 @@ input[type='text'].danger { ...@@ -28,10 +28,6 @@ input[type='text'].danger {
} }
label { label {
&.control-label {
@extend .col-sm-2;
}
&.inline-label { &.inline-label {
margin: 0; margin: 0;
} }
...@@ -41,6 +37,10 @@ label { ...@@ -41,6 +37,10 @@ label {
} }
} }
.control-label {
@extend .col-sm-2;
}
.inline-input-group { .inline-input-group {
width: 250px; width: 250px;
} }
......
...@@ -9,8 +9,7 @@ ...@@ -9,8 +9,7 @@
@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) { @mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) {
.page-with-sidebar { .page-with-sidebar {
.header-logo { .header-logo {
background-color: $color; background: $color-darker;
border-color: $color;
a { a {
color: $color-light; color: $color-light;
...@@ -21,7 +20,7 @@ ...@@ -21,7 +20,7 @@
} }
&:hover { &:hover {
background-color: $color-darker; background-color: $color-dark;
a { a {
color: #fff; color: #fff;
...@@ -91,8 +90,8 @@ ...@@ -91,8 +90,8 @@
} }
$theme-blue: #2980b9; $theme-blue: #2980b9;
$theme-charcoal: #333c47; $theme-charcoal: #3d454d;
$theme-graphite: #888; $theme-graphite: #666;
$theme-gray: #373737; $theme-gray: #373737;
$theme-green: #019875; $theme-green: #019875;
$theme-violet: #548; $theme-violet: #548;
...@@ -103,11 +102,11 @@ body { ...@@ -103,11 +102,11 @@ body {
} }
&.ui_charcoal { &.ui_charcoal {
@include gitlab-theme(#c5d0de, $theme-charcoal, #2b333d, #24272d); @include gitlab-theme(#d6d7d9, #485157, $theme-charcoal, #353b41);
} }
&.ui_graphite { &.ui_graphite {
@include gitlab-theme(#ccc, $theme-graphite, #777, #666); @include gitlab-theme(#ccc, #777, $theme-graphite, #555);
} }
&.ui_gray { &.ui_gray {
......
...@@ -6,12 +6,12 @@ header { ...@@ -6,12 +6,12 @@ header {
transition-duration: .3s; transition-duration: .3s;
&.navbar-empty { &.navbar-empty {
height: 58px; height: $header-height;
background: #fff; background: #fff;
border-bottom: 1px solid $btn-gray-hover; border-bottom: 1px solid $btn-gray-hover;
.center-logo { .center-logo {
margin: 11px 0; margin: 8px 0;
text-align: center; text-align: center;
#tanuki-logo, img { #tanuki-logo, img {
......
...@@ -209,6 +209,15 @@ ...@@ -209,6 +209,15 @@
float: right; float: right;
padding: 7px 0 0; padding: 7px 0 0;
@media (max-width: $screen-xs-min) {
float: none;
padding: 0 9px;
.dropdown-new {
width: 100%;
}
}
i { i {
color: $layout-link-gray; color: $layout-link-gray;
} }
...@@ -225,6 +234,10 @@ ...@@ -225,6 +234,10 @@
.dropdown { .dropdown {
margin-left: 7px; margin-left: 7px;
@media (max-width: $screen-xs-min) {
margin-left: 0;
}
} }
} }
...@@ -260,4 +273,10 @@ ...@@ -260,4 +273,10 @@
.page-with-layout-nav { .page-with-layout-nav {
margin-top: 50px; margin-top: 50px;
&.controls-dropdown-visible {
@media (max-width: $screen-xs-min) {
margin-top: 96px;
}
}
} }
...@@ -312,7 +312,7 @@ ...@@ -312,7 +312,7 @@
} }
.nav-sidebar li a { .nav-sidebar li a {
width: 230px; width: $sidebar_width;
&.back-link { &.back-link {
i { i {
......
...@@ -269,3 +269,11 @@ h1, h2, h3, h4 { ...@@ -269,3 +269,11 @@ h1, h2, h3, h4 {
text-align: right; text-align: right;
} }
} }
.idiff.deletion {
background: $line-removed-dark;
}
.idiff.addition {
background: $line-added-dark;
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Layout * Layout
*/ */
$sidebar_collapsed_width: 62px; $sidebar_collapsed_width: 62px;
$sidebar_width: 230px; $sidebar_width: 220px;
$gutter_collapsed_width: 62px; $gutter_collapsed_width: 62px;
$gutter_width: 290px; $gutter_width: 290px;
$gutter_inner_width: 258px; $gutter_inner_width: 258px;
...@@ -12,7 +12,7 @@ $gutter_inner_width: 258px; ...@@ -12,7 +12,7 @@ $gutter_inner_width: 258px;
*/ */
$border-color: #e5e5e5; $border-color: #e5e5e5;
$focus-border-color: #3aabf0; $focus-border-color: #3aabf0;
$table-border-color: #ececec; $table-border-color: #f0f0f0;
$background-color: #fafafa; $background-color: #fafafa;
/* /*
...@@ -178,6 +178,7 @@ $table-border-gray: #f0f0f0; ...@@ -178,6 +178,7 @@ $table-border-gray: #f0f0f0;
$line-target-blue: #eaf3fc; $line-target-blue: #eaf3fc;
$line-select-yellow: #fcf8e7; $line-select-yellow: #fcf8e7;
$line-select-yellow-dark: #f0e2bd; $line-select-yellow-dark: #f0e2bd;
/* /*
* Fonts * Fonts
*/ */
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
} }
} }
.zen-cotrol { .zen-control {
padding: 0; padding: 0;
color: #555; color: #555;
background: none; background: none;
......
@import "framework/variables";
table.code {
width: 100%;
font-family: monospace;
border: none;
border-collapse: separate;
margin: 0;
padding: 0;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
td {
line-height: $code_line_height;
font-family: monospace;
font-size: $code_font_size;
}
td.diff-line-num {
margin: 0;
padding: 0;
border: none;
background: $background-color;
color: rgba(0, 0, 0, 0.3);
padding: 0 5px;
border-right: 1px solid $border-color;
text-align: right;
min-width: 35px;
max-width: 50px;
width: 35px;
}
td.line_content {
display: block;
margin: 0;
padding: 0 0.5em;
border: none;
white-space: pre;
}
}
@import "highlight/white";
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
.file-title { .file-title {
@extend .monospace; @extend .monospace;
line-height: 42px; line-height: 35px;
padding-top: 7px; padding-top: 7px;
padding-bottom: 7px; padding-bottom: 7px;
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
.editor-file-name { .editor-file-name {
@extend .monospace; @extend .monospace;
float: left; float: left;
margin-right: 10px; margin-right: 10px;
} }
...@@ -59,7 +59,22 @@ ...@@ -59,7 +59,22 @@
} }
.encoding-selector, .encoding-selector,
.license-selector { .license-selector,
.gitignore-selector {
display: inline-block; display: inline-block;
vertical-align: top;
font-family: $regular_font;
}
.gitignore-selector {
.dropdown {
line-height: 21px;
}
.dropdown-menu-toggle {
vertical-align: top;
width: 220px;
}
} }
} }
...@@ -125,7 +125,7 @@ ...@@ -125,7 +125,7 @@
.right-sidebar { .right-sidebar {
position: fixed; position: fixed;
top: 50px; top: $header-height;
bottom: 0; bottom: 0;
right: 0; right: 0;
z-index: 10; z-index: 10;
...@@ -150,6 +150,10 @@ ...@@ -150,6 +150,10 @@
font-weight: 600; font-weight: 600;
} }
.light {
font-weight: normal;
}
.sidebar-collapsed-icon { .sidebar-collapsed-icon {
display: none; display: none;
} }
......
...@@ -226,8 +226,7 @@ ul.notes { ...@@ -226,8 +226,7 @@ ul.notes {
} }
} }
.note-action-button, .note-action-button {
.discussion-action-button {
display: inline-block; display: inline-block;
margin-left: 10px; margin-left: 10px;
line-height: 24px; line-height: 24px;
......
.pipeline-stage {
overflow: hidden;
text-overflow: ellipsis;
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
} }
.no-ssh-key-message, .project-limit-message { .no-ssh-key-message, .project-limit-message {
background-color: #f28d35; background-color: #f28d35;
margin-bottom: 16px; margin-bottom: 0;
} }
.new_project, .new_project,
.edit_project { .edit_project {
...@@ -149,6 +149,10 @@ ...@@ -149,6 +149,10 @@
white-space: nowrap; white-space: nowrap;
margin: 0 11px 0 4px; margin: 0 11px 0 4px;
a {
color: inherit;
}
&:hover { &:hover {
background: #fff; background: #fff;
} }
...@@ -161,7 +165,7 @@ ...@@ -161,7 +165,7 @@
display: inline-table; display: inline-table;
margin-right: 12px; margin-right: 12px;
a { > a {
margin: -1px; margin: -1px;
} }
} }
......
...@@ -9,6 +9,6 @@ class Admin::AbuseReportsController < Admin::ApplicationController ...@@ -9,6 +9,6 @@ class Admin::AbuseReportsController < Admin::ApplicationController
abuse_report.remove_user(deleted_by: current_user) if params[:remove_user] abuse_report.remove_user(deleted_by: current_user) if params[:remove_user]
abuse_report.destroy abuse_report.destroy
render nothing: true head :ok
end end
end end
...@@ -19,6 +19,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -19,6 +19,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
redirect_to admin_runners_path redirect_to admin_runners_path
end end
def reset_health_check_token
@application_setting.reset_health_check_access_token!
flash[:notice] = 'New health check access token has been generated!'
redirect_to :back
end
def clear_repository_check_states def clear_repository_check_states
RepositoryCheck::ClearWorker.perform_async RepositoryCheck::ClearWorker.perform_async
...@@ -53,6 +59,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -53,6 +59,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
end end
end end
enabled_oauth_sign_in_sources = params[:application_setting].delete(:enabled_oauth_sign_in_sources)
params[:application_setting][:disabled_oauth_sign_in_sources] =
AuthHelper.button_based_providers.map(&:to_s) -
Array(enabled_oauth_sign_in_sources)
params.require(:application_setting).permit( params.require(:application_setting).permit(
:default_projects_limit, :default_projects_limit,
:default_branch_protection, :default_branch_protection,
...@@ -94,8 +106,10 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -94,8 +106,10 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:email_author_in_body, :email_author_in_body,
:repository_checks_enabled, :repository_checks_enabled,
:metrics_packet_size, :metrics_packet_size,
:send_user_confirmation_email,
restricted_visibility_levels: [], restricted_visibility_levels: [],
import_sources: [] import_sources: [],
disabled_oauth_sign_in_sources: []
) )
end end
end end
...@@ -32,7 +32,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController ...@@ -32,7 +32,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_back_or_default(default: { action: 'index' }) } format.html { redirect_back_or_default(default: { action: 'index' }) }
format.js { render nothing: true } format.js { head :ok }
end end
end end
......
class Admin::HealthCheckController < Admin::ApplicationController
def show
@errors = HealthCheck::Utils.process_checks('standard')
end
end
...@@ -6,7 +6,7 @@ class Admin::KeysController < Admin::ApplicationController ...@@ -6,7 +6,7 @@ class Admin::KeysController < Admin::ApplicationController
respond_to do |format| respond_to do |format|
format.html format.html
format.js { render nothing: true } format.js { head :ok }
end end
end end
......
...@@ -9,23 +9,18 @@ class Admin::RunnersController < Admin::ApplicationController ...@@ -9,23 +9,18 @@ class Admin::RunnersController < Admin::ApplicationController
end end
def show def show
@builds = @runner.builds.order('id DESC').first(30) assign_builds_and_projects
@projects =
if params[:search].present?
::Project.search(params[:search])
else
Project.all
end
@projects = @projects.where.not(id: @runner.projects.select(:id)) if @runner.projects.any?
@projects = @projects.page(params[:page]).per(30)
end end
def update def update
@runner.update_attributes(runner_params) if @runner.update_attributes(runner_params)
respond_to do |format|
respond_to do |format| format.js
format.js format.html { redirect_to admin_runner_path(@runner) }
format.html { redirect_to admin_runner_path(@runner) } end
else
assign_builds_and_projects
render 'show'
end end
end end
...@@ -58,6 +53,18 @@ class Admin::RunnersController < Admin::ApplicationController ...@@ -58,6 +53,18 @@ class Admin::RunnersController < Admin::ApplicationController
end end
def runner_params def runner_params
params.require(:runner).permit(:token, :description, :tag_list, :active) params.require(:runner).permit(Ci::Runner::FORM_EDITABLE)
end
def assign_builds_and_projects
@builds = runner.builds.order('id DESC').first(30)
@projects =
if params[:search].present?
::Project.search(params[:search])
else
Project.all
end
@projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any?
@projects = @projects.page(params[:page]).per(30)
end end
end end
...@@ -11,7 +11,7 @@ class Admin::SpamLogsController < Admin::ApplicationController ...@@ -11,7 +11,7 @@ class Admin::SpamLogsController < Admin::ApplicationController
redirect_to admin_spam_logs_path, notice: "User #{spam_log.user.username} was successfully removed." redirect_to admin_spam_logs_path, notice: "User #{spam_log.user.username} was successfully removed."
else else
spam_log.destroy spam_log.destroy
render nothing: true head :ok
end end
end end
end end
...@@ -119,6 +119,7 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -119,6 +119,7 @@ class Admin::UsersController < Admin::ApplicationController
user_params_with_pass.merge!( user_params_with_pass.merge!(
password: params[:user][:password], password: params[:user][:password],
password_confirmation: params[:user][:password_confirmation], password_confirmation: params[:user][:password_confirmation],
password_expires_at: Time.now
) )
end end
...@@ -153,7 +154,7 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -153,7 +154,7 @@ class Admin::UsersController < Admin::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_back_or_admin_user(notice: "Successfully removed email.") } format.html { redirect_back_or_admin_user(notice: "Successfully removed email.") }
format.js { render nothing: true } format.js { head :ok }
end end
end end
......
...@@ -176,7 +176,7 @@ class ApplicationController < ActionController::Base ...@@ -176,7 +176,7 @@ class ApplicationController < ActionController::Base
end end
def check_password_expiration def check_password_expiration
if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user?
redirect_to new_profile_password_path and return redirect_to new_profile_password_path and return
end end
end end
......
...@@ -122,7 +122,7 @@ module CreatesCommit ...@@ -122,7 +122,7 @@ module CreatesCommit
# Merge request from fork to this project # Merge request from fork to this project
@mr_source_project = @tree_edit_project @mr_source_project = @tree_edit_project
@mr_target_project = @project @mr_target_project = @project
@mr_target_branch ||= @ref @mr_target_branch ||= @ref
end end
end end
end end
...@@ -6,7 +6,7 @@ module ToggleSubscriptionAction ...@@ -6,7 +6,7 @@ module ToggleSubscriptionAction
subscribable_resource.toggle_subscription(current_user) subscribable_resource.toggle_subscription(current_user)
render nothing: true head :ok
end end
private private
......
...@@ -28,7 +28,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -28,7 +28,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
end end
def starred def starred
@projects = current_user.starred_projects.sorted_by_activity @projects = current_user.viewable_starred_projects.sorted_by_activity
@projects = filter_projects(@projects) @projects = filter_projects(@projects)
@projects = @projects.includes(:namespace, :forked_from_project, :tags) @projects = @projects.includes(:namespace, :forked_from_project, :tags)
@projects = @projects.sort(@sort = params[:sort]) @projects = @projects.sort(@sort = params[:sort])
......
...@@ -12,7 +12,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController ...@@ -12,7 +12,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_to dashboard_todos_path, notice: todo_notice } format.html { redirect_to dashboard_todos_path, notice: todo_notice }
format.js { render nothing: true } format.js { head :ok }
format.json do format.json do
render json: { count: @todos.size, done_count: current_user.todos.done.count } render json: { count: @todos.size, done_count: current_user.todos.done.count }
end end
...@@ -24,7 +24,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController ...@@ -24,7 +24,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 { render nothing: true } format.js { head :ok }
format.json do format.json do
find_todos find_todos
render json: { count: @todos.size, done_count: current_user.todos.done.count } render json: { count: @todos.size, done_count: current_user.todos.done.count }
......
...@@ -25,7 +25,7 @@ class DashboardController < Dashboard::ApplicationController ...@@ -25,7 +25,7 @@ class DashboardController < Dashboard::ApplicationController
def load_events def load_events
projects = projects =
if params[:filter] == "starred" if params[:filter] == "starred"
current_user.starred_projects current_user.viewable_starred_projects
else else
current_user.authorized_projects current_user.authorized_projects
end end
......
...@@ -40,7 +40,7 @@ class Groups::GroupMembersController < Groups::ApplicationController ...@@ -40,7 +40,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' } format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' }
format.js { render nothing: true } format.js { head :ok }
end end
end end
......
class HealthCheckController < HealthCheck::HealthCheckController
before_action :validate_health_check_access!
private
def validate_health_check_access!
render_404 unless token_valid?
end
def token_valid?
token = params[:token].presence || request.headers['TOKEN']
token.present? &&
ActiveSupport::SecurityUtils.variable_size_secure_compare(
token,
current_application_settings.health_check_access_token
)
end
def render_404
render file: Rails.root.join('public', '404'), layout: false, status: '404'
end
end
class JwtController < ApplicationController
skip_before_action :authenticate_user!
skip_before_action :verify_authenticity_token
before_action :authenticate_project_or_user
SERVICES = {
Auth::ContainerRegistryAuthenticationService::AUDIENCE => Auth::ContainerRegistryAuthenticationService,
}
def auth
service = SERVICES[params[:service]]
return head :not_found unless service
result = service.new(@project, @user, auth_params).execute
render json: result, status: result[:http_status]
end
private
def authenticate_project_or_user
authenticate_with_http_basic do |login, password|
# if it's possible we first try to authenticate project with login and password
@project = authenticate_project(login, password)
return if @project
@user = authenticate_user(login, password)
return if @user
render_403
end
end
def auth_params
params.permit(:service, :scope, :offline_token, :account, :client_id)
end
def authenticate_project(login, password)
if login == 'gitlab-ci-token'
Project.find_by(builds_enabled: true, runners_token: password)
end
end
def authenticate_user(login, password)
# TODO: this is a copy and paste from grack_auth,
# it should be refactored in the future
user = Gitlab::Auth.new.find(login, password)
# If the user authenticated successfully, we reset the auth failure count
# from Rack::Attack for that IP. A client may attempt to authenticate
# with a username and blank password first, and only after it receives
# a 401 error does it present a password. Resetting the count prevents
# false positives from occurring.
#
# Otherwise, we let Rack::Attack know there was a failed authentication
# attempt from this IP. This information is stored in the Rails cache
# (Redis) and will be used by the Rack::Attack middleware to decide
# whether to block requests from this IP.
config = Gitlab.config.rack_attack.git_basic_auth
if config.enabled
if user
# A successful login will reset the auth failure count from this IP
Rack::Attack::Allow2Ban.reset(request.ip, config)
else
banned = Rack::Attack::Allow2Ban.filter(request.ip, config) do
# Unless the IP is whitelisted, return true so that Allow2Ban
# increments the counter (stored in Rails.cache) for the IP
if config.ip_whitelist.include?(request.ip)
false
else
true
end
end
if banned
Rails.logger.info "IP #{request.ip} failed to login " \
"as #{login} but has been temporarily banned from Git auth"
return
end
end
end
user
end
end
...@@ -24,7 +24,7 @@ class Profiles::EmailsController < Profiles::ApplicationController ...@@ -24,7 +24,7 @@ class Profiles::EmailsController < Profiles::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_to profile_emails_url } format.html { redirect_to profile_emails_url }
format.js { render nothing: true } format.js { head :ok }
end end
end end
......
...@@ -32,7 +32,7 @@ class Profiles::KeysController < Profiles::ApplicationController ...@@ -32,7 +32,7 @@ class Profiles::KeysController < Profiles::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_to profile_keys_url } format.html { redirect_to profile_keys_url }
format.js { render nothing: true } format.js { head :ok }
end end
end end
......
...@@ -38,6 +38,14 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -38,6 +38,14 @@ class Projects::BuildsController < Projects::ApplicationController
end end
end end
def trace
respond_to do |format|
format.json do
render json: @build.trace_with_state(params[:state]).merge!(id: @build.id, status: @build.status)
end
end
end
def retry def retry
unless @build.retryable? unless @build.retryable?
return render_404 return render_404
......
...@@ -17,12 +17,12 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -17,12 +17,12 @@ class Projects::CommitController < Projects::ApplicationController
def show def show
apply_diff_view_cookie! apply_diff_view_cookie!
@line_notes = commit.notes.inline @grouped_diff_notes = commit.notes.grouped_diff_notes
@note = @project.build_commit_note(commit) @note = @project.build_commit_note(commit)
@notes = commit.notes.not_inline.fresh @notes = commit.notes.non_diff_notes.fresh
@noteable = @commit @noteable = @commit
@comments_allowed = @reply_allowed = true @comments_target = {
@comments_target = {
noteable_type: 'Commit', noteable_type: 'Commit',
commit_id: @commit.id commit_id: @commit.id
} }
...@@ -67,10 +67,10 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -67,10 +67,10 @@ class Projects::CommitController < Projects::ApplicationController
create_commit(Commits::RevertService, success_notice: "The #{@commit.change_type_title} has been successfully reverted.", create_commit(Commits::RevertService, success_notice: "The #{@commit.change_type_title} has been successfully reverted.",
success_path: successful_change_path, failure_path: failed_change_path) success_path: successful_change_path, failure_path: failed_change_path)
end end
def cherry_pick def cherry_pick
assign_change_commit_vars(@commit.cherry_pick_branch_name) assign_change_commit_vars(@commit.cherry_pick_branch_name)
return render_404 if @target_branch.blank? return render_404 if @target_branch.blank?
create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title} has been successfully cherry-picked.", create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title} has been successfully cherry-picked.",
......
...@@ -22,7 +22,8 @@ class Projects::CompareController < Projects::ApplicationController ...@@ -22,7 +22,8 @@ class Projects::CompareController < Projects::ApplicationController
@base_commit = @project.merge_base_commit(@base_ref, @head_ref) @base_commit = @project.merge_base_commit(@base_ref, @head_ref)
@diffs = compare.diffs(diff_options) @diffs = compare.diffs(diff_options)
@diff_refs = [@base_commit, @commit] @diff_refs = [@base_commit, @commit]
@line_notes = [] @diff_notes_disabled = true
@grouped_diff_notes = {}
end end
end end
......
class Projects::ContainerRegistryController < Projects::ApplicationController
before_action :verify_registry_enabled
before_action :authorize_read_container_image!
before_action :authorize_update_container_image!, only: [:destroy]
layout 'project'
def index
@tags = container_registry_repository.tags
end
def destroy
url = namespace_project_container_registry_index_path(project.namespace, project)
if tag.delete
redirect_to url
else
redirect_to url, alert: 'Failed to remove tag'
end
end
private
def verify_registry_enabled
render_404 unless Gitlab.config.registry.enabled
end
def container_registry_repository
@container_registry_repository ||= project.container_registry_repository
end
def tag
@tag ||= container_registry_repository.tag(params[:id])
end
end
...@@ -27,8 +27,10 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -27,8 +27,10 @@ class Projects::HooksController < Projects::ApplicationController
if !@project.empty_repo? if !@project.empty_repo?
status, message = TestHookService.new.execute(hook, current_user) status, message = TestHookService.new.execute(hook, current_user)
if status if status && status >= 200 && status < 400
flash[:notice] = 'Hook successfully executed.' flash[:notice] = "Hook executed successfully: HTTP #{status}"
elsif status
flash[:alert] = "Hook executed successfully but returned HTTP #{status} #{message}"
else else
flash[:alert] = "Hook execution failed: #{message}" flash[:alert] = "Hook execution failed: #{message}"
end end
......
...@@ -20,6 +20,7 @@ class Projects::ImportsController < Projects::ApplicationController ...@@ -20,6 +20,7 @@ class Projects::ImportsController < Projects::ApplicationController
@project.import_retry @project.import_retry
else else
@project.import_start @project.import_start
@project.add_import_job
end end
end end
......
...@@ -73,12 +73,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -73,12 +73,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController
# but we need it for the "View file @ ..." link by deleted files # but we need it for the "View file @ ..." link by deleted files
@base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit @base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit
@comments_allowed = @reply_allowed = true
@comments_target = { @comments_target = {
noteable_type: 'MergeRequest', noteable_type: 'MergeRequest',
noteable_id: @merge_request.id noteable_id: @merge_request.id
} }
@line_notes = @merge_request.notes.where("line_code is not null")
@grouped_diff_notes = @merge_request.notes.grouped_diff_notes
respond_to do |format| respond_to do |format|
format.html format.html
...@@ -117,6 +117,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -117,6 +117,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@commit = @merge_request.last_commit @commit = @merge_request.last_commit
@base_commit = @merge_request.diff_base_commit @base_commit = @merge_request.diff_base_commit
@diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare @diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare
@diff_notes_disabled = true
@ci_commit = @merge_request.ci_commit @ci_commit = @merge_request.ci_commit
@statuses = @ci_commit.statuses if @ci_commit @statuses = @ci_commit.statuses if @ci_commit
...@@ -300,7 +301,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -300,7 +301,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
# Build a note object for comment form # Build a note object for comment form
@note = @project.notes.new(noteable: @merge_request) @note = @project.notes.new(noteable: @merge_request)
@notes = @merge_request.mr_and_commit_notes.nonawards.inc_author.fresh @notes = @merge_request.mr_and_commit_notes.nonawards.inc_author.fresh
@discussions = Note.discussions_from_notes(@notes) @discussions = @notes.discussions
@noteable = @merge_request @noteable = @merge_request
# Get commits from repository # Get commits from repository
...@@ -333,7 +334,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -333,7 +334,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
params.require(:merge_request).permit( params.require(:merge_request).permit(
:title, :assignee_id, :source_project_id, :source_branch, :title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id, :target_project_id, :target_branch, :milestone_id,
:state_event, :description, :task_num, label_ids: [] :state_event, :description, :task_num, :force_remove_source_branch,
label_ids: []
) )
end end
......
...@@ -75,7 +75,7 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -75,7 +75,7 @@ class Projects::MilestonesController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_to namespace_project_milestones_path } format.html { redirect_to namespace_project_milestones_path }
format.js { render nothing: true } format.js { head :ok }
end end
end end
......
...@@ -43,7 +43,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -43,7 +43,7 @@ class Projects::NotesController < Projects::ApplicationController
end end
respond_to do |format| respond_to do |format|
format.js { render nothing: true } format.js { head :ok }
end end
end end
...@@ -52,7 +52,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -52,7 +52,7 @@ class Projects::NotesController < Projects::ApplicationController
note.update_attribute(:attachment, nil) note.update_attribute(:attachment, nil)
respond_to do |format| respond_to do |format|
format.js { render nothing: true } format.js { head :ok }
end end
end end
...@@ -96,7 +96,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -96,7 +96,7 @@ class Projects::NotesController < Projects::ApplicationController
end end
def note_to_discussion_html(note) def note_to_discussion_html(note)
return unless note.for_diff_line? return unless note.diff_note?
if params[:view] == 'parallel' if params[:view] == 'parallel'
template = "projects/notes/_diff_notes_with_reply_parallel" template = "projects/notes/_diff_notes_with_reply_parallel"
...@@ -120,7 +120,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -120,7 +120,7 @@ class Projects::NotesController < Projects::ApplicationController
end end
def note_to_discussion_with_diff_html(note) def note_to_discussion_with_diff_html(note)
return unless note.for_diff_line? return unless note.diff_note?
render_to_string( render_to_string(
"projects/notes/_discussion", "projects/notes/_discussion",
...@@ -158,7 +158,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -158,7 +158,7 @@ class Projects::NotesController < Projects::ApplicationController
def note_params def note_params
params.require(:note).permit( params.require(:note).permit(
:note, :noteable, :noteable_id, :noteable_type, :project_id, :note, :noteable, :noteable_id, :noteable_type, :project_id,
:attachment, :line_code, :commit_id :attachment, :line_code, :commit_id, :type
) )
end end
......
class Projects::PipelinesController < Projects::ApplicationController
before_action :pipeline, except: [:index, :new, :create]
before_action :commit, only: [:show]
before_action :authorize_read_pipeline!
before_action :authorize_create_pipeline!, only: [:new, :create]
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
def index
@scope = params[:scope]
all_pipelines = project.ci_commits
@pipelines_count = all_pipelines.count
@running_or_pending_count = all_pipelines.running_or_pending.count
@pipelines = PipelinesFinder.new(project).execute(all_pipelines, @scope)
@pipelines = @pipelines.order(id: :desc).page(params[:page]).per(30)
end
def new
@pipeline = project.ci_commits.new(ref: @project.default_branch)
end
def create
@pipeline = Ci::CreatePipelineService.new(project, current_user, create_params).execute
unless @pipeline.persisted?
render 'new'
return
end
redirect_to namespace_project_pipeline_path(project.namespace, project, @pipeline)
end
def show
end
def retry
pipeline.retry_failed
redirect_back_or_default default: namespace_project_pipelines_path(project.namespace, project)
end
def cancel
pipeline.cancel_running
redirect_back_or_default default: namespace_project_pipelines_path(project.namespace, project)
end
private
def create_params
params.require(:pipeline).permit(:ref)
end
def pipeline
@pipeline ||= project.ci_commits.find_by!(id: params[:id])
end
def commit
@commit ||= @pipeline.commit_data
end
end
...@@ -55,7 +55,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -55,7 +55,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
format.html do format.html do
redirect_to namespace_project_project_members_path(@project.namespace, @project) redirect_to namespace_project_project_members_path(@project.namespace, @project)
end end
format.js { render nothing: true } format.js { head :ok }
end end
end end
...@@ -81,7 +81,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -81,7 +81,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_to dashboard_projects_path, notice: "You left the project." } format.html { redirect_to dashboard_projects_path, notice: "You left the project." }
format.js { render nothing: true } format.js { head :ok }
end end
else else
if current_user == @project.owner if current_user == @project.owner
......
...@@ -39,7 +39,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController ...@@ -39,7 +39,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_to namespace_project_protected_branches_path } format.html { redirect_to namespace_project_protected_branches_path }
format.js { render nothing: true } format.js { head :ok }
end end
end end
......
...@@ -20,7 +20,7 @@ class Projects::RunnersController < Projects::ApplicationController ...@@ -20,7 +20,7 @@ class Projects::RunnersController < Projects::ApplicationController
if @runner.update_attributes(runner_params) if @runner.update_attributes(runner_params)
redirect_to runner_path(@runner), notice: 'Runner was successfully updated.' redirect_to runner_path(@runner), notice: 'Runner was successfully updated.'
else else
redirect_to runner_path(@runner), alert: 'Runner was not updated.' render 'edit'
end end
end end
...@@ -64,6 +64,6 @@ class Projects::RunnersController < Projects::ApplicationController ...@@ -64,6 +64,6 @@ class Projects::RunnersController < Projects::ApplicationController
end end
def runner_params def runner_params
params.require(:runner).permit(:description, :tag_list, :active) params.require(:runner).permit(Ci::Runner::FORM_EDITABLE)
end end
end end
...@@ -3,20 +3,44 @@ class Projects::VariablesController < Projects::ApplicationController ...@@ -3,20 +3,44 @@ class Projects::VariablesController < Projects::ApplicationController
layout 'project_settings' layout 'project_settings'
def index
@variable = Ci::Variable.new
end
def show def show
@variable = @project.variables.find(params[:id])
end end
def update def update
if project.update_attributes(project_params) @variable = @project.variables.find(params[:id])
if @variable.update_attributes(project_params)
redirect_to namespace_project_variables_path(project.namespace, project), notice: 'Variable was successfully updated.'
else
render action: "show"
end
end
def create
@variable = Ci::Variable.new(project_params)
if @variable.valid? && @project.variables << @variable
redirect_to namespace_project_variables_path(project.namespace, project), notice: 'Variables were successfully updated.' redirect_to namespace_project_variables_path(project.namespace, project), notice: 'Variables were successfully updated.'
else else
render action: 'show' render action: "index"
end end
end end
def destroy
@key = @project.variables.find(params[:id])
@key.destroy
redirect_to namespace_project_variables_path(project.namespace, project), notice: 'Variable was successfully removed.'
end
private private
def project_params def project_params
params.require(:project).permit({ variables_attributes: [:id, :key, :value, :_destroy] }) params.require(:variable).permit([:id, :key, :value, :_destroy])
end end
end end
...@@ -101,13 +101,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -101,13 +101,7 @@ class ProjectsController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.html do format.html do
if current_user @notification_setting = current_user.notification_settings_for(@project) if current_user
@membership = @project.team.find_member(current_user.id)
if @membership
@notification_setting = current_user.notification_settings_for(@project)
end
end
if @project.repository_exists? if @project.repository_exists?
if @project.empty_repo? if @project.empty_repo?
...@@ -147,6 +141,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -147,6 +141,7 @@ class ProjectsController < Projects::ApplicationController
@suggestions = { @suggestions = {
emojis: AwardEmoji.urls, emojis: AwardEmoji.urls,
issues: autocomplete.issues, issues: autocomplete.issues,
milestones: autocomplete.milestones,
mergerequests: autocomplete.merge_requests, mergerequests: autocomplete.merge_requests,
members: participants members: participants
} }
...@@ -235,7 +230,8 @@ class ProjectsController < Projects::ApplicationController ...@@ -235,7 +230,8 @@ class ProjectsController < Projects::ApplicationController
def project_params def project_params
params.require(:project).permit( params.require(:project).permit(
:name, :path, :description, :issues_tracker, :tag_list, :runners_token, :name, :path, :description, :issues_tracker, :tag_list, :runners_token,
:issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch, :issues_enabled, :merge_requests_enabled, :snippets_enabled, :container_registry_enabled,
:issues_tracker_id, :default_branch,
:wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar,
:builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, :builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex,
:public_builds, :public_builds,
......
...@@ -37,8 +37,8 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -37,8 +37,8 @@ class RegistrationsController < Devise::RegistrationsController
super super
end end
def after_sign_up_path_for(_resource) def after_sign_up_path_for(user)
users_almost_there_path user.confirmed? ? dashboard_projects_path : users_almost_there_path
end end
def after_inactive_sign_up_path_for(_resource) def after_inactive_sign_up_path_for(_resource)
......
...@@ -10,7 +10,7 @@ class SnippetsController < ApplicationController ...@@ -10,7 +10,7 @@ class SnippetsController < ApplicationController
# Allow destroy snippet # Allow destroy snippet
before_action :authorize_admin_snippet!, only: [:destroy] before_action :authorize_admin_snippet!, only: [:destroy]
skip_before_action :authenticate_user!, only: [:index, :user_index, :show, :raw] skip_before_action :authenticate_user!, only: [:index, :show, :raw]
layout 'snippets' layout 'snippets'
respond_to :html respond_to :html
......
...@@ -58,6 +58,19 @@ class UsersController < ApplicationController ...@@ -58,6 +58,19 @@ class UsersController < ApplicationController
end end
end end
def snippets
load_snippets
respond_to do |format|
format.html { render 'show' }
format.json do
render json: {
html: view_to_html_string("snippets/_snippets", collection: @snippets)
}
end
end
end
def calendar def calendar
calendar = contributions_calendar calendar = contributions_calendar
@timestamps = calendar.timestamps @timestamps = calendar.timestamps
...@@ -116,6 +129,15 @@ class UsersController < ApplicationController ...@@ -116,6 +129,15 @@ class UsersController < ApplicationController
@groups = JoinedGroupsFinder.new(user).execute(current_user) @groups = JoinedGroupsFinder.new(user).execute(current_user)
end end
def load_snippets
@snippets = SnippetsFinder.new.execute(
current_user,
filter: :by_user,
user: user,
scope: params[:scope]
).page(params[:page])
end
def projects_for_current_user def projects_for_current_user
ProjectsFinder.new.execute(current_user) ProjectsFinder.new.execute(current_user)
end end
......
...@@ -252,8 +252,8 @@ class IssuableFinder ...@@ -252,8 +252,8 @@ class IssuableFinder
if filter_by_no_milestone? if filter_by_no_milestone?
items = items.where(milestone_id: [-1, nil]) items = items.where(milestone_id: [-1, nil])
elsif filter_by_upcoming_milestone? elsif filter_by_upcoming_milestone?
upcoming = Milestone.where(project_id: projects).upcoming upcoming_ids = Milestone.upcoming_ids_by_projects(projects)
items = items.joins(:milestone).where(milestones: { title: upcoming.try(:title) }) items = items.joins(:milestone).where(milestone_id: upcoming_ids)
else else
items = items.joins(:milestone).where(milestones: { title: params[:milestone_title] }) items = items.joins(:milestone).where(milestones: { title: params[:milestone_title] })
......
...@@ -10,7 +10,7 @@ class NotesFinder ...@@ -10,7 +10,7 @@ class NotesFinder
notes = notes =
case target_type case target_type
when "commit" when "commit"
project.notes.for_commit_id(target_id).not_inline project.notes.for_commit_id(target_id).non_diff_notes
when "issue" when "issue"
project.issues.find(target_id).notes.nonawards.inc_author project.issues.find(target_id).notes.nonawards.inc_author
when "merge_request" when "merge_request"
......
class PipelinesFinder
attr_reader :project
def initialize(project)
@project = project
end
def execute(pipelines, scope)
case scope
when 'running'
pipelines.running_or_pending
when 'branches'
from_ids(pipelines, ids_for_ref(pipelines, branches))
when 'tags'
from_ids(pipelines, ids_for_ref(pipelines, tags))
else
pipelines
end
end
private
def ids_for_ref(pipelines, refs)
pipelines.where(ref: refs).group(:ref).select('max(id)')
end
def from_ids(pipelines, ids)
pipelines.unscoped.where(id: ids)
end
def branches
project.repository.branches.map(&:name)
end
def tags
project.repository.tags.map(&:name)
end
end
...@@ -36,7 +36,7 @@ class TodosFinder ...@@ -36,7 +36,7 @@ class TodosFinder
private private
def action_id? def action_id?
action_id.present? && [Todo::ASSIGNED, Todo::MENTIONED].include?(action_id.to_i) action_id.present? && [Todo::ASSIGNED, Todo::MENTIONED, Todo::BUILD_FAILED].include?(action_id.to_i)
end end
def action_id def action_id
......
...@@ -110,8 +110,7 @@ module ApplicationHelper ...@@ -110,8 +110,7 @@ module ApplicationHelper
] ]
# If reference is commit id - we should add it to branch/tag selectbox # If reference is commit id - we should add it to branch/tag selectbox
if(@ref && !options.flatten.include?(@ref) && if @ref && !options.flatten.include?(@ref) && @ref =~ /\A[0-9a-zA-Z]{6,52}\z/
@ref =~ /\A[0-9a-zA-Z]{6,52}\z/)
options << ['Commit', [@ref]] options << ['Commit', [@ref]]
end end
......
...@@ -60,4 +60,18 @@ module ApplicationSettingsHelper ...@@ -60,4 +60,18 @@ module ApplicationSettingsHelper
end end
end end
end end
def oauth_providers_checkboxes
button_based_providers.map do |source|
disabled = current_application_settings.disabled_oauth_sign_in_sources.include?(source.to_s)
css_class = 'btn'
css_class << ' active' unless disabled
checkbox_name = 'application_setting[enabled_oauth_sign_in_sources][]'
label_tag(checkbox_name, class: css_class) do
check_box_tag(checkbox_name, source, !disabled,
autocomplete: 'off') + Gitlab::OAuth::Provider.label_for(source)
end
end
end
end end
...@@ -38,6 +38,16 @@ module AuthHelper ...@@ -38,6 +38,16 @@ module AuthHelper
auth_providers.reject { |provider| form_based_provider?(provider) } auth_providers.reject { |provider| form_based_provider?(provider) }
end end
def enabled_button_based_providers
disabled_providers = current_application_settings.disabled_oauth_sign_in_sources || []
button_based_providers.map(&:to_s) - disabled_providers
end
def button_based_providers_enabled?
enabled_button_based_providers.any?
end
def provider_image_tag(provider, size = 64) def provider_image_tag(provider, size = 64)
label = label_for_provider(provider) label = label_for_provider(provider)
......
...@@ -184,4 +184,14 @@ module BlobHelper ...@@ -184,4 +184,14 @@ module BlobHelper
Other: licenses.reject(&:featured).map { |license| [license.name, license.key] } Other: licenses.reject(&:featured).map { |license| [license.name, license.key] }
} }
end end
def gitignore_names
return @gitignore_names if defined?(@gitignore_names)
@gitignore_names = {
Global: Gitlab::Gitignore.global.map { |gitignore| { name: gitignore.name } },
# Note that the key here doesn't cover it really
Languages: Gitlab::Gitignore.languages_frameworks.map{ |gitignore| { name: gitignore.name } }
}
end
end end
...@@ -38,19 +38,30 @@ module CiStatusHelper ...@@ -38,19 +38,30 @@ module CiStatusHelper
icon(icon_name + ' fw') icon(icon_name + ' fw')
end end
def render_ci_status(ci_commit, tooltip_placement: 'auto left') def render_commit_status(commit, tooltip_placement: 'auto left')
# TODO: split this method into project = commit.project
# - render_commit_status path = builds_namespace_project_commit_path(project.namespace, project, commit)
# - render_pipeline_status render_status_with_link('commit', commit.status, path, tooltip_placement)
link_to ci_icon_for_status(ci_commit.status), end
ci_status_path(ci_commit),
class: "ci-status-link ci-status-icon-#{ci_commit.status.dasherize}", def render_pipeline_status(pipeline, tooltip_placement: 'auto left')
title: "Build #{ci_label_for_status(ci_commit.status)}", project = pipeline.project
data: { toggle: 'tooltip', placement: tooltip_placement } path = namespace_project_pipeline_path(project.namespace, project, pipeline)
render_status_with_link('pipeline', pipeline.status, path, tooltip_placement)
end end
def no_runners_for_project?(project) def no_runners_for_project?(project)
project.runners.blank? && project.runners.blank? &&
Ci::Runner.shared.blank? Ci::Runner.shared.blank?
end end
private
def render_status_with_link(type, status, path, tooltip_placement)
link_to ci_icon_for_status(status),
path,
class: "ci-status-link ci-status-icon-#{status.dasherize}",
title: "#{type.titleize}: #{ci_label_for_status(status)}",
data: { toggle: 'tooltip', placement: tooltip_placement }
end
end end
...@@ -2,8 +2,8 @@ module DiffHelper ...@@ -2,8 +2,8 @@ module DiffHelper
def mark_inline_diffs(old_line, new_line) def mark_inline_diffs(old_line, new_line)
old_diffs, new_diffs = Gitlab::Diff::InlineDiff.new(old_line, new_line).inline_diffs old_diffs, new_diffs = Gitlab::Diff::InlineDiff.new(old_line, new_line).inline_diffs
marked_old_line = Gitlab::Diff::InlineDiffMarker.new(old_line).mark(old_diffs) marked_old_line = Gitlab::Diff::InlineDiffMarker.new(old_line).mark(old_diffs, mode: :deletion)
marked_new_line = Gitlab::Diff::InlineDiffMarker.new(new_line).mark(new_diffs) marked_new_line = Gitlab::Diff::InlineDiffMarker.new(new_line).mark(new_diffs, mode: :addition)
[marked_old_line, marked_new_line] [marked_old_line, marked_new_line]
end end
...@@ -55,22 +55,18 @@ module DiffHelper ...@@ -55,22 +55,18 @@ module DiffHelper
end end
end end
def line_comments def organize_comments(left, right)
@line_comments ||= @line_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code) notes_left = notes_right = nil
end
def organize_comments(type_left, type_right, line_code_left, line_code_right)
comments_left = comments_right = nil
unless type_left.nil? && type_right == 'new' unless left[:type].nil? && right[:type] == 'new'
comments_left = line_comments[line_code_left] notes_left = @grouped_diff_notes[left[:line_code]]
end end
unless type_left.nil? && type_right.nil? unless left[:type].nil? && right[:type].nil?
comments_right = line_comments[line_code_right] notes_right = @grouped_diff_notes[right[:line_code]]
end end
[comments_left, comments_right] [notes_left, notes_right]
end end
def inline_diff_btn def inline_diff_btn
...@@ -96,8 +92,8 @@ module DiffHelper ...@@ -96,8 +92,8 @@ module DiffHelper
].join(' ').html_safe ].join(' ').html_safe
end end
def commit_for_diff(diff) def commit_for_diff(diff_file)
if diff.deleted_file if diff_file.deleted_file
@base_commit || @commit.parent || @commit @base_commit || @commit.parent || @commit
else else
@commit @commit
......
...@@ -32,12 +32,6 @@ module EmailsHelper ...@@ -32,12 +32,6 @@ module EmailsHelper
nil nil
end end
def color_email_diff(diffcontent)
formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', inline_theme: 'github')
lexer = Rouge::Lexers::Diff
raw formatter.format(lexer.lex(diffcontent))
end
def password_reset_token_valid_time def password_reset_token_valid_time
valid_hours = Devise.reset_password_within / 60 / 60 valid_hours = Devise.reset_password_within / 60 / 60
if valid_hours >= 24 if valid_hours >= 24
......
...@@ -3,7 +3,7 @@ module EventsHelper ...@@ -3,7 +3,7 @@ module EventsHelper
author = event.author author = event.author
if author if author
link_to author.name, user_path(author.username), title: h(author.name) link_to author.name, user_path(author.username), title: author.name
else else
event.author_name event.author_name
end end
...@@ -39,15 +39,6 @@ module EventsHelper ...@@ -39,15 +39,6 @@ module EventsHelper
end end
end end
def icon_for_event
{
EventFilter.push => 'upload',
EventFilter.merged => 'check-square-o',
EventFilter.comments => 'comments',
EventFilter.team => 'user',
}
end
def event_preposition(event) def event_preposition(event)
if event.push? || event.commented? || event.target if event.push? || event.commented? || event.target
"at" "at"
...@@ -66,11 +57,7 @@ module EventsHelper ...@@ -66,11 +57,7 @@ module EventsHelper
words << event.ref_name words << event.ref_name
words << "at" words << "at"
elsif event.commented? elsif event.commented?
if event.note_commit? words << event.note_target_reference
words << event.note_short_commit_id
else
words << "##{truncate event.note_target_iid}"
end
words << "at" words << "at"
elsif event.milestone? elsif event.milestone?
words << "##{event.target_iid}" if event.target_iid words << "##{event.target_iid}" if event.target_iid
...@@ -93,21 +80,12 @@ module EventsHelper ...@@ -93,21 +80,12 @@ module EventsHelper
elsif event.merge_request? elsif event.merge_request?
namespace_project_merge_request_url(event.project.namespace, namespace_project_merge_request_url(event.project.namespace,
event.project, event.merge_request) event.project, event.merge_request)
elsif event.note? && event.note_commit? elsif event.note? && event.commit_note?
namespace_project_commit_url(event.project.namespace, event.project, namespace_project_commit_url(event.project.namespace, event.project,
event.note_target) event.note_target)
elsif event.note? elsif event.note?
if event.note_target if event.note_target
if event.note_commit? event_note_target_path(event)
namespace_project_commit_path(event.project.namespace, event.project,
event.note_commit_id,
anchor: dom_id(event.target))
elsif event.note_project_snippet?
namespace_project_snippet_path(event.project.namespace,
event.project, event.note_target)
else
event_note_target_path(event)
end
end end
elsif event.push? elsif event.push?
push_event_feed_url(event) push_event_feed_url(event)
...@@ -143,42 +121,30 @@ module EventsHelper ...@@ -143,42 +121,30 @@ module EventsHelper
end end
def event_note_target_path(event) def event_note_target_path(event)
if event.note? && event.note_commit? if event.note? && event.commit_note?
namespace_project_commit_path(event.project.namespace, event.project, namespace_project_commit_path(event.project.namespace,
event.note_target) event.project,
event.note_target,
anchor: dom_id(event.target))
elsif event.project_snippet_note?
namespace_project_snippet_path(event.project.namespace,
event.project,
event.note_target,
anchor: dom_id(event.target))
else else
polymorphic_path([event.project.namespace.becomes(Namespace), polymorphic_path([event.project.namespace.becomes(Namespace),
event.project, event.note_target], event.project, event.note_target],
anchor: dom_id(event.target)) anchor: dom_id(event.target))
end end
end end
def event_note_title_html(event) def event_note_title_html(event)
if event.note_target if event.note_target
if event.note_commit? link_to(event_note_target_path(event), title: event.target_title, class: 'has-tooltip') do
link_to( "#{event.note_target_type} #{event.note_target_reference}"
namespace_project_commit_path(event.project.namespace, event.project,
event.note_commit_id,
anchor: dom_id(event.target), title: h(event.target_title)),
class: "commit_short_id"
) do
"#{event.note_target_type} #{event.note_short_commit_id}"
end
elsif event.note_project_snippet?
link_to(namespace_project_snippet_path(event.project.namespace,
event.project,
event.note_target), title: h(event.project.name)) do
"#{event.note_target_type} #{truncate event.note_target.to_reference}"
end
else
link_to event_note_target_path(event) do
"#{event.note_target_type} #{truncate event.note_target.to_reference}"
end
end end
else else
content_tag :strong do content_tag(:strong, '(deleted)')
"(deleted)"
end
end end
end end
......
...@@ -13,7 +13,7 @@ module GitlabMarkdownHelper ...@@ -13,7 +13,7 @@ module GitlabMarkdownHelper
def link_to_gfm(body, url, html_options = {}) def link_to_gfm(body, url, html_options = {})
return "" if body.blank? return "" if body.blank?
escaped_body = if body =~ /\A\<img/ escaped_body = if body.start_with?('<img')
body body
else else
escape_once(body) escape_once(body)
......
...@@ -33,6 +33,10 @@ module GitlabRoutingHelper ...@@ -33,6 +33,10 @@ module GitlabRoutingHelper
namespace_project_builds_path(project.namespace, project, *args) namespace_project_builds_path(project.namespace, project, *args)
end end
def project_container_registry_path(project, *args)
namespace_project_container_registry_index_path(project.namespace, project, *args)
end
def activity_project_path(project, *args) def activity_project_path(project, *args)
activity_namespace_project_path(project.namespace, project, *args) activity_namespace_project_path(project.namespace, project, *args)
end end
......
...@@ -43,4 +43,12 @@ module NavHelper ...@@ -43,4 +43,12 @@ module NavHelper
class_name += " with-horizontal-nav" if defined?(nav) && nav class_name += " with-horizontal-nav" if defined?(nav) && nav
class_name class_name
end end
def layout_nav_class
"page-with-layout-nav" if defined?(nav) && nav
end
def layout_dropdown_class
"controls-dropdown-visible" if current_user
end
end end
module NotesHelper module NotesHelper
# Helps to distinguish e.g. commit notes in mr notes list # Helps to distinguish e.g. commit notes in mr notes list
def note_for_main_target?(note) def note_for_main_target?(note)
(@noteable.class.name == note.noteable_type && !note.for_diff_line?) @noteable.class.name == note.noteable_type && !note.diff_note?
end end
def note_target_fields(note) def note_target_fields(note)
...@@ -15,16 +15,6 @@ module NotesHelper ...@@ -15,16 +15,6 @@ module NotesHelper
note.editable? && can?(current_user, :admin_note, note) note.editable? && can?(current_user, :admin_note, note)
end end
def link_to_commit_diff_line_note(note)
if note.for_commit_diff_line?
link_to(
"#{note.diff_file_name}:L#{note.diff_new_line}",
namespace_project_commit_path(@project.namespace, @project,
note.noteable, anchor: note.line_code)
)
end
end
def noteable_json(noteable) def noteable_json(noteable)
{ {
id: noteable.id, id: noteable.id,
...@@ -35,7 +25,7 @@ module NotesHelper ...@@ -35,7 +25,7 @@ module NotesHelper
end end
def link_to_new_diff_note(line_code, line_type = nil) def link_to_new_diff_note(line_code, line_type = nil)
discussion_id = Note.build_discussion_id( discussion_id = LegacyDiffNote.build_discussion_id(
@comments_target[:noteable_type], @comments_target[:noteable_type],
@comments_target[:noteable_id] || @comments_target[:commit_id], @comments_target[:noteable_id] || @comments_target[:commit_id],
line_code line_code
...@@ -45,9 +35,10 @@ module NotesHelper ...@@ -45,9 +35,10 @@ module NotesHelper
noteable_type: @comments_target[:noteable_type], noteable_type: @comments_target[:noteable_type],
noteable_id: @comments_target[:noteable_id], noteable_id: @comments_target[:noteable_id],
commit_id: @comments_target[:commit_id], commit_id: @comments_target[:commit_id],
line_type: line_type,
line_code: line_code, line_code: line_code,
discussion_id: discussion_id, note_type: LegacyDiffNote.name,
line_type: line_type discussion_id: discussion_id
} }
button_tag(class: 'btn add-diff-note js-add-diff-note-button', button_tag(class: 'btn add-diff-note js-add-diff-note-button',
...@@ -57,18 +48,24 @@ module NotesHelper ...@@ -57,18 +48,24 @@ module NotesHelper
end end
end end
def link_to_reply_diff(note, line_type = nil) def link_to_reply_discussion(note, line_type = nil)
return unless current_user return unless current_user
data = { data = {
noteable_type: note.noteable_type, noteable_type: note.noteable_type,
noteable_id: note.noteable_id, noteable_id: note.noteable_id,
commit_id: note.commit_id, commit_id: note.commit_id,
line_code: note.line_code,
discussion_id: note.discussion_id, discussion_id: note.discussion_id,
line_type: line_type line_type: line_type
} }
if note.diff_note?
data.merge!(
line_code: note.line_code,
note_type: LegacyDiffNote.name
)
end
button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button', button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
data: data, title: 'Add a reply' data: data, title: 'Add a reply'
end end
......
...@@ -124,11 +124,7 @@ module ProjectsHelper ...@@ -124,11 +124,7 @@ module ProjectsHelper
end end
def license_short_name(project) def license_short_name(project)
no_license_key = project.repository.license_key.nil? || return 'LICENSE' if project.repository.license_key.nil?
# Back-compat if cache contains 'no-license', can be removed in a few weeks
project.repository.license_key == 'no-license'
return 'LICENSE' if no_license_key
license = Licensee::License.new(project.repository.license_key) license = Licensee::License.new(project.repository.license_key)
...@@ -138,20 +134,28 @@ module ProjectsHelper ...@@ -138,20 +134,28 @@ module ProjectsHelper
private private
def get_project_nav_tabs(project, current_user) def get_project_nav_tabs(project, current_user)
nav_tabs = [:home, :forks] nav_tabs = [:home]
if !project.empty_repo? && can?(current_user, :download_code, project) if !project.empty_repo? && can?(current_user, :download_code, project)
nav_tabs << [:files, :commits, :network, :graphs] nav_tabs << [:files, :commits, :network, :graphs, :forks]
end end
if project.repo_exists? && can?(current_user, :read_merge_request, project) if project.repo_exists? && can?(current_user, :read_merge_request, project)
nav_tabs << :merge_requests nav_tabs << :merge_requests
end end
if can?(current_user, :read_pipeline, project)
nav_tabs << :pipelines
end
if can?(current_user, :read_build, project) if can?(current_user, :read_build, project)
nav_tabs << :builds nav_tabs << :builds
end end
if Gitlab.config.registry.enabled && can?(current_user, :read_container_image, project)
nav_tabs << :container_registry
end
if can?(current_user, :admin_project, project) if can?(current_user, :admin_project, project)
nav_tabs << :settings nav_tabs << :settings
end end
......
...@@ -59,7 +59,7 @@ module SearchHelper ...@@ -59,7 +59,7 @@ module SearchHelper
# Autocomplete results for the current project, if it's defined # Autocomplete results for the current project, if it's defined
def project_autocomplete def project_autocomplete
if @project && @project.repository.exists? && @project.repository.root_ref if @project && @project.repository.exists? && @project.repository.root_ref
ref = @ref || @project.repository.root_ref ref = @ref || @project.repository.root_ref
[ [
{ category: "Current Project", label: "Files", url: namespace_project_tree_path(@project.namespace, @project, ref) }, { category: "Current Project", label: "Files", url: namespace_project_tree_path(@project.namespace, @project, ref) },
......
...@@ -18,7 +18,7 @@ module SelectsHelper ...@@ -18,7 +18,7 @@ module SelectsHelper
first_user: first_user, first_user: first_user,
current_user: opts[:current_user] || false, current_user: opts[:current_user] || false,
"push-code-to-protected-branches" => opts[:push_code_to_protected_branches], "push-code-to-protected-branches" => opts[:push_code_to_protected_branches],
author_id: opts[:author_id] || '' author_id: opts[:author_id] || ''
} }
} }
......
...@@ -112,7 +112,7 @@ module TabHelper ...@@ -112,7 +112,7 @@ module TabHelper
end end
def profile_tab_class def profile_tab_class
if controller.controller_path =~ /\Aprofiles/ if controller.controller_path.start_with?('profiles')
return 'active' return 'active'
end end
......
...@@ -11,6 +11,7 @@ module TodosHelper ...@@ -11,6 +11,7 @@ module TodosHelper
case todo.action case todo.action
when Todo::ASSIGNED then 'assigned you' when Todo::ASSIGNED then 'assigned you'
when Todo::MENTIONED then 'mentioned you on' when Todo::MENTIONED then 'mentioned you on'
when Todo::BUILD_FAILED then 'The build failed for your'
end end
end end
...@@ -28,8 +29,11 @@ module TodosHelper ...@@ -28,8 +29,11 @@ module TodosHelper
namespace_project_commit_path(todo.project.namespace.becomes(Namespace), todo.project, namespace_project_commit_path(todo.project.namespace.becomes(Namespace), todo.project,
todo.target, anchor: anchor) todo.target, anchor: anchor)
else else
polymorphic_path([todo.project.namespace.becomes(Namespace), path = [todo.project.namespace.becomes(Namespace), todo.project, todo.target]
todo.project, todo.target], anchor: anchor)
path.unshift(:builds) if todo.build_failed?
polymorphic_path(path, anchor: anchor)
end end
end end
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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