diff --git a/.gitignore b/.gitignore
index ce6a363fe3..8f861d76a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,46 +4,46 @@
.bundle
.chef
.directory
-/.envrc
-/.gitlab_shell_secret
+.envrc
+.gitlab_shell_secret
.idea
-/.rbenv-version
+.rbenv-version
.rbx/
-/.ruby-gemset
-/.ruby-version
-/.rvmrc
+.ruby-gemset
+.ruby-version
+.rvmrc
.sass-cache/
-/.secret
-/.vagrant
-/.byebug_history
-/Vagrantfile
-/backups/*
-/config/aws.yml
-/config/database.yml
-/config/gitlab.yml
-/config/gitlab_ci.yml
-/config/initializers/rack_attack.rb
-/config/initializers/smtp_settings.rb
-/config/initializers/relative_url.rb
-/config/resque.yml
-/config/unicorn.rb
-/config/secrets.yml
-/config/sidekiq.yml
-/coverage/*
-/db/*.sqlite3
-/db/*.sqlite3-journal
-/db/data.yml
-/doc/code/*
-/dump.rdb
-/log/*.log*
-/nohup.out
-/public/assets/
-/public/uploads.*
-/public/uploads/
-/shared/artifacts/
-/rails_best_practices_output.html
+.secret
+.vagrant
+.byebug_history
+Vagrantfile
+backups/*
+config/aws.yml
+config/database.yml
+config/gitlab.yml
+config/gitlab_ci.yml
+config/initializers/rack_attack.rb
+config/initializers/smtp_settings.rb
+config/initializers/relative_url.rb
+config/resque.yml
+config/unicorn.rb
+config/secrets.yml
+config/sidekiq.yml
+coverage/*
+db/*.sqlite3
+db/*.sqlite3-journal
+db/data.yml
+doc/code/*
+dump.rdb
+log/*.log*
+nohup.out
+public/assets/
+public/uploads.*
+public/uploads/
+shared/artifacts/
+rails_best_practices_output.html
/tags
-/tmp/*
-/vendor/bundle/*
-/builds/*
-/shared/*
+tmp/
+vendor/bundle/*
+builds/*
+shared/*
diff --git a/.rubocop.yml b/.rubocop.yml
index 84a8015b41..9f179efa3c 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -1,5 +1,3 @@
-require: rubocop-rspec
-
AllCops:
TargetRubyVersion: 2.1
# Cop names are not displayed in offense messages by default. Change behavior
@@ -23,7 +21,6 @@ AllCops:
- 'lib/email_validator.rb'
- 'lib/gitlab/upgrader.rb'
- 'lib/gitlab/seeder.rb'
- - 'generator_templates/**/*'
##################### Style ##################################
@@ -59,7 +56,7 @@ Style/AndOr:
# Use `Array#join` instead of `Array#*`.
Style/ArrayJoin:
- Enabled: true
+ Enabled: false
# Use only ascii symbols in comments.
Style/AsciiComments:
@@ -71,7 +68,7 @@ Style/AsciiIdentifiers:
# Checks for uses of Module#attr.
Style/Attr:
- Enabled: true
+ Enabled: false
# Avoid the use of BEGIN blocks.
Style/BeginBlock:
@@ -83,7 +80,7 @@ Style/BarePercentLiterals:
# Do not use block comments.
Style/BlockComments:
- Enabled: true
+ Enabled: false
# Put end statement of multiline block on its own line.
Style/BlockEndNewline:
@@ -124,7 +121,7 @@ Style/ClassCheck:
# Use self when defining module/class methods.
Style/ClassMethods:
- Enabled: true
+ Enabled: false
# Avoid the use of class variables.
Style/ClassVars:
@@ -154,7 +151,7 @@ Style/ConstantName:
# Use def with parentheses when there are arguments.
Style/DefWithParentheses:
- Enabled: true
+ Enabled: false
# Checks for use of deprecated Hash methods.
Style/DeprecatedHashMethods:
@@ -218,15 +215,15 @@ Style/EmptyLiteral:
# Avoid the use of END blocks.
Style/EndBlock:
- Enabled: true
+ Enabled: false
# Use Unix-style line endings.
Style/EndOfLine:
- Enabled: true
+ Enabled: false
# Favor the use of Fixnum#even? && Fixnum#odd?
Style/EvenOdd:
- Enabled: true
+ Enabled: false
# Do not use unnecessary spacing.
Style/ExtraSpacing:
@@ -234,20 +231,15 @@ Style/ExtraSpacing:
# Use snake_case for source file names.
Style/FileName:
- Enabled: true
-
-# Checks for a line break before the first parameter in a multi-line method
-# parameter definition.
-Style/FirstMethodParameterLineBreak:
- Enabled: true
+ Enabled: false
# Checks for flip flops.
Style/FlipFlop:
- Enabled: true
+ Enabled: false
# Checks use of for or each in multiline loops.
Style/For:
- Enabled: true
+ Enabled: false
# Enforce the use of Kernel#sprintf, Kernel#format or String#%.
Style/FormatString:
@@ -255,7 +247,7 @@ Style/FormatString:
# Do not introduce global variables.
Style/GlobalVars:
- Enabled: true
+ Enabled: false
# Check for conditionals that can be replaced with guard clauses.
Style/GuardClause:
@@ -276,7 +268,7 @@ Style/IfUnlessModifier:
# Do not use if x; .... Use the ternary operator instead.
Style/IfWithSemicolon:
- Enabled: true
+ Enabled: false
# Checks that conditional statements do not have an identical line at the
# end of each branch, which can validly be moved out of the conditional.
@@ -284,9 +276,9 @@ Style/IdenticalConditionalBranches:
Enabled: false
# Checks the indentation of the first line of the right-hand-side of a
-# multi-line assignment.
+# multi-line assignment.
Style/IndentAssignment:
- Enabled: true
+ Enabled: false
# Keep indentation straight.
Style/IndentationConsistency:
@@ -306,7 +298,7 @@ Style/IndentHash:
# Use Kernel#loop for infinite loops.
Style/InfiniteLoop:
- Enabled: true
+ Enabled: false
# Use the new lambda literal syntax for single-line blocks.
Style/Lambda:
@@ -314,11 +306,11 @@ Style/Lambda:
# Use lambda.call(...) instead of lambda.(...).
Style/LambdaCall:
- Enabled: true
+ Enabled: false
# Comments should start with a space.
Style/LeadingCommentSpace:
- Enabled: true
+ Enabled: false
# Use \ instead of + or << to concatenate two string literals at line end.
Style/LineEndConcatenation:
@@ -330,22 +322,16 @@ Style/MethodCallParentheses:
# Checks if the method definitions have or don't have parentheses.
Style/MethodDefParentheses:
- Enabled: true
+ Enabled: false
# Use the configured style when naming methods.
Style/MethodName:
- Enabled: true
+ Enabled: false
# Checks for usage of `extend self` in modules.
Style/ModuleFunction:
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.
Style/MultilineBlockChain:
Enabled: false
@@ -354,32 +340,15 @@ Style/MultilineBlockChain:
Style/MultilineBlockLayout:
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.
Style/MultilineIfThen:
- Enabled: true
-
-# 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
# one line.
Style/MultilineMethodCallIndentation:
Enabled: false
-# Checks that the closing brace in a method definition is symmetrical with
-# respect to the opening brace and the method parameters.
-Style/MultilineMethodDefinitionBraceLayout:
- Enabled: false
-
# Checks indentation of binary operations that span more than one line.
Style/MultilineOperationIndentation:
Enabled: false
@@ -394,7 +363,7 @@ Style/MutableConstant:
# Favor unless over if for negative conditions (or control flow or).
Style/NegatedIf:
- Enabled: true
+ Enabled: false
# Favor until over while for negative conditions.
Style/NegatedWhile:
@@ -402,7 +371,7 @@ Style/NegatedWhile:
# Avoid using nested modifiers.
Style/NestedModifier:
- Enabled: true
+ Enabled: false
# Parenthesize method calls which are nested inside the argument list of
# another parenthesized method call.
@@ -439,7 +408,7 @@ Style/OneLineConditional:
# When defining binary operators, name the argument other.
Style/OpMethod:
- Enabled: true
+ Enabled: false
# Check for simple usages of parallel assignment. It will only warn when
# the number of variables matches on both sides of the assignment.
@@ -486,9 +455,10 @@ Style/RedundantException:
Style/RedundantFreeze:
Enabled: false
+# TODO: Enable RedundantParentheses Cop.
# Checks for parentheses that seem not to serve any purpose.
Style/RedundantParentheses:
- Enabled: true
+ Enabled: false
# Don't use return where it's not required.
Style/RedundantReturn:
@@ -514,12 +484,11 @@ Style/SelfAssignment:
# Don't use semicolons to terminate expressions.
Style/Semicolon:
- Enabled: true
+ Enabled: false
# Checks for proper usage of fail and raise.
Style/SignalException:
- EnforcedStyle: only_raise
- Enabled: true
+ Enabled: false
# Enforces the names of some block params.
Style/SingleLineBlockParams:
@@ -540,28 +509,29 @@ Style/SpaceAfterComma:
# Do not put a space between a method name and the opening parenthesis in a
# method definition.
Style/SpaceAfterMethodName:
- Enabled: true
+ Enabled: false
# Tracks redundant space after the ! operator.
Style/SpaceAfterNot:
- Enabled: true
+ Enabled: false
# Use spaces after semicolons.
Style/SpaceAfterSemicolon:
- Enabled: true
+ Enabled: false
# Checks that the equals signs in parameter default assignments have or don't
# have surrounding space depending on configuration.
Style/SpaceAroundEqualsInParameterDefault:
Enabled: false
+# TODO: Enable SpaceAroundKeyword Cop.
# Use a space around keywords if appropriate.
Style/SpaceAroundKeyword:
- Enabled: true
+ Enabled: false
# Use a single space around operators.
Style/SpaceAroundOperators:
- Enabled: true
+ Enabled: false
# Checks that the left block brace has or doesn't have space before it.
Style/SpaceBeforeBlockBraces:
@@ -569,11 +539,11 @@ Style/SpaceBeforeBlockBraces:
# No spaces before commas.
Style/SpaceBeforeComma:
- Enabled: true
+ Enabled: false
# Checks for missing space between code and a comment on the same line.
Style/SpaceBeforeComment:
- Enabled: true
+ Enabled: false
# Checks that exactly one space is used between a method name and the first
# argument for method calls without parentheses.
@@ -582,7 +552,7 @@ Style/SpaceBeforeFirstArg:
# No spaces before semicolons.
Style/SpaceBeforeSemicolon:
- Enabled: true
+ Enabled: false
# Checks that block braces have or don't have surrounding space.
# For blocks taking parameters, checks that the left brace has or doesn't
@@ -604,12 +574,11 @@ Style/SpaceInsideParens:
# No spaces inside range literals.
Style/SpaceInsideRangeLiteral:
- Enabled: true
+ Enabled: false
# Checks for padding/surrounding spaces inside string interpolation.
Style/SpaceInsideStringInterpolation:
- EnforcedStyle: no_space
- Enabled: true
+ Enabled: false
# Avoid Perl-style global variables.
Style/SpecialGlobalVars:
@@ -617,8 +586,7 @@ Style/SpecialGlobalVars:
# Check for the usage of parentheses around stabby lambda arguments.
Style/StabbyLambdaParentheses:
- EnforcedStyle: require_parentheses
- Enabled: true
+ Enabled: false
# Checks if uses of quotes match the configured preference.
Style/StringLiterals:
@@ -631,9 +599,7 @@ Style/StringLiteralsInInterpolation:
# Checks if configured preferred methods are used over non-preferred.
Style/StringMethods:
- PreferredMethods:
- intern: to_sym
- Enabled: true
+ Enabled: false
# Use %i or %I for arrays of symbols.
Style/SymbolArray:
@@ -691,24 +657,23 @@ Style/UnneededPercentQ:
# Don't interpolate global, instance and class variables directly in strings.
Style/VariableInterpolation:
- Enabled: true
+ Enabled: false
# Use the configured style when naming variables.
Style/VariableName:
- EnforcedStyle: snake_case
- Enabled: true
+ Enabled: false
# Use when x then ... for one-line cases.
Style/WhenThen:
- Enabled: true
+ Enabled: false
# Checks for redundant do after while or until.
Style/WhileUntilDo:
- Enabled: true
+ Enabled: false
# Favor modifier while/until usage when you have a single-line body.
Style/WhileUntilModifier:
- Enabled: true
+ Enabled: false
# Use %w or %W for arrays of words.
Style/WordArray:
@@ -784,28 +749,28 @@ Lint/AssignmentInCondition:
# Align block ends correctly.
Lint/BlockAlignment:
- Enabled: true
+ Enabled: false
# Default values in optional keyword arguments and optional ordinal arguments
# should not refer back to the name of the argument.
Lint/CircularArgumentReference:
- Enabled: true
+ Enabled: false
# Checks for condition placed in a confusing position relative to the keyword.
Lint/ConditionPosition:
- Enabled: true
+ Enabled: false
# Check for debugger calls.
Lint/Debugger:
- Enabled: true
+ Enabled: false
# Align ends corresponding to defs correctly.
Lint/DefEndAlignment:
- Enabled: true
+ Enabled: false
# Check for deprecated class method calls.
Lint/DeprecatedClassMethods:
- Enabled: true
+ Enabled: false
# Check for duplicate method definitions.
Lint/DuplicateMethods:
@@ -817,15 +782,15 @@ Lint/DuplicatedKey:
# Check for immutable argument given to each_with_object.
Lint/EachWithObjectArgument:
- Enabled: true
+ Enabled: false
# Check for odd code arrangement in an else block.
Lint/ElseLayout:
- Enabled: true
+ Enabled: false
# Checks for empty ensure block.
Lint/EmptyEnsure:
- Enabled: true
+ Enabled: false
# Checks for empty string interpolation.
Lint/EmptyInterpolation:
@@ -833,36 +798,37 @@ Lint/EmptyInterpolation:
# Align ends correctly.
Lint/EndAlignment:
- Enabled: true
+ Enabled: false
# END blocks should not be placed inside method definitions.
Lint/EndInMethod:
- Enabled: true
+ Enabled: false
# Do not use return in an ensure block.
Lint/EnsureReturn:
- Enabled: true
+ Enabled: false
# The use of eval represents a serious security risk.
Lint/Eval:
- Enabled: true
+ Enabled: false
# Catches floating-point literals too large or small for Ruby to represent.
Lint/FloatOutOfRange:
- Enabled: true
+ Enabled: false
# The number of parameters to format/sprint must match the fields.
Lint/FormatParameterMismatch:
- Enabled: true
+ Enabled: false
# Don't suppress exception.
Lint/HandleExceptions:
Enabled: false
+# TODO: Enable ImplicitStringConcatenation Cop.
# Checks for adjacent string literals on the same line, which could better be
# represented as a single string literal.
Lint/ImplicitStringConcatenation:
- Enabled: true
+ Enabled: false
# TODO: Enable IneffectiveAccessModifier Cop.
# Checks for attempts to use `private` or `protected` to set the visibility
@@ -873,15 +839,15 @@ Lint/IneffectiveAccessModifier:
# Checks for invalid character literals with a non-escaped whitespace
# character.
Lint/InvalidCharacterLiteral:
- Enabled: true
+ Enabled: false
# Checks of literals used in conditions.
Lint/LiteralInCondition:
- Enabled: true
+ Enabled: false
# Checks for literals used in interpolation.
Lint/LiteralInInterpolation:
- Enabled: true
+ Enabled: false
# Use Kernel#loop with break rather than begin/end/until or begin/end/while
# for post-loop tests.
@@ -890,11 +856,11 @@ Lint/Loop:
# Do not use nested method definitions.
Lint/NestedMethodDefinition:
- Enabled: true
+ Enabled: false
# Do not omit the accumulator when calling `next` in a `reduce`/`inject` block.
Lint/NextWithoutAccumulator:
- Enabled: true
+ Enabled: false
# Checks for method calls with a space before the opening parenthesis.
Lint/ParenthesesAsGroupedExpression:
@@ -903,11 +869,11 @@ Lint/ParenthesesAsGroupedExpression:
# Checks for `rand(1)` calls. Such calls always return `0` and most likely
# a mistake.
Lint/RandOne:
- Enabled: true
+ Enabled: false
# Use parentheses in the method call to avoid confusion about precedence.
Lint/RequireParentheses:
- Enabled: true
+ Enabled: false
# Avoid rescuing the Exception class.
Lint/RescueException:
@@ -942,7 +908,7 @@ Lint/UnusedMethodArgument:
# Unreachable code.
Lint/UnreachableCode:
- Enabled: true
+ Enabled: false
# Checks for useless access modifiers.
Lint/UselessAccessModifier:
@@ -954,31 +920,33 @@ Lint/UselessAssignment:
# Checks for comparison of something with itself.
Lint/UselessComparison:
- Enabled: true
+ Enabled: false
# Checks for useless `else` in `begin..end` without `rescue`.
Lint/UselessElseWithoutRescue:
- Enabled: true
+ Enabled: false
# Checks for useless setter call to a local variable.
Lint/UselessSetterCall:
- Enabled: true
+ Enabled: false
# Possible use of operator/literal/variable in void context.
Lint/Void:
- Enabled: true
+ Enabled: false
##################### Performance ############################
+# TODO: Enable Casecmp Cop.
# Use `casecmp` rather than `downcase ==`.
Performance/Casecmp:
- Enabled: true
+ Enabled: false
+# TODO: Enable DoubleStartEndWith Cop.
# Use `str.{start,end}_with?(x, ..., y, ...)` instead of
# `str.{start,end}_with?(x, ...) || str.{start,end}_with?(y, ...)`.
Performance/DoubleStartEndWith:
- Enabled: true
+ Enabled: false
# TODO: Enable EndWith Cop.
# Use `end_with?` instead of a regex match anchored to the end of a string.
@@ -989,9 +957,10 @@ Performance/EndWith:
Performance/LstripRstrip:
Enabled: true
+# TODO: Enable RangeInclude Cop.
# Use `Range#cover?` instead of `Range#include?`.
Performance/RangeInclude:
- Enabled: true
+ Enabled: false
# TODO: Enable RedundantBlockCall Cop.
# Use `yield` instead of `block.call`.
@@ -1011,24 +980,26 @@ Performance/RedundantMerge:
MaxKeyValuePairs: 2
Enabled: false
+# TODO: Enable RedundantSortBy Cop.
# Use `sort` instead of `sort_by { |x| x }`.
Performance/RedundantSortBy:
- Enabled: true
+ Enabled: false
+# TODO: Enable StartWith Cop.
# Use `start_with?` instead of a regex match anchored to the beginning of a
# string.
Performance/StartWith:
- Enabled: true
-
+ Enabled: false
# Use `tr` instead of `gsub` when you are replacing the same number of
# characters. Use `delete` instead of `gsub` when you are deleting
# characters.
Performance/StringReplacement:
- Enabled: true
+ Enabled: false
+# TODO: Enable TimesMap Cop.
# Checks for `.times.map` calls.
Performance/TimesMap:
- Enabled: true
+ Enabled: false
##################### Rails ##################################
@@ -1053,11 +1024,11 @@ Rails/Delegate:
# Prefer `find_by` over `where.first`.
Rails/FindBy:
- Enabled: true
+ Enabled: false
# Prefer `all.find_each` over `all.find`.
Rails/FindEach:
- Enabled: true
+ Enabled: false
# Prefer has_many :through to has_and_belongs_to_many.
Rails/HasAndBelongsToMany:
@@ -1069,7 +1040,7 @@ Rails/Output:
# Checks for incorrect grammar when using methods like `3.day.ago`.
Rails/PluralizationGrammar:
- Enabled: true
+ Enabled: false
# Checks for `read_attribute(:attr)` and `write_attribute(:attr, val)`.
Rails/ReadWriteAttribute:
@@ -1077,7 +1048,7 @@ Rails/ReadWriteAttribute:
# Checks the arguments of ActiveRecord scopes.
Rails/ScopeArgs:
- Enabled: true
+ Enabled: false
# Checks the correct usage of time zone aware methods.
# http://danilenko.org/2012/7/6/rails_timezones
@@ -1087,65 +1058,3 @@ Rails/TimeZone:
# Use validates :attribute, hash of validations.
Rails/Validation:
Enabled: false
-
-##################### RSpec ##################################
-
-# Check that instances are not being stubbed globally.
-RSpec/AnyInstance:
- Enabled: false
-
-# Check that the first argument to the top level describe is the tested class or
-# module.
-RSpec/DescribeClass:
- Enabled: false
-
-# Use `described_class` for tested class / module.
-RSpec/DescribeMethod:
- Enabled: false
-
-# Checks that the second argument to top level describe is the tested method
-# name.
-RSpec/DescribedClass:
- Enabled: false
-
-# Checks for long example.
-RSpec/ExampleLength:
- Enabled: false
- Max: 5
-
-# Do not use should when describing your tests.
-RSpec/ExampleWording:
- Enabled: false
- CustomTransform:
- be: is
- have: has
- not: does not
- IgnoredWords: []
-
-# Checks the file and folder naming of the spec file.
-RSpec/FilePath:
- Enabled: false
- CustomTransform:
- RuboCop: rubocop
- RSpec: rspec
-
-# Checks if there are focused specs.
-RSpec/Focus:
- Enabled: true
-
-# Checks for the usage of instance variables.
-RSpec/InstanceVariable:
- Enabled: false
-
-# Checks for multiple top-level describes.
-RSpec/MultipleDescribes:
- Enabled: false
-
-# Enforces the usage of the same method on all negative message expectations.
-RSpec/NotToNot:
- EnforcedStyle: not_to
- Enabled: true
-
-# Prefer using verifying doubles over normal doubles.
-RSpec/VerifiedDoubles:
- Enabled: false
diff --git a/CHANGELOG b/CHANGELOG
index ec026b8f39..822fa4be56 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,180 +1,47 @@
Please view this file on the master branch, on stable branches it's out of date.
-v 8.9.0 (unreleased)
- - Allow enabling wiki page events from Webhook management UI
- - Make EmailsOnPushWorker use Sidekiq mailers queue
- - Fix wiki page events' webhook to point to the wiki repository
- - Fix issue todo not remove when leave project !4150 (Long Nguyen)
- - Allow forking projects with restricted visibility level
- - Improve note validation to prevent errors when creating invalid note via API
- - Reduce number of fog gem dependencies
- - Remove project notification settings associated with deleted projects
- - Fix 404 page when viewing TODOs that contain milestones or labels in different projects
- - Redesign navigation for project pages
- - Fix groups API to list only user's accessible projects
- - Redesign account and email confirmation emails
- - Use gitlab-shell v3.0.0
- - Add DB index on users.state
- - Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database
- - Changed the Slack build message to use the singular duration if necessary (Aran Koning)
- - Fix issues filter when ordering by milestone
- - Todos will display target state if issuable target is 'Closed' or 'Merged'
- - Fix bug when sorting issues by milestone due date and filtering by two or more labels
- - Link to blank group icon doesn't throw a 404 anymore
- - Remove 'main language' feature
- - Pipelines can be canceled only when there are running builds
- - Use downcased path to container repository as this is expected path by Docker
- - Projects pending deletion will render a 404 page
- - Measure queue duration between gitlab-workhorse and Rails
- - Make authentication service for Container Registry to be compatible with < Docker 1.11
- - Add Application Setting to configure Container Registry token expire delay (default 5min)
- - Cache assigned issue and merge request counts in sidebar nav
- - Cache project build count in sidebar nav
- - Reduce number of queries needed to render issue labels in the sidebar
- - Improve error handling importing projects
- - Put project Files and Commits tabs under Code tab
-
-v 8.8.3
- - Fix 404 page when viewing TODOs that contain milestones or labels in different projects. !4312
- - Fixed JS error when trying to remove discussion form. !4303
- - Fixed issue with button color when no CI enabled. !4287
- - Fixed potential issue with 2 CI status polling events happening. !3869
- - Improve design of Pipeline view. !4230
- - Fix gitlab importer failing to import new projects due to missing credentials. !4301
- - Fix import URL migration not rescuing with the correct Error. !4321
- - Fix health check access token changing due to old application settings being used. !4332
- - Make authentication service for Container Registry to be compatible with Docker versions before 1.11. !4363
- - Add Application Setting to configure Container Registry token expire delay (default 5 min). !4364
- - Pass the "Remember me" value to the 2FA token form. !4369
- - Fix incorrect links on pipeline page when merge request created from fork. !4376
- - Use downcased path to container repository as this is expected path by Docker. !4420
- - Fix wiki project clone address error (chujinjin). !4429
- - Fix serious performance bug with rendering Markdown with InlineDiffFilter. !4392
- - Fix missing number on generated ordered list element. !4437
- - Prevent disclosure of notes on confidential issues in search results.
-
-v 8.8.2
- - Added remove due date button. !4209
- - Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources. !4242
- - Fix Error 500 in CI charts by gracefully handling commits with no durations. !4245
- - Fix table UI on CI builds page. !4249
- - Fix backups if registry is disabled. !4263
- - Fixed issue with merge button color. !4211
- - Fixed issue with enter key selecting wrong option in dropdown. !4210
- - When creating a .gitignore file a dropdown with templates will be provided. !4075
- - Fix concurrent request when updating build log in browser. !4183
-
-v 8.8.1
- - Add documentation for the "Health Check" feature
- - Allow anonymous users to access a public project's pipelines !4233
- - 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 500 when attempting to retrieve project license when HEAD points to non-existent ref
+v 8.8.0 (unreleased)
- Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen)
- - 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.
- Escape HTML in commit titles in system note messages
- - Improve design of Pipeline View
- - 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
- 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
- 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
- Make build status canceled if any of the jobs was canceled and none failed
- 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
- Bump mail_room to 0.7.0 to fix stuck IDLE connections
- Remove future dates from contribution calendar graph.
- 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
- 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
- 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
- - Added authentication service for Container Registry
- Display informative message when new milestone is created
- - Sanitize milestones and labels titles
- - 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)
- Added button to toggle whitespaces changes on diff view
- Backport GitHub Enterprise import support from EE
- 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)
- - 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
- 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
- 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)
- 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)
- Expire repository exists? and has_visible_content? caches after a push if necessary
- - Fix unintentional filtering bug in Issue/MR sorted by milestone due (Takuya Noguchi)
- - 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
- - 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.7
- - Fix import by `Any Git URL` broken if the URL contains a space
-
-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
- - Fix notification delay when changing status of an issue
-
-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)
+ - Fix unintentional filtering bug in issues sorted by milestone due (Takuya Noguchi)
v 8.7.4
- - Links for Redmine issue references are generated correctly again !4048 (Benedikt Huss)
- - Fix setting trusted proxies !3970
- - 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
+ - Fix always showing build notification message when switching between merge requests
v 8.7.3
- 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.
- Fix the line code when importing PR review comments from GitHub. !4010
- 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
- The "New Branch" button is now loaded asynchronously
@@ -983,7 +850,7 @@ v 8.1.3
- Use issue editor as cross reference comment author when issue is edited with a new mention
- Add Facebook authentication
-v 8.1.1
+v 8.1.2
- Fix cloning Wiki repositories via HTTP (Stan Hu)
- Add migration to remove satellites directory
- Fix specific runners visibility
@@ -1608,17 +1475,20 @@ v 7.10.0
- Fix stuck Merge Request merging events from old installations (Ben Bodenmiller)
- Fix merge request comments on files with multiple commits
- Fix Resource Owner Password Authentication Flow
- - Add icons to Add dropdown items.
- - Allow admin to create public deploy keys that are accessible to any project.
- - Warn when gitlab-shell version doesn't match requirement.
- - Skip email confirmation when set by admin or via LDAP.
- - 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
+ - Contains no changes
+ - Add icons to Add dropdown items.
+ - Allow admin to create public deploy keys that are accessible to any project.
+ - Warn when gitlab-shell version doesn't match requirement.
+ - Skip email confirmation when set by admin or via LDAP.
+ - Only allow users to reference groups, projects, issues, MRs, commits they have access to.
+
v 7.9.3
- Contains no changes
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a15f8c4fec..9fe4cf7b0f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -311,11 +311,13 @@ request is as follows:
1. Create a feature branch
1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code
1. Add your changes to the [CHANGELOG](CHANGELOG)
-1. If you are writing documentation, make sure to read the [documentation styleguide][doc-styleguide]
+1. If you are changing the README, some documentation or other things which
+ have no effect on the tests, add `[ci skip]` somewhere in the commit message
+ and make sure to read the [documentation styleguide][doc-styleguide]
1. If you have multiple commits please combine them into one commit by
[squashing them][git-squash]
1. Push the commit(s) to your fork
-1. Submit a merge request (MR) to the `master` branch
+1. Submit a merge request (MR) to the master branch
1. The MR title should describe the change you want to make
1. The MR description should give a motive for your change and the method you
used to achieve it, see the [merge request description format]
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 4a36342fca..37c2961c24 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-3.0.0
+2.7.2
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index 0a1ffad4b4..39e898a4f9 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-0.7.4
+0.7.1
diff --git a/Gemfile b/Gemfile
index d9429de786..1137ef4d72 100644
--- a/Gemfile
+++ b/Gemfile
@@ -18,8 +18,9 @@ gem "mysql2", '~> 0.3.16', group: :mysql
gem "pg", '~> 0.18.2', group: :postgres
# Authentication libraries
-gem 'devise', '~> 4.0'
+gem 'devise', '~> 3.5.4'
gem 'doorkeeper', '~> 3.1'
+gem 'devise-async', '~> 0.9.0'
gem 'omniauth', '~> 1.3.1'
gem 'omniauth-auth0', '~> 1.4.1'
gem 'omniauth-azure-oauth2', '~> 0.0.6'
@@ -35,16 +36,15 @@ gem 'omniauth-shibboleth', '~> 1.2.0'
gem 'omniauth-twitter', '~> 1.2.0'
gem 'omniauth_crowd', '~> 2.2.0'
gem 'rack-oauth2', '~> 1.2.1'
-gem 'jwt'
# Spam and anti-bot protection
gem 'recaptcha', require: 'recaptcha/rails'
gem 'akismet', '~> 2.0'
# Two-factor authentication
-gem 'devise-two-factor', '~> 3.0.0'
+gem 'devise-two-factor', '~> 2.0.0'
gem 'rqrcode-rails3', '~> 0.1.7'
-gem 'attr_encrypted', '~> 3.0.0'
+gem 'attr_encrypted', '~> 1.3.4'
# Browser detection
gem "browser", '~> 1.0.0'
@@ -72,7 +72,7 @@ gem 'grape-entity', '~> 0.4.2'
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
# Pagination
-gem "kaminari", "~> 0.17.0"
+gem "kaminari", "~> 0.16.3"
# HAML
gem "haml-rails", '~> 0.9.0'
@@ -83,14 +83,8 @@ gem "carrierwave", '~> 0.10.0'
# Drag and Drop UI
gem 'dropzonejs-rails', '~> 0.7.1'
-# for backups
-gem 'fog-aws', '~> 0.9'
-gem 'fog-core', '~> 1.40'
-gem 'fog-local', '~> 0.3'
-gem 'fog-google', '~> 0.3'
-gem 'fog-openstack', '~> 0.1'
-
# for aws storage
+gem "fog", "~> 1.36.0"
gem "unf", '~> 0.1.4'
# Authorization
@@ -126,7 +120,7 @@ group :unicorn do
end
# State machine
-gem "state_machines-activerecord", '~> 0.4.0'
+gem "state_machines-activerecord", '~> 0.3.0'
# Run events after state machine commits
gem 'after_commit_queue'
@@ -183,6 +177,9 @@ gem 'ruby-fogbugz', '~> 0.2.1'
# d3
gem 'd3_rails', '~> 3.5.0'
+#cal-heatmap
+gem 'cal-heatmap-rails', '~> 3.6.0'
+
# underscore-rails
gem "underscore-rails", "~> 1.8.0"
@@ -200,7 +197,7 @@ gem 'licensee', '~> 8.0.0'
gem "rack-attack", '~> 4.3.1'
# Ace editor
-gem 'ace-rails-ap', '~> 4.0.2'
+gem 'ace-rails-ap', '~> 2.0.1'
# Keyboard shortcuts
gem 'mousetrap-rails', '~> 1.4.6'
@@ -221,13 +218,13 @@ gem 'gitlab_emoji', '~> 0.3.0'
gem 'gon', '~> 6.0.1'
gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 4.1.0'
+gem 'jquery-scrollto-rails', '~> 1.4.3'
gem 'jquery-ui-rails', '~> 5.0.0'
gem 'raphael-rails', '~> 2.1.2'
gem 'request_store', '~> 1.3.0'
gem 'select2-rails', '~> 3.5.9'
gem 'virtus', '~> 1.0.1'
gem 'net-ssh', '~> 3.0.1'
-gem 'base32', '~> 0.3.0'
# Sentry integration
gem 'sentry-raven', '~> 0.15'
@@ -245,6 +242,7 @@ group :development do
gem "foreman"
gem 'brakeman', '~> 3.2.0', require: false
+ gem "annotate", "~> 2.7.0"
gem 'letter_opener_web', '~> 1.3.0'
gem 'quiet_assets', '~> 1.0.2'
gem 'rerun', '~> 0.11.0'
@@ -295,10 +293,9 @@ group :development, :test do
gem 'spring-commands-spinach', '~> 1.1.0'
gem 'spring-commands-teaspoon', '~> 0.0.2'
- gem 'rubocop', '~> 0.40.0', require: false
- gem 'rubocop-rspec', '~> 1.5.0', require: false
+ gem 'rubocop', '~> 0.38.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 'flog', require: false
gem 'flay', require: false
@@ -328,7 +325,8 @@ gem "mail_room", "~> 0.7"
gem 'email_reply_parser', '~> 0.5.8'
## CI
-gem 'activerecord-session_store', '~> 1.0.0'
+gem 'activerecord-deprecated_finders', '~> 1.0.3'
+gem 'activerecord-session_store', '~> 0.1.0'
gem "nested_form", '~> 0.3.2'
# OAuth
@@ -336,6 +334,3 @@ gem 'oauth2', '~> 1.0.0'
# Soft deletion
gem "paranoia", "~> 2.0"
-
-# Health check
-gem 'health_check', '~> 1.5.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index 8ae25269e6..fe083c2b56 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,8 +1,9 @@
GEM
remote: https://rubygems.org/
specs:
+ CFPropertyList (2.3.2)
RedCloth (4.2.9)
- ace-rails-ap (4.0.2)
+ ace-rails-ap (2.0.1)
actionmailer (4.2.6)
actionpack (= 4.2.6)
actionview (= 4.2.6)
@@ -32,12 +33,11 @@ GEM
activemodel (= 4.2.6)
activesupport (= 4.2.6)
arel (~> 6.0)
- activerecord-session_store (1.0.0)
- actionpack (>= 4.0, < 5.1)
- activerecord (>= 4.0, < 5.1)
- multi_json (~> 1.11, >= 1.11.2)
- rack (>= 1.5.2, < 3)
- railties (>= 4.0, < 5.1)
+ activerecord-deprecated_finders (1.0.4)
+ activerecord-session_store (0.1.2)
+ actionpack (>= 4.0.0, < 5)
+ activerecord (>= 4.0.0, < 5)
+ railties (>= 4.0.0, < 5)
activesupport (4.2.6)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
@@ -51,6 +51,9 @@ GEM
activerecord (>= 3.0)
akismet (2.0.0)
allocations (1.0.4)
+ annotate (2.7.0)
+ activerecord (>= 3.2, < 6.0)
+ rake (~> 10.4)
arel (6.0.3)
asana (0.4.0)
faraday (~> 0.9)
@@ -59,8 +62,8 @@ GEM
oauth2 (~> 1.0)
asciidoctor (1.5.3)
ast (2.2.0)
- attr_encrypted (3.0.1)
- encryptor (~> 3.0.0)
+ attr_encrypted (1.3.4)
+ encryptor (>= 1.3.0)
attr_required (1.0.0)
autoprefixer-rails (6.2.3)
execjs
@@ -71,8 +74,7 @@ GEM
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
babosa (1.0.2)
- base32 (0.3.2)
- bcrypt (3.1.11)
+ bcrypt (3.1.10)
benchmark-ips (2.3.0)
better_errors (1.0.1)
coderay (>= 1.0.0)
@@ -101,6 +103,7 @@ GEM
bundler (~> 1.2)
thor (~> 0.18)
byebug (8.2.1)
+ cal-heatmap-rails (3.6.0)
capybara (2.6.2)
addressable
mime-types (>= 1.16)
@@ -154,18 +157,21 @@ GEM
activerecord (>= 3.2.0, < 5.0)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
- devise (4.1.1)
+ devise (3.5.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
- railties (>= 4.1.0, < 5.1)
+ railties (>= 3.2.6, < 5)
responders
+ thread_safe (~> 0.1)
warden (~> 1.2.3)
- devise-two-factor (3.0.0)
+ devise-async (0.9.0)
+ devise (~> 3.2)
+ devise-two-factor (2.0.1)
activesupport
- attr_encrypted (>= 1.3, < 4, != 2)
- devise (~> 4.0)
+ attr_encrypted (~> 1.3.2)
+ devise (~> 3.5.0)
railties
- rotp (~> 2.0)
+ rotp (~> 2)
diff-lcs (1.2.5)
diffy (3.0.7)
docile (1.1.5)
@@ -177,12 +183,12 @@ GEM
email_spec (1.6.0)
launchy (~> 2.1)
mail (~> 2.2)
- encryptor (3.0.0)
+ encryptor (1.3.0)
equalizer (0.0.11)
erubis (2.7.0)
escape_utils (1.1.1)
eventmachine (1.0.8)
- excon (0.49.0)
+ excon (0.45.4)
execjs (2.6.0)
expression_parser (0.9.0)
factory_girl (4.5.0)
@@ -199,6 +205,8 @@ GEM
multi_json
ffaker (2.0.0)
ffi (1.9.10)
+ fission (0.5.0)
+ CFPropertyList (~> 2.2)
flay (2.6.1)
ruby_parser (~> 3.0)
sexp_processor (~> 4.0)
@@ -208,28 +216,109 @@ GEM
flowdock (0.7.1)
httparty (~> 0.7)
multi_json
- fog-aws (0.9.2)
+ fog (1.36.0)
+ fog-aliyun (>= 0.1.0)
+ fog-atmos
+ fog-aws (>= 0.6.0)
+ fog-brightbox (~> 0.4)
+ fog-core (~> 1.32)
+ fog-dynect (~> 0.0.2)
+ fog-ecloud (~> 0.1)
+ fog-google (<= 0.1.0)
+ fog-json
+ fog-local
+ fog-powerdns (>= 0.1.1)
+ fog-profitbricks
+ fog-radosgw (>= 0.0.2)
+ fog-riakcs
+ fog-sakuracloud (>= 0.0.4)
+ fog-serverlove
+ fog-softlayer
+ fog-storm_on_demand
+ fog-terremark
+ fog-vmfusion
+ fog-voxel
+ fog-xenserver
+ fog-xml (~> 0.1.1)
+ ipaddress (~> 0.5)
+ nokogiri (~> 1.5, >= 1.5.11)
+ fog-aliyun (0.1.0)
+ fog-core (~> 1.27)
+ fog-json (~> 1.0)
+ ipaddress (~> 0.8)
+ xml-simple (~> 1.1)
+ fog-atmos (0.1.0)
+ fog-core
+ fog-xml
+ fog-aws (0.8.1)
fog-core (~> 1.27)
fog-json (~> 1.0)
fog-xml (~> 0.1)
ipaddress (~> 0.8)
- fog-core (1.40.0)
+ fog-brightbox (0.10.1)
+ fog-core (~> 1.22)
+ fog-json
+ inflecto (~> 0.0.2)
+ fog-core (1.35.0)
builder
- excon (~> 0.49)
+ excon (~> 0.45)
formatador (~> 0.2)
- fog-google (0.3.2)
+ fog-dynect (0.0.2)
+ fog-core
+ fog-json
+ fog-xml
+ fog-ecloud (0.3.0)
+ fog-core
+ fog-xml
+ fog-google (0.1.0)
fog-core
fog-json
fog-xml
fog-json (1.0.2)
fog-core (~> 1.0)
multi_json (~> 1.10)
- fog-local (0.3.0)
+ fog-local (0.2.1)
fog-core (~> 1.27)
- fog-openstack (0.1.6)
- fog-core (>= 1.39)
- fog-json (>= 1.0)
- ipaddress (>= 0.8)
+ fog-powerdns (0.1.1)
+ fog-core (~> 1.27)
+ fog-json (~> 1.0)
+ fog-xml (~> 0.1)
+ fog-profitbricks (0.0.5)
+ fog-core
+ fog-xml
+ nokogiri
+ fog-radosgw (0.0.5)
+ fog-core (>= 1.21.0)
+ fog-json
+ fog-xml (>= 0.0.1)
+ fog-riakcs (0.1.0)
+ fog-core
+ fog-json
+ fog-xml
+ fog-sakuracloud (1.7.5)
+ fog-core
+ fog-json
+ fog-serverlove (0.1.2)
+ fog-core
+ fog-json
+ fog-softlayer (1.0.3)
+ fog-core
+ fog-json
+ fog-storm_on_demand (0.1.1)
+ fog-core
+ fog-json
+ fog-terremark (0.1.0)
+ fog-core
+ fog-xml
+ fog-vmfusion (0.1.0)
+ fission
+ fog-core
+ fog-voxel (0.1.0)
+ fog-core
+ fog-xml
+ fog-xenserver (0.2.2)
+ fog-core
+ fog-xml
fog-xml (0.1.2)
fog-core
nokogiri (~> 1.5, >= 1.5.11)
@@ -316,8 +405,6 @@ GEM
html2haml (>= 1.0.1)
railties (>= 4.0.1)
hashie (3.4.3)
- health_check (1.5.1)
- rails (>= 2.3.0)
highline (1.7.8)
hipchat (1.5.2)
httparty
@@ -338,15 +425,18 @@ GEM
httpclient (2.7.0.1)
i18n (0.7.0)
ice_nine (0.11.1)
+ inflecto (0.0.2)
influxdb (0.2.3)
cause
json
- ipaddress (0.8.3)
+ ipaddress (0.8.2)
jquery-atwho-rails (1.3.2)
jquery-rails (4.1.1)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
+ jquery-scrollto-rails (1.4.3)
+ railties (> 3.1, < 5.0)
jquery-turbolinks (2.1.0)
railties (>= 3.1.0)
turbolinks
@@ -354,7 +444,7 @@ GEM
railties (>= 3.2.16)
json (1.8.3)
jwt (1.5.2)
- kaminari (0.17.0)
+ kaminari (0.16.3)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.10.0)
@@ -462,7 +552,7 @@ GEM
orm_adapter (0.5.0)
paranoia (2.1.4)
activerecord (~> 4.0)
- parser (2.3.1.0)
+ parser (2.3.0.6)
ast (~> 2.2)
pg (0.18.4)
poltergeist (1.9.0)
@@ -568,7 +658,7 @@ GEM
responders (2.1.1)
railties (>= 4.2.0, < 5.1)
rinku (1.7.3)
- rotp (2.1.2)
+ rotp (2.1.1)
rouge (1.10.1)
rqrcode (0.7.0)
chunky_png
@@ -597,17 +687,15 @@ GEM
rspec-retry (0.4.5)
rspec-core
rspec-support (3.4.1)
- rubocop (0.40.0)
- parser (>= 2.3.1.0, < 3.0)
+ rubocop (0.38.0)
+ parser (>= 2.3.0.6, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
- rubocop-rspec (1.5.0)
- rubocop (>= 0.40.0)
ruby-fogbugz (0.2.1)
crack (~> 0.4)
- ruby-progressbar (1.8.1)
+ ruby-progressbar (1.7.5)
ruby-saml (1.1.2)
nokogiri (>= 1.5.10)
uuid (~> 2.3)
@@ -701,11 +789,11 @@ GEM
activesupport (>= 4.0)
sprockets (>= 3.0.0)
state_machines (0.4.0)
- state_machines-activemodel (0.4.0)
- activemodel (>= 4.1, < 5.1)
+ state_machines-activemodel (0.3.0)
+ activemodel (~> 4.1)
state_machines (>= 0.4.0)
- state_machines-activerecord (0.4.0)
- activerecord (>= 4.1, < 5.1)
+ state_machines-activerecord (0.3.0)
+ activerecord (~> 4.1)
state_machines-activemodel (>= 0.3.0)
stringex (2.5.2)
systemu (2.6.5)
@@ -754,7 +842,7 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.7.2)
- unicode-display_width (1.0.5)
+ unicode-display_width (1.0.2)
unicorn (4.9.0)
kgio (~> 2.6)
rack
@@ -771,7 +859,7 @@ GEM
coercible (~> 1.0)
descendants_tracker (~> 0.0, >= 0.0.3)
equalizer (~> 0.0, >= 0.0.9)
- warden (1.2.6)
+ warden (1.2.4)
rack (>= 1.0)
web-console (2.3.0)
activemodel (>= 4.0)
@@ -788,6 +876,7 @@ GEM
builder
expression_parser
rinku
+ xml-simple (1.1.5)
xpath (2.0.0)
nokogiri (~> 1.3)
@@ -796,19 +885,20 @@ PLATFORMS
DEPENDENCIES
RedCloth (~> 4.2.9)
- ace-rails-ap (~> 4.0.2)
- activerecord-session_store (~> 1.0.0)
+ ace-rails-ap (~> 2.0.1)
+ activerecord-deprecated_finders (~> 1.0.3)
+ activerecord-session_store (~> 0.1.0)
acts-as-taggable-on (~> 3.4)
addressable (~> 2.3.8)
after_commit_queue
akismet (~> 2.0)
allocations (~> 1.0)
+ annotate (~> 2.7.0)
asana (~> 0.4.0)
asciidoctor (~> 1.5.2)
- attr_encrypted (~> 3.0.0)
+ attr_encrypted (~> 1.3.4)
awesome_print (~> 1.2.0)
babosa (~> 1.0.2)
- base32 (~> 0.3.0)
benchmark-ips
better_errors (~> 1.0.1)
binding_of_caller (~> 0.7.2)
@@ -818,6 +908,7 @@ DEPENDENCIES
bullet
bundler-audit
byebug
+ cal-heatmap-rails (~> 3.6.0)
capybara (~> 2.6.2)
capybara-screenshot (~> 1.0.0)
carrierwave (~> 0.10.0)
@@ -830,8 +921,9 @@ DEPENDENCIES
d3_rails (~> 3.5.0)
database_cleaner (~> 1.4.0)
default_value_for (~> 3.0.0)
- devise (~> 4.0)
- devise-two-factor (~> 3.0.0)
+ devise (~> 3.5.4)
+ devise-async (~> 0.9.0)
+ devise-two-factor (~> 2.0.0)
diffy (~> 3.0.3)
doorkeeper (~> 3.1)
dropzonejs-rails (~> 0.7.1)
@@ -841,11 +933,7 @@ DEPENDENCIES
ffaker (~> 2.0.0)
flay
flog
- fog-aws (~> 0.9)
- fog-core (~> 1.40)
- fog-google (~> 0.3)
- fog-local (~> 0.3)
- fog-openstack (~> 0.1)
+ fog (~> 1.36.0)
font-awesome-rails (~> 4.2)
foreman
fuubar (~> 2.0.0)
@@ -863,17 +951,16 @@ DEPENDENCIES
grape (~> 0.13.0)
grape-entity (~> 0.4.2)
haml-rails (~> 0.9.0)
- health_check (~> 1.5.1)
hipchat (~> 1.5.0)
html-pipeline (~> 1.11.0)
httparty (~> 0.13.3)
influxdb (~> 0.2)
jquery-atwho-rails (~> 1.3.2)
jquery-rails (~> 4.1.0)
+ jquery-scrollto-rails (~> 1.4.3)
jquery-turbolinks (~> 2.1.0)
jquery-ui-rails (~> 5.0.0)
- jwt
- kaminari (~> 0.17.0)
+ kaminari (~> 0.16.3)
letter_opener_web (~> 1.3.0)
licensee (~> 8.0.0)
loofah (~> 2.0.3)
@@ -929,8 +1016,7 @@ DEPENDENCIES
rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.4.0)
rspec-retry
- rubocop (~> 0.40.0)
- rubocop-rspec (~> 1.5.0)
+ rubocop (~> 0.38.0)
ruby-fogbugz (~> 0.2.1)
sanitize (~> 2.0)
sass-rails (~> 5.0.0)
@@ -955,7 +1041,7 @@ DEPENDENCIES
spring-commands-spinach (~> 1.1.0)
spring-commands-teaspoon (~> 0.0.2)
sprockets (~> 3.6.0)
- state_machines-activerecord (~> 0.4.0)
+ state_machines-activerecord (~> 0.3.0)
task_list (~> 1.0.2)
teaspoon (~> 1.1.0)
teaspoon-jasmine (~> 2.2.0)
@@ -975,4 +1061,4 @@ DEPENDENCIES
wikicloth (= 0.8.1)
BUNDLED WITH
- 1.12.4
+ 1.12.1
diff --git a/README.md b/README.md
index fee93d5f9c..5e41665a6b 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,9 @@
# GitLab
[](https://gitlab.com/gitlab-org/gitlab-ce/commits/master)
+[](https://semaphoreci.com/gitlabhq/gitlabhq)
[](https://codeclimate.com/github/gitlabhq/gitlabhq)
+[](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master)
## Canonical source
@@ -33,11 +35,11 @@ There are two editions of GitLab:
On [about.gitlab.com](https://about.gitlab.com/) you can find more information about:
-- [Subscriptions](https://about.gitlab.com/pricing/)
+- [Subscriptions](https://about.gitlab.com/subscription/)
- [Consultancy](https://about.gitlab.com/consultancy/)
- [Community](https://about.gitlab.com/community/)
- [Hosted GitLab.com](https://about.gitlab.com/gitlab-com/) use GitLab as a free service
-- [GitLab Enterprise Edition](https://about.gitlab.com/features/#enterprise) with additional features aimed at larger organizations.
+- [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee/) with additional features aimed at larger organizations.
- [GitLab CI](https://about.gitlab.com/gitlab-ci/) a continuous integration (CI) server that is easy to integrate with GitLab.
## Requirements
diff --git a/VERSION b/VERSION
index 6c07f65628..d5a967c393 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-8.9.0-pre
+8.8.0-pre
diff --git a/app/assets/images/ci/arch.jpg b/app/assets/images/ci/arch.jpg
new file mode 100644
index 0000000000..0e05674e84
Binary files /dev/null and b/app/assets/images/ci/arch.jpg differ
diff --git a/app/assets/images/ci/favicon.ico b/app/assets/images/ci/favicon.ico
new file mode 100644
index 0000000000..9663d4d00b
Binary files /dev/null and b/app/assets/images/ci/favicon.ico differ
diff --git a/app/assets/images/ci/loader.gif b/app/assets/images/ci/loader.gif
new file mode 100644
index 0000000000..2fcb8f2da0
Binary files /dev/null and b/app/assets/images/ci/loader.gif differ
diff --git a/app/assets/images/ci/no_avatar.png b/app/assets/images/ci/no_avatar.png
new file mode 100644
index 0000000000..752d26adba
Binary files /dev/null and b/app/assets/images/ci/no_avatar.png differ
diff --git a/app/assets/images/ci/rails.png b/app/assets/images/ci/rails.png
new file mode 100644
index 0000000000..d5edc04e65
Binary files /dev/null and b/app/assets/images/ci/rails.png differ
diff --git a/app/assets/images/ci/service_sample.png b/app/assets/images/ci/service_sample.png
new file mode 100644
index 0000000000..65d29e3fd8
Binary files /dev/null and b/app/assets/images/ci/service_sample.png differ
diff --git a/app/assets/images/mailers/gitlab_header_logo.png b/app/assets/images/mailers/gitlab_header_logo.png
deleted file mode 100644
index 35ca186088..0000000000
Binary files a/app/assets/images/mailers/gitlab_header_logo.png and /dev/null differ
diff --git a/app/assets/images/mailers/gitlab_tanuki_2x.png b/app/assets/images/mailers/gitlab_tanuki_2x.png
deleted file mode 100644
index 551dd6ce2c..0000000000
Binary files a/app/assets/images/mailers/gitlab_tanuki_2x.png and /dev/null differ
diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee
index 3f61ea1eaf..dd1bbb3755 100644
--- a/app/assets/javascripts/api.js.coffee
+++ b/app/assets/javascripts/api.js.coffee
@@ -1,15 +1,14 @@
@Api =
- groupsPath: "/api/:version/groups.json"
- groupPath: "/api/:version/groups/:id.json"
- namespacesPath: "/api/:version/namespaces.json"
- groupProjectsPath: "/api/:version/groups/:id/projects.json"
- projectsPath: "/api/:version/projects.json"
- labelsPath: "/api/:version/projects/:id/labels"
- licensePath: "/api/:version/licenses/:key"
- gitignorePath: "/api/:version/gitignores/:key"
+ groups_path: "/api/:version/groups.json"
+ group_path: "/api/:version/groups/:id.json"
+ namespaces_path: "/api/:version/namespaces.json"
+ group_projects_path: "/api/:version/groups/:id/projects.json"
+ projects_path: "/api/:version/projects.json"
+ labels_path: "/api/:version/projects/:id/labels"
+ license_path: "/api/:version/licenses/:key"
group: (group_id, callback) ->
- url = Api.buildUrl(Api.groupPath)
+ url = Api.buildUrl(Api.group_path)
url = url.replace(':id', group_id)
$.ajax(
@@ -23,7 +22,7 @@
# Return groups list. Filtered by query
# Only active groups retrieved
groups: (query, skip_ldap, callback) ->
- url = Api.buildUrl(Api.groupsPath)
+ url = Api.buildUrl(Api.groups_path)
$.ajax(
url: url
@@ -37,7 +36,7 @@
# Return namespaces list. Filtered by query
namespaces: (query, callback) ->
- url = Api.buildUrl(Api.namespacesPath)
+ url = Api.buildUrl(Api.namespaces_path)
$.ajax(
url: url
@@ -51,7 +50,7 @@
# Return projects list. Filtered by query
projects: (query, order, callback) ->
- url = Api.buildUrl(Api.projectsPath)
+ url = Api.buildUrl(Api.projects_path)
$.ajax(
url: url
@@ -65,7 +64,7 @@
callback(projects)
newLabel: (project_id, data, callback) ->
- url = Api.buildUrl(Api.labelsPath)
+ url = Api.buildUrl(Api.labels_path)
url = url.replace(':id', project_id)
data.private_token = gon.api_token
@@ -81,7 +80,7 @@
# Return group projects list. Filtered by query
groupProjects: (group_id, query, callback) ->
- url = Api.buildUrl(Api.groupProjectsPath)
+ url = Api.buildUrl(Api.group_projects_path)
url = url.replace(':id', group_id)
$.ajax(
@@ -96,7 +95,7 @@
# Return text for a specific license
licenseText: (key, data, callback) ->
- url = Api.buildUrl(Api.licensePath).replace(':key', key)
+ url = Api.buildUrl(Api.license_path).replace(':key', key)
$.ajax(
url: url
@@ -104,12 +103,6 @@
).done (license) ->
callback(license)
- gitignoreText: (key, callback) ->
- url = Api.buildUrl(Api.gitignorePath).replace(':key', key)
-
- $.get url, (gitignore) ->
- callback(gitignore)
-
buildUrl: (url) ->
url = gon.relative_url_root + url if gon.relative_url_root?
return url.replace(':version', gon.api_version)
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index 18c1aa0d4e..5bac8eef1c 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -18,6 +18,8 @@
#= require jquery.atwho
#= require jquery.scrollTo
#= require jquery.turbolinks
+#= require d3
+#= require cal-heatmap
#= require turbolinks
#= require autosave
#= require bootstrap/affix
@@ -50,13 +52,7 @@
#= require shortcuts_network
#= require jquery.nicescroll
#= require date.format
-#= require_directory ./behaviors
-#= require_directory ./blob
-#= require_directory ./ci
-#= require_directory ./commit
-#= require_directory ./extensions
-#= require_directory ./lib
-#= require_directory .
+#= require_tree .
#= require fuzzaldrin-plus
#= require cropper
@@ -208,7 +204,6 @@ $ ->
$('.header-content .title').toggle()
$('.header-content .navbar-collapse').toggle()
$('.navbar-toggle').toggleClass('active')
- $('.navbar-toggle i').toggleClass("fa-angle-right fa-angle-left")
# Show/hide comments on diff
$("body").on "click", ".js-toggle-diff-comments", (e) ->
@@ -250,6 +245,38 @@ $ ->
if $navIcon.hasClass('fa-angle-left')
$navIconToggle.trigger('click')
+ $(document)
+ .off 'click', '.js-sidebar-toggle'
+ .on 'click', '.js-sidebar-toggle', (e, triggered) ->
+ e.preventDefault()
+ $this = $(this)
+ $thisIcon = $this.find 'i'
+ $allGutterToggleIcons = $('.js-sidebar-toggle i')
+ if $thisIcon.hasClass('fa-angle-double-right')
+ $allGutterToggleIcons
+ .removeClass('fa-angle-double-right')
+ .addClass('fa-angle-double-left')
+ $('aside.right-sidebar')
+ .removeClass('right-sidebar-expanded')
+ .addClass('right-sidebar-collapsed')
+ $('.page-with-sidebar')
+ .removeClass('right-sidebar-expanded')
+ .addClass('right-sidebar-collapsed')
+ else
+ $allGutterToggleIcons
+ .removeClass('fa-angle-double-left')
+ .addClass('fa-angle-double-right')
+ $('aside.right-sidebar')
+ .removeClass('right-sidebar-collapsed')
+ .addClass('right-sidebar-expanded')
+ $('.page-with-sidebar')
+ .removeClass('right-sidebar-collapsed')
+ .addClass('right-sidebar-expanded')
+ if not triggered
+ $.cookie("collapsed_gutter",
+ $('.right-sidebar')
+ .hasClass('right-sidebar-collapsed'), { path: '/' })
+
fitSidebarForSize = ->
oldBootstrapBreakpoint = bootstrapBreakpoint
bootstrapBreakpoint = bp.getBreakpointSize()
diff --git a/app/assets/javascripts/blob/blob_gitignore_selector.js.coffee b/app/assets/javascripts/blob/blob_gitignore_selector.js.coffee
deleted file mode 100644
index cc8a497d08..0000000000
--- a/app/assets/javascripts/blob/blob_gitignore_selector.js.coffee
+++ /dev/null
@@ -1,58 +0,0 @@
-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
- )
diff --git a/app/assets/javascripts/blob/edit_blob.js.coffee b/app/assets/javascripts/blob/edit_blob.js.coffee
index 79141e768b..eea9aa972e 100644
--- a/app/assets/javascripts/blob/edit_blob.js.coffee
+++ b/app/assets/javascripts/blob/edit_blob.js.coffee
@@ -13,7 +13,6 @@ class @EditBlob
@initModePanesAndLinks()
new BlobLicenseSelector(@editor)
- new BlobGitignoreSelectors(editor: @editor)
initModePanesAndLinks: ->
@$editModePanes = $(".js-edit-mode-pane")
diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee
new file mode 100644
index 0000000000..d80e0e716c
--- /dev/null
+++ b/app/assets/javascripts/calendar.js.coffee
@@ -0,0 +1,34 @@
+class @Calendar
+ constructor: (timestamps, starting_year, starting_month, calendar_activities_path) ->
+ cal = new CalHeatMap()
+ cal.init
+ itemName: ["contribution"]
+ data: timestamps
+ start: new Date(starting_year, starting_month)
+ domainLabelFormat: "%b"
+ id: "cal-heatmap"
+ domain: "month"
+ subDomain: "day"
+ range: 12
+ tooltip: true
+ label:
+ position: "top"
+ legend: [
+ 0
+ 10
+ 20
+ 30
+ ]
+ legendCellPadding: 3
+ cellSize: $('.user-calendar').width() / 73
+ onClick: (date, count) ->
+ formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
+ $.ajax
+ url: calendar_activities_path
+ data:
+ date: formated_date
+ cache: false
+ dataType: "html"
+ success: (data) ->
+ $(".user-calendar-activities").html data
+
diff --git a/app/assets/javascripts/ci/application.js.coffee b/app/assets/javascripts/ci/application.js.coffee
index ca24c1d759..05aa0f366b 100644
--- a/app/assets/javascripts/ci/application.js.coffee
+++ b/app/assets/javascripts/ci/application.js.coffee
@@ -1,6 +1,34 @@
+# This is a manifest file that'll be compiled into application.js, which will include all the files
+# listed below.
+#
+# Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+# or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+#
+# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+# the compiled file.
+#
+# WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+# GO AFTER THE REQUIRES BELOW.
+#
#= require pager
#= require jquery_nested_form
#= require_tree .
+#
+$(document).on 'click', '.edit-runner-link', (event) ->
+ event.preventDefault()
+
+ descr = $(this).closest('.runner-description').first()
+ descr.addClass('hide')
+ form = descr.next('.runner-description-form')
+ descrInput = form.find('input.description')
+ originalValue = descrInput.val()
+ form.removeClass('hide')
+ form.find('.cancel').on 'click', (event) ->
+ event.preventDefault()
+
+ form.addClass('hide')
+ descrInput.val(originalValue)
+ descr.removeClass('hide')
$(document).on 'click', '.assign-all-runner', ->
$(this).replaceWith(' Assign in progress..')
diff --git a/app/assets/javascripts/ci/build.coffee b/app/assets/javascripts/ci/build.coffee
index 98d05e4127..7afe8bf79e 100644
--- a/app/assets/javascripts/ci/build.coffee
+++ b/app/assets/javascripts/ci/build.coffee
@@ -1,12 +1,9 @@
class CiBuild
@interval: null
- @state: null
- constructor: (build_url, build_status, build_state) ->
+ constructor: (build_url, build_status) ->
clearInterval(CiBuild.interval)
- @state = build_state
-
@initScrollButtonAffix()
if build_status == "running" || build_status == "pending"
@@ -28,22 +25,15 @@ class CiBuild
#
CiBuild.interval = setInterval =>
if window.location.href.split("#").first() is build_url
- last_state = @state
$.ajax
- url: build_url + "/trace.json?state=" + encodeURIComponent(@state)
+ url: build_url
dataType: "json"
- success: (log) =>
- return unless last_state is @state
-
- if log.state and log.status is "running"
- @state = log.state
- if log.append
- $('.fa-refresh').before log.html
- else
- $('#build-trace code').html log.html
- $('#build-trace code').append ''
+ success: (build) =>
+ if build.status == "running"
+ $('#build-trace code').html build.trace_html
+ $('#build-trace code').append ''
@checkAutoscroll()
- else if log.status isnt build_status
+ else if build.status != build_status
Turbolinks.visit build_url
, 4000
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index a3185f8764..f91aa3c5ad 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -16,6 +16,7 @@ class Dispatcher
shortcut_handler = null
switch page
when 'projects:issues:index'
+ Issues.init()
Issuable.init()
shortcut_handler = new ShortcutsNavigation()
when 'projects:issues:show'
@@ -118,7 +119,7 @@ class Dispatcher
new UsersSelect()
when 'projects'
new NamespaceSelect()
- when 'dashboard', 'root'
+ when 'dashboard'
shortcut_handler = new ShortcutsDashboardNavigation()
when 'profiles'
new Profile()
diff --git a/app/assets/javascripts/due_date_select.js.coffee b/app/assets/javascripts/due_date_select.js.coffee
index 3cc7018517..a4304786cb 100644
--- a/app/assets/javascripts/due_date_select.js.coffee
+++ b/app/assets/javascripts/due_date_select.js.coffee
@@ -11,7 +11,6 @@ class @DueDateSelect
$block = $dropdown.closest('.block')
$selectbox = $dropdown.closest('.selectbox')
$value = $block.find('.value')
- $valueContent = $block.find('.value-content')
$sidebarValue = $('.js-due-date-sidebar-value', $block)
fieldName = $dropdown.data('field-name')
@@ -24,15 +23,11 @@ class @DueDateSelect
$value.removeAttr('style')
)
- addDueDate = (isDropdown) ->
+ addDueDate = ->
# Create the post date
value = $("input[name='#{fieldName}']").val()
-
- if value isnt ''
- date = new Date value.replace(new RegExp('-', 'g'), ',')
- mediumDate = $.datepicker.formatDate 'M d, yy', date
- else
- mediumDate = 'None'
+ date = new Date value.replace(new RegExp('-', 'g'), ',')
+ mediumDate = $.datepicker.formatDate 'M d, yy', date
data = {}
data[abilityName] = {}
@@ -44,35 +39,23 @@ class @DueDateSelect
data: data
beforeSend: ->
$loading.fadeIn()
- if isDropdown
- $dropdown.trigger('loading.gl.dropdown')
- $selectbox.hide()
+ $dropdown.trigger('loading.gl.dropdown')
+ $selectbox.hide()
$value.removeAttr('style')
- $valueContent.html(mediumDate)
+ $value.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) ->
- if isDropdown
- $dropdown.trigger('loaded.gl.dropdown')
- $dropdown.dropdown('toggle')
+ $dropdown.trigger('loaded.gl.dropdown')
+ $dropdown.dropdown('toggle')
$loading.fadeOut()
- $block.on 'click', '.js-remove-due-date', (e) ->
- e.preventDefault()
- $("input[name='#{fieldName}']").val ''
- addDueDate(false)
-
$datePicker.datepicker(
dateFormat: 'yy-mm-dd',
defaultDate: $("input[name='#{fieldName}']").val()
altField: "input[name='#{fieldName}']"
onSelect: ->
- addDueDate(true)
+ addDueDate()
)
$(document)
diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee
index 41dba34210..61e3f811e7 100644
--- a/app/assets/javascripts/gfm_auto_complete.js.coffee
+++ b/app/assets/javascripts/gfm_auto_complete.js.coffee
@@ -18,10 +18,6 @@ GitLab.GfmAutoComplete =
Issues:
template: '
@@ -107,7 +100,7 @@ class @UserTabs
if action is 'activity'
@loadActivities(source)
- if action in ['groups', 'contributed', 'projects', 'snippets']
+ if action in ['groups', 'contributed', 'projects']
@loadTab(source, action)
loadTab: (source, action) ->
diff --git a/app/assets/javascripts/users/application.js.coffee b/app/assets/javascripts/users/application.js.coffee
deleted file mode 100644
index 647ffbf5f4..0000000000
--- a/app/assets/javascripts/users/application.js.coffee
+++ /dev/null
@@ -1,8 +0,0 @@
-# This is a manifest file that'll be compiled into including all the files listed below.
-# Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
-# be included in the compiled file accessible from http://example.com/assets/application.js
-# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
-# the compiled file.
-#
-#= require d3
-#= require_tree .
diff --git a/app/assets/javascripts/users/calendar.js.coffee b/app/assets/javascripts/users/calendar.js.coffee
deleted file mode 100644
index 26a2606153..0000000000
--- a/app/assets/javascripts/users/calendar.js.coffee
+++ /dev/null
@@ -1,198 +0,0 @@
-class @Calendar
- constructor: (timestamps, @calendar_activities_path) ->
- @currentSelectedDate = ''
- @daySpace = 1
- @daySize = 15
- @daySizeWithSpace = @daySize + (@daySpace * 2)
- @monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
- @months = []
- @highestValue = 0
-
- # Get the highest value from the timestampes
- _.each timestamps, (count) =>
- if count > @highestValue
- @highestValue = count
-
- # Loop through the timestamps to create a group of objects
- # The group of objects will be grouped based on the day of the week they are
- @timestampsTmp = []
- i = 0
- group = 0
- _.each timestamps, (count, date) =>
- newDate = new Date parseInt(date) * 1000
- day = newDate.getDay()
-
- # Create a new group array if this is the first day of the week
- # or if is first object
- if (day is 0 and i isnt 0) or i is 0
- @timestampsTmp.push []
- group++
-
- innerArray = @timestampsTmp[group-1]
-
- # Push to the inner array the values that will be used to render map
- innerArray.push
- count: count
- date: newDate
- day: day
-
- i++
-
- # Init color functions
- @color = @initColor()
- @colorKey = @initColorKey()
-
- # Init the svg element
- @renderSvg(group)
- @renderDays()
- @renderMonths()
- @renderDayTitles()
- @renderKey()
-
- @initTooltips()
-
- renderSvg: (group) ->
- @svg = d3.select '.js-contrib-calendar'
- .append 'svg'
- .attr 'width', (group + 1) * @daySizeWithSpace
- .attr 'height', 167
- .attr 'class', 'contrib-calendar'
-
- renderDays: ->
- @svg.selectAll 'g'
- .data @timestampsTmp
- .enter()
- .append 'g'
- .attr 'transform', (group, i) =>
- _.each group, (stamp, a) =>
- if a is 0 and stamp.day is 0
- month = stamp.date.getMonth()
- x = (@daySizeWithSpace * i + 1) + @daySizeWithSpace
- lastMonth = _.last(@months)
- if lastMonth?
- lastMonthX = lastMonth.x
-
- if !lastMonth?
- @months.push
- month: month
- x: x
- else if month isnt lastMonth.month and x - @daySizeWithSpace isnt lastMonthX
- @months.push
- month: month
- x: x
-
- "translate(#{(@daySizeWithSpace * i + 1) + @daySizeWithSpace}, 18)"
- .selectAll 'rect'
- .data (stamp) ->
- stamp
- .enter()
- .append 'rect'
- .attr 'x', '0'
- .attr 'y', (stamp, i) =>
- (@daySizeWithSpace * stamp.day)
- .attr 'width', @daySize
- .attr 'height', @daySize
- .attr 'title', (stamp) =>
- contribText = 'No contributions'
-
- if stamp.count > 0
- contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}"
-
- date = dateFormat(stamp.date, 'mmm d, yyyy')
-
- "#{contribText}
#{date}"
- .attr 'class', 'user-contrib-cell js-tooltip'
- .attr 'fill', (stamp) =>
- if stamp.count isnt 0
- @color(stamp.count)
- else
- '#ededed'
- .attr 'data-container', 'body'
- .on 'click', @clickDay
-
- renderDayTitles: ->
- days = [{
- text: 'M'
- y: 29 + (@daySizeWithSpace * 1)
- }, {
- text: 'W'
- y: 29 + (@daySizeWithSpace * 3)
- }, {
- text: 'F'
- y: 29 + (@daySizeWithSpace * 5)
- }]
- @svg.append 'g'
- .selectAll 'text'
- .data days
- .enter()
- .append 'text'
- .attr 'text-anchor', 'middle'
- .attr 'x', 8
- .attr 'y', (day) ->
- day.y
- .text (day) ->
- day.text
- .attr 'class', 'user-contrib-text'
-
- renderMonths: ->
- @svg.append 'g'
- .selectAll 'text'
- .data @months
- .enter()
- .append 'text'
- .attr 'x', (date) ->
- date.x
- .attr 'y', 10
- .attr 'class', 'user-contrib-text'
- .text (date) =>
- @monthNames[date.month]
-
- renderKey: ->
- keyColors = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)]
- @svg.append 'g'
- .attr 'transform', "translate(18, #{@daySizeWithSpace * 8 + 16})"
- .selectAll 'rect'
- .data keyColors
- .enter()
- .append 'rect'
- .attr 'width', @daySize
- .attr 'height', @daySize
- .attr 'x', (color, i) =>
- @daySizeWithSpace * i
- .attr 'y', 0
- .attr 'fill', (color) ->
- color
-
- initColor: ->
- d3.scale
- .linear()
- .range(['#acd5f2', '#254e77'])
- .domain([0, @highestValue])
-
- initColorKey: ->
- d3.scale
- .linear()
- .range(['#acd5f2', '#254e77'])
- .domain([0, 3])
-
- clickDay: (stamp) =>
- if @currentSelectedDate isnt stamp.date
- @currentSelectedDate = stamp.date
- formatted_date = @currentSelectedDate.getFullYear() + "-" + (@currentSelectedDate.getMonth()+1) + "-" + @currentSelectedDate.getDate()
-
- $.ajax
- url: @calendar_activities_path
- data:
- date: formatted_date
- cache: false
- dataType: 'html'
- beforeSend: ->
- $('.user-calendar-activities').html '
'
- success: (data) ->
- $('.user-calendar-activities').html data
- else
- $('.user-calendar-activities').html ''
-
- initTooltips: ->
- $('.js-contrib-calendar .js-tooltip').tooltip
- html: true
diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee
index 519618aa61..b80b1b861c 100644
--- a/app/assets/javascripts/users_select.js.coffee
+++ b/app/assets/javascripts/users_select.js.coffee
@@ -93,9 +93,7 @@ class @UsersSelect
$dropdown.glDropdown(
data: (term, callback) =>
- isAuthorFilter = $('.js-author-search')
-
- @users term, term is '' and isAuthorFilter, (users) =>
+ @users term, (users) =>
if term.length is 0
showDivider = 0
@@ -140,7 +138,7 @@ class @UsersSelect
toggleLabel: (selected) ->
if selected && 'id' of selected
- if selected.text then selected.text else selected.name
+ selected.name
else
defaultLabel
@@ -221,7 +219,7 @@ class @UsersSelect
multiple: $(select).hasClass('multiselect')
minimumInputLength: 0
query: (query) =>
- @users query.term, @projectId?, (users) =>
+ @users query.term, (users) =>
data = { results: users }
if query.term.length == 0
@@ -304,7 +302,7 @@ class @UsersSelect
# Return users list. Filtered by query
# Only active users retrieved
- users: (query, fromProject, callback) =>
+ users: (query, callback) =>
url = @buildUrl(@usersPath)
$.ajax(
@@ -313,7 +311,7 @@ class @UsersSelect
search: query
per_page: 20
active: true
- project_id: @projectId if fromProject
+ project_id: @projectId
group_id: @groupId
current_user: @showCurrentUser
author_id: @authorId
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index 8b93665d08..69b3b6586d 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -8,7 +8,9 @@
*= require select2
*= require_self
*= require dropzone/basic
+ *= require cal-heatmap
*= require cropper.css
+ *= require animate
*/
/*
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index 3cbddc59f1..560de9fc0b 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -5,7 +5,6 @@
@import 'framework/tw_bootstrap';
@import "framework/layout";
-@import "framework/animations.scss";
@import "framework/avatar.scss";
@import "framework/blocks.scss";
@import "framework/buttons.scss";
diff --git a/app/assets/stylesheets/framework/animations.scss b/app/assets/stylesheets/framework/animations.scss
deleted file mode 100644
index 1fec61bdba..0000000000
--- a/app/assets/stylesheets/framework/animations.scss
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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;
-}
diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss
index bb8d71fbae..f5ce70b606 100644
--- a/app/assets/stylesheets/framework/avatar.scss
+++ b/app/assets/stylesheets/framework/avatar.scss
@@ -45,7 +45,6 @@
&.s32 { font-size: 20px; line-height: 32px; }
&.s40 { font-size: 16px; line-height: 40px; }
&.s60 { font-size: 32px; line-height: 60px; }
- &.s70 { font-size: 34px; line-height: 70px; }
&.s90 { font-size: 36px; line-height: 90px; }
&.s110 { font-size: 40px; line-height: 112px; font-weight: 300; }
&.s140 { font-size: 72px; line-height: 140px; }
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 6981f834d3..434a26d57c 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -24,8 +24,8 @@
background-color: $background-color;
padding: $gl-padding;
margin-bottom: 0;
- border-top: 1px solid $white-dark;
- border-bottom: 1px solid $white-dark;
+ border-top: 1px solid $border-color;
+ border-bottom: 1px solid $border-color;
color: $gl-gray;
&.oneline-block {
@@ -110,9 +110,9 @@
.cover-title {
color: $gl-header-color;
margin: 0;
- font-size: 24px;
+ font-size: 23px;
font-weight: normal;
- margin-bottom: 5px;
+ margin: 16px 0 5px;
color: #4c4e54;
font-size: 23px;
line-height: 1.1;
@@ -137,6 +137,7 @@
}
.cover-desc {
+ padding: 0 $gl-padding 3px;
color: $gl-text-color;
&.username:last-child {
@@ -204,7 +205,7 @@
.content-block {
padding: $gl-padding 0;
- border-bottom: 1px solid $white-dark;
+ border-bottom: 1px solid $border-color;
&.oneline-block {
line-height: 36px;
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 467f3b35d7..eaf85bb17c 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -16,19 +16,6 @@
@include btn-default;
}
-@mixin btn-outline($background, $text, $border, $hover-background, $hover-text, $hover-border) {
- background-color: $background;
- color: $text;
- border-color: $border;
-
- &:hover,
- &:focus {
- background-color: $hover-background;
- color: $hover-text;
- border-color: $hover-border;;
- }
-}
-
@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) {
background-color: $light;
border-color: $border-light;
@@ -119,14 +106,11 @@
@include btn-blue;
}
+ &.btn-close,
&.btn-warning {
@include btn-orange;
}
- &.btn-close {
- @include btn-outline($white-light, $orange-normal, $orange-normal, $orange-light, $white-light, $orange-light);
- }
-
&.btn-danger,
&.btn-remove,
&.btn-red {
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index 8642b7530e..11f39d583b 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -1,44 +1,70 @@
.calender-block {
- padding-left: 0;
- padding-right: 0;
-
@media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) {
overflow-x: scroll;
}
}
.user-calendar-activities {
+ .calendar_onclick_hr {
+ padding: 0;
+ margin: 10px 0;
+ }
+
.str-truncated {
max-width: 70%;
}
- .user-calendar-activities-loading {
- font-size: 24px;
- }
-}
-
-.user-calendar {
- text-align: center;
-
- .calendar {
- display: inline-block;
- }
-}
-
-.user-contrib-cell {
- &:hover {
+ .text-expander {
+ background: #eee;
+ color: #555;
+ padding: 0 5px;
cursor: pointer;
- stroke: #000;
+ margin-left: 4px;
+ &:hover {
+ background-color: #ddd;
+ }
}
}
-.user-contrib-text {
- font-size: 12px;
- fill: #959494;
-}
+/**
+* This overwrites the default values of the cal-heatmap gem
+*/
+.calendar {
+ .qi {
+ fill: #fff;
+ }
-.calendar-hint {
- margin-top: -23px;
- float: right;
- font-size: 12px;
+ .q1 {
+ fill: #ededed !important;
+ }
+
+ .q2 {
+ fill: #acd5f2 !important;
+ }
+
+ .q3 {
+ fill: #7fa8d1 !important;
+ }
+
+ .q4 {
+ fill: #49729b !important;
+ }
+
+ .q5 {
+ fill: #254e77 !important;
+ }
+
+ .future {
+ visibility: hidden;
+ }
+
+ .domain-background {
+ fill: none;
+ shape-rendering: crispedges;
+ }
+
+ .ch-tooltip {
+ padding: 3px;
+ font-weight: 550;
+ }
}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index f8aecd0558..3386523dbf 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -289,7 +289,7 @@ table {
text-shadow: none;
@media (min-width: $screen-sm-min) {
- margin-top: 8px;
+ margin-top: 11px;
}
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 93c63c6984..4bf3a05040 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -154,7 +154,7 @@
color: $dropdown-header-color;
font-size: 13px;
line-height: 22px;
- padding: 0 10px;
+ padding: 0 10px 10px;
}
.separator + .dropdown-header {
@@ -162,10 +162,6 @@
}
}
-.dropdown-menu-full-width {
- width: 100%;
-}
-
.dropdown-menu-paging {
.dropdown-page-two,
.dropdown-menu-back {
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 71a9f79be3..61d9954c6c 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -5,10 +5,6 @@
.file-holder {
border: 1px solid $border-color;
- &.file-holder-no-border {
- border: 0;
- }
-
&.readme-holder {
margin: $gl-padding-top 0;
}
@@ -27,17 +23,8 @@
word-wrap: break-word;
border-radius: 3px 3px 0 0;
- &.file-title-clear {
- padding-left: 0;
- padding-right: 0;
- background-color: transparent;
-
- .file-actions {
- right: 0;
- }
- }
-
.file-actions {
+ float: right;
position: absolute;
top: 5px;
right: 15px;
@@ -49,6 +36,22 @@
}
}
+ .filename {
+ &.old {
+ display: inline-block;
+ span.idiff {
+ background-color: #f8cbcb;
+ }
+ }
+
+ &.new {
+ display: inline-block;
+ span.idiff {
+ background-color: #a6f3a6;
+ }
+ }
+ }
+
a:not(.btn) {
color: $gl-dark-link-color;
}
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index 46acc3b772..558b133f59 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -28,6 +28,10 @@ input[type='text'].danger {
}
label {
+ &.control-label {
+ @extend .col-sm-2;
+ }
+
&.inline-label {
margin: 0;
}
@@ -37,10 +41,6 @@ label {
}
}
-.control-label {
- @extend .col-sm-2;
-}
-
.inline-input-group {
width: 250px;
}
diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss
index 16cf394c42..c83cf88159 100644
--- a/app/assets/stylesheets/framework/gitlab-theme.scss
+++ b/app/assets/stylesheets/framework/gitlab-theme.scss
@@ -9,7 +9,8 @@
@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) {
.page-with-sidebar {
.header-logo {
- background: $color-darker;
+ background-color: $color;
+ border-color: $color;
a {
color: $color-light;
@@ -20,13 +21,9 @@
}
&:hover {
- background-color: $color-dark;
+ background-color: $color-darker;
a {
color: #fff;
-
- h3 {
- color: #fff;
- }
}
}
}
@@ -90,8 +87,8 @@
}
$theme-blue: #2980b9;
-$theme-charcoal: #3d454d;
-$theme-graphite: #666;
+$theme-charcoal: #333c47;
+$theme-graphite: #888;
$theme-gray: #373737;
$theme-green: #019875;
$theme-violet: #548;
@@ -102,11 +99,11 @@ body {
}
&.ui_charcoal {
- @include gitlab-theme(#d6d7d9, #485157, $theme-charcoal, #353b41);
+ @include gitlab-theme(#c5d0de, $theme-charcoal, #2b333d, #24272d);
}
&.ui_graphite {
- @include gitlab-theme(#ccc, #777, $theme-graphite, #555);
+ @include gitlab-theme(#ccc, $theme-graphite, #777, #666);
}
&.ui_gray {
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 0da96c4017..97f9d58200 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -6,12 +6,12 @@ header {
transition-duration: .3s;
&.navbar-empty {
- height: $header-height;
+ height: 58px;
background: #fff;
- border-bottom: 1px solid $btn-gray-hover;
+ border-bottom: 1px solid #eee;
.center-logo {
- margin: 8px 0;
+ margin: 11px 0;
text-align: center;
#tanuki-logo, img {
@@ -22,18 +22,14 @@ header {
}
&.navbar-gitlab {
- padding: 0 16px;
+ padding: 0 20px;
z-index: 100;
margin-bottom: 0;
- height: $header-height;
+ min-height: $header-height;
background-color: $background-color;
border: none;
border-bottom: 1px solid $border-color;
- @media (max-width: $screen-xs-min) {
- padding: 0 16px;
- }
-
&.with-horizontal-nav {
border-bottom: none;
}
@@ -64,44 +60,16 @@ header {
margin: 6px 0;
border-radius: 0;
position: absolute;
- right: -10px;
- padding: 6px 10px;
+ right: 2px;
&:hover {
- background-color: $btn-gray-hover;
+ background-color: #eee;
}
-
&.active {
color: $gl-icon-color;
}
}
}
-
- &.header-collapsed {
- padding: 0 16px;
- }
-
- .side-nav-toggle {
- display: none;
- position: absolute;
- left: -10px;
- margin: 6px 0;
- padding: 6px 10px;
- border: none;
- background-color: $background-color;
-
- &:hover {
- background-color: $btn-gray-hover;
- }
-
- &:focus {
- outline: none;
- }
-
- @media (max-width: $screen-xs-min) {
- display: block;
- }
- }
}
.header-content {
@@ -109,10 +77,6 @@ header {
height: $header-height;
padding-right: 40px;
- @media (max-width: $screen-xs-min) {
- padding-left: 40px;
- }
-
@media (min-width: $screen-sm-min) {
padding-right: 0;
}
@@ -181,10 +145,6 @@ header {
@media (min-width: $screen-md-min) {
@include collapsed-header;
}
-
- @media (max-width: $screen-xs-min) {
- margin-left: 0;
- }
}
.header-expanded {
@@ -193,10 +153,6 @@ header {
@media (min-width: $screen-md-min) {
margin-left: $sidebar_width;
}
-
- @media (max-width: $screen-xs-min) {
- margin-left: 0;
- }
}
@media (max-width: $screen-xs-max) {
diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss
index bd531f8376..33cbee8598 100644
--- a/app/assets/stylesheets/framework/mobile.scss
+++ b/app/assets/stylesheets/framework/mobile.scss
@@ -48,6 +48,10 @@
display: block;
}
+ .project-home-desc {
+ font-size: 21px;
+ }
+
.project-repo-buttons,
.git-clone-holder {
display: none;
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index 7eb7a8e454..7c18e93a26 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -1,34 +1,3 @@
-@mixin fade($gradient-direction, $rgba, $gradient-color) {
- visibility: visible;
- opacity: 1;
- position: absolute;
- bottom: 12px;
- width: 43px;
- height: 30px;
- transition-duration: .3s;
- -webkit-transform: translateZ(0);
- background: -webkit-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
- background: -o-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
- background: -moz-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
- background: linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
-
- &.end-scroll {
- visibility: hidden;
- opacity: 0;
- transition-duration: .3s;
- }
-}
-
-@mixin scrolling-links() {
- white-space: nowrap;
- overflow-x: auto;
- overflow-y: hidden;
- -webkit-overflow-scrolling: touch;
- &::-webkit-scrollbar {
- display: none;
- }
-}
-
.nav-links {
padding: 0;
margin: 0;
@@ -150,7 +119,7 @@
}
input {
- height: 35px;
+ height: 34px;
display: inline-block;
position: relative;
top: 2px;
@@ -227,22 +196,14 @@
position: fixed;
top: $header-height;
width: 100%;
- z-index: 11;
+ z-index: 1;
background: $background-color;
border-bottom: 1px solid $border-color;
transition-duration: .3s;
- .container-fluid {
- position: relative;
- }
-
.controls {
float: right;
- padding: 7px 0 0;
-
- @media (max-width: $screen-xs-max) {
- display: none;
- }
+ padding: 7px 5px 0 0;
i {
color: $layout-link-gray;
@@ -260,31 +221,14 @@
.dropdown {
margin-left: 7px;
-
- @media (max-width: $screen-xs-min) {
- margin-left: 0;
- }
-
- li.active {
- font-weight: bold;
- }
}
}
.nav-links {
- @include scrolling-links();
border-bottom: none;
height: 51px;
-
- .fade-right {
- @include fade(left, rgba(250, 250, 250, 0.4), $background-color);
- right: 0;
- }
-
- .fade-left {
- @include fade(right, rgba(250, 250, 250, 0.4), $background-color);
- left: 0;
- }
+ white-space: nowrap;
+ overflow-x: auto;
li {
@@ -308,62 +252,8 @@
}
}
- .nav-control {
- .fade-right {
-
- @media (min-width: $screen-xs-max) {
- right: 67px;
- }
- @media (max-width: $screen-xs-min) {
- right: 0;
- }
- }
- }
-}
-
-.nav-block {
- position: relative;
-
- .nav-links {
- @include scrolling-links();
-
- .fade-right {
- @include fade(left, rgba(255, 255, 255, 0.4), $white-light);
- right: 0;
- }
-
- .fade-left {
- @include fade(right, rgba(255, 255, 255, 0.4), $white-light);
- left: 0;
- }
-
- &.event-filter {
- .fade-right {
- visibility: hidden;
-
- @media (max-width: $screen-xs-max) {
- visibility: visible;
- }
- }
- }
- }
}
.page-with-layout-nav {
- margin-top: $header-height + 2;
-
- .right-sidebar {
- top: ($header-height * 2) + 2;
- }
-}
-
-.activities {
-
- .nav-block {
- border-bottom: 1px solid $border-color;
-
- .nav-links {
- border-bottom: none;
- }
- }
+ margin-top: 50px;
}
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 67f491b6d9..e940fd7286 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -98,7 +98,7 @@
}
.sidebar-user {
- padding: 7px 22px;
+ padding: 9px 22px;
position: fixed;
bottom: 40px;
width: $sidebar_width;
@@ -210,33 +210,15 @@
}
}
-.sidebar-wrapper {
- &.hidden-nav {
- width: 0;
- }
-}
-
.page-sidebar-collapsed {
padding-left: $sidebar_collapsed_width;
- @media (max-width: $screen-xs-min) {
- padding-left: 0;
- }
-
.sidebar-wrapper {
width: $sidebar_collapsed_width;
- @media (max-width: $screen-xs-min) {
- width: 0;
- }
-
.header-logo {
width: $sidebar_collapsed_width;
- @media (max-width: $screen-xs-min) {
- width: 0;
- }
-
a {
padding-left: ($sidebar_collapsed_width - 36) / 2;
@@ -262,22 +244,12 @@
.collapse-nav a {
width: $sidebar_collapsed_width;
-
- @media (max-width: $screen-xs-min) {
- width: 0;
- }
}
.sidebar-user {
padding-left: ($sidebar_collapsed_width - 36) / 2;
width: $sidebar_collapsed_width;
- @media (max-width: $screen-xs-min) {
- width: 0;
- padding-left: 0;
- padding-right: 0;
- }
-
.username {
display: none;
}
@@ -286,10 +258,6 @@
.layout-nav {
padding-right: $sidebar_collapsed_width;
-
- @media (max-width: $screen-xs-min) {
- padding-right: 0;;
- }
}
}
@@ -300,10 +268,6 @@
padding-left: $sidebar_width;
}
- @media (max-width: $screen-xs-min) {
- padding-left: 0;
- }
-
.sidebar-wrapper {
width: $sidebar_width;
@@ -312,7 +276,7 @@
}
.nav-sidebar li a {
- width: $sidebar_width;
+ width: 230px;
&.back-link {
i {
@@ -323,17 +287,7 @@
}
.layout-nav {
- @media (max-width: $screen-xs-min) {
- padding-right: 0;
- }
-
- @media (min-width: $screen-xs-min) and (max-width: $screen-md-min) {
- padding-right: 62px;
- }
-
- @media (min-width: $screen-md-min) {
- padding-right: $sidebar_width;
- }
+ padding-right: $sidebar_width;
}
}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 3575984b22..2779cd5678 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -269,11 +269,3 @@ h1, h2, h3, h4 {
text-align: right;
}
}
-
-.idiff.deletion {
- background: $line-removed-dark;
-}
-
-.idiff.addition {
- background: $line-added-dark;
-}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index f253da814b..ccb4e5381b 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -2,7 +2,7 @@
* Layout
*/
$sidebar_collapsed_width: 62px;
-$sidebar_width: 220px;
+$sidebar_width: 230px;
$gutter_collapsed_width: 62px;
$gutter_width: 290px;
$gutter_inner_width: 258px;
@@ -12,7 +12,7 @@ $gutter_inner_width: 258px;
*/
$border-color: #e5e5e5;
$focus-border-color: #3aabf0;
-$table-border-color: #f0f0f0;
+$table-border-color: #ececec;
$background-color: #fafafa;
/*
@@ -63,8 +63,7 @@ $gl-padding-top: 10px;
/*
* Misc
*/
-$row-hover: #f7faff;
-$row-hover-border: #b2d7ff;
+$row-hover: #f4f8fe;
$progress-color: #c0392b;
$avatar_radius: 50%;
$header-height: 50px;
@@ -105,7 +104,7 @@ $blue-medium-light: #3498cb;
$blue-medium: #2f8ebf;
$blue-medium-dark: #2d86b4;
-$orange-light: #fc8a51;
+$orange-light: rgba(252, 109, 38, 0.80);
$orange-normal: #e75e40;
$orange-dark: #ce5237;
@@ -120,8 +119,8 @@ $border-white-light: #f1f2f4;
$border-white-normal: #d6dae2;
$border-white-dark: #c6cacf;
-$border-gray-light: #dcdcdc;
-$border-gray-normal: rgba(0, 0, 0, 0.10);
+$border-gray-light: rgba(0, 0, 0, 0.06);
+$border-gray-normal: rgba(0, 0, 0, 0.10);;
$border-gray-dark: #c6cacf;
$border-green-light: #2faa60;
@@ -179,7 +178,6 @@ $table-border-gray: #f0f0f0;
$line-target-blue: #eaf3fc;
$line-select-yellow: #fcf8e7;
$line-select-yellow-dark: #f0e2bd;
-
/*
* Fonts
*/
@@ -217,7 +215,6 @@ $dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color;
$btn-active-gray: #ececec;
$btn-placeholder-gray: #c7c7c7;
$btn-white-active: #848484;
-$btn-gray-hover: #eee;
/*
* Award emoji
diff --git a/app/assets/stylesheets/framework/zen.scss b/app/assets/stylesheets/framework/zen.scss
index ff02ebdd34..f870ea0d87 100644
--- a/app/assets/stylesheets/framework/zen.scss
+++ b/app/assets/stylesheets/framework/zen.scss
@@ -32,7 +32,7 @@
}
}
-.zen-control {
+.zen-cotrol {
padding: 0;
color: #555;
background: none;
diff --git a/app/assets/stylesheets/mailers/devise.scss b/app/assets/stylesheets/mailers/devise.scss
deleted file mode 100644
index 28611a5ec8..0000000000
--- a/app/assets/stylesheets/mailers/devise.scss
+++ /dev/null
@@ -1,134 +0,0 @@
-// NOTE: This stylesheet is for the exclusive use of the `devise_mailer` layout
-// used for Devise email templates, and _should not_ be included in any
-// application stylesheets.
-//
-// Styles defined here are embedded directly into the resulting email HTML via
-// the `premailer` gem.
-
-$body-background-color: #363636;
-$message-background-color: #fafafa;
-
-$header-color: #6b4fbb;
-$body-color: #444;
-$cta-color: #e14329;
-$footer-link-color: #7e7e7e;
-
-$font-family: Helvetica, Arial, sans-serif;
-
-body {
- background-color: $body-background-color;
- font-family: $font-family;
- margin: 0;
- padding: 0;
-}
-
-table {
- -premailer-cellpadding: 0;
- -premailer-cellspacing: 0;
-
- border: 0;
- border-collapse: separate;
-
- wrapper {
- background-color: $body-background-color;
- width: 100%;
- }
-
- header {
- margin: 0 auto;
- text-align: left;
- width: 600px;
- }
-
- body {
- background-color: $message-background-color;
- border: 1px solid #000;
- border-radius: 4px;
- margin: 0 auto;
- width: 600px;
- }
-
- footer {
- color: $footer-link-color;
- font-size: 14px;
- text-align: center;
- width: 100%;
- }
-
- td {
- body-container {
- padding: 20px 40px;
- }
- }
-}
-
-.center {
- text-align: center;
-}
-
-#logo {
- border: none;
- outline: none;
- min-height: 88px;
- width: 134px;
-}
-
-#content {
- h2 {
- color: $header-color;
- font-size: 30px;
- font-weight: 400;
- line-height: 34px;
- margin-top: 0;
- }
-
- p {
- color: $body-color;
- font-size: 17px;
- line-height: 24px;
- margin-bottom: 0;
- }
-}
-
-#cta {
- border: 1px solid $cta-color;
- border-radius: 3px;
- display: inline-block;
- margin: 20px 0;
- padding: 12px 24px;
-
- a {
- background-color: $message-background-color;
- color: $cta-color;
- display: inline-block;
- text-decoration: none;
- }
-}
-
-#tanuki {
- padding: 40px 0 0;
-
- img {
- border: none;
- outline: none;
- width: 37px;
- min-height: 36px;
- }
-}
-
-#tagline {
- font-size: 22px;
- font-weight: 100;
- padding: 4px 0 40px;
-}
-
-#social {
- padding: 0 10px 20px;
- width: 600px;
- word-spacing: 20px;
-
- a {
- color: $footer-link-color;
- text-decoration: none;
- }
-}
diff --git a/app/assets/stylesheets/mailers/repository_push_email.scss b/app/assets/stylesheets/mailers/repository_push_email.scss
deleted file mode 100644
index 001994db97..0000000000
--- a/app/assets/stylesheets/mailers/repository_push_email.scss
+++ /dev/null
@@ -1,43 +0,0 @@
-@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";
diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss
index fc3f214aba..c2cd227571 100644
--- a/app/assets/stylesheets/pages/commit.scss
+++ b/app/assets/stylesheets/pages/commit.scss
@@ -26,28 +26,8 @@
.commit-info-row {
margin-bottom: 10px;
-
- &.commit-info-row-header {
- line-height: 34px;
-
- @media (min-width: $screen-sm-min) {
- margin-bottom: 0;
- }
-
- .commit-options-dropdown-caret {
- @media (max-width: $screen-sm) {
- margin-left: 0;
- }
- }
- }
-
.avatar {
@extend .avatar-inline;
- margin-left: 0;
-
- @media (min-width: $screen-sm-min) {
- margin-left: 4px;
- }
}
.commit-committer-link,
.commit-author-link {
@@ -55,6 +35,10 @@
font-weight: bold;
}
+ .time_ago {
+ margin-left: 8px;
+ }
+
.fa-clipboard {
color: $dropdown-title-btn-color;
}
diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss
index 1b389d8352..5e61e61d85 100644
--- a/app/assets/stylesheets/pages/detail_page.scss
+++ b/app/assets/stylesheets/pages/detail_page.scss
@@ -29,6 +29,8 @@
margin-top: 6px;
p {
+ overflow-x: auto;
+
&:last-child {
margin-bottom: 0;
}
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index 22679c764d..8981f070a2 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -23,7 +23,7 @@
.file-title {
@extend .monospace;
- line-height: 35px;
+ line-height: 42px;
padding-top: 7px;
padding-bottom: 7px;
@@ -43,7 +43,7 @@
.editor-file-name {
@extend .monospace;
-
+
float: left;
margin-right: 10px;
}
@@ -59,22 +59,7 @@
}
.encoding-selector,
- .license-selector,
- .gitignore-selector {
+ .license-selector {
display: inline-block;
- vertical-align: top;
- font-family: $regular_font;
- }
-
- .gitignore-selector {
-
- .dropdown {
- line-height: 21px;
- }
-
- .dropdown-menu-toggle {
- vertical-align: top;
- width: 220px;
- }
}
}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 787c387379..1cf3023ecc 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -125,7 +125,7 @@
.right-sidebar {
position: fixed;
- top: $header-height;
+ top: 58px;
bottom: 0;
right: 0;
z-index: 10;
@@ -150,10 +150,6 @@
font-weight: 600;
}
- .light {
- font-weight: normal;
- }
-
.sidebar-collapsed-icon {
display: none;
}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 4e35ca329e..fc9db97132 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -40,6 +40,11 @@
}
}
+.issue-search-form {
+ margin: 0;
+ height: 24px;
+}
+
form.edit-issue {
margin: 0;
}
@@ -91,3 +96,8 @@ form.edit-issue {
.issue-form .select2-container {
width: 250px !important;
}
+
+.issue-closed-by-widget {
+ color: $gl-text-color;
+ margin-left: 52px;
+}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 8046e203a9..c4005ba1e6 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -41,7 +41,7 @@
margin: 0;
margin-left: 20px;
padding: 5px;
- padding-top: 8px;
+ padding-top: 12px;
line-height: 20px;
&.right {
@@ -110,29 +110,6 @@
p:last-child {
margin-bottom: 0;
}
-
- @media (max-width: $screen-sm-max) {
- h4 {
- font-size: 15px;
- }
-
- p {
- font-size: 13px;
- }
-
- .btn,
- .btn-group,
- .accept-action {
- width: 100%;
- margin-bottom: 4px;
- }
-
- .accept-control {
- width: 100%;
- text-align: center;
- margin: 0;
- }
- }
}
.mr-widget-footer {
@@ -303,5 +280,11 @@
background-color: $white-light;
color: $gl-placeholder-color;
}
+
+ th,
+ td {
+ padding: 16px;
+ }
}
}
+
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index a3e1ac13a4..624c8249f7 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -226,7 +226,8 @@ ul.notes {
}
}
-.note-action-button {
+.note-action-button,
+.discussion-action-button {
display: inline-block;
margin-left: 10px;
line-height: 24px;
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
deleted file mode 100644
index 6128868b67..0000000000
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ /dev/null
@@ -1,24 +0,0 @@
-.pipelines {
- .stage {
- max-width: 100px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- .duration, .finished_at {
- margin: 4px 0;
- }
-
- .commit-title {
- margin: 0;
- }
-
- .controls {
- white-space: nowrap;
- }
-
- .btn {
- margin: 4px;
- }
-}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 167ab40d88..abc5a0e987 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -66,6 +66,12 @@
}
}
+.calendar-hint {
+ margin-top: -12px;
+ float: right;
+ font-size: 12px;
+}
+
.profile-link-holder {
display: inline;
@@ -128,6 +134,14 @@
}
}
+.change-username-title {
+ color: $gl-warning;
+}
+
+.remove-account-title {
+ color: $gl-danger;
+}
+
.provider-btn-group {
display: inline-block;
margin-right: 10px;
@@ -204,7 +218,7 @@
.btn {
display: inline-block;
- width: 46%;
+ width: 48%;
}
}
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index edef336481..c20f04653f 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -7,10 +7,10 @@
}
.no-ssh-key-message, .project-limit-message {
background-color: #f28d35;
- margin-bottom: 0;
+ margin-bottom: 16px;
}
.new_project,
-.edit-project {
+.edit_project {
fieldset.features {
.control-label {
font-weight: normal;
@@ -26,13 +26,8 @@
}
.project-home-panel {
- background: $white-light;
- text-align: left;
- padding: 24px 0;
-
- .container-fluid {
- position: relative;
- }
+ padding-bottom: 40px;
+ border-bottom: 1px solid $border-color;
.cover-controls {
.project-settings-dropdown {
@@ -48,55 +43,21 @@
}
}
- .cover-title {
- margin-bottom: 0;
- }
+ .project-identicon-holder {
+ margin-bottom: 16px;
- .project-image-container {
- @include make-sm-column(1);
- max-width: 86px;
- min-width: 86px;
- padding-right: 0;
- margin: 11px 0;
-
- @media (max-width: $screen-md-max) {
- padding-left: 0;
- margin: 0 0 10px;
- max-width: none;
- min-width: none;
-
- .avatar.s70 {
- margin: auto;
- }
- }
- }
-
- .project-info {
- @include make-sm-column(10);
-
- h1 {
- font-size: 24px;
- font-weight: normal;
- margin: 0;
+ .avatar, .identicon {
+ margin: 0 auto;
+ float: none;
}
- .project-home-desc {
- p {
- margin: 0;
- }
+ .identicon {
+ @include border-radius(50%);
}
}
- .identicon {
- float: left;
- @include border-radius(50%);
- }
-
- .avatar {
- float: none;
- }
-
.notifications-btn {
+ margin-top: -28px;
.fa-bell {
margin-right: 6px;
@@ -108,45 +69,28 @@
}
.project-repo-buttons {
- font-size: 0;
+ margin-top: 20px;
+ margin-bottom: 0;
+
+ .count-buttons {
+ display: block;
+ margin-bottom: 20px;
+ }
+
+ .clone-row {
+ .split-repo-buttons,
+ .project-clone-holder {
+ display: inline-block;
+ }
+
+ .split-repo-buttons {
+ margin: 0 12px;
+ }
+ }
.btn {
@include btn-gray;
- padding: 3px 10px;
text-transform: none;
- background-color: $background-color;
-
- .fa {
- color: $layout-link-gray;
- }
-
- .fa-caret-down {
- margin-left: 3px;
- }
- }
-
- .btn-group:not(:first-child):not(:last-child) > .btn {
- border-top-right-radius: 3px;
- border-bottom-right-radius: 3px;
- }
-
- form {
- margin-left: 10px;
- }
-
- .count-buttons {
- display: inline-block;
- vertical-align: top;
- margin-top: 16px;
- }
-
- .project-clone-holder {
- display: inline-block;
- margin-top: 16px;
-
- input {
- height: 29px;
- }
}
.count-with-arrow {
@@ -196,18 +140,14 @@
line-height: 13px;
padding: $gl-vert-padding $gl-padding;
letter-spacing: .4px;
- padding: 7px 14px;
+ padding: 10px 14px;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
white-space: nowrap;
- margin: 0 10px 0 4px;
-
- a {
- color: inherit;
- }
+ margin: 0 11px 0 4px;
&:hover {
background: #fff;
@@ -215,37 +155,13 @@
}
}
}
-
- .project-right-buttons {
- position: absolute;
- right: 16px;
- bottom: 0;
-
- .btn {
- padding: 3px 10px;
- background-color: $background-color;
- }
-
- @media (max-width: 1304px) {
- top: 0;
- }
- }
-
- @media (max-width: $screen-md-max) {
- text-align: center;
-
- .project-info,
- .project-image-container {
- width: 100%;
- }
- }
}
.split-one {
display: inline-table;
margin-right: 12px;
- > a {
+ a {
margin: -1px;
}
}
@@ -369,11 +285,11 @@ a.deploy-project-label {
}
.project-stats {
+ text-align: center;
margin-top: $gl-padding;
margin-bottom: 0;
- padding: 16px 0;
- background-color: $white-light;
- font-size: 0;
+ padding-top: 10px;
+ padding-bottom: 4px;
ul.nav {
display: inline-block;
@@ -384,11 +300,12 @@ a.deploy-project-label {
}
.nav > li > a {
+ @include btn-default;
+ @include btn-gray;
+
background-color: transparent;
- margin-right: 12px;
- padding: 0 10px;
- font-size: 15px;
- color: $notes-light-color;
+ border: 1px solid #f7f8fa;
+ margin-left: 12px;
}
li {
@@ -408,10 +325,6 @@ a.deploy-project-label {
background-color: #f0f2f5;
}
}
-
- &.row-content-block.second-block {
- margin-top: 0;
- }
}
pre.light-well {
@@ -529,14 +442,9 @@ pre.light-well {
border-top: 0;
.edit-project-readme {
- z-index: 2;
+ z-index: 100;
position: relative;
}
-
- .wiki h1 {
- border-bottom: none;
- padding: 0;
- }
}
.git-clone-holder {
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index 037ad52054..2bff70c8c6 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -28,7 +28,6 @@
}
.search-input {
- padding-right: 20px;
border: none;
font-size: 14px;
outline: none;
@@ -48,7 +47,6 @@
display: inline-block;
background-color: $location-badge-bg;
vertical-align: top;
- cursor: default;
}
.search-input-container {
@@ -57,7 +55,7 @@
position: relative;
}
- .search-input-wrap {
+ .search-location-badge, .search-input-wrap {
// Fallback if flexbox is not supported
display: inline-block;
}
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index 2e8f356298..3fb7008571 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -12,11 +12,3 @@
border: 1px solid $warning-message-border;
border-radius: $border-radius-base;
}
-
-.warning-title {
- color: $gl-warning;
-}
-
-.danger-title {
- color: $gl-danger;
-}
diff --git a/app/assets/stylesheets/pages/snippets.scss b/app/assets/stylesheets/pages/snippets.scss
index 2aa939b7dc..639d639d5b 100644
--- a/app/assets/stylesheets/pages/snippets.scss
+++ b/app/assets/stylesheets/pages/snippets.scss
@@ -16,6 +16,19 @@
}
}
+.snippet-box {
+ @include border-radius(2px);
+
+ display: block;
+ float: left;
+ padding: 0 $gl-padding;
+ font-weight: normal;
+ margin-right: 10px;
+ font-size: $gl-font-size;
+ border: 1px solid;
+ line-height: 32px;
+}
+
.markdown-snippet-copy {
position: fixed;
top: -10px;
@@ -23,34 +36,3 @@
max-height: 0;
max-width: 0;
}
-
-.file-holder.snippet-file-content {
- padding-bottom: $gl-padding;
- border-bottom: 1px solid $border-color;
-
- .file-title {
- padding-top: $gl-padding;
- padding-bottom: $gl-padding;
- }
-
- .file-actions {
- top: 12px;
- }
-
- .file-content {
- border-left: 1px solid $border-color;
- border-right: 1px solid $border-color;
- border-bottom: 1px solid $border-color;
- }
-}
-
-.snippet-title {
- font-size: 24px;
- font-weight: normal;
-}
-
-.snippet-actions {
- @media (min-width: $screen-sm-min) {
- float: right;
- }
-}
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index afc00a6857..e51c3491da 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -29,17 +29,6 @@
.todo-item {
.todo-title {
@include str-truncated(calc(100% - 174px));
- overflow: visible;
- }
-
- .status-box {
- margin: 0;
- float: none;
- display: inline-block;
- font-weight: normal;
- padding: 0 5px;
- line-height: inherit;
- font-size: 14px;
}
.todo-body {
@@ -87,11 +76,12 @@
@media (max-width: $screen-xs-max) {
.todo-item {
+ padding-left: $gl-padding;
+
.todo-title {
white-space: normal;
overflow: visible;
max-width: 100%;
- margin-bottom: 10px;
}
.avatar {
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index f16fc7f388..a84fc2e031 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -15,23 +15,16 @@
margin-bottom: 0;
tr {
- border-bottom: 1px solid $table-border-gray;
- border-top: 1px solid $table-border-gray;
-
- td, th {
+ > td, > th {
line-height: 23px;
}
&:hover {
- cursor: pointer;
-
td {
- background-color: $row-hover;
- border-top: 1px solid $row-hover-border;
- border-bottom: 1px solid $row-hover-border;
+ background: $row-hover;
}
+ cursor: pointer;
}
-
&.selected {
td {
background: $gray-dark;
diff --git a/app/controllers/admin/abuse_reports_controller.rb b/app/controllers/admin/abuse_reports_controller.rb
index 5055c318a5..e9b0972bdd 100644
--- a/app/controllers/admin/abuse_reports_controller.rb
+++ b/app/controllers/admin/abuse_reports_controller.rb
@@ -9,6 +9,6 @@ class Admin::AbuseReportsController < Admin::ApplicationController
abuse_report.remove_user(deleted_by: current_user) if params[:remove_user]
abuse_report.destroy
- head :ok
+ render nothing: true
end
end
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 0a34a12e2a..ec22548dde 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -19,12 +19,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
redirect_to admin_runners_path
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
RepositoryCheck::ClearWorker.perform_async
@@ -59,12 +53,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
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(
:default_projects_limit,
:default_branch_protection,
@@ -106,11 +94,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:email_author_in_body,
:repository_checks_enabled,
:metrics_packet_size,
- :send_user_confirmation_email,
- :container_registry_token_expire_delay,
restricted_visibility_levels: [],
- import_sources: [],
- disabled_oauth_sign_in_sources: []
+ import_sources: []
)
end
end
diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb
index 82055006ac..fc34292498 100644
--- a/app/controllers/admin/broadcast_messages_controller.rb
+++ b/app/controllers/admin/broadcast_messages_controller.rb
@@ -32,7 +32,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
respond_to do |format|
format.html { redirect_back_or_default(default: { action: 'index' }) }
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
diff --git a/app/controllers/admin/health_check_controller.rb b/app/controllers/admin/health_check_controller.rb
deleted file mode 100644
index 241c7be0ea..0000000000
--- a/app/controllers/admin/health_check_controller.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class Admin::HealthCheckController < Admin::ApplicationController
- def show
- @errors = HealthCheck::Utils.process_checks('standard')
- end
-end
diff --git a/app/controllers/admin/keys_controller.rb b/app/controllers/admin/keys_controller.rb
index 054bb52b69..cb33fdd976 100644
--- a/app/controllers/admin/keys_controller.rb
+++ b/app/controllers/admin/keys_controller.rb
@@ -6,7 +6,7 @@ class Admin::KeysController < Admin::ApplicationController
respond_to do |format|
format.html
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
index 7345c91f67..a701d49b84 100644
--- a/app/controllers/admin/runners_controller.rb
+++ b/app/controllers/admin/runners_controller.rb
@@ -9,18 +9,23 @@ class Admin::RunnersController < Admin::ApplicationController
end
def show
- 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
def update
- if @runner.update_attributes(runner_params)
- respond_to do |format|
- format.js
- format.html { redirect_to admin_runner_path(@runner) }
- end
- else
- assign_builds_and_projects
- render 'show'
+ @runner.update_attributes(runner_params)
+
+ respond_to do |format|
+ format.js
+ format.html { redirect_to admin_runner_path(@runner) }
end
end
@@ -53,18 +58,6 @@ class Admin::RunnersController < Admin::ApplicationController
end
def runner_params
- 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)
+ params.require(:runner).permit(:token, :description, :tag_list, :active)
end
end
diff --git a/app/controllers/admin/spam_logs_controller.rb b/app/controllers/admin/spam_logs_controller.rb
index 3a2f018531..377e9741e5 100644
--- a/app/controllers/admin/spam_logs_controller.rb
+++ b/app/controllers/admin/spam_logs_controller.rb
@@ -11,7 +11,7 @@ class Admin::SpamLogsController < Admin::ApplicationController
redirect_to admin_spam_logs_path, notice: "User #{spam_log.user.username} was successfully removed."
else
spam_log.destroy
- head :ok
+ render nothing: true
end
end
end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index f35f4a8c81..f2f654c7bc 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -119,7 +119,6 @@ class Admin::UsersController < Admin::ApplicationController
user_params_with_pass.merge!(
password: params[:user][:password],
password_confirmation: params[:user][:password_confirmation],
- password_expires_at: Time.now
)
end
@@ -154,7 +153,7 @@ class Admin::UsersController < Admin::ApplicationController
respond_to do |format|
format.html { redirect_back_or_admin_user(notice: "Successfully removed email.") }
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index c28d1ca9e3..17b3f49aed 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -176,7 +176,7 @@ class ApplicationController < ActionController::Base
end
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
end
end
@@ -232,7 +232,7 @@ class ApplicationController < ActionController::Base
end
def configure_permitted_parameters
- devise_parameter_sanitizer.permit(:sign_in, keys: [:username, :email, :password, :login, :remember_me, :otp_attempt])
+ devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password, :login, :remember_me, :otp_attempt) }
end
def hexdigest(string)
@@ -263,7 +263,7 @@ class ApplicationController < ActionController::Base
# internal repos where you are not a member. Enable this filter
# or improve current implementation to filter only issues you
# created or assigned or mentioned
- # @filter_params[:authorized_only] = true
+ #@filter_params[:authorized_only] = true
end
@filter_params
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 3865b2d61f..eb0abc80ab 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -31,24 +31,6 @@ class AutocompleteController < ApplicationController
render json: @user, only: [:name, :username, :id], methods: [:avatar_url]
end
- def projects
- project = Project.find_by_id(params[:project_id])
-
- projects = current_user.authorized_projects
- projects = projects.select do |project|
- current_user.can?(:admin_issue, project)
- end
-
- no_project = {
- id: 0,
- name_with_namespace: 'No project',
- }
- projects.unshift(no_project)
- projects.delete(project)
-
- render json: projects.to_json(only: [:id, :name_with_namespace], methods: :name_with_namespace)
- end
-
private
def find_users
diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb
index dacb5679dd..787416c17a 100644
--- a/app/controllers/concerns/creates_commit.rb
+++ b/app/controllers/concerns/creates_commit.rb
@@ -122,7 +122,7 @@ module CreatesCommit
# Merge request from fork to this project
@mr_source_project = @tree_edit_project
@mr_target_project = @project
- @mr_target_branch ||= @ref
+ @mr_target_branch ||= @ref
end
end
end
diff --git a/app/controllers/concerns/toggle_subscription_action.rb b/app/controllers/concerns/toggle_subscription_action.rb
index 9e3b9be2ff..8a43c0b93c 100644
--- a/app/controllers/concerns/toggle_subscription_action.rb
+++ b/app/controllers/concerns/toggle_subscription_action.rb
@@ -6,7 +6,7 @@ module ToggleSubscriptionAction
subscribable_resource.toggle_subscription(current_user)
- head :ok
+ render nothing: true
end
private
diff --git a/app/controllers/dashboard/labels_controller.rb b/app/controllers/dashboard/labels_controller.rb
index 2a88350a4c..23a4ef21ea 100644
--- a/app/controllers/dashboard/labels_controller.rb
+++ b/app/controllers/dashboard/labels_controller.rb
@@ -1,6 +1,6 @@
class Dashboard::LabelsController < Dashboard::ApplicationController
def index
- labels = Label.where(project_id: projects).select(:id, :title, :color).uniq(:title)
+ labels = Label.where(project_id: projects).select(:title, :color).uniq(:title)
respond_to do |format|
format.json { render json: labels }
diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
index c08eb81153..71acc244a9 100644
--- a/app/controllers/dashboard/projects_controller.rb
+++ b/app/controllers/dashboard/projects_controller.rb
@@ -28,7 +28,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
end
def starred
- @projects = current_user.viewable_starred_projects.sorted_by_activity
+ @projects = current_user.starred_projects.sorted_by_activity
@projects = filter_projects(@projects)
@projects = @projects.includes(:namespace, :forked_from_project, :tags)
@projects = @projects.sort(@sort = params[:sort])
diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb
index f9a1929c11..5abf97342c 100644
--- a/app/controllers/dashboard/todos_controller.rb
+++ b/app/controllers/dashboard/todos_controller.rb
@@ -12,7 +12,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
respond_to do |format|
format.html { redirect_to dashboard_todos_path, notice: todo_notice }
- format.js { head :ok }
+ format.js { render nothing: true }
format.json do
render json: { count: @todos.size, done_count: current_user.todos.done.count }
end
@@ -24,7 +24,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
respond_to do |format|
format.html { redirect_to dashboard_todos_path, notice: 'All todos were marked as done.' }
- format.js { head :ok }
+ format.js { render nothing: true }
format.json do
find_todos
render json: { count: @todos.size, done_count: current_user.todos.done.count }
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 4dda4e51f6..1dce4a2172 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -25,7 +25,7 @@ class DashboardController < Dashboard::ApplicationController
def load_events
projects =
if params[:filter] == "starred"
- current_user.viewable_starred_projects
+ current_user.starred_projects
else
current_user.authorized_projects
end
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index 48dbf656e8..d5ef33888c 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -40,7 +40,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
respond_to do |format|
format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' }
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
diff --git a/app/controllers/health_check_controller.rb b/app/controllers/health_check_controller.rb
deleted file mode 100644
index 037da7d2bc..0000000000
--- a/app/controllers/health_check_controller.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-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
diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb
deleted file mode 100644
index cee3b6c43e..0000000000
--- a/app/controllers/jwt_controller.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-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, :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
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index f35d631df0..df98f56a1c 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -97,7 +97,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
handle_signup_error
end
- def handle_service_ticket(provider, ticket)
+ def handle_service_ticket provider, ticket
Gitlab::OAuth::Session.create provider, ticket
session[:service_tickets] ||= {}
session[:service_tickets][provider] = ticket
diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb
index 1c24c4db99..0ede9b8e21 100644
--- a/app/controllers/profiles/emails_controller.rb
+++ b/app/controllers/profiles/emails_controller.rb
@@ -24,7 +24,7 @@ class Profiles::EmailsController < Profiles::ApplicationController
respond_to do |format|
format.html { redirect_to profile_emails_url }
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb
index 830e0b9591..a12549d6bc 100644
--- a/app/controllers/profiles/keys_controller.rb
+++ b/app/controllers/profiles/keys_controller.rb
@@ -32,7 +32,7 @@ class Profiles::KeysController < Profiles::ApplicationController
respond_to do |format|
format.html { redirect_to profile_keys_url }
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 776ba92c9a..be872a93fe 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -26,7 +26,7 @@ class Projects::ApplicationController < ApplicationController
project_path = "#{namespace}/#{id}"
@project = Project.find_with_namespace(project_path)
- if can?(current_user, :read_project, @project) && !@project.pending_delete?
+ if @project && can?(current_user, :read_project, @project)
if @project.path_with_namespace != project_path
redirect_to request.original_url.gsub(project_path, @project.path_with_namespace)
end
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index dd9508da04..d09e7375b6 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -50,7 +50,7 @@ class Projects::BranchesController < Projects::ApplicationController
redirect_to namespace_project_branches_path(@project.namespace,
@project), status: 303
end
- format.js { render nothing: true, status: status[:return_code] }
+ format.js { render status: status[:return_code] }
end
end
diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb
index bb1f6c5e98..b8b9e78427 100644
--- a/app/controllers/projects/builds_controller.rb
+++ b/app/controllers/projects/builds_controller.rb
@@ -38,14 +38,6 @@ class Projects::BuildsController < Projects::ApplicationController
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
unless @build.retryable?
return render_404
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 10b5932aff..a202cb3869 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -17,12 +17,12 @@ class Projects::CommitController < Projects::ApplicationController
def show
apply_diff_view_cookie!
- @grouped_diff_notes = commit.notes.grouped_diff_notes
-
+ @line_notes = commit.notes.inline
@note = @project.build_commit_note(commit)
- @notes = commit.notes.non_diff_notes.fresh
+ @notes = commit.notes.not_inline.fresh
@noteable = @commit
- @comments_target = {
+ @comments_allowed = @reply_allowed = true
+ @comments_target = {
noteable_type: 'Commit',
commit_id: @commit.id
}
@@ -67,10 +67,10 @@ class Projects::CommitController < Projects::ApplicationController
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)
end
-
+
def cherry_pick
assign_change_commit_vars(@commit.cherry_pick_branch_name)
-
+
return render_404 if @target_branch.blank?
create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title} has been successfully cherry-picked.",
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index af0b69a244..671d5c2302 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -22,8 +22,7 @@ class Projects::CompareController < Projects::ApplicationController
@base_commit = @project.merge_base_commit(@base_ref, @head_ref)
@diffs = compare.diffs(diff_options)
@diff_refs = [@base_commit, @commit]
- @diff_notes_disabled = true
- @grouped_diff_notes = {}
+ @line_notes = []
end
end
diff --git a/app/controllers/projects/container_registry_controller.rb b/app/controllers/projects/container_registry_controller.rb
deleted file mode 100644
index d1f4649720..0000000000
--- a/app/controllers/projects/container_registry_controller.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-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
diff --git a/app/controllers/projects/find_file_controller.rb b/app/controllers/projects/find_file_controller.rb
index cf53ad0a67..54a0c447ae 100644
--- a/app/controllers/projects/find_file_controller.rb
+++ b/app/controllers/projects/find_file_controller.rb
@@ -1,26 +1,26 @@
-# Controller for viewing a repository's file structure
-class Projects::FindFileController < Projects::ApplicationController
- include ExtractsPath
- include ActionView::Helpers::SanitizeHelper
- include TreeHelper
-
- before_action :require_non_empty_project
- before_action :assign_ref_vars
- before_action :authorize_download_code!
-
- def show
- return render_404 unless @repository.commit(@ref)
-
- respond_to do |format|
- format.html
- end
- end
-
- def list
- file_paths = @repo.ls_files(@ref)
-
- respond_to do |format|
- format.json { render json: file_paths }
- end
- end
-end
+# Controller for viewing a repository's file structure
+class Projects::FindFileController < Projects::ApplicationController
+ include ExtractsPath
+ include ActionView::Helpers::SanitizeHelper
+ include TreeHelper
+
+ before_action :require_non_empty_project
+ before_action :assign_ref_vars
+ before_action :authorize_download_code!
+
+ def show
+ return render_404 unless @repository.commit(@ref)
+
+ respond_to do |format|
+ format.html
+ end
+ end
+
+ def list
+ file_paths = @repo.ls_files(@ref)
+
+ respond_to do |format|
+ format.json { render json: file_paths }
+ end
+ end
+end
diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index a60027ff47..dfa9bd259e 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -27,10 +27,8 @@ class Projects::HooksController < Projects::ApplicationController
if !@project.empty_repo?
status, message = TestHookService.new.execute(hook, current_user)
- if status && status >= 200 && status < 400
- flash[:notice] = "Hook executed successfully: HTTP #{status}"
- elsif status
- flash[:alert] = "Hook executed successfully but returned HTTP #{status} #{message}"
+ if status
+ flash[:notice] = 'Hook successfully executed.'
else
flash[:alert] = "Hook execution failed: #{message}"
end
@@ -63,8 +61,7 @@ class Projects::HooksController < Projects::ApplicationController
:push_events,
:tag_push_events,
:token,
- :url,
- :wiki_page_events
+ :url
)
end
end
diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb
index a1b84afcd9..7756f0f0ed 100644
--- a/app/controllers/projects/imports_controller.rb
+++ b/app/controllers/projects/imports_controller.rb
@@ -20,7 +20,6 @@ class Projects::ImportsController < Projects::ApplicationController
@project.import_retry
else
@project.import_start
- @project.add_import_job
end
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index d54284d7b2..9c147b3689 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -73,12 +73,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController
# but we need it for the "View file @ ..." link by deleted files
@base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit
+ @comments_allowed = @reply_allowed = true
@comments_target = {
noteable_type: 'MergeRequest',
noteable_id: @merge_request.id
}
-
- @grouped_diff_notes = @merge_request.notes.grouped_diff_notes
+ @line_notes = @merge_request.notes.where("line_code is not null")
respond_to do |format|
format.html
@@ -117,7 +117,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@commit = @merge_request.last_commit
@base_commit = @merge_request.diff_base_commit
@diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare
- @diff_notes_disabled = true
@ci_commit = @merge_request.ci_commit
@statuses = @ci_commit.statuses if @ci_commit
@@ -205,7 +204,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def branch_from
- # This is always source
+ #This is always source
@source_project = @merge_request.nil? ? @project : @merge_request.source_project
@commit = @repository.commit(params[:ref]) if params[:ref].present?
render layout: false
@@ -229,8 +228,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
if ci_commit
status = ci_commit.status
coverage = ci_commit.try(:coverage)
-
- status ||= "preparing"
else
ci_service = @merge_request.source_project.ci_service
status = ci_service.commit_status(merge_request.last_commit.sha, merge_request.source_branch) if ci_service
@@ -240,6 +237,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
end
+ status = "preparing" if status.nil?
+
response = {
title: merge_request.title,
sha: merge_request.last_commit_short_sha,
@@ -301,7 +300,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
# Build a note object for comment form
@note = @project.notes.new(noteable: @merge_request)
@notes = @merge_request.mr_and_commit_notes.nonawards.inc_author.fresh
- @discussions = @notes.discussions
+ @discussions = Note.discussions_from_notes(@notes)
@noteable = @merge_request
# Get commits from repository
@@ -334,8 +333,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
params.require(:merge_request).permit(
:title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id,
- :state_event, :description, :task_num, :force_remove_source_branch,
- label_ids: []
+ :state_event, :description, :task_num, label_ids: []
)
end
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index da2892bfb3..f7b6d137bd 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -75,7 +75,7 @@ class Projects::MilestonesController < Projects::ApplicationController
respond_to do |format|
format.html { redirect_to namespace_project_milestones_path }
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index 40b24d550e..707a0d0e5c 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -43,7 +43,7 @@ class Projects::NotesController < Projects::ApplicationController
end
respond_to do |format|
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
@@ -52,7 +52,7 @@ class Projects::NotesController < Projects::ApplicationController
note.update_attribute(:attachment, nil)
respond_to do |format|
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
@@ -96,7 +96,7 @@ class Projects::NotesController < Projects::ApplicationController
end
def note_to_discussion_html(note)
- return unless note.diff_note?
+ return unless note.for_diff_line?
if params[:view] == 'parallel'
template = "projects/notes/_diff_notes_with_reply_parallel"
@@ -120,7 +120,7 @@ class Projects::NotesController < Projects::ApplicationController
end
def note_to_discussion_with_diff_html(note)
- return unless note.diff_note?
+ return unless note.for_diff_line?
render_to_string(
"projects/notes/_discussion",
@@ -158,7 +158,7 @@ class Projects::NotesController < Projects::ApplicationController
def note_params
params.require(:note).permit(
:note, :noteable, :noteable_id, :noteable_type, :project_id,
- :attachment, :line_code, :commit_id, :type
+ :attachment, :line_code, :commit_id
)
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
deleted file mode 100644
index b36081205d..0000000000
--- a/app/controllers/projects/pipelines_controller.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-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
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
index cdea5f0b77..33b2625c0a 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -55,7 +55,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
format.html do
redirect_to namespace_project_project_members_path(@project.namespace, @project)
end
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
@@ -81,7 +81,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
respond_to do |format|
format.html { redirect_to dashboard_projects_path, notice: "You left the project." }
- format.js { head :ok }
+ format.js { render nothing: true }
end
else
if current_user == @project.owner
diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb
index efa7bf14d0..e49259c34b 100644
--- a/app/controllers/projects/protected_branches_controller.rb
+++ b/app/controllers/projects/protected_branches_controller.rb
@@ -39,7 +39,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
respond_to do |format|
format.html { redirect_to namespace_project_protected_branches_path }
- format.js { head :ok }
+ format.js { render nothing: true }
end
end
diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb
index 0b4fa57250..0dd2d6a99b 100644
--- a/app/controllers/projects/runners_controller.rb
+++ b/app/controllers/projects/runners_controller.rb
@@ -20,7 +20,7 @@ class Projects::RunnersController < Projects::ApplicationController
if @runner.update_attributes(runner_params)
redirect_to runner_path(@runner), notice: 'Runner was successfully updated.'
else
- render 'edit'
+ redirect_to runner_path(@runner), alert: 'Runner was not updated.'
end
end
@@ -64,6 +64,6 @@ class Projects::RunnersController < Projects::ApplicationController
end
def runner_params
- params.require(:runner).permit(Ci::Runner::FORM_EDITABLE)
+ params.require(:runner).permit(:description, :tag_list, :active)
end
end
diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb
index 6f06872939..0023465457 100644
--- a/app/controllers/projects/variables_controller.rb
+++ b/app/controllers/projects/variables_controller.rb
@@ -3,44 +3,20 @@ class Projects::VariablesController < Projects::ApplicationController
layout 'project_settings'
- def index
- @variable = Ci::Variable.new
- end
-
def show
- @variable = @project.variables.find(params[:id])
end
def update
- @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
+ if project.update_attributes(project_params)
redirect_to namespace_project_variables_path(project.namespace, project), notice: 'Variables were successfully updated.'
else
- render action: "index"
+ render action: 'show'
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
def project_params
- params.require(:variable).permit([:id, :key, :value, :_destroy])
+ params.require(:project).permit({ variables_attributes: [:id, :key, :value, :_destroy] })
end
end
diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb
index 4b404eb03f..0d6c32fabd 100644
--- a/app/controllers/projects/wikis_controller.rb
+++ b/app/controllers/projects/wikis_controller.rb
@@ -91,8 +91,8 @@ class Projects::WikisController < Projects::ApplicationController
def markdown_preview
text = params[:text]
- ext = Gitlab::ReferenceExtractor.new(@project, current_user)
- ext.analyze(text, author: current_user)
+ ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user)
+ ext.analyze(text)
render json: {
body: view_context.markdown(text, pipeline: :wiki, project_wiki: @project_wiki),
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index f94e2a84fa..3768efe142 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -101,7 +101,13 @@ class ProjectsController < Projects::ApplicationController
respond_to do |format|
format.html do
- @notification_setting = current_user.notification_settings_for(@project) if current_user
+ 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.empty_repo?
@@ -141,7 +147,6 @@ class ProjectsController < Projects::ApplicationController
@suggestions = {
emojis: AwardEmoji.urls,
issues: autocomplete.issues,
- milestones: autocomplete.milestones,
mergerequests: autocomplete.merge_requests,
members: participants
}
@@ -197,8 +202,8 @@ class ProjectsController < Projects::ApplicationController
def markdown_preview
text = params[:text]
- ext = Gitlab::ReferenceExtractor.new(@project, current_user)
- ext.analyze(text, author: current_user)
+ ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user)
+ ext.analyze(text)
render json: {
body: view_context.markdown(text),
@@ -230,8 +235,7 @@ class ProjectsController < Projects::ApplicationController
def project_params
params.require(:project).permit(
:name, :path, :description, :issues_tracker, :tag_list, :runners_token,
- :issues_enabled, :merge_requests_enabled, :snippets_enabled, :container_registry_enabled,
- :issues_tracker_id, :default_branch,
+ :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch,
: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,
:public_builds,
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 75b78a49ea..352bff1938 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -37,8 +37,8 @@ class RegistrationsController < Devise::RegistrationsController
super
end
- def after_sign_up_path_for(user)
- user.confirmed? ? dashboard_projects_path : users_almost_there_path
+ def after_sign_up_path_for(_resource)
+ users_almost_there_path
end
def after_inactive_sign_up_path_for(_resource)
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index d68c2a708e..c29f4609e9 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -1,6 +1,5 @@
class SessionsController < Devise::SessionsController
include AuthenticatesWithTwoFactor
- include Devise::Controllers::Rememberable
include Recaptcha::ClientHelper
skip_before_action :check_2fa_requirement, only: [:destroy]
@@ -97,7 +96,6 @@ class SessionsController < Devise::SessionsController
# Remove any lingering user data from login
session.delete(:otp_user_id)
- remember_me(user) if user_params[:remember_me] == '1'
sign_in(user) and return
else
flash.now[:alert] = 'Invalid two-factor code.'
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index 2a17c1f34d..2daceed039 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -10,7 +10,7 @@ class SnippetsController < ApplicationController
# Allow destroy snippet
before_action :authorize_admin_snippet!, only: [:destroy]
- skip_before_action :authenticate_user!, only: [:index, :show, :raw]
+ skip_before_action :authenticate_user!, only: [:index, :user_index, :show, :raw]
layout 'snippets'
respond_to :html
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index a99632454d..2ae180c8a1 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -58,22 +58,11 @@ class UsersController < ApplicationController
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
calendar = contributions_calendar
@timestamps = calendar.timestamps
+ @starting_year = calendar.starting_year
+ @starting_month = calendar.starting_month
render 'calendar', layout: false
end
@@ -127,15 +116,6 @@ class UsersController < ApplicationController
@groups = JoinedGroupsFinder.new(user).execute(current_user)
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
ProjectsFinder.new.execute(current_user)
end
diff --git a/app/finders/group_projects_finder.rb b/app/finders/group_projects_finder.rb
index aa8f4c1d0e..3b9a421b11 100644
--- a/app/finders/group_projects_finder.rb
+++ b/app/finders/group_projects_finder.rb
@@ -18,7 +18,7 @@ class GroupProjectsFinder < UnionFinder
projects = []
if current_user
- if @group.users.include?(current_user) || current_user.admin?
+ if @group.users.include?(current_user)
projects << @group.projects unless only_shared
projects << @group.shared_projects unless only_owned
else
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 7d8c56f4c2..f00f3f709e 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -250,12 +250,12 @@ class IssuableFinder
def by_milestone(items)
if milestones?
if filter_by_no_milestone?
- items = items.left_joins_milestones.where(milestone_id: [-1, nil])
+ items = items.where(milestone_id: [-1, nil])
elsif filter_by_upcoming_milestone?
- upcoming_ids = Milestone.upcoming_ids_by_projects(projects)
- items = items.left_joins_milestones.where(milestone_id: upcoming_ids)
+ upcoming = Milestone.where(project_id: projects).upcoming
+ items = items.joins(:milestone).where(milestones: { title: upcoming.try(:title) })
else
- items = items.with_milestone(params[:milestone_title])
+ items = items.joins(:milestone).where(milestones: { title: params[:milestone_title] })
if projects
items = items.where(milestones: { project_id: projects })
@@ -271,7 +271,7 @@ class IssuableFinder
if filter_by_no_label?
items = items.without_label
else
- items = items.with_label(label_names, params[:sort])
+ items = items.with_label(label_names)
if projects
items = items.where(labels: { project_id: projects })
end
diff --git a/app/finders/notes_finder.rb b/app/finders/notes_finder.rb
index c41be33353..fa4c635f55 100644
--- a/app/finders/notes_finder.rb
+++ b/app/finders/notes_finder.rb
@@ -10,7 +10,7 @@ class NotesFinder
notes =
case target_type
when "commit"
- project.notes.for_commit_id(target_id).non_diff_notes
+ project.notes.for_commit_id(target_id).not_inline
when "issue"
project.issues.find(target_id).notes.nonawards.inc_author
when "merge_request"
diff --git a/app/finders/pipelines_finder.rb b/app/finders/pipelines_finder.rb
deleted file mode 100644
index c19a795d46..0000000000
--- a/app/finders/pipelines_finder.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-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
diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb
index 4bd46a7608..3ba27c4050 100644
--- a/app/finders/todos_finder.rb
+++ b/app/finders/todos_finder.rb
@@ -36,7 +36,7 @@ class TodosFinder
private
def action_id?
- action_id.present? && [Todo::ASSIGNED, Todo::MENTIONED, Todo::BUILD_FAILED].include?(action_id.to_i)
+ action_id.present? && [Todo::ASSIGNED, Todo::MENTIONED].include?(action_id.to_i)
end
def action_id
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 439b015b3b..3e0074da39 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -110,7 +110,8 @@ module ApplicationHelper
]
# If reference is commit id - we should add it to branch/tag selectbox
- if @ref && !options.flatten.include?(@ref) && @ref =~ /\A[0-9a-zA-Z]{6,52}\z/
+ if(@ref && !options.flatten.include?(@ref) &&
+ @ref =~ /\A[0-9a-zA-Z]{6,52}\z/)
options << ['Commit', [@ref]]
end
@@ -262,8 +263,6 @@ module ApplicationHelper
assignee_id: params[:assignee_id],
author_id: params[:author_id],
sort: params[:sort],
- issue_search: params[:issue_search],
- label_name: params[:label_name]
}
options = exist_opts.merge(options)
@@ -274,11 +273,16 @@ module ApplicationHelper
end
end
- params = options.compact
-
- params.delete(:label_name) unless add_label
-
- "#{request.path}?#{params.to_param}"
+ path = request.path
+ path << "?#{options.to_param}"
+ if add_label
+ if params[:label_name].present? and params[:label_name].respond_to?('any?')
+ params[:label_name].each do |label|
+ path << "&label_name[]=#{label}"
+ end
+ end
+ end
+ path
end
def outdated_browser?
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 03080d2593..914b0ef604 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -60,18 +60,4 @@ module ApplicationSettingsHelper
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
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index b05fa0a14d..b4f80fd9b3 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -38,16 +38,6 @@ module AuthHelper
auth_providers.reject { |provider| form_based_provider?(provider) }
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)
label = label_for_provider(provider)
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index cec2dc753f..93241b3afb 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -184,14 +184,4 @@ module BlobHelper
Other: licenses.reject(&:featured).map { |license| [license.name, license.key] }
}
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
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index f742922d92..a9047ede8c 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -30,7 +30,7 @@ module ButtonHelper
content_tag :a, protocol,
class: klass,
- href: project.http_url_to_repo,
+ href: @project.http_url_to_repo,
data: {
html: true,
placement: 'right',
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index cfad17dcac..417050b413 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -38,30 +38,19 @@ module CiStatusHelper
icon(icon_name + ' fw')
end
- def render_commit_status(commit, tooltip_placement: 'auto left')
- project = commit.project
- path = builds_namespace_project_commit_path(project.namespace, project, commit)
- render_status_with_link('commit', commit.status, path, tooltip_placement)
- end
-
- def render_pipeline_status(pipeline, tooltip_placement: 'auto left')
- project = pipeline.project
- path = namespace_project_pipeline_path(project.namespace, project, pipeline)
- render_status_with_link('pipeline', pipeline.status, path, tooltip_placement)
+ def render_ci_status(ci_commit, tooltip_placement: 'auto left')
+ # TODO: split this method into
+ # - render_commit_status
+ # - render_pipeline_status
+ link_to ci_icon_for_status(ci_commit.status),
+ ci_status_path(ci_commit),
+ class: "ci-status-link ci-status-icon-#{ci_commit.status.dasherize}",
+ title: "Build #{ci_label_for_status(ci_commit.status)}",
+ data: { toggle: 'tooltip', placement: tooltip_placement }
end
def no_runners_for_project?(project)
project.runners.blank? &&
Ci::Runner.shared.blank?
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
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index d328f56c80..b59c3982ed 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -123,14 +123,13 @@ module CommitsHelper
)
end
- def revert_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
+ def revert_commit_link(commit, continue_to_path, btn_class: nil)
return unless current_user
- tooltip = "Revert this #{commit.change_type_title} in a new merge request" if has_tooltip
+ tooltip = "Revert this #{commit.change_type_title} in a new merge request"
if can_collaborate_with_project?
- btn_class = "btn btn-grouped btn-close btn-#{btn_class}" unless btn_class.nil?
- link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}"
+ link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: tooltip, class: "btn btn-default btn-grouped btn-#{btn_class} has-tooltip"
elsif can?(current_user, :fork_project, @project)
continue_params = {
to: continue_to_path,
@@ -141,20 +140,17 @@ module CommitsHelper
namespace_key: current_user.namespace.id,
continue: continue_params)
- btn_class = "btn btn-grouped btn-close" unless btn_class.nil?
-
- link_to 'Revert', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip)
+ link_to 'Revert', fork_path, class: 'btn btn-grouped btn-close', method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip
end
end
- def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
+ def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil)
return unless current_user
tooltip = "Cherry-pick this #{commit.change_type_title} in a new merge request"
if can_collaborate_with_project?
- btn_class = "btn btn-default btn-grouped btn-#{btn_class}" unless btn_class.nil?
- link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}"
+ link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: tooltip, class: "btn btn-default btn-grouped btn-#{btn_class} has-tooltip"
elsif can?(current_user, :fork_project, @project)
continue_params = {
to: continue_to_path,
@@ -165,8 +161,7 @@ module CommitsHelper
namespace_key: current_user.namespace.id,
continue: continue_params)
- btn_class = "btn btn-grouped btn-close" unless btn_class.nil?
- link_to 'Cherry-pick', fork_path, class: "#{btn_class}", method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip)
+ link_to 'Cherry-pick', fork_path, class: 'btn btn-grouped btn-close', method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip
end
end
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index cbe4717683..9f73edb455 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -2,8 +2,8 @@ module DiffHelper
def mark_inline_diffs(old_line, new_line)
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, mode: :deletion)
- marked_new_line = Gitlab::Diff::InlineDiffMarker.new(new_line).mark(new_diffs, mode: :addition)
+ marked_old_line = Gitlab::Diff::InlineDiffMarker.new(old_line).mark(old_diffs)
+ marked_new_line = Gitlab::Diff::InlineDiffMarker.new(new_line).mark(new_diffs)
[marked_old_line, marked_new_line]
end
@@ -39,11 +39,11 @@ module DiffHelper
end
def unfold_bottom_class(bottom)
- bottom ? 'js-unfold-bottom' : ''
+ (bottom) ? 'js-unfold-bottom' : ''
end
def unfold_class(unfold)
- unfold ? 'unfold js-unfold' : ''
+ (unfold) ? 'unfold js-unfold' : ''
end
def diff_line_content(line, line_type = nil)
@@ -55,18 +55,22 @@ module DiffHelper
end
end
- def organize_comments(left, right)
- notes_left = notes_right = nil
+ def line_comments
+ @line_comments ||= @line_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code)
+ end
- unless left[:type].nil? && right[:type] == 'new'
- notes_left = @grouped_diff_notes[left[:line_code]]
+ 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'
+ comments_left = line_comments[line_code_left]
end
- unless left[:type].nil? && right[:type].nil?
- notes_right = @grouped_diff_notes[right[:line_code]]
+ unless type_left.nil? && type_right.nil?
+ comments_right = line_comments[line_code_right]
end
- [notes_left, notes_right]
+ [comments_left, comments_right]
end
def inline_diff_btn
@@ -92,8 +96,8 @@ module DiffHelper
].join(' ').html_safe
end
- def commit_for_diff(diff_file)
- if diff_file.deleted_file
+ def commit_for_diff(diff)
+ if diff.deleted_file
@base_commit || @commit.parent || @commit
else
@commit
diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb
index 8466d0aa0b..41b5bd7be9 100644
--- a/app/helpers/emails_helper.rb
+++ b/app/helpers/emails_helper.rb
@@ -32,6 +32,12 @@ module EmailsHelper
nil
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
valid_hours = Devise.reset_password_within / 60 / 60
if valid_hours >= 24
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index bfedcb1c42..592bad8ba2 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -3,7 +3,7 @@ module EventsHelper
author = event.author
if author
- link_to author.name, user_path(author.username), title: author.name
+ link_to author.name, user_path(author.username), title: h(author.name)
else
event.author_name
end
@@ -39,6 +39,15 @@ module EventsHelper
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)
if event.push? || event.commented? || event.target
"at"
@@ -57,7 +66,11 @@ module EventsHelper
words << event.ref_name
words << "at"
elsif event.commented?
- words << event.note_target_reference
+ if event.note_commit?
+ words << event.note_short_commit_id
+ else
+ words << "##{truncate event.note_target_iid}"
+ end
words << "at"
elsif event.milestone?
words << "##{event.target_iid}" if event.target_iid
@@ -80,12 +93,21 @@ module EventsHelper
elsif event.merge_request?
namespace_project_merge_request_url(event.project.namespace,
event.project, event.merge_request)
- elsif event.note? && event.commit_note?
+ elsif event.note? && event.note_commit?
namespace_project_commit_url(event.project.namespace, event.project,
event.note_target)
elsif event.note?
if event.note_target
- event_note_target_path(event)
+ if event.note_commit?
+ 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
elsif event.push?
push_event_feed_url(event)
@@ -121,30 +143,42 @@ module EventsHelper
end
def event_note_target_path(event)
- if event.note? && event.commit_note?
- namespace_project_commit_path(event.project.namespace,
- 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))
+ if event.note? && event.note_commit?
+ namespace_project_commit_path(event.project.namespace, event.project,
+ event.note_target)
else
polymorphic_path([event.project.namespace.becomes(Namespace),
event.project, event.note_target],
- anchor: dom_id(event.target))
+ anchor: dom_id(event.target))
end
end
def event_note_title_html(event)
if event.note_target
- link_to(event_note_target_path(event), title: event.target_title, class: 'has-tooltip') do
- "#{event.note_target_type} #{event.note_target_reference}"
+ if event.note_commit?
+ link_to(
+ 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
else
- content_tag(:strong, '(deleted)')
+ content_tag :strong do
+ "(deleted)"
+ end
end
end
@@ -159,6 +193,28 @@ module EventsHelper
"--broken encoding"
end
+ def event_to_atom(xml, event)
+ if event.visible_to_user?(current_user)
+ xml.entry do
+ event_link = event_feed_url(event)
+ event_title = event_feed_title(event)
+ event_summary = event_feed_summary(event)
+
+ xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
+ xml.link href: event_link
+ xml.title truncate(event_title, length: 80)
+ xml.updated event.created_at.xmlschema
+ xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(event.author_email))
+ xml.author do |author|
+ xml.name event.author_name
+ xml.email event.author_email
+ end
+
+ xml.summary(type: "xhtml") { |x| x << event_summary unless event_summary.nil? }
+ end
+ end
+ end
+
def event_row_class(event)
if event.body?
"event-block"
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index 0a1b48af21..3a45205563 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -13,7 +13,7 @@ module GitlabMarkdownHelper
def link_to_gfm(body, url, html_options = {})
return "" if body.blank?
- escaped_body = if body.start_with?('
![]()
opts[:push_code_to_protected_branches],
- author_id: opts[:author_id] || ''
+ author_id: opts[:author_id] || ''
}
}
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index 563ddd2a51..96a8367100 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -95,9 +95,7 @@ module TabHelper
end
def project_tab_class
- if controller.controller_path.start_with?('projects')
- return 'active'
- end
+ return "active" if current_page?(controller: "/projects", action: :edit, id: @project)
if ['services', 'hooks', 'deploy_keys', 'protected_branches'].include? controller.controller_name
"active"
@@ -114,7 +112,7 @@ module TabHelper
end
def profile_tab_class
- if controller.controller_path.start_with?('profiles')
+ if controller.controller_path =~ /\Aprofiles/
return 'active'
end
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index b4923fbb13..2f06668218 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -11,15 +11,12 @@ module TodosHelper
case todo.action
when Todo::ASSIGNED then 'assigned you'
when Todo::MENTIONED then 'mentioned you on'
- when Todo::BUILD_FAILED then 'The build failed for your'
end
end
def todo_target_link(todo)
target = todo.target_type.titleize.downcase
- link_to "#{target} #{todo.target_reference}", todo_target_path(todo),
- class: 'has-tooltip',
- title: todo.target.title
+ link_to "#{target} #{todo.target_reference}", todo_target_path(todo), { title: todo.target.title }
end
def todo_target_path(todo)
@@ -31,21 +28,8 @@ module TodosHelper
namespace_project_commit_path(todo.project.namespace.becomes(Namespace), todo.project,
todo.target, anchor: anchor)
else
- path = [todo.project.namespace.becomes(Namespace), todo.project, todo.target]
-
- path.unshift(:builds) if todo.build_failed?
-
- polymorphic_path(path, anchor: anchor)
- end
- end
-
- def todo_target_state_pill(todo)
- return unless show_todo_state?(todo)
-
- content_tag(:span, nil, class: 'target-status') do
- content_tag(:span, nil, class: "status-box status-box-#{todo.target.state.dasherize}") do
- todo.target.state.capitalize
- end
+ polymorphic_path([todo.project.namespace.becomes(Namespace),
+ todo.project, todo.target], anchor: anchor)
end
end
@@ -107,10 +91,4 @@ module TodosHelper
options_from_collection_for_select(types, 'name', 'title', params[:type])
end
-
- private
-
- def show_todo_state?(todo)
- (todo.target.is_a?(MergeRequest) || todo.target.is_a?(Issue)) && ['closed', 'merged'].include?(todo.target.state)
- end
end
diff --git a/app/mailers/devise_mailer.rb b/app/mailers/devise_mailer.rb
index 415f6e1288..b616add283 100644
--- a/app/mailers/devise_mailer.rb
+++ b/app/mailers/devise_mailer.rb
@@ -1,6 +1,4 @@
class DeviseMailer < Devise::Mailer
default from: "#{Gitlab.config.gitlab.email_display_name} <#{Gitlab.config.gitlab.email_from}>"
default reply_to: Gitlab.config.gitlab.email_reply_to
-
- layout 'devise_mailer'
end
diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb
index fdf1e9f5af..377c2999d6 100644
--- a/app/mailers/emails/projects.rb
+++ b/app/mailers/emails/projects.rb
@@ -59,20 +59,20 @@ module Emails
subject: subject("Project was moved"))
end
- def repository_push_email(project_id, opts = {})
+ def repository_push_email(project_id, recipient, opts = {})
@message =
- Gitlab::Email::Message::RepositoryPush.new(self, project_id, opts)
+ Gitlab::Email::Message::RepositoryPush.new(self, project_id, recipient, opts)
# used in notify layout
@target_url = @message.target_url
- @project = Project.find(project_id)
- @diff_notes_disabled = true
+ @project = Project.find project_id
add_project_headers
headers['X-GitLab-Author'] = @message.author_username
mail(from: sender(@message.author_id, @message.send_from_committer_email?),
reply_to: @message.reply_to,
+ to: @message.recipient,
subject: @message.subject)
end
end
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 1c663bdd52..826e5f96fa 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -10,8 +10,6 @@ class Notify < BaseMailer
include Emails::Builds
add_template_helper MergeRequestsHelper
- add_template_helper DiffHelper
- add_template_helper BlobHelper
add_template_helper EmailsHelper
def test_email(recipient_email, subject, body)
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 44515550d9..6103a2947e 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -23,41 +23,20 @@ class Ability
end.concat(global_abilities(user))
end
- # Given a list of users and a project this method returns the users that can
- # read the given project.
- def users_that_can_read_project(users, project)
- if project.public?
- users
- else
- users.select do |user|
- if user.admin?
- true
- elsif project.internal? && !user.external?
- true
- elsif project.owner == user
- true
- elsif project.team.members.include?(user)
- true
- else
- false
- end
- end
- end
- end
-
# List of possible abilities for anonymous user
def anonymous_abilities(user, subject)
- if subject.is_a?(PersonalSnippet)
+ case true
+ when subject.is_a?(PersonalSnippet)
anonymous_personal_snippet_abilities(subject)
- elsif subject.is_a?(ProjectSnippet)
+ when subject.is_a?(ProjectSnippet)
anonymous_project_snippet_abilities(subject)
- elsif subject.is_a?(CommitStatus)
+ when subject.is_a?(CommitStatus)
anonymous_commit_status_abilities(subject)
- elsif subject.is_a?(Project) || subject.respond_to?(:project)
+ when subject.is_a?(Project) || subject.respond_to?(:project)
anonymous_project_abilities(subject)
- elsif subject.is_a?(Group) || subject.respond_to?(:group)
+ when subject.is_a?(Group) || subject.respond_to?(:group)
anonymous_group_abilities(subject)
- elsif subject.is_a?(User)
+ when subject.is_a?(User)
anonymous_user_abilities
else
[]
@@ -81,9 +60,7 @@ class Ability
:read_project_member,
:read_merge_request,
:read_note,
- :read_pipeline,
:read_commit_status,
- :read_container_image,
:download_code
]
@@ -226,8 +203,6 @@ class Ability
:admin_label,
:read_commit_status,
:read_build,
- :read_container_image,
- :read_pipeline,
]
end
@@ -239,13 +214,9 @@ class Ability
:update_commit_status,
:create_build,
:update_build,
- :create_pipeline,
- :update_pipeline,
:create_merge_request,
:create_wiki,
- :push_code,
- :create_container_image,
- :update_container_image,
+ :push_code
]
end
@@ -271,9 +242,7 @@ class Ability
:admin_wiki,
:admin_project,
:admin_commit_status,
- :admin_build,
- :admin_container_image,
- :admin_pipeline
+ :admin_build
]
end
@@ -316,11 +285,6 @@ class Ability
unless project.builds_enabled
rules += named_abilities('build')
- rules += named_abilities('pipeline')
- end
-
- unless project.container_registry_enabled
- rules += named_abilities('container_image')
end
rules
diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb
index b01a244032..b61f512312 100644
--- a/app/models/abuse_report.rb
+++ b/app/models/abuse_report.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: abuse_reports
+#
+# id :integer not null, primary key
+# reporter_id :integer
+# user_id :integer
+# message :text
+# created_at :datetime
+# updated_at :datetime
+#
+
class AbuseReport < ActiveRecord::Base
belongs_to :reporter, class_name: 'User'
belongs_to :user
diff --git a/app/models/appearance.rb b/app/models/appearance.rb
index 4cf8dd9a8c..4528760fef 100644
--- a/app/models/appearance.rb
+++ b/app/models/appearance.rb
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: appearances
+#
+# id :integer not null, primary key
+# title :string
+# description :text
+# header_logo :string
+# logo :string
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
class Appearance < ActiveRecord::Base
validates :title, presence: true
validates :description, presence: true
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 42f908aa34..72ec91d290 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -1,13 +1,63 @@
+# == Schema Information
+#
+# Table name: application_settings
+#
+# id :integer not null, primary key
+# default_projects_limit :integer
+# signup_enabled :boolean
+# signin_enabled :boolean
+# gravatar_enabled :boolean
+# sign_in_text :text
+# created_at :datetime
+# updated_at :datetime
+# home_page_url :string
+# default_branch_protection :integer default(2)
+# restricted_visibility_levels :text
+# version_check_enabled :boolean default(TRUE)
+# max_attachment_size :integer default(10), not null
+# default_project_visibility :integer
+# default_snippet_visibility :integer
+# restricted_signup_domains :text
+# user_oauth_applications :boolean default(TRUE)
+# after_sign_out_path :string
+# session_expire_delay :integer default(10080), not null
+# import_sources :text
+# help_page_text :text
+# admin_notification_email :string
+# shared_runners_enabled :boolean default(TRUE), not null
+# max_artifacts_size :integer default(100), not null
+# runners_registration_token :string
+# require_two_factor_authentication :boolean default(FALSE)
+# two_factor_grace_period :integer default(48)
+# metrics_enabled :boolean default(FALSE)
+# metrics_host :string default("localhost")
+# metrics_pool_size :integer default(16)
+# metrics_timeout :integer default(10)
+# metrics_method_call_threshold :integer default(10)
+# recaptcha_enabled :boolean default(FALSE)
+# recaptcha_site_key :string
+# recaptcha_private_key :string
+# metrics_port :integer default(8089)
+# metrics_sample_interval :integer default(15)
+# sentry_enabled :boolean default(FALSE)
+# sentry_dsn :string
+# akismet_enabled :boolean default(FALSE)
+# akismet_api_key :string
+# email_author_in_body :boolean default(FALSE)
+# default_group_visibility :integer
+# repository_checks_enabled :boolean default(FALSE)
+# metrics_packet_size :integer default(1)
+# shared_runners_text :text
+#
+
class ApplicationSetting < ActiveRecord::Base
include TokenAuthenticatable
add_authentication_token_field :runners_registration_token
- add_authentication_token_field :health_check_access_token
CACHE_KEY = 'application_setting.last'
serialize :restricted_visibility_levels
serialize :import_sources
- serialize :disabled_oauth_sign_in_sources, Array
serialize :restricted_signup_domains, Array
attr_accessor :restricted_signup_domains_raw
@@ -51,10 +101,6 @@ class ApplicationSetting < ActiveRecord::Base
presence: true,
numericality: { only_integer: true, greater_than: 0 }
- validates :container_registry_token_expire_delay,
- presence: true,
- numericality: { only_integer: true, greater_than: 0 }
-
validates_each :restricted_visibility_levels do |record, attr, value|
unless value.nil?
value.each do |level|
@@ -75,18 +121,7 @@ class ApplicationSetting < ActiveRecord::Base
end
end
- validates_each :disabled_oauth_sign_in_sources do |record, attr, value|
- unless value.nil?
- value.each do |source|
- unless Devise.omniauth_providers.include?(source.to_sym)
- record.errors.add(attr, "'#{source}' is not an OAuth sign-in source")
- end
- end
- end
- end
-
before_save :ensure_runners_registration_token
- before_save :ensure_health_check_access_token
after_commit do
Rails.cache.write(CACHE_KEY, self)
@@ -102,10 +137,6 @@ class ApplicationSetting < ActiveRecord::Base
Rails.cache.delete(CACHE_KEY)
end
- def self.cached
- Rails.cache.fetch(CACHE_KEY)
- end
-
def self.create_from_defaults
create(
default_projects_limit: Settings.gitlab['default_projects_limit'],
@@ -128,9 +159,6 @@ class ApplicationSetting < ActiveRecord::Base
recaptcha_enabled: false,
akismet_enabled: false,
repository_checks_enabled: true,
- disabled_oauth_sign_in_sources: [],
- send_user_confirmation_email: false,
- container_registry_token_expire_delay: 5,
)
end
@@ -157,8 +185,4 @@ class ApplicationSetting < ActiveRecord::Base
def runners_registration_token
ensure_runners_registration_token!
end
-
- def health_check_access_token
- ensure_health_check_access_token!
- end
end
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index 967ffd46db..44b090260e 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -1,3 +1,17 @@
+# == Schema Information
+#
+# Table name: audit_events
+#
+# id :integer not null, primary key
+# author_id :integer not null
+# type :string not null
+# entity_id :integer not null
+# entity_type :string not null
+# details :text
+# created_at :datetime
+# updated_at :datetime
+#
+
class AuditEvent < ActiveRecord::Base
serialize :details, Hash
diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb
index 61498140f2..075ac733bf 100644
--- a/app/models/broadcast_message.rb
+++ b/app/models/broadcast_message.rb
@@ -1,3 +1,17 @@
+# == Schema Information
+#
+# Table name: broadcast_messages
+#
+# id :integer not null, primary key
+# message :text not null
+# starts_at :datetime
+# ends_at :datetime
+# created_at :datetime
+# updated_at :datetime
+# color :string
+# font :string
+#
+
class BroadcastMessage < ActiveRecord::Base
include Sortable
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 64723ab6b4..4bc3a225e2 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -1,3 +1,40 @@
+# == Schema Information
+#
+# Table name: ci_builds
+#
+# id :integer not null, primary key
+# project_id :integer
+# status :string
+# finished_at :datetime
+# trace :text
+# created_at :datetime
+# updated_at :datetime
+# started_at :datetime
+# runner_id :integer
+# coverage :float
+# commit_id :integer
+# commands :text
+# job_id :integer
+# name :string
+# deploy :boolean default(FALSE)
+# options :text
+# allow_failure :boolean default(FALSE), not null
+# stage :string
+# trigger_request_id :integer
+# stage_idx :integer
+# tag :boolean
+# ref :string
+# user_id :integer
+# type :string
+# target_url :string
+# description :string
+# artifacts_file :text
+# gl_project_id :integer
+# artifacts_metadata :text
+# erased_by_id :integer
+# erased_at :datetime
+#
+
module Ci
class Build < CommitStatus
belongs_to :runner, class_name: 'Ci::Runner'
@@ -53,7 +90,6 @@ module Ci
new_build.stage_idx = build.stage_idx
new_build.trigger_request = build.trigger_request
new_build.save
- MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build)
new_build
end
end
@@ -96,12 +132,8 @@ module Ci
end
def trace_html
- trace_with_state[:html] || ''
- end
-
- def trace_with_state(state = nil)
- trace_with_state = Ci::Ansi2html::convert(trace, state) if trace.present?
- trace_with_state || {}
+ html = Ci::Ansi2html::convert(trace) if trace.present?
+ html || ''
end
def timeout
@@ -206,7 +238,7 @@ module Ci
end
def recreate_trace_dir
- unless Dir.exist?(dir_to_trace)
+ unless Dir.exists?(dir_to_trace)
FileUtils.mkdir_p(dir_to_trace)
end
end
@@ -286,20 +318,14 @@ module Ci
project.runners_token
end
- def valid_token?(token)
+ def valid_token? token
project.valid_runners_token? token
end
def can_be_served?(runner)
- return false unless has_tags? || runner.run_untagged?
-
(tag_list - runner.tag_list).empty?
end
- def has_tags?
- tag_list.any?
- end
-
def any_runners_online?
project.any_runners? { |runner| runner.active? && runner.online? && can_be_served?(runner) }
end
@@ -313,7 +339,6 @@ module Ci
build_data = Gitlab::BuildDataBuilder.build(self)
project.execute_hooks(build_data.dup, :build_hooks)
project.execute_services(build_data.dup, :build_hooks)
- project.running_or_pending_build_count(force: true)
end
def artifacts?
diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb
index f22b573a94..4ac4e0fb8b 100644
--- a/app/models/ci/commit.rb
+++ b/app/models/ci/commit.rb
@@ -1,3 +1,25 @@
+# == Schema Information
+#
+# Table name: ci_commits
+#
+# id :integer not null, primary key
+# project_id :integer
+# ref :string
+# sha :string
+# before_sha :string
+# push_data :text
+# created_at :datetime
+# updated_at :datetime
+# tag :boolean default(FALSE)
+# yaml_errors :text
+# committed_at :datetime
+# gl_project_id :integer
+# status :string
+# started_at :datetime
+# finished_at :datetime
+# duration :integer
+#
+
module Ci
class Commit < ActiveRecord::Base
extend Ci::Model
@@ -8,6 +30,8 @@ module Ci
has_many :builds, class_name: 'Ci::Build'
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest'
+ delegate :stages, to: :statuses
+
validates_presence_of :sha
validates_presence_of :status
validate :valid_commit_sha
@@ -20,8 +44,7 @@ module Ci
end
def self.stages
- # We use pluck here due to problems with MySQL which doesn't allow LIMIT/OFFSET in queries
- CommitStatus.where(commit: pluck(:id)).stages
+ CommitStatus.where(commit: all).stages
end
def project_id
@@ -66,29 +89,6 @@ module Ci
end
end
- def cancelable?
- builds.running_or_pending.any?
- end
-
- def cancel_running
- builds.running_or_pending.each(&:cancel)
- end
-
- def retry_failed
- builds.latest.failed.select(&:retryable?).each(&:retry)
- end
-
- def latest?
- return false unless ref
- commit = project.commit(ref)
- return false unless commit
- commit.sha == sha
- end
-
- def triggered?
- trigger_requests.any?
- end
-
def create_builds(user, trigger_request = nil)
return unless config_processor
config_processor.stages.any? do |stage|
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index adb6529220..add59a0889 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -1,10 +1,28 @@
+# == Schema Information
+#
+# Table name: ci_runners
+#
+# id :integer not null, primary key
+# token :string
+# created_at :datetime
+# updated_at :datetime
+# description :string
+# contacted_at :datetime
+# active :boolean default(TRUE), not null
+# is_shared :boolean default(FALSE)
+# name :string
+# version :string
+# revision :string
+# platform :string
+# architecture :string
+#
+
module Ci
class Runner < ActiveRecord::Base
extend Ci::Model
LAST_CONTACT_TIME = 5.minutes.ago
- AVAILABLE_SCOPES = %w[specific shared active paused online]
- FORM_EDITABLE = %i[description tag_list active run_untagged]
+ AVAILABLE_SCOPES = ['specific', 'shared', 'active', 'paused', 'online']
has_many :builds, class_name: 'Ci::Build'
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
@@ -26,8 +44,6 @@ module Ci
.where("ci_runner_projects.gl_project_id = :project_id OR ci_runners.is_shared = true", project_id: project_id)
end
- validate :tag_constraints
-
acts_as_taggable
# Searches for runners matching the given query.
@@ -60,7 +76,7 @@ module Ci
end
def display_name
- return short_sha if description.blank?
+ return short_sha unless !description.blank?
description
end
@@ -98,18 +114,5 @@ module Ci
def short_sha
token[0...8] if token
end
-
- def has_tags?
- tag_list.any?
- end
-
- private
-
- def tag_constraints
- unless has_tags? || run_untagged?
- errors.add(:tags_list,
- 'can not be empty when runner is not allowed to pick untagged jobs')
- end
- end
end
end
diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb
index 4b44ffa886..7b16f207a2 100644
--- a/app/models/ci/runner_project.rb
+++ b/app/models/ci/runner_project.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: ci_runner_projects
+#
+# id :integer not null, primary key
+# runner_id :integer not null
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# gl_project_id :integer
+#
+
module Ci
class RunnerProject < ActiveRecord::Base
extend Ci::Model
diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb
index a0b19b51a1..4f3f4d79fa 100644
--- a/app/models/ci/trigger.rb
+++ b/app/models/ci/trigger.rb
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: ci_triggers
+#
+# id :integer not null, primary key
+# token :string
+# project_id :integer
+# deleted_at :datetime
+# created_at :datetime
+# updated_at :datetime
+# gl_project_id :integer
+#
+
module Ci
class Trigger < ActiveRecord::Base
extend Ci::Model
diff --git a/app/models/ci/trigger_request.rb b/app/models/ci/trigger_request.rb
index 872d5fb31d..9973d2e5ad 100644
--- a/app/models/ci/trigger_request.rb
+++ b/app/models/ci/trigger_request.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: ci_trigger_requests
+#
+# id :integer not null, primary key
+# trigger_id :integer not null
+# variables :text
+# created_at :datetime
+# updated_at :datetime
+# commit_id :integer
+#
+
module Ci
class TriggerRequest < ActiveRecord::Base
extend Ci::Model
diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb
index f8d5d4486f..4229fe085a 100644
--- a/app/models/ci/variable.rb
+++ b/app/models/ci/variable.rb
@@ -1,3 +1,17 @@
+# == Schema Information
+#
+# Table name: ci_variables
+#
+# id :integer not null, primary key
+# project_id :integer
+# key :string
+# value :text
+# encrypted_value :text
+# encrypted_value_salt :string
+# encrypted_value_iv :string
+# gl_project_id :integer
+#
+
module Ci
class Variable < ActiveRecord::Base
extend Ci::Model
@@ -11,9 +25,6 @@ module Ci
format: { with: /\A[a-zA-Z0-9_]+\z/,
message: "can contain only letters, digits and '_'." }
- attr_encrypted :value,
- mode: :per_attribute_iv_and_salt,
- key: Gitlab::Application.secrets.db_key_base,
- algorithm: 'aes-256-cbc'
+ attr_encrypted :value, mode: :per_attribute_iv_and_salt, key: Gitlab::Application.secrets.db_key_base
end
end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index f96c7cb34d..562c3ed15b 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -8,10 +8,7 @@ class Commit
include StaticModel
attr_mentionable :safe_message, pipeline: :single_line
-
- participant :author
- participant :committer
- participant :notes_with_associations
+ participant :author, :committer, :notes
attr_accessor :project
@@ -197,10 +194,6 @@ class Commit
project.notes.for_commit_id(self.id)
end
- def notes_with_associations
- notes.includes(:author, :project)
- end
-
def method_missing(m, *args, &block)
@raw.send(m, *args, &block)
end
@@ -226,7 +219,7 @@ class Commit
def revert_branch_name
"revert-#{short_id}"
end
-
+
def cherry_pick_branch_name
project.repository.next_branch("cherry-pick-#{short_id}", mild: true)
end
@@ -258,13 +251,11 @@ class Commit
end
def has_been_reverted?(current_user = nil, noteable = self)
- ext = all_references(current_user)
-
- noteable.notes_with_associations.system.each do |note|
- note.all_references(current_user, extractor: ext)
- end
-
- ext.commits.any? { |commit_ref| commit_ref.reverts_commit?(self) }
+ Gitlab::ReferenceExtractor.lazily do
+ noteable.notes.system.flat_map do |note|
+ note.all_references(current_user).commits
+ end
+ end.any? { |commit_ref| commit_ref.reverts_commit?(self) }
end
def change_type_title
diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb
index 4066958f67..51673897d9 100644
--- a/app/models/commit_range.rb
+++ b/app/models/commit_range.rb
@@ -62,7 +62,7 @@ class CommitRange
def initialize(range_string, project)
@project = project
- range_string = range_string.strip
+ range_string.strip!
unless range_string =~ /\A#{PATTERN}\z/
raise ArgumentError, "invalid CommitRange string format: #{range_string}"
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index f774b6e0ef..1260c448de 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -1,3 +1,40 @@
+# == Schema Information
+#
+# Table name: ci_builds
+#
+# id :integer not null, primary key
+# project_id :integer
+# status :string
+# finished_at :datetime
+# trace :text
+# created_at :datetime
+# updated_at :datetime
+# started_at :datetime
+# runner_id :integer
+# coverage :float
+# commit_id :integer
+# commands :text
+# job_id :integer
+# name :string
+# deploy :boolean default(FALSE)
+# options :text
+# allow_failure :boolean default(FALSE), not null
+# stage :string
+# trigger_request_id :integer
+# stage_idx :integer
+# tag :boolean
+# ref :string
+# user_id :integer
+# type :string
+# target_url :string
+# description :string
+# artifacts_file :text
+# gl_project_id :integer
+# artifacts_metadata :text
+# erased_by_id :integer
+# erased_at :datetime
+#
+
class CommitStatus < ActiveRecord::Base
include Statuseable
@@ -14,8 +51,7 @@ class CommitStatus < ActiveRecord::Base
alias_attribute :author, :user
scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :commit_id)) }
- scope :retried, -> { where.not(id: latest) }
- scope :ordered, -> { order(:name) }
+ scope :ordered, -> { order(:ref, :stage_idx, :name) }
scope :ignored, -> { where(allow_failure: true, status: [:failed, :canceled]) }
state_machine :status, initial: :pending do
@@ -46,10 +82,6 @@ class CommitStatus < ActiveRecord::Base
after_transition [:pending, :running] => :success do |commit_status|
MergeRequests::MergeWhenBuildSucceedsService.new(commit_status.commit.project, nil).trigger(commit_status)
end
-
- after_transition any => :failed do |commit_status|
- MergeRequests::AddTodoWhenBuildFailsService.new(commit_status.commit.project, nil).execute(commit_status)
- end
end
delegate :sha, :short_sha, to: :commit
@@ -59,15 +91,13 @@ class CommitStatus < ActiveRecord::Base
end
def self.stages
- # We group by stage name, but order stages by theirs' index
- unscoped.from(all, :sg).group('stage').order('max(stage_idx)', 'stage').pluck('sg.stage')
+ order_by = 'max(stage_idx)'
+ group('stage').order(order_by).pluck(:stage, order_by).map(&:first).compact
end
def self.stages_status
- # We execute subquery for each stage to calculate a stage status
- statuses = unscoped.from(all, :sg).group('stage').pluck('sg.stage', all.where('stage=sg.stage').status_sql)
- statuses.inject({}) do |h, k|
- h[k.first] = k.last
+ all.stages.inject({}) do |h, stage|
+ h[stage] = all.where(stage: stage).status
h
end
end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index e86d5236ab..2e4efc4e8d 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -31,21 +31,18 @@ module Issuable
scope :unassigned, -> { where("assignee_id IS NULL") }
scope :of_projects, ->(ids) { where(project_id: ids) }
scope :of_milestones, ->(ids) { where(milestone_id: ids) }
- scope :with_milestone, ->(title) { left_joins_milestones.where(milestones: { title: title }) }
scope :opened, -> { with_state(:opened, :reopened) }
scope :only_opened, -> { with_state(:opened) }
scope :only_reopened, -> { with_state(:reopened) }
scope :closed, -> { with_state(:closed) }
-
- scope :left_joins_milestones, -> { joins("LEFT OUTER JOIN milestones ON #{table_name}.milestone_id = milestones.id") }
- scope :order_milestone_due_desc, -> { left_joins_milestones.reorder('milestones.due_date IS NULL, milestones.id IS NULL, milestones.due_date DESC') }
- scope :order_milestone_due_asc, -> { left_joins_milestones.reorder('milestones.due_date IS NULL, milestones.id IS NULL, milestones.due_date ASC') }
-
+ scope :order_milestone_due_desc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date DESC, milestones.id DESC') }
+ scope :order_milestone_due_asc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date ASC, milestones.id ASC') }
scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) }
+
scope :join_project, -> { joins(:project) }
scope :references_project, -> { references(:project) }
scope :non_archived, -> { join_project.where(projects: { archived: false }) }
-
+ scope :outer_join_milestone, -> { joins("LEFT OUTER JOIN milestones ON milestones.id = #{table_name}.milestone_id") }
delegate :name,
:email,
@@ -59,23 +56,11 @@ module Issuable
prefix: true
attr_mentionable :title, pipeline: :single_line
- attr_mentionable :description
-
- participant :author
- participant :assignee
- participant :notes_with_associations
-
+ attr_mentionable :description, cache: true
+ participant :author, :assignee, :notes_with_associations
strip_attributes :title
acts_as_paranoid
-
- after_save :update_assignee_cache_counts, if: :assignee_id_changed?
-
- def update_assignee_cache_counts
- # make sure we flush the cache for both the old *and* new assignee
- User.find(assignee_id_was).update_cache_counts if assignee_id_was
- assignee.update_cache_counts if assignee
- end
end
module ClassMethods
@@ -138,29 +123,13 @@ module Issuable
joins(join_clause).group(issuable_table[:id]).reorder("COUNT(notes.id) DESC")
end
- def with_label(title, sort = nil)
- if title.is_a?(Array) && title.size > 1
- joins(:labels).where(labels: { title: title }).group(*grouping_columns(sort)).having("COUNT(DISTINCT labels.title) = #{title.size}")
+ def with_label(title)
+ if title.is_a?(Array) && title.count > 1
+ joins(:labels).where(labels: { title: title }).group('issues.id').having("count(distinct labels.title) = #{title.count}")
else
joins(:labels).where(labels: { title: title })
end
end
-
- # Includes table keys in group by clause when sorting
- # preventing errors in postgres
- #
- # Returns an array of arel columns
- def grouping_columns(sort)
- grouping_columns = [arel_table[:id]]
-
- if ["milestone_due_desc", "milestone_due_asc"].include?(sort)
- milestone_table = Milestone.arel_table
- grouping_columns << milestone_table[:id]
- grouping_columns << milestone_table[:due_date]
- end
-
- grouping_columns
- end
end
def today?
@@ -191,10 +160,6 @@ module Issuable
notes.awards.where(note: "thumbsup").count
end
- def user_notes_count
- notes.user.count
- end
-
def subscribed_without_subscriptions?(user)
participants(user).include?(user)
end
@@ -213,10 +178,6 @@ module Issuable
hook_data
end
- def labels_array
- labels.to_a
- end
-
def label_names
labels.order('title ASC').pluck(:title)
end
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index f00b5b8497..98f71ae8cb 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -23,7 +23,7 @@ module Mentionable
included do
if self < Participable
- participant -> (user, ext) { all_references(user, extractor: ext) }
+ participant ->(current_user) { mentioned_users(current_user) }
end
end
@@ -43,22 +43,23 @@ module Mentionable
self
end
- def all_references(current_user = nil, text = nil, extractor: nil)
- extractor ||= Gitlab::ReferenceExtractor.
- new(project, current_user || author)
+ def all_references(current_user = self.author, text = nil)
+ ext = Gitlab::ReferenceExtractor.new(self.project, current_user, self.author)
if text
- extractor.analyze(text, author: author)
+ ext.analyze(text)
else
self.class.mentionable_attrs.each do |attr, options|
- text = __send__(attr)
- options = options.merge(cache_key: [self, attr], author: author)
+ text = send(attr)
- extractor.analyze(text, options)
+ context = options.dup
+ context[:cache_key] = [self, attr] if context.delete(:cache) && self.persisted?
+
+ ext.analyze(text, context)
end
end
- extractor
+ ext
end
def mentioned_users(current_user = nil)
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index 9056722f45..fc6f83b918 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -3,6 +3,8 @@
# Contains functionality related to objects that can have participants, such as
# an author, an assignee and people mentioned in its description or comments.
#
+# Used by Issue, Note, MergeRequest, Snippet and Commit.
+#
# Usage:
#
# class Issue < ActiveRecord::Base
@@ -10,36 +12,22 @@
#
# # ...
#
-# participant :author
-# participant :assignee
-# participant :notes
-#
-# participant -> (current_user, ext) do
-# ext.analyze('...')
-# end
+# participant :author, :assignee, :notes, ->(current_user) { mentioned_users(current_user) }
# end
#
# issue = Issue.last
# users = issue.participants
+# # `users` will contain the issue's author, its assignee,
+# # all users returned by its #mentioned_users method,
+# # as well as all participants to all of the issue's notes,
+# # since Note implements Participable as well.
+#
module Participable
extend ActiveSupport::Concern
module ClassMethods
- # Adds a list of participant attributes. Attributes can either be symbols or
- # Procs.
- #
- # When using a Proc instead of a Symbol the Proc will be given two
- # arguments:
- #
- # 1. The current user (as an instance of User)
- # 2. An instance of `Gitlab::ReferenceExtractor`
- #
- # It is expected that a Proc populates the given reference extractor
- # instance with data. The return value of the Proc is ignored.
- #
- # attr - The name of the attribute or a Proc
- def participant(attr)
- participant_attrs << attr
+ def participant(*attrs)
+ participant_attrs.concat(attrs)
end
def participant_attrs
@@ -47,42 +35,42 @@ module Participable
end
end
- # Returns the users participating in a discussion.
- #
- # This method processes attributes of objects in breadth-first order.
- #
- # Returns an Array of User instances.
- def participants(current_user = nil)
- current_user ||= author
- ext = Gitlab::ReferenceExtractor.new(project, current_user)
- participants = Set.new
- process = [self]
+ # Be aware that this method makes a lot of sql queries.
+ # Save result into variable if you are going to reuse it inside same request
+ def participants(current_user = self.author)
+ participants =
+ Gitlab::ReferenceExtractor.lazily do
+ self.class.participant_attrs.flat_map do |attr|
+ value =
+ if attr.respond_to?(:call)
+ instance_exec(current_user, &attr)
+ else
+ send(attr)
+ end
- until process.empty?
- source = process.pop
+ participants_for(value, current_user)
+ end.compact.uniq
+ end
- case source
- when User
- participants << source
- when Participable
- source.class.participant_attrs.each do |attr|
- if attr.respond_to?(:call)
- source.instance_exec(current_user, ext, &attr)
- else
- process << source.__send__(attr)
- end
- end
- when Enumerable, ActiveRecord::Relation
- # This uses reverse_each so we can use "pop" to get the next value to
- # process (in order). Using unshift instead of pop would require
- # moving all Array values one index to the left (which can be
- # expensive).
- source.reverse_each { |obj| process << obj }
+ unless Gitlab::ReferenceExtractor.lazy?
+ participants.select! do |user|
+ user.can?(:read_project, project)
end
end
- participants.merge(ext.users)
+ participants
+ end
- Ability.users_that_can_read_project(participants.to_a, project)
+ private
+
+ def participants_for(value, current_user = nil)
+ case value
+ when User, Banzai::LazyReference
+ [value]
+ when Enumerable, ActiveRecord::Relation
+ value.flat_map { |v| participants_for(v, current_user) }
+ when Participable
+ value.participants(current_user)
+ end
end
end
diff --git a/app/models/concerns/subscribable.rb b/app/models/concerns/subscribable.rb
index 083257f100..d5a881b244 100644
--- a/app/models/concerns/subscribable.rb
+++ b/app/models/concerns/subscribable.rb
@@ -36,12 +36,6 @@ module Subscribable
update(subscribed: !subscribed?(user))
end
- def subscribe(user)
- subscriptions.
- find_or_initialize_by(user_id: user.id).
- update(subscribed: true)
- end
-
def unsubscribe(user)
subscriptions.
find_or_initialize_by(user_id: user.id).
diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb
index 2c525d4cd7..43cf625f77 100644
--- a/app/models/deploy_key.rb
+++ b/app/models/deploy_key.rb
@@ -1,3 +1,18 @@
+# == Schema Information
+#
+# Table name: keys
+#
+# id :integer not null, primary key
+# user_id :integer
+# created_at :datetime
+# updated_at :datetime
+# key :text
+# title :string
+# type :string
+# fingerprint :string
+# public :boolean default(FALSE), not null
+#
+
class DeployKey < Key
has_many :deploy_keys_projects, dependent: :destroy
has_many :projects, through: :deploy_keys_projects
diff --git a/app/models/deploy_keys_project.rb b/app/models/deploy_keys_project.rb
index ae8486bd9a..18db521741 100644
--- a/app/models/deploy_keys_project.rb
+++ b/app/models/deploy_keys_project.rb
@@ -1,3 +1,14 @@
+# == Schema Information
+#
+# Table name: deploy_keys_projects
+#
+# id :integer not null, primary key
+# deploy_key_id :integer not null
+# project_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+#
+
class DeployKeysProject < ActiveRecord::Base
belongs_to :project
belongs_to :deploy_key
diff --git a/app/models/email.rb b/app/models/email.rb
index 32a412ab87..eae2472f33 100644
--- a/app/models/email.rb
+++ b/app/models/email.rb
@@ -1,3 +1,14 @@
+# == Schema Information
+#
+# Table name: emails
+#
+# id :integer not null, primary key
+# user_id :integer not null
+# email :string not null
+# created_at :datetime
+# updated_at :datetime
+#
+
class Email < ActiveRecord::Base
include Sortable
diff --git a/app/models/event.rb b/app/models/event.rb
index 716039fb54..25c7c3e6dc 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -1,3 +1,19 @@
+# == Schema Information
+#
+# Table name: events
+#
+# id :integer not null, primary key
+# target_type :string
+# target_id :integer
+# title :string
+# data :text
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# action :integer
+# author_id :integer
+#
+
class Event < ActiveRecord::Base
include Sortable
default_scope { where.not(author_id: nil) }
@@ -80,7 +96,7 @@ class Event < ActiveRecord::Base
end
def target_title
- target.try(:title)
+ target.title if target && target.respond_to?(:title)
end
def created?
@@ -266,20 +282,28 @@ class Event < ActiveRecord::Base
branch? && project.default_branch != branch_name
end
+ def note_commit_id
+ target.commit_id
+ end
+
def target_iid
target.respond_to?(:iid) ? target.iid : target_id
end
- def commit_note?
- target.for_commit?
+ def note_short_commit_id
+ Commit.truncate_sha(note_commit_id)
+ end
+
+ def note_commit?
+ target.noteable_type == "Commit"
end
def issue_note?
- note? && target && target.for_issue?
+ note? && target && target.noteable_type == "Issue"
end
- def project_snippet_note?
- target.for_snippet?
+ def note_project_snippet?
+ target.noteable_type == "Snippet"
end
def note_target
@@ -287,22 +311,19 @@ class Event < ActiveRecord::Base
end
def note_target_id
- if commit_note?
+ if note_commit?
target.commit_id
else
target.noteable_id.to_s
end
end
- def note_target_reference
- return unless note_target
-
- # Commit#to_reference returns the full SHA, but we want the short one here
- if commit_note?
- note_target.short_id
+ def note_target_iid
+ if note_target.respond_to?(:iid)
+ note_target.iid
else
- note_target.to_reference
- end
+ note_target_id
+ end.to_s
end
def note_target_type
diff --git a/app/models/forked_project_link.rb b/app/models/forked_project_link.rb
index 9803bae0be..9b0c6263a9 100644
--- a/app/models/forked_project_link.rb
+++ b/app/models/forked_project_link.rb
@@ -1,3 +1,14 @@
+# == Schema Information
+#
+# Table name: forked_project_links
+#
+# id :integer not null, primary key
+# forked_to_project_id :integer not null
+# forked_from_project_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+#
+
class ForkedProjectLink < ActiveRecord::Base
belongs_to :forked_to_project, class_name: Project
belongs_to :forked_from_project, class_name: Project
diff --git a/app/models/generic_commit_status.rb b/app/models/generic_commit_status.rb
index fa54e3540d..d4afd8cbe8 100644
--- a/app/models/generic_commit_status.rb
+++ b/app/models/generic_commit_status.rb
@@ -1,3 +1,40 @@
+# == Schema Information
+#
+# Table name: ci_builds
+#
+# id :integer not null, primary key
+# project_id :integer
+# status :string
+# finished_at :datetime
+# trace :text
+# created_at :datetime
+# updated_at :datetime
+# started_at :datetime
+# runner_id :integer
+# coverage :float
+# commit_id :integer
+# commands :text
+# job_id :integer
+# name :string
+# deploy :boolean default(FALSE)
+# options :text
+# allow_failure :boolean default(FALSE), not null
+# stage :string
+# trigger_request_id :integer
+# stage_idx :integer
+# tag :boolean
+# ref :string
+# user_id :integer
+# type :string
+# target_url :string
+# description :string
+# artifacts_file :text
+# gl_project_id :integer
+# artifacts_metadata :text
+# erased_by_id :integer
+# erased_at :datetime
+#
+
class GenericCommitStatus < CommitStatus
before_validation :set_default_values
diff --git a/app/models/group.rb b/app/models/group.rb
index aec92e335e..cff7687795 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -1,3 +1,20 @@
+# == Schema Information
+#
+# Table name: namespaces
+#
+# id :integer not null, primary key
+# name :string not null
+# path :string not null
+# owner_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string
+# description :string default(""), not null
+# avatar :string
+# share_with_group_lock :boolean default(FALSE)
+# visibility_level :integer default(20), not null
+#
+
require 'carrierwave/orm/activerecord'
class Group < Namespace
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index ba42a8eeb7..2b8f34a056 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -1,3 +1,25 @@
+# == Schema Information
+#
+# Table name: web_hooks
+#
+# id :integer not null, primary key
+# url :string(2000)
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string default("ProjectHook")
+# service_id :integer
+# push_events :boolean default(TRUE), not null
+# issues_events :boolean default(FALSE), not null
+# merge_requests_events :boolean default(FALSE), not null
+# tag_push_events :boolean default(FALSE)
+# note_events :boolean default(FALSE), not null
+# enable_ssl_verification :boolean default(TRUE)
+# build_events :boolean default(FALSE), not null
+# wiki_page_events :boolean default(FALSE), not null
+# token :string
+#
+
class ProjectHook < WebHook
belongs_to :project
diff --git a/app/models/hooks/service_hook.rb b/app/models/hooks/service_hook.rb
index eef24052a0..0e176de5ef 100644
--- a/app/models/hooks/service_hook.rb
+++ b/app/models/hooks/service_hook.rb
@@ -1,3 +1,25 @@
+# == Schema Information
+#
+# Table name: web_hooks
+#
+# id :integer not null, primary key
+# url :string(2000)
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string default("ProjectHook")
+# service_id :integer
+# push_events :boolean default(TRUE), not null
+# issues_events :boolean default(FALSE), not null
+# merge_requests_events :boolean default(FALSE), not null
+# tag_push_events :boolean default(FALSE)
+# note_events :boolean default(FALSE), not null
+# enable_ssl_verification :boolean default(TRUE)
+# build_events :boolean default(FALSE), not null
+# wiki_page_events :boolean default(FALSE), not null
+# token :string
+#
+
class ServiceHook < WebHook
belongs_to :service
diff --git a/app/models/hooks/system_hook.rb b/app/models/hooks/system_hook.rb
index 777bad1e72..ad508cbbcb 100644
--- a/app/models/hooks/system_hook.rb
+++ b/app/models/hooks/system_hook.rb
@@ -1,3 +1,25 @@
+# == Schema Information
+#
+# Table name: web_hooks
+#
+# id :integer not null, primary key
+# url :string(2000)
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string default("ProjectHook")
+# service_id :integer
+# push_events :boolean default(TRUE), not null
+# issues_events :boolean default(FALSE), not null
+# merge_requests_events :boolean default(FALSE), not null
+# tag_push_events :boolean default(FALSE)
+# note_events :boolean default(FALSE), not null
+# enable_ssl_verification :boolean default(TRUE)
+# build_events :boolean default(FALSE), not null
+# wiki_page_events :boolean default(FALSE), not null
+# token :string
+#
+
class SystemHook < WebHook
def async_execute(data, hook_name)
Sidekiq::Client.enqueue(SystemHookWorker, id, data, hook_name)
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index 8b87b6c3d6..8e58c9583a 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -1,3 +1,25 @@
+# == Schema Information
+#
+# Table name: web_hooks
+#
+# id :integer not null, primary key
+# url :string(2000)
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string default("ProjectHook")
+# service_id :integer
+# push_events :boolean default(TRUE), not null
+# issues_events :boolean default(FALSE), not null
+# merge_requests_events :boolean default(FALSE), not null
+# tag_push_events :boolean default(FALSE)
+# note_events :boolean default(FALSE), not null
+# enable_ssl_verification :boolean default(TRUE)
+# build_events :boolean default(FALSE), not null
+# wiki_page_events :boolean default(FALSE), not null
+# token :string
+#
+
class WebHook < ActiveRecord::Base
include Sortable
include HTTParty
@@ -38,7 +60,7 @@ class WebHook < ActiveRecord::Base
basic_auth: auth)
end
- [response.code, response.to_s]
+ [(response.code >= 200 && response.code < 300), ActionView::Base.full_sanitizer.sanitize(response.to_s)]
rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e
logger.error("WebHook Error => #{e}")
[false, e.to_s]
diff --git a/app/models/identity.rb b/app/models/identity.rb
index 3bacc450e6..ef4d5f9909 100644
--- a/app/models/identity.rb
+++ b/app/models/identity.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: identities
+#
+# id :integer not null, primary key
+# extern_uid :string
+# provider :string
+# user_id :integer
+# created_at :datetime
+# updated_at :datetime
+#
+
class Identity < ActiveRecord::Base
include Sortable
include CaseSensitivity
diff --git a/app/models/issue.rb b/app/models/issue.rb
index bd0fbc96d1..abaa509707 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: issues
+#
+# id :integer not null, primary key
+# title :string
+# assignee_id :integer
+# author_id :integer
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# position :integer default(0)
+# branch_name :string
+# description :text
+# milestone_id :integer
+# state :string
+# iid :integer
+# updated_by_id :integer
+# moved_to_id :integer
+# confidential :boolean default(FALSE)
+# deleted_at :datetime
+# due_date :date
+#
+
require 'carrierwave/orm/activerecord'
class Issue < ActiveRecord::Base
@@ -95,13 +119,14 @@ class Issue < ActiveRecord::Base
end
def referenced_merge_requests(current_user = nil)
- ext = all_references(current_user)
-
- notes_with_associations.each do |object|
- object.all_references(current_user, extractor: ext)
+ @referenced_merge_requests ||= {}
+ @referenced_merge_requests[current_user] ||= begin
+ Gitlab::ReferenceExtractor.lazily do
+ [self, *notes].flat_map do |note|
+ note.all_references(current_user).merge_requests
+ end
+ end.sort_by(&:iid).uniq
end
-
- ext.merge_requests.sort_by(&:iid)
end
# All branches containing the current issue's ID, except for
@@ -138,13 +163,9 @@ class Issue < ActiveRecord::Base
def closed_by_merge_requests(current_user = nil)
return [] unless open?
- ext = all_references(current_user)
-
- notes.system.each do |note|
- note.all_references(current_user, extractor: ext)
- end
-
- ext.merge_requests.select { |mr| mr.open? && mr.closes_issue?(self) }
+ notes.system.flat_map do |note|
+ note.all_references(current_user).merge_requests
+ end.uniq.select { |mr| mr.open? && mr.closes_issue?(self) }
end
def moved?
diff --git a/app/models/key.rb b/app/models/key.rb
index 0532e84f47..b2b57849f8 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -1,3 +1,18 @@
+# == Schema Information
+#
+# Table name: keys
+#
+# id :integer not null, primary key
+# user_id :integer
+# created_at :datetime
+# updated_at :datetime
+# key :text
+# title :string
+# type :string
+# fingerprint :string
+# public :boolean default(FALSE), not null
+#
+
require 'digest/md5'
class Key < ActiveRecord::Base
@@ -26,7 +41,7 @@ class Key < ActiveRecord::Base
end
def publishable_key
- # Removes anything beyond the keytype and key itself
+ #Removes anything beyond the keytype and key itself
self.key.split[0..1].join(' ')
end
diff --git a/app/models/label.rb b/app/models/label.rb
index e5ad11983b..9a22398d95 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -1,3 +1,17 @@
+# == Schema Information
+#
+# Table name: labels
+#
+# id :integer not null, primary key
+# title :string
+# color :string
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# template :boolean default(FALSE)
+# description :string
+#
+
class Label < ActiveRecord::Base
include Referable
include Subscribable
@@ -103,10 +117,6 @@ class Label < ActiveRecord::Base
LabelsHelper::text_color_for_bg(self.color)
end
- def title=(value)
- write_attribute(:title, Sanitize.clean(value.to_s)) if value.present?
- end
-
private
def label_format_reference(format = :id)
diff --git a/app/models/label_link.rb b/app/models/label_link.rb
index 47bd6eaf35..7b8e872b6d 100644
--- a/app/models/label_link.rb
+++ b/app/models/label_link.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: label_links
+#
+# id :integer not null, primary key
+# label_id :integer
+# target_id :integer
+# target_type :string
+# created_at :datetime
+# updated_at :datetime
+#
+
class LabelLink < ActiveRecord::Base
belongs_to :target, polymorphic: true
belongs_to :label
diff --git a/app/models/legacy_diff_note.rb b/app/models/legacy_diff_note.rb
deleted file mode 100644
index bbefc911b2..0000000000
--- a/app/models/legacy_diff_note.rb
+++ /dev/null
@@ -1,157 +0,0 @@
-class LegacyDiffNote < Note
- serialize :st_diff
-
- validates :line_code, presence: true, line_code: true
-
- before_create :set_diff
-
- class << self
- def build_discussion_id(noteable_type, noteable_id, line_code, active = true)
- [super(noteable_type, noteable_id), line_code, active].join("-")
- end
- end
-
- def diff_note?
- true
- end
-
- def legacy_diff_note?
- true
- end
-
- def discussion_id
- @discussion_id ||= self.class.build_discussion_id(noteable_type, noteable_id || commit_id, line_code, active?)
- end
-
- def diff_file_hash
- line_code.split('_')[0] if line_code
- end
-
- def diff_old_line
- line_code.split('_')[1].to_i if line_code
- end
-
- def diff_new_line
- line_code.split('_')[2].to_i if line_code
- end
-
- def diff
- @diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map)
- end
-
- def diff_file_path
- diff.new_path.presence || diff.old_path
- end
-
- def diff_lines
- @diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.each_line)
- end
-
- def diff_line
- @diff_line ||= diff_lines.find { |line| generate_line_code(line) == self.line_code }
- end
-
- def diff_line_text
- diff_line.try(:text)
- end
-
- def diff_line_type
- diff_line.try(:type)
- end
-
- def highlighted_diff_lines
- Gitlab::Diff::Highlight.new(diff_lines).highlight
- end
-
- def truncated_diff_lines
- max_number_of_lines = 16
- prev_match_line = nil
- prev_lines = []
-
- highlighted_diff_lines.each do |line|
- if line.type == "match"
- prev_lines.clear
- prev_match_line = line
- else
- prev_lines << line
-
- break if generate_line_code(line) == self.line_code
-
- prev_lines.shift if prev_lines.length >= max_number_of_lines
- end
- end
-
- prev_lines
- end
-
- # Check if this note is part of an "active" discussion
- #
- # This will always return true for anything except MergeRequest noteables,
- # which have special logic.
- #
- # If the note's current diff cannot be matched in the MergeRequest's current
- # diff, it's considered inactive.
- def active?
- return @active if defined?(@active)
- return true if for_commit?
- return true unless self.diff
- return false unless noteable
-
- noteable_diff = find_noteable_diff
-
- if noteable_diff
- parsed_lines = Gitlab::Diff::Parser.new.parse(noteable_diff.diff.each_line)
-
- @active = parsed_lines.any? { |line_obj| line_obj.text == diff_line_text }
- else
- @active = false
- end
-
- @active
- end
-
- private
-
- def find_diff
- return nil unless noteable
- return @diff if defined?(@diff)
-
- @diff = noteable.diffs(Commit.max_diff_options).find do |d|
- d.new_path && Digest::SHA1.hexdigest(d.new_path) == diff_file_hash
- end
- end
-
- def set_diff
- # First lets find notes with same diff
- # before iterating over all mr diffs
- diff = diff_for_line_code unless for_merge_request?
- diff ||= find_diff
-
- self.st_diff = diff.to_hash if diff
- end
-
- def diff_for_line_code
- attributes = {
- noteable_type: noteable_type,
- line_code: line_code
- }
-
- if for_commit?
- attributes[:commit_id] = commit_id
- else
- attributes[:noteable_id] = noteable_id
- end
-
- self.class.where(attributes).last.try(:diff)
- end
-
- def generate_line_code(line)
- Gitlab::Diff::LineCode.generate(diff_file_path, line.new_pos, line.old_pos)
- end
-
- # Find the diff on noteable that matches our own
- def find_noteable_diff
- diffs = noteable.diffs(Commit.max_diff_options)
- diffs.find { |d| d.new_path == self.diff.new_path }
- end
-end
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
index 18657c3e1c..927e764af9 100644
--- a/app/models/lfs_object.rb
+++ b/app/models/lfs_object.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: lfs_objects
+#
+# id :integer not null, primary key
+# oid :string not null
+# size :integer not null
+# created_at :datetime
+# updated_at :datetime
+# file :string
+#
+
class LfsObject < ActiveRecord::Base
has_many :lfs_objects_projects, dependent: :destroy
has_many :projects, through: :lfs_objects_projects
diff --git a/app/models/lfs_objects_project.rb b/app/models/lfs_objects_project.rb
index 0fd5f089db..890736bfc8 100644
--- a/app/models/lfs_objects_project.rb
+++ b/app/models/lfs_objects_project.rb
@@ -1,3 +1,14 @@
+# == Schema Information
+#
+# Table name: lfs_objects_projects
+#
+# id :integer not null, primary key
+# lfs_object_id :integer not null
+# project_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+#
+
class LfsObjectsProject < ActiveRecord::Base
belongs_to :project
belongs_to :lfs_object
diff --git a/app/models/member.rb b/app/models/member.rb
index d3060f07fc..cca82da89f 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -1,3 +1,22 @@
+# == Schema Information
+#
+# Table name: members
+#
+# id :integer not null, primary key
+# access_level :integer not null
+# source_id :integer not null
+# source_type :string not null
+# user_id :integer
+# notification_level :integer not null
+# type :string
+# created_at :datetime
+# updated_at :datetime
+# created_by_id :integer
+# invite_email :string
+# invite_token :string
+# invite_accepted_at :datetime
+#
+
class Member < ActiveRecord::Base
include Sortable
include Gitlab::Access
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index f63a0debf1..a48c1943e6 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -1,3 +1,22 @@
+# == Schema Information
+#
+# Table name: members
+#
+# id :integer not null, primary key
+# access_level :integer not null
+# source_id :integer not null
+# source_type :string not null
+# user_id :integer
+# notification_level :integer not null
+# type :string
+# created_at :datetime
+# updated_at :datetime
+# created_by_id :integer
+# invite_email :string
+# invite_token :string
+# invite_accepted_at :datetime
+#
+
class GroupMember < Member
SOURCE_TYPE = 'Namespace'
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 46955b430f..143350a0b5 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -1,3 +1,22 @@
+# == Schema Information
+#
+# Table name: members
+#
+# id :integer not null, primary key
+# access_level :integer not null
+# source_id :integer not null
+# source_type :string not null
+# user_id :integer
+# notification_level :integer not null
+# type :string
+# created_at :datetime
+# updated_at :datetime
+# created_by_id :integer
+# invite_email :string
+# invite_token :string
+# invite_accepted_at :datetime
+#
+
class ProjectMember < Member
SOURCE_TYPE = 'Project'
@@ -5,6 +24,7 @@ class ProjectMember < Member
belongs_to :project, class_name: 'Project', foreign_key: 'source_id'
+
# Make sure project member points only to project as it source
default_value_for :source_type, SOURCE_TYPE
validates_format_of :source_type, with: /\AProject\z/
@@ -14,8 +34,6 @@ class ProjectMember < Member
scope :in_projects, ->(projects) { where(source_id: projects.pluck(:id)) }
scope :with_user, ->(user) { where(user_id: user.id) }
- before_destroy :delete_member_todos
-
class << self
# Add users to project teams with passed access option
@@ -103,10 +121,6 @@ class ProjectMember < Member
private
- def delete_member_todos
- user.todos.where(project_id: source_id).destroy_all if user
- end
-
def send_invite
notification_service.invite_project_member(self, @raw_invite_token)
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 722c258244..4175e1e5fb 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -1,3 +1,33 @@
+# == Schema Information
+#
+# Table name: merge_requests
+#
+# id :integer not null, primary key
+# target_branch :string not null
+# source_branch :string not null
+# source_project_id :integer not null
+# author_id :integer
+# assignee_id :integer
+# title :string
+# created_at :datetime
+# updated_at :datetime
+# milestone_id :integer
+# state :string
+# merge_status :string
+# target_project_id :integer not null
+# iid :integer
+# description :text
+# position :integer default(0)
+# locked_at :datetime
+# updated_by_id :integer
+# merge_error :string
+# merge_params :text
+# merge_when_build_succeeds :boolean default(FALSE), not null
+# merge_user_id :integer
+# merge_commit_sha :string
+# deleted_at :datetime
+#
+
class MergeRequest < ActiveRecord::Base
include InternalId
include Issuable
@@ -26,10 +56,6 @@ class MergeRequest < ActiveRecord::Base
# when creating new merge request
attr_accessor :can_be_created, :compare_commits, :compare
- # Temporary fields to store target_sha, and base_sha to
- # compare when importing pull requests from GitHub
- attr_accessor :base_target_sha, :head_source_sha
-
state_machine :state, initial: :opened do
event :close do
transition [:reopened, :opened] => :closed
@@ -286,18 +312,6 @@ class MergeRequest < ActiveRecord::Base
last_commit == source_project.commit(source_branch)
end
- def should_remove_source_branch?
- merge_params['should_remove_source_branch'].present?
- end
-
- def force_remove_source_branch?
- merge_params['force_remove_source_branch'].present?
- end
-
- def remove_source_branch?
- should_remove_source_branch? || force_remove_source_branch?
- end
-
def mr_and_commit_notes
# Fetch comments only from last 100 commits
commits_for_notes_limit = 100
@@ -438,10 +452,7 @@ class MergeRequest < ActiveRecord::Base
self.merge_when_build_succeeds = false
self.merge_user = nil
- if merge_params
- merge_params.delete('should_remove_source_branch')
- merge_params.delete('commit_message')
- end
+ self.merge_params = nil
self.save
end
@@ -509,14 +520,10 @@ class MergeRequest < ActiveRecord::Base
end
def target_sha
- return @base_target_sha if defined?(@base_target_sha)
-
- target_project.repository.commit(target_branch).try(:sha)
+ @target_sha ||= target_project.repository.commit(target_branch).try(:sha)
end
def source_sha
- return @head_source_sha if defined?(@head_source_sha)
-
last_commit.try(:sha) || source_tip.try(:sha)
end
@@ -537,7 +544,7 @@ class MergeRequest < ActiveRecord::Base
end
def ref_is_fetched?
- File.exist?(File.join(project.repository.path_to_repo, ref_path))
+ File.exists?(File.join(project.repository.path_to_repo, ref_path))
end
def ensure_ref_fetched
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 7d5103748f..8951e92a0b 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -1,3 +1,18 @@
+# == Schema Information
+#
+# Table name: merge_request_diffs
+#
+# id :integer not null, primary key
+# state :string
+# st_commits :text
+# st_diffs :text
+# merge_request_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+# base_commit_sha :string
+# real_size :string
+#
+
class MergeRequestDiff < ActiveRecord::Base
include Sortable
@@ -6,7 +21,7 @@ class MergeRequestDiff < ActiveRecord::Base
belongs_to :merge_request
- delegate :head_source_sha, :target_branch, :source_branch, to: :merge_request, prefix: nil
+ delegate :target_branch, :source_branch, to: :merge_request, prefix: nil
state_machine :state, initial: :empty do
state :collected
@@ -38,8 +53,8 @@ class MergeRequestDiff < ActiveRecord::Base
@diffs_no_whitespace ||= begin
compare = Gitlab::Git::Compare.new(
self.repository.raw_repository,
- self.base,
- self.head,
+ self.target_branch,
+ self.source_sha,
)
compare.diffs(options)
end
@@ -98,7 +113,9 @@ class MergeRequestDiff < ActiveRecord::Base
commits = compare.commits
if commits.present?
- commits = Commit.decorate(commits, merge_request.source_project).reverse
+ commits = Commit.decorate(commits, merge_request.source_project).
+ sort_by(&:created_at).
+ reverse
end
commits
@@ -142,7 +159,7 @@ class MergeRequestDiff < ActiveRecord::Base
self.st_diffs = new_diffs
- self.base_commit_sha = self.repository.merge_base(self.head, self.base)
+ self.base_commit_sha = self.repository.merge_base(self.source_sha, self.target_branch)
self.save
end
@@ -158,24 +175,10 @@ class MergeRequestDiff < ActiveRecord::Base
end
def source_sha
- return head_source_sha if head_source_sha.present?
-
source_commit = merge_request.source_project.commit(source_branch)
source_commit.try(:sha)
end
- def target_sha
- merge_request.target_sha
- end
-
- def base
- self.target_sha || self.target_branch
- end
-
- def head
- self.source_sha
- end
-
def compare
@compare ||=
begin
@@ -184,8 +187,8 @@ class MergeRequestDiff < ActiveRecord::Base
Gitlab::Git::Compare.new(
self.repository.raw_repository,
- self.base,
- self.head
+ self.target_branch,
+ self.source_sha
)
end
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index e0c8454a99..5ee8a965ad 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -1,3 +1,18 @@
+# == Schema Information
+#
+# Table name: milestones
+#
+# id :integer not null, primary key
+# title :string not null
+# project_id :integer not null
+# description :text
+# due_date :date
+# created_at :datetime
+# updated_at :datetime
+# state :string
+# iid :integer
+#
+
class Milestone < ActiveRecord::Base
# Represents a "No Milestone" state used for filtering Issues and Merge
# Requests that have no milestone assigned.
@@ -59,67 +74,25 @@ class Milestone < ActiveRecord::Base
end
end
- def self.reference_prefix
- '%'
- end
-
def self.reference_pattern
- # NOTE: The iid pattern only matches when all characters on the expression
- # are digits, so it will match %2 but not %2.1 because that's probably a
- # milestone name and we want it to be matched as such.
- @reference_pattern ||= %r{
- (#{Project.reference_pattern})?
- #{Regexp.escape(reference_prefix)}
- (?:
- (?
- \d+(?!\S\w)\b # Integer-based milestone iid, or
- ) |
- (?
- [^"\s]+\b | # String-based single-word milestone title, or
- "[^"]+" # String-based multi-word milestone surrounded in quotes
- )
- )
- }x
+ nil
end
def self.link_reference_pattern
@link_reference_pattern ||= super("milestones", /(?\d+)/)
end
- def self.upcoming_ids_by_projects(projects)
- rel = unscoped.of_projects(projects).active.where('due_date > ?', Time.now)
-
- if Gitlab::Database.postgresql?
- rel.order(:project_id, :due_date).select('DISTINCT ON (project_id) id')
- else
- rel.
- group(:project_id).
- having('due_date = MIN(due_date)').
- pluck(:id, :project_id, :due_date).
- map(&:first)
- end
+ def self.upcoming
+ self.where('due_date > ?', Time.now).reorder(due_date: :asc).first
end
- ##
- # Returns the String necessary to reference this Milestone in Markdown
- #
- # format - Symbol format to use (default: :iid, optional: :name)
- #
- # Examples:
- #
- # Milestone.first.to_reference # => "%1"
- # Milestone.first.to_reference(format: :name) # => "%\"goal\""
- # Milestone.first.to_reference(project) # => "gitlab-org/gitlab-ce%1"
- #
- def to_reference(from_project = nil, format: :iid)
- format_reference = milestone_format_reference(format)
- reference = "#{self.class.reference_prefix}#{format_reference}"
+ def to_reference(from_project = nil)
+ escaped_title = self.title.gsub("]", "\\]")
- if cross_project_reference?(from_project)
- project.to_reference + reference
- else
- reference
- end
+ h = Gitlab::Routing.url_helpers
+ url = h.namespace_project_milestone_url(self.project.namespace, self.project, self)
+
+ "[#{escaped_title}](#{url})"
end
def reference_link_text(from_project = nil)
@@ -156,10 +129,6 @@ class Milestone < ActiveRecord::Base
nil
end
- def title=(value)
- write_attribute(:title, Sanitize.clean(value.to_s)) if value.present?
- end
-
# Sorts the issues for the given IDs.
#
# This method runs a single SQL query using a CASE statement to update the
@@ -191,16 +160,4 @@ class Milestone < ActiveRecord::Base
issues.where(id: ids).
update_all(["position = CASE #{conditions} ELSE position END", *pairs])
end
-
- private
-
- def milestone_format_reference(format = :iid)
- raise ArgumentError, 'Unknown format' unless [:iid, :name].include?(format)
-
- if format == :name && !name.include?('"')
- %("#{name}")
- else
- iid
- end
- end
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index da19462f26..741e912171 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -1,3 +1,20 @@
+# == Schema Information
+#
+# Table name: namespaces
+#
+# id :integer not null, primary key
+# name :string not null
+# path :string not null
+# owner_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string
+# description :string default(""), not null
+# avatar :string
+# share_with_group_lock :boolean default(FALSE)
+# visibility_level :integer default(20), not null
+#
+
class Namespace < ActiveRecord::Base
include Sortable
include Gitlab::ShellAdapter
@@ -110,10 +127,6 @@ class Namespace < ActiveRecord::Base
# Ensure old directory exists before moving it
gitlab_shell.add_namespace(path_was)
- if any_project_has_container_registry_tags?
- raise Exception.new('Namespace cannot be moved, because at least one project has tags in container registry')
- end
-
if gitlab_shell.mv_namespace(path_was, path)
Gitlab::UploadsTransfer.new.rename_namespace(path_was, path)
@@ -135,10 +148,6 @@ class Namespace < ActiveRecord::Base
end
end
- def any_project_has_container_registry_tags?
- projects.any?(&:has_container_registry_tags?)
- end
-
def send_update_instructions
projects.each do |project|
project.send_move_instructions("#{path_was}/#{project.path}")
diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb
index a2aee2f925..f4e9012537 100644
--- a/app/models/network/graph.rb
+++ b/app/models/network/graph.rb
@@ -22,16 +22,9 @@ module Network
def collect_notes
h = Hash.new(0)
-
- @project
- .notes
- .where('noteable_type = ?', 'Commit')
- .group('notes.commit_id')
- .select('notes.commit_id, count(notes.id) as note_count')
- .each do |item|
- h[item.commit_id] = item.note_count.to_i
- end
-
+ @project.notes.where('noteable_type = ?' ,"Commit").group('notes.commit_id').select('notes.commit_id, count(notes.id) as note_count').each do |item|
+ h[item.commit_id] = item.note_count.to_i
+ end
h
end
@@ -96,7 +89,7 @@ module Network
end
end
- if self.class.max_count / 2 < offset
+ if self.class.max_count / 2 < offset then
# get max index that commit is displayed in the center.
offset - self.class.max_count / 2
else
@@ -137,7 +130,7 @@ module Network
commit.parents(@map).each do |parent|
range = commit.time..parent.time
- space = if commit.space >= parent.space
+ space = if commit.space >= parent.space then
find_free_parent_space(range, parent.space, -1, commit.space)
else
find_free_parent_space(range, commit.space, -1, parent.space)
@@ -151,7 +144,7 @@ module Network
end
def find_free_parent_space(range, space_base, space_step, space_default)
- if is_overlap?(range, space_default)
+ if is_overlap?(range, space_default) then
find_free_space(range, space_step, space_base, space_default)
else
space_default
@@ -162,9 +155,9 @@ module Network
range.each do |i|
if i != range.first &&
i != range.last &&
- @commits[i].spaces.include?(overlap_space)
+ @commits[i].spaces.include?(overlap_space) then
- return true
+ return true;
end
end
@@ -205,7 +198,7 @@ module Network
# Visit branching chains
leaves.each do |l|
parents = l.parents(@map).select{|p| p.space.zero?}
- parents.each do |p|
+ for p in parents
place_chain(p, l.time)
end
end
@@ -223,7 +216,7 @@ module Network
end
def mark_reserved(time_range, space)
- time_range.each do |day|
+ for day in time_range
@reserved[day].push(space)
end
end
@@ -232,15 +225,15 @@ module Network
space_default ||= space_base
reserved = []
- time_range.each do |day|
+ for day in time_range
reserved.push(*@reserved[day])
end
reserved.uniq!
space = space_default
- while reserved.include?(space)
+ while reserved.include?(space) do
space += space_step
- if space < space_base
+ if space < space_base then
space_step *= -1
space = space_base + space_step
end
@@ -260,7 +253,7 @@ module Network
leaves = []
leaves.push(commit) if commit.space.zero?
- loop do
+ while true
return leaves if commit.parents(@map).count.zero?
commit = commit.parents(@map).first
diff --git a/app/models/note.rb b/app/models/note.rb
index c21981ead8..deee2b9e88 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -1,12 +1,34 @@
+# == Schema Information
+#
+# Table name: notes
+#
+# id :integer not null, primary key
+# note :text
+# noteable_type :string
+# author_id :integer
+# created_at :datetime
+# updated_at :datetime
+# project_id :integer
+# attachment :string
+# line_code :string
+# commit_id :string
+# noteable_id :integer
+# system :boolean default(FALSE), not null
+# st_diff :text
+# updated_by_id :integer
+# is_award :boolean default(FALSE), not null
+#
+
+require 'carrierwave/orm/activerecord'
+
class Note < ActiveRecord::Base
- extend ActiveModel::Naming
include Gitlab::CurrentSettings
include Participable
include Mentionable
default_value_for :system, false
- attr_mentionable :note, pipeline: :note
+ attr_mentionable :note, cache: true, pipeline: :note
participant :author
belongs_to :project
@@ -19,33 +41,29 @@ class Note < ActiveRecord::Base
delegate :gfm_reference, :local_reference, to: :noteable
delegate :name, to: :project, prefix: true
delegate :name, :email, to: :author, prefix: true
- delegate :title, to: :noteable, allow_nil: true
before_validation :set_award!
+ before_validation :clear_blank_line_code!
validates :note, :project, presence: true
validates :note, uniqueness: { scope: [:author, :noteable_type, :noteable_id] }, if: ->(n) { n.is_award }
validates :note, inclusion: { in: Emoji.emojis_names }, if: ->(n) { n.is_award }
+ validates :line_code, line_code: true, allow_blank: true
# Attachments are deprecated and are handled by Markdown uploader
validates :attachment, file_size: { maximum: :max_attachment_size }
- validates :noteable_type, presence: true
- validates :noteable_id, presence: true, unless: :for_commit?
- validates :commit_id, presence: true, if: :for_commit?
+ validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' }
+ validates :commit_id, presence: true, if: ->(n) { n.noteable_type == 'Commit' }
validates :author, presence: true
- validate unless: :for_commit? do |note|
- unless note.noteable.try(:project) == note.project
- errors.add(:invalid_project, 'Note and noteable project mismatch')
- end
- end
-
mount_uploader :attachment, AttachmentUploader
# Scopes
scope :awards, ->{ where(is_award: true) }
scope :nonawards, ->{ where(is_award: false) }
scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) }
+ scope :inline, ->{ where("line_code IS NOT NULL") }
+ scope :not_inline, ->{ where(line_code: nil) }
scope :system, ->{ where(system: true) }
scope :user, ->{ where(system: false) }
scope :common, ->{ where(noteable_type: ["", nil]) }
@@ -53,61 +71,52 @@ class Note < ActiveRecord::Base
scope :inc_author_project, ->{ includes(:project, :author) }
scope :inc_author, ->{ includes(:author) }
- scope :legacy_diff_notes, ->{ where(type: 'LegacyDiffNote') }
- scope :non_diff_notes, ->{ where(type: ['Note', nil]) }
-
scope :with_associations, -> do
includes(:author, :noteable, :updated_by,
project: [:project_members, { group: [:group_members] }])
end
- before_validation :clear_blank_line_code!
+ serialize :st_diff
+ before_create :set_diff, if: ->(n) { n.line_code.present? }
class << self
- def model_name
- ActiveModel::Name.new(self, nil, 'note')
+ def discussions_from_notes(notes)
+ discussion_ids = []
+ discussions = []
+
+ notes.each do |note|
+ next if discussion_ids.include?(note.discussion_id)
+
+ # don't group notes for the main target
+ if !note.for_diff_line? && note.for_merge_request?
+ discussions << [note]
+ else
+ discussions << notes.select do |other_note|
+ note.discussion_id == other_note.discussion_id
+ end
+ discussion_ids << note.discussion_id
+ end
+ end
+
+ discussions
end
- def build_discussion_id(noteable_type, noteable_id)
- [:discussion, noteable_type.try(:underscore), noteable_id].join("-")
- end
-
- def discussions
- all.group_by(&:discussion_id).values
- end
-
- def grouped_diff_notes
- legacy_diff_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code)
+ def build_discussion_id(type, id, line_code)
+ [:discussion, type.try(:underscore), id, line_code].join("-").to_sym
end
# Searches for notes matching the given query.
#
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
#
- # query - The search query as a String.
- # as_user - Limit results to those viewable by a specific user
+ # query - The search query as a String.
#
# Returns an ActiveRecord::Relation.
- def search(query, as_user: nil)
+ def search(query)
table = arel_table
pattern = "%#{query}%"
- found_notes = joins('LEFT JOIN issues ON issues.id = noteable_id').
- where(table[:note].matches(pattern))
-
- if as_user
- found_notes.where('
- issues.confidential IS NULL
- OR issues.confidential IS FALSE
- OR (issues.confidential IS TRUE
- AND (issues.author_id = :user_id
- OR issues.assignee_id = :user_id
- OR issues.project_id IN(:project_ids)))',
- user_id: as_user.id,
- project_ids: as_user.authorized_projects.select(:id))
- else
- found_notes.where('issues.confidential IS NULL OR issues.confidential IS FALSE')
- end
+ where(table[:note].matches(pattern))
end
def grouped_awards
@@ -128,39 +137,167 @@ class Note < ActiveRecord::Base
system && SystemNoteService.cross_reference?(note)
end
- def diff_note?
- false
- end
-
- def legacy_diff_note?
- false
- end
-
- def active?
- true
- end
-
- def discussion_id
- @discussion_id ||=
- if for_merge_request?
- [:discussion, :note, id].join("-")
- else
- self.class.build_discussion_id(noteable_type, noteable_id || commit_id)
- end
- end
-
def max_attachment_size
current_application_settings.max_attachment_size.megabytes.to_i
end
+ def find_diff
+ return nil unless noteable
+ return @diff if defined?(@diff)
+
+ # Don't use ||= because nil is a valid value for @diff
+ @diff = noteable.diffs(Commit.max_diff_options).find do |d|
+ Digest::SHA1.hexdigest(d.new_path) == diff_file_index if d.new_path
+ end
+ end
+
def hook_attrs
attributes
end
+ def set_diff
+ # First lets find notes with same diff
+ # before iterating over all mr diffs
+ diff = diff_for_line_code unless for_merge_request?
+ diff ||= find_diff
+
+ self.st_diff = diff.to_hash if diff
+ end
+
+ def diff
+ @diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map)
+ end
+
+ def diff_for_line_code
+ Note.where(noteable_id: noteable_id, noteable_type: noteable_type, line_code: line_code).last.try(:diff)
+ end
+
+ # Check if this note is part of an "active" discussion
+ #
+ # This will always return true for anything except MergeRequest noteables,
+ # which have special logic.
+ #
+ # If the note's current diff cannot be matched in the MergeRequest's current
+ # diff, it's considered inactive.
+ def active?
+ return true unless self.diff
+ return false unless noteable
+ return @active if defined?(@active)
+
+ noteable_diff = find_noteable_diff
+
+ if noteable_diff
+ parsed_lines = Gitlab::Diff::Parser.new.parse(noteable_diff.diff.each_line)
+
+ @active = parsed_lines.any? { |line_obj| line_obj.text == diff_line }
+ else
+ @active = false
+ end
+
+ @active
+ end
+
+ def diff_file_index
+ line_code.split('_')[0] if line_code
+ end
+
+ def diff_file_name
+ diff.new_path if diff
+ end
+
+ def file_path
+ if diff.new_path.present?
+ diff.new_path
+ elsif diff.old_path.present?
+ diff.old_path
+ end
+ end
+
+ def diff_old_line
+ line_code.split('_')[1].to_i if line_code
+ end
+
+ def diff_new_line
+ line_code.split('_')[2].to_i if line_code
+ end
+
+ def generate_line_code(line)
+ Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos)
+ end
+
+ def diff_line
+ return @diff_line if @diff_line
+
+ if diff
+ diff_lines.each do |line|
+ if generate_line_code(line) == self.line_code
+ @diff_line = line.text
+ end
+ end
+ end
+
+ @diff_line
+ end
+
+ def diff_line_type
+ return @diff_line_type if @diff_line_type
+
+ if diff
+ diff_lines.each do |line|
+ if generate_line_code(line) == self.line_code
+ @diff_line_type = line.type
+ end
+ end
+ end
+
+ @diff_line_type
+ end
+
+ def truncated_diff_lines
+ max_number_of_lines = 16
+ prev_match_line = nil
+ prev_lines = []
+
+ highlighted_diff_lines.each do |line|
+ if line.type == "match"
+ prev_lines.clear
+ prev_match_line = line
+ else
+ prev_lines << line
+
+ break if generate_line_code(line) == self.line_code
+
+ prev_lines.shift if prev_lines.length >= max_number_of_lines
+ end
+ end
+
+ prev_lines
+ end
+
+ def diff_lines
+ @diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.each_line)
+ end
+
+ def highlighted_diff_lines
+ Gitlab::Diff::Highlight.new(diff_lines).highlight
+ end
+
+ def discussion_id
+ @discussion_id ||= Note.build_discussion_id(noteable_type, noteable_id || commit_id, line_code)
+ end
+
def for_commit?
noteable_type == "Commit"
end
+ def for_commit_diff_line?
+ for_commit? && for_diff_line?
+ end
+
+ def for_diff_line?
+ line_code.present?
+ end
+
def for_issue?
noteable_type == "Issue"
end
@@ -169,6 +306,10 @@ class Note < ActiveRecord::Base
noteable_type == "MergeRequest"
end
+ def for_merge_request_diff_line?
+ for_merge_request? && for_diff_line?
+ end
+
def for_snippet?
noteable_type == "Snippet"
end
@@ -241,8 +382,14 @@ class Note < ActiveRecord::Base
self.line_code = nil if self.line_code.blank?
end
+ # Find the diff on noteable that matches our own
+ def find_noteable_diff
+ diffs = noteable.diffs(Commit.max_diff_options)
+ diffs.find { |d| d.new_path == self.diff.new_path }
+ end
+
def awards_supported?
- (for_issue? || for_merge_request?) && !diff_note?
+ (for_issue? || for_merge_request?) && !for_diff_line?
end
def contains_emoji_only?
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index 5001738f41..846773752a 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: notification_settings
+#
+# id :integer not null, primary key
+# user_id :integer not null
+# source_id :integer not null
+# source_type :string not null
+# level :integer default(0), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
class NotificationSetting < ActiveRecord::Base
enum level: { disabled: 0, participating: 1, watch: 2, global: 3, mention: 4 }
diff --git a/app/models/oauth_access_token.rb b/app/models/oauth_access_token.rb
index 116fb71ac0..c78c7f4aa0 100644
--- a/app/models/oauth_access_token.rb
+++ b/app/models/oauth_access_token.rb
@@ -1,3 +1,18 @@
+# == Schema Information
+#
+# Table name: oauth_access_tokens
+#
+# id :integer not null, primary key
+# resource_owner_id :integer
+# application_id :integer
+# token :string not null
+# refresh_token :string
+# expires_in :integer
+# revoked_at :datetime
+# created_at :datetime not null
+# scopes :string
+#
+
class OauthAccessToken < ActiveRecord::Base
belongs_to :resource_owner, class_name: 'User'
belongs_to :application, class_name: 'Doorkeeper::Application'
diff --git a/app/models/personal_snippet.rb b/app/models/personal_snippet.rb
index 82c1c4de3a..1d5f4c5025 100644
--- a/app/models/personal_snippet.rb
+++ b/app/models/personal_snippet.rb
@@ -1,2 +1,18 @@
+# == Schema Information
+#
+# Table name: snippets
+#
+# id :integer not null, primary key
+# title :string
+# content :text
+# author_id :integer not null
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# file_name :string
+# type :string
+# visibility_level :integer default(0), not null
+#
+
class PersonalSnippet < Snippet
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 74db163bcb..fdbabc7cf7 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1,3 +1,48 @@
+# == Schema Information
+#
+# Table name: projects
+#
+# id :integer not null, primary key
+# name :string
+# path :string
+# description :text
+# created_at :datetime
+# updated_at :datetime
+# creator_id :integer
+# issues_enabled :boolean default(TRUE), not null
+# merge_requests_enabled :boolean default(TRUE), not null
+# wiki_enabled :boolean default(TRUE), not null
+# namespace_id :integer
+# issues_tracker :string default("gitlab"), not null
+# issues_tracker_id :string
+# snippets_enabled :boolean default(TRUE), not null
+# last_activity_at :datetime
+# import_url :string
+# visibility_level :integer default(0), not null
+# archived :boolean default(FALSE), not null
+# avatar :string
+# import_status :string
+# repository_size :float default(0.0)
+# star_count :integer default(0), not null
+# import_type :string
+# import_source :string
+# commit_count :integer default(0)
+# import_error :text
+# ci_id :integer
+# builds_enabled :boolean default(TRUE), not null
+# shared_runners_enabled :boolean default(TRUE), not null
+# runners_token :string
+# build_coverage_regex :string
+# build_allow_git_fetch :boolean default(TRUE), not null
+# build_timeout :integer default(3600), not null
+# pending_delete :boolean default(FALSE)
+# public_builds :boolean default(TRUE), not null
+# main_language :string
+# pushes_since_gc :integer default(0)
+# last_repository_check_failed :boolean
+# last_repository_check_at :datetime
+#
+
require 'carrierwave/orm/activerecord'
class Project < ActiveRecord::Base
@@ -22,7 +67,6 @@ class Project < ActiveRecord::Base
default_value_for :builds_enabled, gitlab_config_features.builds
default_value_for :wiki_enabled, gitlab_config_features.wiki
default_value_for :snippets_enabled, gitlab_config_features.snippets
- default_value_for :container_registry_enabled, gitlab_config_features.container_registry
default_value_for(:shared_runners_enabled) { current_application_settings.shared_runners_enabled }
# set last_activity_at to the same as created_at
@@ -50,8 +94,6 @@ class Project < ActiveRecord::Base
attr_accessor :new_default_branch
attr_accessor :old_path_with_namespace
- alias_attribute :title, :name
-
# Relations
belongs_to :creator, foreign_key: 'creator_id', class_name: 'User'
belongs_to :group, -> { where(type: Group) }, foreign_key: 'namespace_id'
@@ -171,17 +213,17 @@ class Project < ActiveRecord::Base
scope :sorted_by_activity, -> { reorder(last_activity_at: :desc) }
scope :sorted_by_stars, -> { reorder('projects.star_count DESC') }
+ scope :sorted_by_names, -> { joins(:namespace).reorder('namespaces.name ASC, projects.name ASC') }
+ scope :without_user, ->(user) { where('projects.id NOT IN (:ids)', ids: user.authorized_projects.map(&:id) ) }
+ scope :without_team, ->(team) { team.projects.present? ? where('projects.id NOT IN (:ids)', ids: team.projects.map(&:id)) : scoped }
+ scope :not_in_group, ->(group) { where('projects.id NOT IN (:ids)', ids: group.project_ids ) }
scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) }
+ scope :in_group_namespace, -> { joins(:group) }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) }
- scope :visible_to_user, ->(user) { where(id: user.authorized_projects.select(:id).reorder(nil)) }
scope :non_archived, -> { where(archived: false) }
scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct }
- scope :with_push, -> { joins(:events).where('events.action = ?', Event::PUSHED) }
-
- scope :active, -> { joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') }
- scope :abandoned, -> { where('projects.last_activity_at < ?', 6.months.ago) }
state_machine :import_status, initial: :none do
event :import_start do
@@ -204,10 +246,23 @@ class Project < ActiveRecord::Base
state :finished
state :failed
- after_transition any => :finished, do: :reset_cache_and_import_attrs
+ after_transition any => :started, do: :schedule_add_import_job
+ after_transition any => :finished, do: :clear_import_data
end
class << self
+ def abandoned
+ where('projects.last_activity_at < ?', 6.months.ago)
+ end
+
+ def with_push
+ joins(:events).where('events.action = ?', Event::PUSHED)
+ end
+
+ def active
+ joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC')
+ end
+
# Searches for a list of projects based on the query given in `query`.
#
# On PostgreSQL this method uses "ILIKE" to perform a case-insensitive
@@ -269,6 +324,10 @@ class Project < ActiveRecord::Base
projects.iwhere('projects.path' => project_path).take
end
+ def find_by_ci_id(id)
+ find_by(ci_id: id.to_i)
+ end
+
def visibility_levels
Gitlab::VisibilityLevel.options
end
@@ -299,6 +358,10 @@ class Project < ActiveRecord::Base
joins(join_body).reorder('join_note_counts.amount DESC')
end
+
+ def visible_to_user(user)
+ where(id: user.authorized_projects.select(:id).reorder(nil))
+ end
end
def team
@@ -309,34 +372,6 @@ class Project < ActiveRecord::Base
@repository ||= Repository.new(path_with_namespace, self)
end
- def container_registry_path_with_namespace
- path_with_namespace.downcase
- end
-
- def container_registry_repository
- return unless Gitlab.config.registry.enabled
-
- @container_registry_repository ||= begin
- token = Auth::ContainerRegistryAuthenticationService.full_access_token(container_registry_path_with_namespace)
- url = Gitlab.config.registry.api_url
- host_port = Gitlab.config.registry.host_port
- registry = ContainerRegistry::Registry.new(url, token: token, path: host_port)
- registry.repository(container_registry_path_with_namespace)
- end
- end
-
- def container_registry_repository_url
- if Gitlab.config.registry.enabled
- "#{Gitlab.config.registry.host_port}/#{container_registry_path_with_namespace}"
- end
- end
-
- def has_container_registry_tags?
- return unless container_registry_repository
-
- container_registry_repository.tags.any?
- end
-
def commit(id = 'HEAD')
repository.commit(id)
end
@@ -350,6 +385,10 @@ class Project < ActiveRecord::Base
id && persisted?
end
+ def schedule_add_import_job
+ run_after_commit(:add_import_job)
+ end
+
def add_import_job
if forked?
job_id = RepositoryForkWorker.perform_async(self.id, forked_from_project.path_with_namespace, self.namespace.path)
@@ -364,7 +403,7 @@ class Project < ActiveRecord::Base
end
end
- def reset_cache_and_import_attrs
+ def clear_import_data
update(import_error: nil)
ProjectCacheWorker.perform_async(self.id)
@@ -373,14 +412,14 @@ class Project < ActiveRecord::Base
end
def import_url=(value)
- import_url = Gitlab::UrlSanitizer.new(value)
+ import_url = Gitlab::ImportUrl.new(value)
create_or_update_import_data(credentials: import_url.credentials)
super(import_url.sanitized_url)
end
def import_url
if import_data && super
- import_url = Gitlab::UrlSanitizer.new(super, credentials: import_data.credentials)
+ import_url = Gitlab::ImportUrl.new(super, credentials: import_data.credentials)
import_url.full_url
else
super
@@ -430,18 +469,17 @@ class Project < ActiveRecord::Base
end
def safe_import_url
- Gitlab::UrlSanitizer.new(import_url).masked_url
+ result = URI.parse(self.import_url)
+ result.password = '*****' unless result.password.nil?
+ result.user = '*****' unless result.user.nil? || result.user == "git" #tokens or other data may be saved as user
+ result.to_s
+ rescue
+ self.import_url
end
def check_limit
unless creator.can_create_project? or namespace.kind == 'group'
- projects_limit = creator.projects_limit
-
- if projects_limit == 0
- self.errors.add(:limit_reached, "Personal project creation is not allowed. Please contact your administrator with questions")
- else
- self.errors.add(:limit_reached, "Your project limit is #{projects_limit} projects! Please contact your administrator to increase it")
- end
+ self.errors.add(:limit_reached, "Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it")
end
rescue
self.errors.add(:base, "Can't check your ability to create project")
@@ -749,11 +787,6 @@ class Project < ActiveRecord::Base
expire_caches_before_rename(old_path_with_namespace)
- if has_container_registry_tags?
- # we currently doesn't support renaming repository if it contains tags in container registry
- raise Exception.new('Project cannot be renamed, because tags are present in its container registry')
- end
-
if gitlab_shell.mv_repository(old_path_with_namespace, new_path_with_namespace)
# If repository moved successfully we need to send update instructions to users.
# However we cannot allow rollback since we moved repository
@@ -950,13 +983,13 @@ class Project < ActiveRecord::Base
shared_runners_enabled? && Ci::Runner.shared.active.any?(&block)
end
- def valid_runners_token?(token)
+ def valid_runners_token? token
self.runners_token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.runners_token)
end
# TODO (ayufan): For now we use runners_token (backward compatibility)
# In 8.4 every build will have its own individual token valid for time of build
- def valid_build_token?(token)
+ def valid_build_token? token
self.builds_enabled? && self.runners_token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.runners_token)
end
@@ -1012,24 +1045,6 @@ class Project < ActiveRecord::Base
update_attribute(:pending_delete, true)
end
- def running_or_pending_build_count(force: false)
- Rails.cache.fetch(['projects', id, 'running_or_pending_build_count'], force: force) do
- builds.running_or_pending.count(:all)
- end
- end
-
- def mark_import_as_failed(error_message)
- original_errors = errors.dup
- sanitized_message = Gitlab::UrlSanitizer.sanitize(error_message)
-
- import_fail
- update_column(:import_error, sanitized_message)
- rescue ActiveRecord::ActiveRecordError => e
- Rails.logger.error("Error setting import status to failed: #{e.message}. Original error: #{sanitized_message}")
- ensure
- @errors = original_errors
- end
-
def add_export_job(current_user_id:)
job_id = ProjectExportWorker.perform_async(current_user_id, self.id)
diff --git a/app/models/project_group_link.rb b/app/models/project_group_link.rb
index e52a6bd7c8..66f5a609bf 100644
--- a/app/models/project_group_link.rb
+++ b/app/models/project_group_link.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: project_group_links
+#
+# id :integer not null, primary key
+# project_id :integer not null
+# group_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+# group_access :integer default(30), not null
+#
+
class ProjectGroupLink < ActiveRecord::Base
GUEST = 10
REPORTER = 20
diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb
index ca8a9b4217..7830f764ed 100644
--- a/app/models/project_import_data.rb
+++ b/app/models/project_import_data.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: project_import_data
+#
+# id :integer not null, primary key
+# project_id :integer
+# data :text
+# encrypted_credentials :text
+# encrypted_credentials_iv :string
+# encrypted_credentials_salt :string
+#
+
require 'carrierwave/orm/activerecord'
class ProjectImportData < ActiveRecord::Base
@@ -6,8 +18,7 @@ class ProjectImportData < ActiveRecord::Base
key: Gitlab::Application.secrets.db_key_base,
marshal: true,
encode: true,
- mode: :per_attribute_iv_and_salt,
- algorithm: 'aes-256-cbc'
+ mode: :per_attribute_iv_and_salt
serialize :data, JSON
diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb
index 7c23b76676..368485a060 100644
--- a/app/models/project_services/asana_service.rb
+++ b/app/models/project_services/asana_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
require 'asana'
class AsanaService < Service
diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb
index d839221d31..ffb7455b01 100644
--- a/app/models/project_services/assembla_service.rb
+++ b/app/models/project_services/assembla_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class AssemblaService < Service
include HTTParty
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index 1d1780dcfb..c36ee95e37 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class BambooService < CiService
include HTTParty
diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb
index 86a06321e2..f9f4897a06 100644
--- a/app/models/project_services/buildkite_service.rb
+++ b/app/models/project_services/buildkite_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
require "addressable/uri"
class BuildkiteService < CiService
diff --git a/app/models/project_services/builds_email_service.rb b/app/models/project_services/builds_email_service.rb
index 54da4d74fc..20cdfcaffb 100644
--- a/app/models/project_services/builds_email_service.rb
+++ b/app/models/project_services/builds_email_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class BuildsEmailService < Service
prop_accessor :recipients
boolean_accessor :add_pusher
diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb
index 511b2eac79..28c969fe57 100644
--- a/app/models/project_services/campfire_service.rb
+++ b/app/models/project_services/campfire_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class CampfireService < Service
prop_accessor :token, :subdomain, :room
validates :token, presence: true, if: :activated?
diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb
index 596c00705a..9bc8f982da 100644
--- a/app/models/project_services/ci_service.rb
+++ b/app/models/project_services/ci_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
# Base class for CI services
# List methods you need to implement to get your CI service
# working with GitLab Merge Requests
diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb
index 6b2b1daa72..4d1319eb6f 100644
--- a/app/models/project_services/custom_issue_tracker_service.rb
+++ b/app/models/project_services/custom_issue_tracker_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class CustomIssueTrackerService < IssueTrackerService
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb
index 966dbc41d7..d8e00e018c 100644
--- a/app/models/project_services/drone_ci_service.rb
+++ b/app/models/project_services/drone_ci_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class DroneCiService < CiService
prop_accessor :drone_url, :token, :enable_ssl_verification
diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb
index e0083c43ad..2dbd29062d 100644
--- a/app/models/project_services/emails_on_push_service.rb
+++ b/app/models/project_services/emails_on_push_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class EmailsOnPushService < Service
prop_accessor :send_from_committer_email
prop_accessor :disable_diffs
diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb
index d7b6e50519..5469049bb5 100644
--- a/app/models/project_services/external_wiki_service.rb
+++ b/app/models/project_services/external_wiki_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class ExternalWikiService < Service
include HTTParty
@@ -25,7 +49,7 @@ class ExternalWikiService < Service
def execute(_data)
@response = HTTParty.get(properties['external_wiki_url'], verify: true) rescue nil
- if @response != 200
+ if @response !=200
nil
end
end
diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb
index dd00275187..3dc1e0fbe8 100644
--- a/app/models/project_services/flowdock_service.rb
+++ b/app/models/project_services/flowdock_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
require "flowdock-git-hook"
class FlowdockService < Service
diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb
index 598aca5e06..b4c311cf66 100644
--- a/app/models/project_services/gemnasium_service.rb
+++ b/app/models/project_services/gemnasium_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
require "gemnasium/gitlab_service"
class GemnasiumService < Service
diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb
index bbc312f521..a92f722608 100644
--- a/app/models/project_services/gitlab_ci_service.rb
+++ b/app/models/project_services/gitlab_ci_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
# TODO(ayufan): The GitLabCiService is deprecated and the type should be removed when the database entries are removed
class GitlabCiService < CiService
# We override the active accessor to always make GitLabCiService disabled
diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb
index 5d17c35833..1adaeeb3b2 100644
--- a/app/models/project_services/gitlab_issue_tracker_service.rb
+++ b/app/models/project_services/gitlab_issue_tracker_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class GitlabIssueTrackerService < IssueTrackerService
include Gitlab::Routing.url_helpers
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
index 0ff4f4c8dd..f9ddf58872 100644
--- a/app/models/project_services/hipchat_service.rb
+++ b/app/models/project_services/hipchat_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class HipchatService < Service
MAX_COMMITS = 3
diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb
index 2e5e854fc5..b9a592d709 100644
--- a/app/models/project_services/irker_service.rb
+++ b/app/models/project_services/irker_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
require 'uri'
class IrkerService < Service
@@ -70,7 +94,7 @@ class IrkerService < Service
private
def get_channels
- return true unless activated?
+ return true unless :activated?
return true if recipients.nil? || recipients.empty?
map_recipients
diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb
index 6ae9b16d3c..98a3a7c6b8 100644
--- a/app/models/project_services/issue_tracker_service.rb
+++ b/app/models/project_services/issue_tracker_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class IssueTrackerService < Service
validates :project_url, :issues_url, :new_issue_url, presence: true, url: true, if: :activated?
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index beda89d396..ba68658f0b 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class JiraService < IssueTrackerService
include HTTParty
include Gitlab::Routing.url_helpers
diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb
index ad19b7795d..acaa0c3936 100644
--- a/app/models/project_services/pivotaltracker_service.rb
+++ b/app/models/project_services/pivotaltracker_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class PivotaltrackerService < Service
include HTTParty
diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb
index 3dd878e4c7..a640c8cb44 100644
--- a/app/models/project_services/pushover_service.rb
+++ b/app/models/project_services/pushover_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class PushoverService < Service
include HTTParty
base_uri 'https://api.pushover.net/1'
diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb
index 11cce3e056..e2137e92c6 100644
--- a/app/models/project_services/redmine_service.rb
+++ b/app/models/project_services/redmine_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class RedmineService < IssueTrackerService
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb
index cf9e4d5a8b..83ffa53a40 100644
--- a/app/models/project_services/slack_service.rb
+++ b/app/models/project_services/slack_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class SlackService < Service
prop_accessor :webhook, :username, :channel
boolean_accessor :notify_only_broken_builds
diff --git a/app/models/project_services/slack_service/build_message.rb b/app/models/project_services/slack_service/build_message.rb
index 69c21b3fc3..c124cad4af 100644
--- a/app/models/project_services/slack_service/build_message.rb
+++ b/app/models/project_services/slack_service/build_message.rb
@@ -35,8 +35,8 @@ class SlackService
private
def message
- "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}"
- end
+ "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} second(s)"
+ end
def format(string)
Slack::Notifier::LinkFormatter.format(string)
diff --git a/app/models/project_services/slack_service/issue_message.rb b/app/models/project_services/slack_service/issue_message.rb
index 88e053ec19..438ff33fdf 100644
--- a/app/models/project_services/slack_service/issue_message.rb
+++ b/app/models/project_services/slack_service/issue_message.rb
@@ -34,12 +34,7 @@ class SlackService
private
def message
- case state
- when "opened"
- "[#{project_link}] Issue #{state} by #{user_name}"
- else
- "[#{project_link}] Issue #{issue_link} #{state} by #{user_name}"
- end
+ "#{user_name} #{state} #{issue_link} in #{project_link}: *#{title}*"
end
def opened_issue?
@@ -47,11 +42,7 @@ class SlackService
end
def description_message
- [{
- title: issue_title,
- title_link: issue_url,
- text: format(description),
- color: "#C95823" }]
+ [{ text: format(description), color: attachment_color }]
end
def project_link
@@ -59,11 +50,7 @@ class SlackService
end
def issue_link
- "[#{issue_title}](#{issue_url})"
- end
-
- def issue_title
- "##{issue_iid} #{title}"
+ "[issue ##{issue_iid}](#{issue_url})"
end
end
end
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index b0dcb52eba..4015da3150 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
class TeamcityService < CiService
include HTTParty
diff --git a/app/models/project_snippet.rb b/app/models/project_snippet.rb
index 25b5d77764..b4b2807eba 100644
--- a/app/models/project_snippet.rb
+++ b/app/models/project_snippet.rb
@@ -1,3 +1,19 @@
+# == Schema Information
+#
+# Table name: snippets
+#
+# id :integer not null, primary key
+# title :string
+# content :text
+# author_id :integer not null
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# file_name :string
+# type :string
+# visibility_level :integer default(0), not null
+#
+
class ProjectSnippet < Snippet
belongs_to :project
belongs_to :author, class_name: "User"
@@ -7,6 +23,5 @@ class ProjectSnippet < Snippet
# Scopes
scope :fresh, -> { order("created_at DESC") }
- participant :author
- participant :notes_with_associations
+ participant :author, :notes
end
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 25d82929c0..7c1a61bb0b 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -27,10 +27,6 @@ class ProjectWiki
@project.path_with_namespace + ".wiki"
end
- def web_url
- Gitlab::Routing.url_helpers.namespace_project_wiki_url(@project.namespace, @project, :home)
- end
-
def url_to_repo
gitlab_shell.url_to_repo(path_with_namespace)
end
@@ -44,7 +40,7 @@ class ProjectWiki
end
def wiki_base_path
- [Gitlab.config.gitlab.relative_url_root, "/", @project.path_with_namespace, "/wikis"].join('')
+ ["/", @project.path_with_namespace, "/wikis"].join('')
end
# Returns the Gollum::Wiki object.
@@ -117,7 +113,7 @@ class ProjectWiki
end
def page_title_and_dir(title)
- title_array = title.split("/")
+ title_array = title.split("/")
title = title_array.pop
[title, title_array.join("/")]
end
@@ -146,16 +142,6 @@ class ProjectWiki
wiki
end
- def hook_attrs
- {
- web_url: web_url,
- git_ssh_url: ssh_url_to_repo,
- git_http_url: http_url_to_repo,
- path_with_namespace: path_with_namespace,
- default_branch: default_branch
- }
- end
-
private
def init_repo(path_with_namespace)
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 33cf046fa7..3d2052c892 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: protected_branches
+#
+# id :integer not null, primary key
+# project_id :integer not null
+# name :string not null
+# created_at :datetime
+# updated_at :datetime
+# developers_can_push :boolean default(FALSE), not null
+#
+
class ProtectedBranch < ActiveRecord::Base
include Gitlab::ShellAdapter
diff --git a/app/models/release.rb b/app/models/release.rb
index e196b84eb1..dc700d1ea5 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: releases
+#
+# id :integer not null, primary key
+# tag :string
+# description :text
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+#
+
class Release < ActiveRecord::Base
belongs_to :project
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 1ab163510b..7aebfe279f 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -81,7 +81,7 @@ class Repository
def commit(id = 'HEAD')
return nil unless exists?
commit = Gitlab::Git::Commit.find(raw_repository, id)
- commit = ::Commit.new(commit, @project) if commit
+ commit = Commit.new(commit, @project) if commit
commit
rescue Rugged::OdbError
nil
@@ -195,10 +195,6 @@ class Repository
cache.fetch(:branch_names) { branches.map(&:name) }
end
- def branch_exists?(branch_name)
- branch_names.include?(branch_name)
- end
-
def tag_names
cache.fetch(:tag_names) { raw_repository.tag_names }
end
@@ -245,7 +241,7 @@ class Repository
def cache_keys
%i(size branch_names tag_names commit_count
readme version contribution_guide changelog
- license_blob license_key gitignore)
+ license_blob license_key)
end
def build_cache
@@ -256,10 +252,6 @@ class Repository
end
end
- def expire_gitignore
- cache.expire(:gitignore)
- end
-
def expire_tags_cache
cache.expire(:tag_names)
@tags = nil
@@ -461,7 +453,7 @@ class Repository
def version
cache.fetch(:version) do
tree(:head).blobs.find do |file|
- file.name.casecmp('version').zero?
+ file.name.downcase == 'version'
end
end
end
@@ -476,36 +468,32 @@ class Repository
def changelog
cache.fetch(:changelog) do
- file_on_head(/\A(changelog|history|changes|news)/i)
+ tree(:head).blobs.find do |file|
+ file.name =~ /\A(changelog|history|changes|news)/i
+ end
end
end
def license_blob
- return nil unless head_exists?
+ return nil if !exists? || empty?
cache.fetch(:license_blob) do
- file_on_head(/\A(licen[sc]e|copying)(\..+|\z)/i)
+ tree(:head).blobs.find do |file|
+ file.name =~ /\A(licen[sc]e|copying)(\..+|\z)/i
+ end
end
end
def license_key
- return nil unless head_exists?
+ return nil if !exists? || empty?
cache.fetch(:license_key) do
Licensee.license(path).try(:key)
end
end
- def gitignore
- return nil if !exists? || empty?
-
- cache.fetch(:gitignore) do
- file_on_head(/\A\.gitignore\z/)
- end
- end
-
def gitlab_ci_yml
- return nil unless head_exists?
+ return nil if !exists? || empty?
@gitlab_ci_yml ||= tree(:head).blobs.find do |file|
file.name == '.gitlab-ci.yml'
@@ -807,7 +795,7 @@ class Repository
def check_revert_content(commit, base_branch)
source_sha = find_branch(base_branch).target
args = [commit.id, source_sha]
- args << { mainline: 1 } if commit.merge_commit?
+ args << { mainline: 1 } if commit.merge_commit?
revert_index = rugged.revert_commit(*args)
return false if revert_index.conflicts?
@@ -821,7 +809,7 @@ class Repository
def check_cherry_pick_content(commit, base_branch)
source_sha = find_branch(base_branch).target
args = [commit.id, source_sha]
- args << 1 if commit.merge_commit?
+ args << 1 if commit.merge_commit?
cherry_pick_index = rugged.cherrypick_commit(*args)
return false if cherry_pick_index.conflicts?
@@ -862,7 +850,7 @@ class Repository
def search_files(query, ref)
offset = 2
- args = %W(#{Gitlab.config.git.bin_path} grep -i -I -n --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref})
+ args = %W(#{Gitlab.config.git.bin_path} grep -i -I -n --before-context #{offset} --after-context #{offset} -e #{Regexp.escape(query)} #{ref || root_ref})
Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/)
end
@@ -972,6 +960,12 @@ class Repository
end
end
+ def main_language
+ return if empty? || rugged.head_unborn?
+
+ Linguist::Repository.new(rugged, rugged.head.target_id).language
+ end
+
def avatar
return nil unless exists?
@@ -987,12 +981,4 @@ class Repository
def cache
@cache ||= RepositoryCache.new(path_with_namespace)
end
-
- def head_exists?
- exists? && !empty? && !rugged.head_unborn?
- end
-
- def file_on_head(regex)
- tree(:head).blobs.find { |file| file.name =~ regex }
- end
end
diff --git a/app/models/security_event.rb b/app/models/security_event.rb
index d131c11cb6..0bee03974f 100644
--- a/app/models/security_event.rb
+++ b/app/models/security_event.rb
@@ -1,2 +1,16 @@
+# == Schema Information
+#
+# Table name: audit_events
+#
+# id :integer not null, primary key
+# author_id :integer not null
+# type :string not null
+# entity_id :integer not null
+# entity_type :string not null
+# details :text
+# created_at :datetime
+# updated_at :datetime
+#
+
class SecurityEvent < AuditEvent
end
diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb
index 375f195dba..99279a2e08 100644
--- a/app/models/sent_notification.rb
+++ b/app/models/sent_notification.rb
@@ -1,3 +1,17 @@
+# == Schema Information
+#
+# Table name: sent_notifications
+#
+# id :integer not null, primary key
+# project_id :integer
+# noteable_id :integer
+# noteable_type :string
+# recipient_id :integer
+# commit_id :string
+# reply_key :string not null
+# line_code :string
+#
+
class SentNotification < ActiveRecord::Base
belongs_to :project
belongs_to :noteable, polymorphic: true
diff --git a/app/models/service.rb b/app/models/service.rb
index de3fd24584..bf16a54530 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -1,3 +1,27 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string
+# title :string
+# project_id :integer
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
+#
+
# To add new service you should build a class inherited from Service
# and implement a set of methods
class Service < ActiveRecord::Base
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 407697b745..2f905a9094 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -1,3 +1,19 @@
+# == Schema Information
+#
+# Table name: snippets
+#
+# id :integer not null, primary key
+# title :string
+# content :text
+# author_id :integer not null
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# file_name :string
+# type :string
+# visibility_level :integer default(0), not null
+#
+
class Snippet < ActiveRecord::Base
include Gitlab::VisibilityLevel
include Linguist::BlobHelper
@@ -30,8 +46,7 @@ class Snippet < ActiveRecord::Base
scope :public_and_internal, -> { where(visibility_level: [Snippet::PUBLIC, Snippet::INTERNAL]) }
scope :fresh, -> { order("created_at DESC") }
- participant :author
- participant :notes_with_associations
+ participant :author, :notes
def self.reference_prefix
'$'
@@ -101,10 +116,6 @@ class Snippet < ActiveRecord::Base
content.lines.count > 1000
end
- def notes_with_associations
- notes.includes(:author, :project)
- end
-
class << self
# Searches for snippets with a matching title or file name.
#
diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb
index 12df68ef83..f49eb7d88e 100644
--- a/app/models/spam_log.rb
+++ b/app/models/spam_log.rb
@@ -1,3 +1,20 @@
+# == Schema Information
+#
+# Table name: spam_logs
+#
+# id :integer not null, primary key
+# user_id :integer
+# source_ip :string
+# user_agent :string
+# via_api :boolean
+# project_id :integer
+# noteable_type :string
+# title :string
+# description :text
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
class SpamLog < ActiveRecord::Base
belongs_to :user
diff --git a/app/models/subscription.rb b/app/models/subscription.rb
index 3b8aa1eb86..242faa7d32 100644
--- a/app/models/subscription.rb
+++ b/app/models/subscription.rb
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: subscriptions
+#
+# id :integer not null, primary key
+# user_id :integer
+# subscribable_id :integer
+# subscribable_type :string
+# subscribed :boolean
+# created_at :datetime
+# updated_at :datetime
+#
+
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :subscribable, polymorphic: true
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 3a09137332..d85f7bfdf5 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -1,7 +1,24 @@
+# == Schema Information
+#
+# Table name: todos
+#
+# id :integer not null, primary key
+# user_id :integer not null
+# project_id :integer not null
+# target_id :integer
+# target_type :string not null
+# author_id :integer
+# action :integer not null
+# state :string not null
+# created_at :datetime
+# updated_at :datetime
+# note_id :integer
+# commit_id :string
+#
+
class Todo < ActiveRecord::Base
- ASSIGNED = 1
- MENTIONED = 2
- BUILD_FAILED = 3
+ ASSIGNED = 1
+ MENTIONED = 2
belongs_to :author, class_name: "User"
belongs_to :note
@@ -29,10 +46,6 @@ class Todo < ActiveRecord::Base
state :done
end
- def build_failed?
- action == BUILD_FAILED
- end
-
def body
if note.present?
note.note
diff --git a/app/models/user.rb b/app/models/user.rb
index 172845c9d2..959b1f9375 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,3 +1,68 @@
+# == Schema Information
+#
+# Table name: users
+#
+# id :integer not null, primary key
+# email :string default(""), not null
+# encrypted_password :string default(""), not null
+# reset_password_token :string
+# reset_password_sent_at :datetime
+# remember_created_at :datetime
+# sign_in_count :integer default(0)
+# current_sign_in_at :datetime
+# last_sign_in_at :datetime
+# current_sign_in_ip :string
+# last_sign_in_ip :string
+# created_at :datetime
+# updated_at :datetime
+# name :string
+# admin :boolean default(FALSE), not null
+# projects_limit :integer default(10)
+# skype :string default(""), not null
+# linkedin :string default(""), not null
+# twitter :string default(""), not null
+# authentication_token :string
+# theme_id :integer default(1), not null
+# bio :string
+# failed_attempts :integer default(0)
+# locked_at :datetime
+# username :string
+# can_create_group :boolean default(TRUE), not null
+# can_create_team :boolean default(TRUE), not null
+# state :string
+# color_scheme_id :integer default(1), not null
+# notification_level :integer default(1), not null
+# password_expires_at :datetime
+# created_by_id :integer
+# last_credential_check_at :datetime
+# avatar :string
+# confirmation_token :string
+# confirmed_at :datetime
+# confirmation_sent_at :datetime
+# unconfirmed_email :string
+# hide_no_ssh_key :boolean default(FALSE)
+# website_url :string default(""), not null
+# notification_email :string
+# hide_no_password :boolean default(FALSE)
+# password_automatically_set :boolean default(FALSE)
+# location :string
+# encrypted_otp_secret :string
+# encrypted_otp_secret_iv :string
+# encrypted_otp_secret_salt :string
+# otp_required_for_login :boolean default(FALSE), not null
+# otp_backup_codes :text
+# public_email :string default(""), not null
+# dashboard :integer default(0)
+# project_view :integer default(0)
+# consumed_timestep :integer
+# layout :integer default(0)
+# hide_project_limit :boolean default(FALSE)
+# unlock_token :string
+# otp_grace_period_started_at :datetime
+# ldap_email :boolean default(FALSE), not null
+# external :boolean default(FALSE)
+#
+
require 'carrierwave/orm/activerecord'
class User < ActiveRecord::Base
@@ -20,19 +85,14 @@ class User < ActiveRecord::Base
default_value_for :hide_no_password, false
default_value_for :theme_id, gitlab_config.default_theme
- attr_encrypted :otp_secret,
- key: Gitlab::Application.config.secret_key_base,
- mode: :per_attribute_iv_and_salt,
- algorithm: 'aes-256-cbc'
-
devise :two_factor_authenticatable,
- otp_secret_encryption_key: Gitlab::Application.config.secret_key_base
+ otp_secret_encryption_key: File.read(Rails.root.join('.secret')).chomp
alias_attribute :two_factor_enabled, :otp_required_for_login
devise :two_factor_backupable, otp_number_of_backup_codes: 10
serialize :otp_backup_codes, JSON
- devise :lockable, :recoverable, :rememberable, :trackable,
+ devise :lockable, :async, :recoverable, :rememberable, :trackable,
:validatable, :omniauthable, :confirmable, :registerable
attr_accessor :force_random_password
@@ -117,7 +177,6 @@ class User < ActiveRecord::Base
before_save :ensure_external_user_rights
after_save :ensure_namespace_correct
after_initialize :set_projects_limit
- before_create :check_confirmation_email
after_create :post_create_hook
after_destroy :post_destroy_hook
@@ -313,10 +372,6 @@ class User < ActiveRecord::Base
@reset_token
end
- def check_confirmation_email
- skip_confirmation! unless current_application_settings.send_user_confirmation_email
- end
-
def recently_sent_password_reset?
reset_password_sent_at.present? && reset_password_sent_at >= 1.minute.ago
end
@@ -391,17 +446,17 @@ class User < ActiveRecord::Base
Project.where("projects.id IN (#{projects_union.to_sql})")
end
- def viewable_starred_projects
- starred_projects.where("projects.visibility_level IN (?) OR projects.id IN (#{projects_union.to_sql})",
- [Project::PUBLIC, Project::INTERNAL])
- end
-
def owned_projects
@owned_projects ||=
Project.where('namespace_id IN (?) OR namespace_id = ?',
owned_groups.select(:id), namespace.id).joins(:namespace)
end
+ # Team membership in authorized projects
+ def tm_in_authorized_projects
+ ProjectMember.where(source_id: authorized_projects.map(&:id), user_id: self.id)
+ end
+
def is_admin?
admin
end
@@ -491,6 +546,10 @@ class User < ActiveRecord::Base
"#{name} (#{username})"
end
+ def tm_of(project)
+ project.project_member_by_id(self.id)
+ end
+
def already_forked?(project)
!!fork_of(project)
end
@@ -776,23 +835,6 @@ class User < ActiveRecord::Base
notification_settings.find_or_initialize_by(source: source)
end
- def assigned_open_merge_request_count(force: false)
- Rails.cache.fetch(['users', id, 'assigned_open_merge_request_count'], force: force) do
- assigned_merge_requests.opened.count
- end
- end
-
- def assigned_open_issues_count(force: false)
- Rails.cache.fetch(['users', id, 'assigned_open_issues_count'], force: force) do
- assigned_issues.opened.count
- end
- end
-
- def update_cache_counts
- assigned_open_merge_request_count(force: true)
- assigned_open_issues_count(force: true)
- end
-
private
def projects_union
diff --git a/app/models/users_star_project.rb b/app/models/users_star_project.rb
index 0dfe597317..413f3f485a 100644
--- a/app/models/users_star_project.rb
+++ b/app/models/users_star_project.rb
@@ -1,3 +1,14 @@
+# == Schema Information
+#
+# Table name: users_star_projects
+#
+# id :integer not null, primary key
+# project_id :integer not null
+# user_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+#
+
class UsersStarProject < ActiveRecord::Base
belongs_to :project, counter_cache: :star_count, touch: true
belongs_to :user
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
deleted file mode 100644
index e57b95f21e..0000000000
--- a/app/services/auth/container_registry_authentication_service.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-module Auth
- class ContainerRegistryAuthenticationService < BaseService
- include Gitlab::CurrentSettings
-
- AUDIENCE = 'container_registry'
-
- def execute
- return error('not found', 404) unless registry.enabled
-
- unless current_user || project
- return error('forbidden', 403) unless scope
- end
-
- { token: authorized_token(scope).encoded }
- end
-
- def self.full_access_token(*names)
- registry = Gitlab.config.registry
- token = JSONWebToken::RSAToken.new(registry.key)
- token.issuer = registry.issuer
- token.audience = AUDIENCE
- token.expire_time = token_expire_at
- token[:access] = names.map do |name|
- { type: 'repository', name: name, actions: %w(*) }
- end
- token.encoded
- end
-
- private
-
- def authorized_token(*accesses)
- token = JSONWebToken::RSAToken.new(registry.key)
- token.issuer = registry.issuer
- token.audience = params[:service]
- token.subject = current_user.try(:username)
- token.expire_time = ContainerRegistryAuthenticationService.token_expire_at
- token[:access] = accesses.compact
- token
- end
-
- def scope
- return unless params[:scope]
-
- @scope ||= process_scope(params[:scope])
- end
-
- def process_scope(scope)
- type, name, actions = scope.split(':', 3)
- actions = actions.split(',')
- return unless type == 'repository'
-
- process_repository_access(type, name, actions)
- end
-
- def process_repository_access(type, name, actions)
- requested_project = Project.find_with_namespace(name)
- return unless requested_project
-
- actions = actions.select do |action|
- can_access?(requested_project, action)
- end
-
- { type: type, name: name, actions: actions } if actions.present?
- end
-
- def can_access?(requested_project, requested_action)
- return false unless requested_project.container_registry_enabled?
-
- case requested_action
- when 'pull'
- requested_project == project || can?(current_user, :read_container_image, requested_project)
- when 'push'
- requested_project == project || can?(current_user, :create_container_image, requested_project)
- else
- false
- end
- end
-
- def registry
- Gitlab.config.registry
- end
-
- def self.token_expire_at
- Time.now + current_application_settings.container_registry_token_expire_delay.minutes
- end
- end
-end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
deleted file mode 100644
index 5bc0c31cb4..0000000000
--- a/app/services/ci/create_pipeline_service.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-module Ci
- class CreatePipelineService < BaseService
- def execute
- pipeline = project.ci_commits.new(params)
-
- unless ref_names.include?(params[:ref])
- pipeline.errors.add(:base, 'Reference not found')
- return pipeline
- end
-
- unless commit
- pipeline.errors.add(:base, 'Commit not found')
- return pipeline
- end
-
- unless can?(current_user, :create_pipeline, project)
- pipeline.errors.add(:base, 'Insufficient permissions to create a new pipeline')
- return pipeline
- end
-
- begin
- Ci::Commit.transaction do
- pipeline.sha = commit.id
-
- unless pipeline.config_processor
- pipeline.errors.add(:base, pipeline.yaml_errors || 'Missing .gitlab-ci.yml file')
- raise ActiveRecord::Rollback
- end
-
- pipeline.save!
- pipeline.create_builds(current_user)
- end
- rescue
- pipeline.errors.add(:base, 'The pipeline could not be created. Please try again.')
- end
-
- pipeline
- end
-
- private
-
- def ref_names
- @ref_names ||= project.repository.ref_names
- end
-
- def commit
- @commit ||= project.commit(params[:ref])
- end
- end
-end
diff --git a/app/services/create_commit_builds_service.rb b/app/services/create_commit_builds_service.rb
index 5b6fefe669..0d2aa1ff03 100644
--- a/app/services/create_commit_builds_service.rb
+++ b/app/services/create_commit_builds_service.rb
@@ -18,16 +18,19 @@ class CreateCommitBuildsService
return false
end
- commit = Ci::Commit.new(project: project, sha: sha, ref: ref, before_sha: before_sha, tag: tag)
+ commit = project.ci_commit(sha, ref)
+ unless commit
+ commit = project.ci_commits.new(sha: sha, ref: ref, before_sha: before_sha, tag: tag)
- # Skip creating ci_commit when no gitlab-ci.yml is found
- unless commit.ci_yaml_file
- return false
+ # Skip creating ci_commit when no gitlab-ci.yml is found
+ unless commit.ci_yaml_file
+ return false
+ end
+
+ # Create a new ci_commit
+ commit.save!
end
- # Create a new ci_commit
- commit.save!
-
# Skip creating builds for commits that have [ci skip]
unless commit.skip_ci?
# Create builds for commit
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index a886f35981..66136b6261 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -53,6 +53,10 @@ class GitPushService < BaseService
# could cause the last commit of a merge request to change.
update_merge_requests
+ # Checks if the main language has changed in the project and if so
+ # it updates it accordingly
+ update_main_language
+
perform_housekeeping
end
@@ -60,6 +64,19 @@ class GitPushService < BaseService
@project.repository.copy_gitattributes(params[:ref])
end
+ def update_main_language
+ # Performance can be bad so for now only check main_language once
+ # See https://gitlab.com/gitlab-org/gitlab-ce/issues/14937
+ return if @project.main_language.present?
+
+ return unless is_default_branch?
+ return unless push_to_new_branch? || push_to_existing_branch?
+
+ current_language = @project.repository.main_language
+ @project.update_attributes(main_language: current_language)
+ true
+ end
+
protected
def update_merge_requests
diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb
index 299a0a967b..7410442609 100644
--- a/app/services/git_tag_push_service.rb
+++ b/app/services/git_tag_push_service.rb
@@ -23,7 +23,7 @@ class GitTagPushService < BaseService
commits = []
message = nil
- unless Gitlab::Git.blank_ref?(params[:newrev])
+ if !Gitlab::Git.blank_ref?(params[:newrev])
tag_name = Gitlab::Git.ref_name(params[:ref])
tag = project.repository.find_tag(tag_name)
if tag && tag.target == params[:newrev]
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index c7d406cc33..3563cbaa99 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -24,10 +24,6 @@ module Issues
todo_service.reassigned_issue(issue, current_user)
end
- if issue.previous_changes.include?('confidential')
- create_confidentiality_note(issue)
- end
-
added_labels = issue.labels - old_labels
if added_labels.present?
notification_service.relabeled_issue(issue, added_labels, current_user)
@@ -41,11 +37,5 @@ module Issues
def close_service
Issues::CloseService
end
-
- private
-
- def create_confidentiality_note(issue)
- SystemNoteService.change_issue_confidentiality(issue, issue.project, current_user)
- end
end
end
diff --git a/app/services/merge_requests/add_todo_when_build_fails_service.rb b/app/services/merge_requests/add_todo_when_build_fails_service.rb
deleted file mode 100644
index 566049525c..0000000000
--- a/app/services/merge_requests/add_todo_when_build_fails_service.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-module MergeRequests
- class AddTodoWhenBuildFailsService < MergeRequests::BaseService
- # Adds a todo to the parent merge_request when a CI build fails
- def execute(commit_status)
- each_merge_request(commit_status) do |merge_request|
- todo_service.merge_request_build_failed(merge_request)
- end
- end
-
- # Closes any pending build failed todos for the parent MRs when a build is retried
- def close(commit_status)
- each_merge_request(commit_status) do |merge_request|
- todo_service.merge_request_build_retried(merge_request)
- end
- end
- end
-end
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 9d7fca6882..e6837a1869 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -38,30 +38,5 @@ module MergeRequests
def filter_params
super(:merge_request)
end
-
- def merge_request_from(commit_status)
- branches = commit_status.ref
-
- # This is for ref-less builds
- branches ||= @project.repository.branch_names_contains(commit_status.sha)
-
- return [] if branches.blank?
-
- merge_requests = @project.origin_merge_requests.opened.where(source_branch: branches).to_a
- merge_requests += @project.fork_merge_requests.opened.where(source_branch: branches).to_a
-
- merge_requests.uniq.select(&:source_project)
- end
-
- def each_merge_request(commit_status)
- merge_request_from(commit_status).each do |merge_request|
- ci_commit = merge_request.ci_commit
-
- next unless ci_commit
- next unless ci_commit.sha == commit_status.sha
-
- yield merge_request, ci_commit
- end
- end
end
end
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 1b48899bb0..cd4230aa5e 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -66,7 +66,7 @@ module MergeRequests
commits = merge_request.compare_commits
if commits && commits.count == 1
commit = commits.first
- merge_request.title = commit.title
+ merge_request.title = commit.title
merge_request.description ||= commit.description.try(:strip)
elsif iid && (issue = merge_request.target_project.get_issue(iid)) && !issue.try(:confidential?)
case issue
diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb
index 96a25330af..33609d01f2 100644
--- a/app/services/merge_requests/create_service.rb
+++ b/app/services/merge_requests/create_service.rb
@@ -8,14 +8,11 @@ module MergeRequests
@project = Project.find(params[:target_project_id]) if params[:target_project_id]
filter_params
- label_params = params.delete(:label_ids)
- force_remove_source_branch = params.delete(:force_remove_source_branch)
-
- merge_request = MergeRequest.new(params)
+ label_params = params[:label_ids]
+ merge_request = MergeRequest.new(params.except(:label_ids))
merge_request.source_project = source_project
merge_request.target_project ||= source_project
merge_request.author = current_user
- merge_request.merge_params['force_remove_source_branch'] = force_remove_source_branch
if merge_request.save
merge_request.update_attributes(label_ids: label_params)
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index 9aaf5a5e56..9a58383b39 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -45,14 +45,10 @@ module MergeRequests
def after_merge
MergeRequests::PostMergeService.new(project, current_user).execute(merge_request)
- if params[:should_remove_source_branch].present? || @merge_request.force_remove_source_branch?
- DeleteBranchService.new(@merge_request.source_project, branch_deletion_user).
+ if params[:should_remove_source_branch].present?
+ DeleteBranchService.new(@merge_request.source_project, current_user).
execute(merge_request.source_branch)
end
end
-
- def branch_deletion_user
- @merge_request.force_remove_source_branch? ? @merge_request.author : current_user
- end
end
end
diff --git a/app/services/merge_requests/merge_when_build_succeeds_service.rb b/app/services/merge_requests/merge_when_build_succeeds_service.rb
index 8fd6a4ea1f..d6af12f973 100644
--- a/app/services/merge_requests/merge_when_build_succeeds_service.rb
+++ b/app/services/merge_requests/merge_when_build_succeeds_service.rb
@@ -20,9 +20,15 @@ module MergeRequests
# Triggers the automatic merge of merge_request once the build succeeds
def trigger(commit_status)
- each_merge_request(commit_status) do |merge_request, ci_commit|
+ merge_requests = merge_request_from(commit_status)
+
+ merge_requests.each do |merge_request|
next unless merge_request.merge_when_build_succeeds?
next unless merge_request.mergeable?
+
+ ci_commit = merge_request.ci_commit
+ next unless ci_commit
+ next unless ci_commit.sha == commit_status.sha
next unless ci_commit.success?
MergeWorker.perform_async(merge_request.id, merge_request.merge_user_id, merge_request.merge_params)
@@ -41,5 +47,20 @@ module MergeRequests
end
end
+ private
+
+ def merge_request_from(commit_status)
+ branches = commit_status.ref
+
+ # This is for ref-less builds
+ branches ||= @project.repository.branch_names_contains(commit_status.sha)
+
+ return [] if branches.blank?
+
+ merge_requests = @project.origin_merge_requests.opened.where(source_branch: branches).to_a
+ merge_requests += @project.fork_merge_requests.opened.where(source_branch: branches).to_a
+
+ merge_requests.uniq.select(&:source_project)
+ end
end
end
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index fe0579744b..8b3d56c2b4 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -12,7 +12,6 @@ module MergeRequests
close_merge_requests
reload_merge_requests
reset_merge_when_build_succeeds
- mark_pending_todos_done
# Leave a system note if a branch was deleted/added
if branch_added? || branch_removed?
@@ -81,12 +80,6 @@ module MergeRequests
merge_requests_for_source_branch.each(&:reset_merge_when_build_succeeds)
end
- def mark_pending_todos_done
- merge_requests_for_source_branch.each do |merge_request|
- todo_service.merge_request_push(merge_request, @current_user)
- end
- end
-
def find_new_commits
if branch_added?
@commits = []
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index 026a37997d..477c64e737 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -11,8 +11,6 @@ module MergeRequests
params.except!(:target_project_id)
params.except!(:source_branch)
- merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch)
-
update(merge_request)
end
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 2bb312bb25..0158699481 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -5,6 +5,8 @@ module Notes
note.author = current_user
note.system = false
+ return unless valid_project?(note)
+
if note.save
# Finish the harder work in the background
NewNoteWorker.perform_in(2.seconds, note.id, params)
@@ -13,5 +15,14 @@ module Notes
note
end
+
+ private
+
+ def valid_project?(note)
+ return false unless project
+ return true if note.for_commit?
+
+ note.noteable.try(:project) == project
+ end
end
end
diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb
index eb73948006..ba50305dbd 100644
--- a/app/services/projects/autocomplete_service.rb
+++ b/app/services/projects/autocomplete_service.rb
@@ -4,10 +4,6 @@ module Projects
@project.issues.visible_to_user(current_user).opened.select([:iid, :title])
end
- def milestones
- @project.milestones.active.reorder(due_date: :asc, title: :asc).select([:iid, :title])
- end
-
def merge_requests
@project.merge_requests.opened.select([:iid, :title])
end
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 61cac5419a..501e58c140 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -6,7 +6,6 @@ module Projects
def execute
forked_from_project_id = params.delete(:forked_from_project_id)
- import_data = params.delete(:import_data)
@project = Project.new(params)
@@ -50,20 +49,22 @@ module Projects
@project.build_forked_project_link(forked_from_project_id: forked_from_project_id)
end
- save_project_and_import_data(import_data)
+ Project.transaction do
+ @project.save
- @project.import_start if @project.import?
+ if @project.persisted? && !@project.import?
+ raise 'Failed to create repository' unless @project.create_repository
+ end
+ end
after_create_actions if @project.persisted?
- if @project.errors.empty?
- @project.add_import_job if @project.import?
- else
- fail(error: @project.errors.full_messages.join(', '))
- end
@project
rescue => e
- fail(error: e.message)
+ message = "Unable to save project: #{e.message}"
+ Rails.logger.error(message)
+ @project.errors.add(:base, message) if @project
+ @project
end
protected
@@ -92,30 +93,8 @@ module Projects
unless @project.group
@project.team << [current_user, :master, current_user]
end
- end
- def save_project_and_import_data(import_data)
- Project.transaction do
- @project.create_or_update_import_data(data: import_data[:data], credentials: import_data[:credentials]) if import_data
-
- if @project.save && !@project.import?
- raise 'Failed to create repository' unless @project.create_repository
- end
- end
- end
-
- def fail(error:)
- message = "Unable to save project. Error: #{error}"
- message << "Project ID: #{@project.id}" if @project && @project.id
-
- Rails.logger.error(message)
-
- if @project && @project.import?
- @project.errors.add(:base, message)
- @project.mark_import_as_failed(message)
- end
-
- @project
+ @project.import_start if @project.import?
end
end
end
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index f09072975c..19aab999e0 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -26,10 +26,6 @@ module Projects
Project.transaction do
project.destroy!
- unless remove_registry_tags
- raise_error('Failed to remove project container registry. Please try again or contact administrator')
- end
-
unless remove_repository(repo_path)
raise_error('Failed to remove project repository. Please try again or contact administrator')
end
@@ -39,7 +35,7 @@ module Projects
end
end
- log_info("Project \"#{project.path_with_namespace}\" was removed")
+ log_info("Project \"#{project.name}\" was removed")
system_hook_service.execute_hooks_for(project, :destroy)
true
end
@@ -63,12 +59,6 @@ module Projects
end
end
- def remove_registry_tags
- return true unless Gitlab.config.registry.enabled
-
- project.container_registry_repository.delete_tags
- end
-
def raise_error(message)
raise DestroyError.new(message)
end
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index de6dc38cc8..0577ae778d 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -3,7 +3,7 @@ module Projects
def execute
new_params = {
forked_from_project_id: @project.id,
- visibility_level: allowed_visibility_level,
+ visibility_level: @project.visibility_level,
description: @project.description,
name: @project.name,
path: @project.path,
@@ -19,17 +19,5 @@ module Projects
new_project = CreateService.new(current_user, new_params).execute
new_project
end
-
- private
-
- def allowed_visibility_level
- project_level = @project.visibility_level
-
- if Gitlab::VisibilityLevel.non_restricted_level?(project_level)
- project_level
- else
- Gitlab::VisibilityLevel.highest_allowed_level
- end
- end
end
end
diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb
index 43db29315a..3b7c36f090 100644
--- a/app/services/projects/housekeeping_service.rb
+++ b/app/services/projects/housekeeping_service.rb
@@ -22,7 +22,7 @@ module Projects
end
def execute
- raise LeaseTaken unless try_obtain_lease
+ raise LeaseTaken if !try_obtain_lease
GitlabShellOneShotWorker.perform_async(:gc, @project.path_with_namespace)
ensure
diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb
index c4838d31f2..ef15ef6a47 100644
--- a/app/services/projects/import_service.rb
+++ b/app/services/projects/import_service.rb
@@ -39,7 +39,7 @@ module Projects
begin
gitlab_shell.import_repository(project.path_with_namespace, project.import_url)
rescue Gitlab::Shell::Error => e
- raise Error, "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}"
+ raise Error, e.message
end
end
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index 03b57dea51..111b3ec05e 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -34,11 +34,6 @@ module Projects
raise TransferError.new("Project with same path in target namespace already exists")
end
- if project.has_container_registry_tags?
- # we currently doesn't support renaming repository if it contains tags in container registry
- raise TransferError.new('Project cannot be transferred, because tags are present in its container registry')
- end
-
project.expire_caches_before_rename(old_path)
# Apply new namespace id and visibility level
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index 1fb72cf89e..e43b5b51e5 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -85,7 +85,7 @@ class SystemHooksService
path_with_namespace: model.path_with_namespace,
project_id: model.id,
owner_name: owner.name,
- owner_email: owner.respond_to?(:email) ? owner.email : "",
+ owner_email: owner.respond_to?(:email) ? owner.email : "",
project_visibility: Project.visibility_levels.key(model.visibility_level_field).downcase
}
end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 4e8fa0818b..4bdb1b0c07 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -169,33 +169,12 @@ class SystemNoteService
#
# Returns the created Note object
def self.change_title(noteable, project, author, old_title)
- new_title = noteable.title.dup
+ return unless noteable.respond_to?(:title)
- old_diffs, new_diffs = Gitlab::Diff::InlineDiff.new(old_title, new_title).inline_diffs
-
- marked_old_title = Gitlab::Diff::InlineDiffMarker.new(old_title).mark(old_diffs, mode: :deletion, markdown: true)
- marked_new_title = Gitlab::Diff::InlineDiffMarker.new(new_title).mark(new_diffs, mode: :addition, markdown: true)
-
- body = "Changed title: **#{marked_old_title}** → **#{marked_new_title}**"
+ body = "Title changed from **#{old_title}** to **#{noteable.title}**"
create_note(noteable: noteable, project: project, author: author, note: body)
end
- # Called when the confidentiality changes
- #
- # issue - Issue object
- # project - Project owning the issue
- # author - User performing the change
- #
- # Example Note text:
- #
- # "Made the issue confidential"
- #
- # Returns the created Note object
- def self.change_issue_confidentiality(issue, project, author)
- body = issue.confidential ? 'Made the issue confidential' : 'Made the issue visible'
- create_note(noteable: issue, project: project, author: author, note: body)
- end
-
# Called when a branch in Noteable is changed
#
# noteable - Noteable object
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index 4bf4e14472..42c5bca90f 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -80,30 +80,6 @@ class TodoService
mark_pending_todos_as_done(merge_request, current_user)
end
- # When a build fails on the HEAD of a merge request we should:
- #
- # * create a todo for that user to fix it
- #
- def merge_request_build_failed(merge_request)
- create_build_failed_todo(merge_request)
- end
-
- # When a new commit is pushed to a merge request we should:
- #
- # * mark all pending todos related to the merge request for that user as done
- #
- def merge_request_push(merge_request, current_user)
- mark_pending_todos_as_done(merge_request, current_user)
- end
-
- # When a build is retried to a merge request we should:
- #
- # * mark all pending todos related to the merge request for the author as done
- #
- def merge_request_build_retried(merge_request)
- mark_pending_todos_as_done(merge_request, merge_request.author)
- end
-
# When create a note we should:
#
# * mark all pending todos related to the noteable for the note author as done
@@ -169,12 +145,6 @@ class TodoService
create_todos(mentioned_users, attributes)
end
- def create_build_failed_todo(merge_request)
- author = merge_request.author
- attributes = attributes_for_todo(merge_request.project, merge_request, author, Todo::BUILD_FAILED)
- create_todos(author, attributes)
- end
-
def attributes_for_target(target)
attributes = {
project_id: target.project.id,
diff --git a/app/services/wiki_pages/base_service.rb b/app/services/wiki_pages/base_service.rb
index 4c0a2c6b4d..9162f12860 100644
--- a/app/services/wiki_pages/base_service.rb
+++ b/app/services/wiki_pages/base_service.rb
@@ -6,8 +6,9 @@ module WikiPages
object_kind: page.class.name.underscore,
user: current_user.hook_attrs,
project: @project.hook_attrs,
- wiki: @project.wiki.hook_attrs,
- object_attributes: page.hook_attrs
+ object_attributes: page.hook_attrs,
+ # DEPRECATED
+ repository: @project.hook_attrs.slice(:name, :url, :description, :homepage)
}
page_url = Gitlab::UrlBuilder.build(page)
diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml
index 862b86d9d4..2ab01704b7 100644
--- a/app/views/admin/abuse_reports/_abuse_report.html.haml
+++ b/app/views/admin/abuse_reports/_abuse_report.html.haml
@@ -16,7 +16,7 @@
.light.small
= time_ago_with_tooltip(abuse_report.created_at)
%td
- = markdown(abuse_report.message.squish!, pipeline: :single_line, author: reporter)
+ = markdown(abuse_report.message.squish!, pipeline: :single_line)
%td
- if user
= link_to 'Remove user & report', admin_abuse_report_path(abuse_report, remove_user: true),
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index f149f9eb43..e0d8d16a95 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -103,25 +103,12 @@
= f.label :signup_enabled do
= f.check_box :signup_enabled
Sign-up enabled
- .form-group
- .col-sm-offset-2.col-sm-10
- .checkbox
- = f.label :send_user_confirmation_email do
- = f.check_box :send_user_confirmation_email
- Send confirmation email on sign-up
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :signin_enabled do
= f.check_box :signin_enabled
Sign-in enabled
- - if omniauth_enabled? && button_based_providers.any?
- .form-group
- = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth Sign-In sources', class: 'control-label col-sm-2'
- .col-sm-10
- .btn-group{ data: { toggle: 'buttons' } }
- - oauth_providers_checkboxes.each do |source|
- = source
.form-group
= f.label :two_factor_authentication, 'Two-factor authentication', class: 'control-label col-sm-2'
.col-sm-10
@@ -178,14 +165,6 @@
.col-sm-10
= f.number_field :max_artifacts_size, class: 'form-control'
- - if Gitlab.config.registry.enabled
- %fieldset
- %legend Container Registry
- .form-group
- = f.label :container_registry_token_expire_delay, 'Authorization token duration (minutes)', class: 'control-label col-sm-2'
- .col-sm-10
- = f.number_field :container_registry_token_expire_delay, class: 'form-control'
-
%fieldset
%legend Metrics
%p
diff --git a/app/views/admin/builds/index.html.haml b/app/views/admin/builds/index.html.haml
index d74cf8598e..804d7851bd 100644
--- a/app/views/admin/builds/index.html.haml
+++ b/app/views/admin/builds/index.html.haml
@@ -20,7 +20,7 @@
= link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
.row-content-block.second-block
- #{(@scope || 'all').capitalize} builds
+ #{(@scope || 'running').capitalize} builds
%ul.content-list
- if @builds.blank?
@@ -47,3 +47,4 @@
= render "admin/builds/build", build: build
= paginate @builds, theme: 'gitlab'
+
diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
deleted file mode 100644
index c2313986a7..0000000000
--- a/app/views/admin/health_check/show.html.haml
+++ /dev/null
@@ -1,49 +0,0 @@
-- page_title "Health Check"
-
-%h3.page-title
- Health Check
-.bs-callout.clearfix
- .pull-left
- %p
- Access token is
- %code#health-check-token= current_application_settings.health_check_access_token
- = button_to reset_health_check_token_admin_application_settings_path,
- method: :put, class: 'btn btn-default',
- data: { confirm: 'Are you sure you want to reset the health check token?' } do
- = icon('refresh')
- Reset health check access token
-%p.light
- Health information can be retrieved as plain text, JSON, or XML using:
- %ul
- %li
- %code= health_check_url(token: current_application_settings.health_check_access_token)
- %li
- %code= health_check_url(token: current_application_settings.health_check_access_token, format: :json)
- %li
- %code= health_check_url(token: current_application_settings.health_check_access_token, format: :xml)
-
-%p.light
- You can also ask for the status of specific services:
- %ul
- %li
- %code= health_check_url(token: current_application_settings.health_check_access_token, checks: :cache)
- %li
- %code= health_check_url(token: current_application_settings.health_check_access_token, checks: :database)
- %li
- %code= health_check_url(token: current_application_settings.health_check_access_token, checks: :migrations)
-
-%hr
-.panel.panel-default
- .panel-heading
- Current Status:
- - if @errors.blank?
- = icon('circle', class: 'cgreen')
- Healthy
- - else
- = icon('warning', class: 'cred')
- Unhealthy
- .panel-body
- - if @errors.blank?
- No Health Problems Detected
- - else
- = @errors
diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml
index 36b21eefde..6745e58dec 100644
--- a/app/views/admin/runners/_runner.html.haml
+++ b/app/views/admin/runners/_runner.html.haml
@@ -11,10 +11,18 @@
= link_to admin_runner_path(runner) do
= runner.short_sha
%td
- = runner.description
+ .runner-description
+ = runner.description
+ %span (#{link_to 'edit', '#', class: 'edit-runner-link'})
+ .runner-description-form.hide
+ = form_for [:admin, runner], remote: true, html: { class: 'form-inline' } do |f|
+ .form-group
+ = f.text_field :description, class: 'form-control'
+ = f.submit 'Save', class: 'btn'
+ %span (#{link_to 'cancel', '#', class: 'cancel'})
%td
- if runner.shared?
- n/a
+ \-
- else
= runner.projects.count(:all)
%td
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index c3784bf719..8700b4820c 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -9,6 +9,8 @@
%span.runner-state.runner-state-specific
Specific
+
+
- if @runner.shared?
.bs-callout.bs-callout-success
%h4 This runner will process builds from ALL UNASSIGNED projects
@@ -20,9 +22,25 @@
%h4 This runner will process builds only from ASSIGNED projects
%p You can't make this a shared runner.
%hr
-
-.append-bottom-20
- = render '/projects/runners/form', runner: @runner, runner_form_url: admin_runner_path(@runner)
+= form_for @runner, url: admin_runner_path(@runner), html: { class: 'form-horizontal' } do |f|
+ .form-group
+ = label_tag :token, class: 'control-label' do
+ Token
+ .col-sm-10
+ = f.text_field :token, class: 'form-control', readonly: true
+ .form-group
+ = label_tag :description, class: 'control-label' do
+ Description
+ .col-sm-10
+ = f.text_field :description, class: 'form-control'
+ .form-group
+ = label_tag :tag_list, class: 'control-label' do
+ Tags
+ .col-sm-10
+ = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control'
+ .help-block You can setup builds to only use runners with specific tags
+ .form-actions
+ = f.submit 'Save', class: 'btn btn-save'
.row
.col-md-6
diff --git a/app/views/dashboard/issues.atom.builder b/app/views/dashboard/issues.atom.builder
index 83c0c6da21..0d7b1b30dc 100644
--- a/app/views/dashboard/issues.atom.builder
+++ b/app/views/dashboard/issues.atom.builder
@@ -6,5 +6,8 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id issues_dashboard_url
xml.updated @issues.first.created_at.xmlschema if @issues.any?
- xml << render(partial: 'issues/issue', collection: @issues) if @issues.any?
+ @issues.each do |issue|
+ issue_to_atom(xml, issue)
+ end
end
+
diff --git a/app/views/dashboard/projects/index.atom.builder b/app/views/dashboard/projects/index.atom.builder
index fb5be63b47..d4daf07c6c 100644
--- a/app/views/dashboard/projects/index.atom.builder
+++ b/app/views/dashboard/projects/index.atom.builder
@@ -6,5 +6,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id dashboard_projects_url
xml.updated @events[0].updated_at.xmlschema if @events[0]
- xml << render(partial: 'events/event', collection: @events) if @events.any?
+ @events.each do |event|
+ event_to_atom(xml, event)
+ end
end
diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml
index 98f302d2f9..aa0aff86d4 100644
--- a/app/views/dashboard/todos/_todo.html.haml
+++ b/app/views/dashboard/todos/_todo.html.haml
@@ -1,15 +1,13 @@
%li{class: "todo todo-#{todo.done? ? 'done' : 'pending'}", id: dom_id(todo), data:{url: todo_target_path(todo)} }
.todo-item.todo-block
= image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:''
- .todo-title.title
- - unless todo.build_failed?
- = todo_target_state_pill(todo)
- %span.author-name
- - if todo.author
- = link_to_author(todo)
- - else
- (removed)
+ .todo-title.title
+ %span.author-name
+ - if todo.author
+ = link_to_author(todo)
+ - else
+ (removed)
%span.todo-label
= todo_action_name(todo)
- if todo.target
diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb
new file mode 100644
index 0000000000..c6fa8f0ee3
--- /dev/null
+++ b/app/views/devise/mailer/confirmation_instructions.html.erb
@@ -0,0 +1,9 @@
+Welcome <%= @resource.name %>!
+
+<% if @resource.unconfirmed_email.present? %>
+ You can confirm your email (<%= @resource.unconfirmed_email %>) through the link below:
+<% else %>
+ You can confirm your account through the link below:
+<% end %>
+
+<%= link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token) %>
diff --git a/app/views/devise/mailer/confirmation_instructions.html.haml b/app/views/devise/mailer/confirmation_instructions.html.haml
deleted file mode 100644
index 086bb8e083..0000000000
--- a/app/views/devise/mailer/confirmation_instructions.html.haml
+++ /dev/null
@@ -1,16 +0,0 @@
-.center
- - if @resource.unconfirmed_email.present?
- #content
- %h2= @resource.unconfirmed_email
- %p Click the link below to confirm your email address.
- #cta
- = link_to 'Confirm your email address', confirmation_url(@resource, confirmation_token: @token)
- - else
- #content
- - if Gitlab.com?
- %h2 Thanks for signing up to GitLab!
- - else
- %h2 Welcome, #{@resource.name}!
- %p To get started, click the link below to confirm your account.
- #cta
- = link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token)
diff --git a/app/views/devise/mailer/confirmation_instructions.text.erb b/app/views/devise/mailer/confirmation_instructions.text.erb
deleted file mode 100644
index 9f76edb76a..0000000000
--- a/app/views/devise/mailer/confirmation_instructions.text.erb
+++ /dev/null
@@ -1,9 +0,0 @@
-Welcome, <%= @resource.name %>!
-
-<% if @resource.unconfirmed_email.present? %>
-You can confirm your email (<%= @resource.unconfirmed_email %>) through the link below:
-<% else %>
-You can confirm your account through the link below:
-<% end %>
-
-<%= confirmation_url(@resource, confirmation_token: @token) %>
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 28194506ac..d65fa60025 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -4,7 +4,7 @@
= render 'devise/shared/signin_box'
-# Omniauth fits between signin/ldap signin and signup and does not have a surrounding box
- - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled?
+ - if omniauth_enabled? && devise_mapping.omniauthable?
.clearfix.prepend-top-20
= render 'devise/shared/omniauth_box'
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index 8c6a1552a5..c9d1e454a5 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -4,7 +4,6 @@
%h3 Two-factor Authentication
.login-body
= form_for(resource, as: resource_name, url: session_path(resource_name), method: :post) do |f|
- = f.hidden_field :remember_me, value: params[resource_name][:remember_me]
= f.text_field :otp_attempt, class: 'form-control', placeholder: 'Two-factor Authentication code', required: true, autofocus: true
%p.help-block.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.
.prepend-top-20
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index de18bc2d84..ecf680e7b2 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -1,7 +1,7 @@
%p
%span.light
Sign in with
- - providers = enabled_button_based_providers
+ - providers = button_based_providers
- providers.each do |provider|
%span.light
- has_icon = provider_has_icon?(provider)
diff --git a/app/views/doorkeeper/authorizations/new.html.haml b/app/views/doorkeeper/authorizations/new.html.haml
index ce05000720..eae80e5210 100644
--- a/app/views/doorkeeper/authorizations/new.html.haml
+++ b/app/views/doorkeeper/authorizations/new.html.haml
@@ -1,4 +1,4 @@
-%h3.page-title Authorization required
+%h3.page-title Authorize required
%main{:role => "main"}
%p.h4
Authorize
diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml
index 1bc9f60443..dce4081288 100644
--- a/app/views/events/_commit.html.haml
+++ b/app/views/events/_commit.html.haml
@@ -2,4 +2,4 @@
.commit-row-title
= link_to truncate_sha(commit[:id]), namespace_project_commit_path(project.namespace, project, commit[:id]), class: "commit_short_id", alt: '', title: truncate_sha(commit[:id])
·
- = markdown event_commit_title(commit[:message]), project: project, pipeline: :single_line, author: event.author
+ = markdown event_commit_title(commit[:message]), project: project, pipeline: :single_line
diff --git a/app/views/events/_event.atom.builder b/app/views/events/_event.atom.builder
deleted file mode 100644
index 7890e717aa..0000000000
--- a/app/views/events/_event.atom.builder
+++ /dev/null
@@ -1,20 +0,0 @@
-return unless event.visible_to_user?(current_user)
-
-xml.entry do
- xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
- xml.link href: event_feed_url(event)
- xml.title truncate(event_feed_title(event), length: 80)
- xml.updated event.created_at.xmlschema
- xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(event.author_email))
-
- xml.author do
- xml.name event.author_name
- xml.email event.author_email
- end
-
- xml.summary(type: "xhtml") do |summary|
- event_summary = event_feed_summary(event)
-
- summary << event_summary unless event_summary.nil?
- end
-end
diff --git a/app/views/events/_event_issue.atom.haml b/app/views/events/_event_issue.atom.haml
index 083c393621..fad6531002 100644
--- a/app/views/events/_event_issue.atom.haml
+++ b/app/views/events/_event_issue.atom.haml
@@ -1,2 +1,2 @@
%div{xmlns: "http://www.w3.org/1999/xhtml"}
- = markdown(issue.description, pipeline: :atom, project: issue.project, author: issue.author)
+ = markdown(issue.description, pipeline: :atom, project: issue.project)
diff --git a/app/views/events/_event_merge_request.atom.haml b/app/views/events/_event_merge_request.atom.haml
index d7e0560062..19bdc7b9ca 100644
--- a/app/views/events/_event_merge_request.atom.haml
+++ b/app/views/events/_event_merge_request.atom.haml
@@ -1,2 +1,2 @@
%div{xmlns: "http://www.w3.org/1999/xhtml"}
- = markdown(merge_request.description, pipeline: :atom, project: merge_request.project, author: merge_request.author)
+ = markdown(merge_request.description, pipeline: :atom, project: merge_request.project)
diff --git a/app/views/events/_event_note.atom.haml b/app/views/events/_event_note.atom.haml
index 1154f98282..b730ebbd5f 100644
--- a/app/views/events/_event_note.atom.haml
+++ b/app/views/events/_event_note.atom.haml
@@ -1,2 +1,2 @@
%div{xmlns: "http://www.w3.org/1999/xhtml"}
- = markdown(note.note, pipeline: :atom, project: note.project, author: note.author)
+ = markdown(note.note, pipeline: :atom, project: note.project)
diff --git a/app/views/events/_event_push.atom.haml b/app/views/events/_event_push.atom.haml
index 28bee1d0a3..b271b9daff 100644
--- a/app/views/events/_event_push.atom.haml
+++ b/app/views/events/_event_push.atom.haml
@@ -6,7 +6,7 @@
%i
at
= commit[:timestamp].to_time.to_s(:short)
- %blockquote= markdown(escape_once(commit[:message]), pipeline: :atom, project: event.project, author: event.author)
+ %blockquote= markdown(escape_once(commit[:message]), pipeline: :atom, project: event.project)
- if event.commits_count > 15
%p
%i
diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml
index c7f29f2fc0..c994e3b997 100644
--- a/app/views/events/event/_common.html.haml
+++ b/app/views/events/event/_common.html.haml
@@ -4,7 +4,7 @@
= event_action_name(event)
- if event.target
- %strong= link_to event.target.reference_link_text, [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title
+ %strong= link_to event.target.reference_link_text, [event.project.namespace.becomes(Namespace), event.project, event.target]
= event_preposition(event)
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index dc4ff17e31..235bd46107 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -15,7 +15,7 @@
%ul.well-list.event_commits
- few_commits = event.commits[0...2]
- few_commits.each do |commit|
- = render "events/commit", commit: commit, project: project, event: event
+ = render "events/commit", commit: commit, project: project
- create_mr = event.new_ref? && create_mr_button?(event.project.default_branch, event.ref_name, event.project)
- if event.commits_count > 1
diff --git a/app/views/groups/_activities.html.haml b/app/views/groups/_activities.html.haml
index 71cc4d87b1..dc76599b77 100644
--- a/app/views/groups/_activities.html.haml
+++ b/app/views/groups/_activities.html.haml
@@ -4,7 +4,7 @@
.nav-block
- if current_user
.controls
- = link_to group_path(@group, format: :atom, private_token: current_user.private_token), class: 'btn rss-btn' do
+ = link_to dashboard_projects_path(:atom, { private_token: current_user.private_token }), class: 'btn rss-btn' do
%i.fa.fa-rss
= render 'shared/event_filter'
diff --git a/app/views/groups/issues.atom.builder b/app/views/groups/issues.atom.builder
index c19671295a..486d1d8587 100644
--- a/app/views/groups/issues.atom.builder
+++ b/app/views/groups/issues.atom.builder
@@ -1,10 +1,13 @@
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
- xml.title "#{@group.name} issues"
- xml.link href: issues_group_url(format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml"
- xml.link href: issues_group_url, rel: "alternate", type: "text/html"
- xml.id issues_group_url
+ xml.title "#{@user.name} issues"
+ xml.link href: issues_dashboard_url(format: :atom, private_token: @user.private_token), rel: "self", type: "application/atom+xml"
+ xml.link href: issues_dashboard_url, rel: "alternate", type: "text/html"
+ xml.id issues_dashboard_url
xml.updated @issues.first.created_at.xmlschema if @issues.any?
- xml << render(partial: 'issues/issue', collection: @issues) if @issues.any?
+ @issues.each do |issue|
+ issue_to_atom(xml, issue)
+ end
end
+
diff --git a/app/views/groups/show.atom.builder b/app/views/groups/show.atom.builder
index b68bf444d2..c66b82bb48 100644
--- a/app/views/groups/show.atom.builder
+++ b/app/views/groups/show.atom.builder
@@ -6,5 +6,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id group_url(@group)
xml.updated @events[0].updated_at.xmlschema if @events[0]
- xml << render(@events) if @events.any?
+ @events.each do |event|
+ event_to_atom(xml, event)
+ end
end
diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml
index aedb8468ec..e3a356b537 100644
--- a/app/views/import/gitlab/status.html.haml
+++ b/app/views/import/gitlab/status.html.haml
@@ -47,7 +47,7 @@
%td.import-target
= repo["path_with_namespace"]
%td.import-actions.job-status
- = button_tag class: "btn btn-import js-add-to-import" do
+ = button_tag class: "btn js-add-to-import" do
Import
= icon("spinner spin", class: "loading-icon")
diff --git a/app/views/issues/_issue.atom.builder b/app/views/issues/_issue.atom.builder
deleted file mode 100644
index 68a2d19e58..0000000000
--- a/app/views/issues/_issue.atom.builder
+++ /dev/null
@@ -1,14 +0,0 @@
-xml.entry do
- xml.id namespace_project_issue_url(issue.project.namespace, issue.project, issue)
- xml.link href: namespace_project_issue_url(issue.project.namespace, issue.project, issue)
- xml.title truncate(issue.title, length: 80)
- xml.updated issue.created_at.xmlschema
- xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(issue.author_email))
-
- xml.author do |author|
- xml.name issue.author_name
- xml.email issue.author_email
- end
-
- xml.summary issue.title
-end
diff --git a/app/views/kaminari/gitlab/_first_page.html.haml b/app/views/kaminari/gitlab/_first_page.html.haml
index e7a70e3bb2..ada7306d98 100644
--- a/app/views/kaminari/gitlab/_first_page.html.haml
+++ b/app/views/kaminari/gitlab/_first_page.html.haml
@@ -2,7 +2,7 @@
-# available local variables
-# url: url to the first page
-# current_page: a page object for the currently displayed page
--# total_pages: total number of pages
+-# num_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%li.first
diff --git a/app/views/kaminari/gitlab/_gap.html.haml b/app/views/kaminari/gitlab/_gap.html.haml
index 80ca30f36e..3ffd12f858 100644
--- a/app/views/kaminari/gitlab/_gap.html.haml
+++ b/app/views/kaminari/gitlab/_gap.html.haml
@@ -1,7 +1,7 @@
-# Non-link tag that stands for skipped pages...
-# available local variables
-# current_page: a page object for the currently displayed page
--# total_pages: total number of pages
+-# num_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%li{class: "page"}
diff --git a/app/views/kaminari/gitlab/_last_page.html.haml b/app/views/kaminari/gitlab/_last_page.html.haml
index 53f780d1d1..3431d029bc 100644
--- a/app/views/kaminari/gitlab/_last_page.html.haml
+++ b/app/views/kaminari/gitlab/_last_page.html.haml
@@ -2,7 +2,7 @@
-# available local variables
-# url: url to the last page
-# current_page: a page object for the currently displayed page
--# total_pages: total number of pages
+-# num_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%li.last
diff --git a/app/views/kaminari/gitlab/_next_page.html.haml b/app/views/kaminari/gitlab/_next_page.html.haml
index 125f09777b..c805914fc3 100644
--- a/app/views/kaminari/gitlab/_next_page.html.haml
+++ b/app/views/kaminari/gitlab/_next_page.html.haml
@@ -2,7 +2,7 @@
-# available local variables
-# url: url to the next page
-# current_page: a page object for the currently displayed page
--# total_pages: total number of pages
+-# num_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
- if current_page.last?
diff --git a/app/views/kaminari/gitlab/_page.html.haml b/app/views/kaminari/gitlab/_page.html.haml
index 522e4d1d05..a52d883b9a 100644
--- a/app/views/kaminari/gitlab/_page.html.haml
+++ b/app/views/kaminari/gitlab/_page.html.haml
@@ -3,7 +3,7 @@
-# page: a page object for "this" page
-# url: url to this page
-# current_page: a page object for the currently displayed page
--# total_pages: total number of pages
+-# num_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%li{class: "page#{' active' if page.current?}"}
diff --git a/app/views/kaminari/gitlab/_paginator.html.haml b/app/views/kaminari/gitlab/_paginator.html.haml
index f5e0d2ed3f..a12c53bcfe 100644
--- a/app/views/kaminari/gitlab/_paginator.html.haml
+++ b/app/views/kaminari/gitlab/_paginator.html.haml
@@ -1,7 +1,7 @@
-# The container tag
-# available local variables
-# current_page: a page object for the currently displayed page
--# total_pages: total number of pages
+-# num_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
-# paginator: the paginator that renders the pagination tags inside
@@ -9,7 +9,7 @@
%div.gl-pagination
%ul.pagination.clearfix
- unless current_page.first?
- = first_page_tag unless total_pages < 5 # As kaminari will always show the first 5 pages
+ = first_page_tag unless num_pages < 5 # As kaminari will always show the first 5 pages
= prev_page_tag
- each_page do |page|
- if page.left_outer? || page.right_outer? || page.inside_window?
@@ -18,5 +18,5 @@
= gap_tag
= next_page_tag
- unless current_page.last?
- = last_page_tag unless total_pages < 5
+ = last_page_tag unless num_pages < 5
diff --git a/app/views/kaminari/gitlab/_prev_page.html.haml b/app/views/kaminari/gitlab/_prev_page.html.haml
index 7edf10498a..afb20455e0 100644
--- a/app/views/kaminari/gitlab/_prev_page.html.haml
+++ b/app/views/kaminari/gitlab/_prev_page.html.haml
@@ -2,7 +2,7 @@
-# available local variables
-# url: url to the previous page
-# current_page: a page object for the currently displayed page
--# total_pages: total number of pages
+-# num_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
- if current_page.first?
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index b30fb0a5da..79cdbac1f3 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -30,9 +30,6 @@
= javascript_include_tag "application"
- - if page_specific_javascripts
- = javascript_include_tag page_specific_javascripts, {"data-turbolinks-track" => true}
-
= csrf_meta_tags
= include_gon
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 1e961853c7..3c3bc41bf0 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -1,4 +1,5 @@
.page-with-sidebar{ class: "#{page_sidebar_class} #{page_gutter_class}" }
+ = render "layouts/broadcast"
.sidebar-wrapper.nicescroll{ class: nav_sidebar_class }
.header-logo
%a#logo
@@ -25,8 +26,7 @@
.layout-nav
.container-fluid
= render "layouts/nav/#{nav}"
- .content-wrapper{ class: "#{layout_nav_class}" }
- = render "layouts/broadcast"
+ .content-wrapper{ class: ('page-with-layout-nav' if defined?(nav) && nav) }
= render "layouts/flash"
= yield :flash_message
%div{ class: (container_class unless @no_container) }
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index b49207fc31..6b208c3d0b 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -6,8 +6,11 @@
.search.search-form{class: "#{'has-location-badge' if label.present?}"}
= form_tag search_path, method: :get, class: 'navbar-form' do |f|
.search-input-container
- - if label.present?
- .location-badge= label
+ .search-location-badge
+ - if label.present?
+ %span.location-badge
+ %i.location-text
+ = label
.search-input-wrap
.dropdown{ data: {url: search_autocomplete_path } }
= search_field_tag "search", nil, placeholder: 'Search', class: "search-input dropdown-menu-toggle", spellcheck: false, tabindex: "1", autocomplete: 'off', data: { toggle: 'dropdown' }
diff --git a/app/views/layouts/devise_mailer.html.haml b/app/views/layouts/devise_mailer.html.haml
deleted file mode 100644
index c258eafdd5..0000000000
--- a/app/views/layouts/devise_mailer.html.haml
+++ /dev/null
@@ -1,34 +0,0 @@
-!!! 5
-%html
- %head
- %meta(content='text/html; charset=UTF-8' http-equiv='Content-Type')
- = stylesheet_link_tag 'mailers/devise'
-
- %body
- %table#wrapper
- %tr
- %td
- %table#header
- %td{valign: "top"}
- = image_tag('mailers/gitlab_header_logo.png', id: 'logo', alt: 'GitLab Wordmark')
-
- %table#body
- %tr
- %td#body-container
- = yield
-
- - if Gitlab.com?
- %table#footer
- %tr
- %td#tanuki
- = image_tag('mailers/gitlab_tanuki_2x.png', alt: 'GitLab Logo')
- %tr
- %td#tagline
- Everyone can contribute
- %tr
- %td#social
- = link_to 'Blog', 'https://about.gitlab.com/blog/'
- = link_to 'Twitter', 'https://twitter.com/gitlab'
- = link_to 'Facebook', 'https://www.facebook.com/gitlab/'
- = link_to 'YouTube', 'https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg'
- = link_to 'LinkedIn', 'https://www.linkedin.com/company/gitlab-com'
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index c33740e23f..86930d4eaa 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -1,12 +1,9 @@
%header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class }
%div{ class: fluid_layout ? "container-fluid" : "container-fluid" }
.header-content
- %button.side-nav-toggle{type: 'button'}
- %span.sr-only Toggle navigation
- = icon('bars')
%button.navbar-toggle{type: 'button'}
%span.sr-only Toggle navigation
- = icon('angle-left')
+ = icon('bars')
.navbar-collapse.collapse
%ul.nav.navbar-nav
@@ -27,9 +24,8 @@
%li
= link_to dashboard_todos_path, title: 'Todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('bell fw')
- - unless todos_pending_count == 0
- %span.badge.todos-pending-count
- = todos_pending_count
+ %span.badge.todos-pending-count
+ = todos_pending_count
- if current_user.can_create_project?
%li
= link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml
index f292730fe4..280a1b9372 100644
--- a/app/views/layouts/nav/_admin.html.haml
+++ b/app/views/layouts/nav/_admin.html.haml
@@ -41,11 +41,6 @@
= icon('file-text fw')
%span
Logs
- = nav_link(controller: :health_check) do
- = link_to admin_health_check_path, title: 'Health Check' do
- = icon('medkit fw')
- %span
- Health Check
= nav_link(controller: :broadcast_messages) do
= link_to admin_broadcast_messages_path, title: 'Messages' do
= icon('bullhorn fw')
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index 306ebd5fcf..fad4224e94 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -1,6 +1,6 @@
%ul.nav.nav-sidebar
- = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do
- = link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
+ = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: 'home'}) do
+ = link_to dashboard_projects_path, title: 'Projects' do
= icon('bookmark fw')
%span
Projects
@@ -11,7 +11,7 @@
Todos
%span.count.todos-pending-count= number_with_delimiter(todos_pending_count)
= nav_link(path: 'dashboard#activity') do
- = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
+ = link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity' do
= icon('dashboard fw')
%span
Activity
@@ -26,17 +26,17 @@
%span
Milestones
= nav_link(path: 'dashboard#issues') do
- = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do
+ = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'shortcuts-issues' do
= icon('exclamation-circle fw')
%span
Issues
- %span.count= number_with_delimiter(current_user.assigned_open_issues_count)
+ %span.count= number_with_delimiter(current_user.assigned_issues.opened.count)
= nav_link(path: 'dashboard#merge_requests') do
- = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do
+ = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do
= icon('tasks fw')
%span
Merge Requests
- %span.count= number_with_delimiter(current_user.assigned_open_merge_request_count)
+ %span.count= number_with_delimiter(current_user.assigned_merge_requests.opened.count)
= nav_link(controller: :snippets) do
= link_to dashboard_snippets_path, title: 'Snippets' do
= icon('clipboard fw')
diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml
index de15add361..3438005863 100644
--- a/app/views/layouts/nav/_group.html.haml
+++ b/app/views/layouts/nav/_group.html.haml
@@ -1,40 +1,37 @@
-%div{ class: nav_control_class }
- = render 'layouts/nav/group_settings'
+= render 'layouts/nav/group_settings'
- %ul.nav-links.scrolling-tabs
- .fade-left
- = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
- = link_to group_path(@group), title: 'Home' do
- = icon('group fw')
- %span
- Group
- = nav_link(path: 'groups#activity') do
- = link_to activity_group_path(@group), title: 'Activity' do
- = icon('dashboard fw')
- %span
- Activity
- = nav_link(controller: [:group, :milestones]) do
- = link_to group_milestones_path(@group), title: 'Milestones' do
- = icon('clock-o fw')
- %span
- Milestones
- = nav_link(path: 'groups#issues') do
- = link_to issues_group_path(@group), title: 'Issues' do
- = icon('exclamation-circle fw')
- %span
- Issues
- - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
- %span.badge.count= number_with_delimiter(issues.count)
- = nav_link(path: 'groups#merge_requests') do
- = link_to merge_requests_group_path(@group), title: 'Merge Requests' do
- = icon('tasks fw')
- %span
- Merge Requests
- - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute
- %span.badge.count= number_with_delimiter(merge_requests.count)
- = nav_link(controller: [:group_members]) do
- = link_to group_group_members_path(@group), title: 'Members' do
- = icon('users fw')
- %span
- Members
- .fade-right
+%ul.nav-links
+ = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
+ = link_to group_path(@group), title: 'Home' do
+ = icon('group fw')
+ %span
+ Group
+ = nav_link(path: 'groups#activity') do
+ = link_to activity_group_path(@group), title: 'Activity' do
+ = icon('dashboard fw')
+ %span
+ Activity
+ = nav_link(controller: [:group, :milestones]) do
+ = link_to group_milestones_path(@group), title: 'Milestones' do
+ = icon('clock-o fw')
+ %span
+ Milestones
+ = nav_link(path: 'groups#issues') do
+ = link_to issues_group_path(@group), title: 'Issues' do
+ = icon('exclamation-circle fw')
+ %span
+ Issues
+ - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
+ %span.badge.count= number_with_delimiter(issues.count)
+ = nav_link(path: 'groups#merge_requests') do
+ = link_to merge_requests_group_path(@group), title: 'Merge Requests' do
+ = icon('tasks fw')
+ %span
+ Merge Requests
+ - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute
+ %span.badge.count= number_with_delimiter(merge_requests.count)
+ = nav_link(controller: [:group_members]) do
+ = link_to group_group_members_path(@group), title: 'Members' do
+ = icon('users fw')
+ %span
+ Members
diff --git a/app/views/layouts/nav/_group_settings.html.haml b/app/views/layouts/nav/_group_settings.html.haml
index 0b2673f1a8..e391ec7f2b 100644
--- a/app/views/layouts/nav/_group_settings.html.haml
+++ b/app/views/layouts/nav/_group_settings.html.haml
@@ -1,7 +1,7 @@
- if current_user
- if access = @group.users.find_by(id: current_user.id)
.controls
- .dropdown.group-settings-dropdown
+ %span.dropdown.group-settings-dropdown
%a.dropdown-new.btn.btn-default#group-settings-button{href: '#', 'data-toggle' => 'dropdown'}
= icon('cog')
= icon('caret-down')
diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml
index 2efc6c48a4..d730840d63 100644
--- a/app/views/layouts/nav/_profile.html.haml
+++ b/app/views/layouts/nav/_profile.html.haml
@@ -1,5 +1,4 @@
-%ul.nav-links.scrolling-tabs
- .fade-left
+%ul.nav-links
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path, title: 'Profile Settings' do
= icon('user fw')
@@ -48,4 +47,3 @@
= icon('history fw')
%span
Audit Log
- .fade-right
diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml
index 9792c1c93b..479bde3371 100644
--- a/app/views/layouts/nav/_project.html.haml
+++ b/app/views/layouts/nav/_project.html.haml
@@ -1,131 +1,131 @@
-- if current_user
- .controls
- - access = user_max_access_in_project(current_user.id, @project)
- - can_edit = can?(current_user, :admin_project, @project)
- .dropdown.project-settings-dropdown
- %a.dropdown-new.btn.btn-default#project-settings-button{href: '#', 'data-toggle' => 'dropdown'}
- = icon('cog')
- = icon('caret-down')
- %ul.dropdown-menu.dropdown-menu-align-right
- = render 'layouts/nav/project_settings'
- %li.divider
- - if can_edit
- %li
- = link_to edit_project_path(@project) do
- Edit Project
- - if access
- %li
- = link_to leave_namespace_project_project_members_path(@project.namespace, @project),
- data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do
- Leave Project
-
-%div{ class: nav_control_class }
- %ul.nav-links.scrolling-tabs
- .fade-left
- = nav_link(path: 'projects#show', html_options: {class: 'home'}) do
- = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
- = icon('bookmark fw')
+%ul.nav.nav-sidebar
+ - if @project.group
+ = nav_link do
+ = link_to group_path(@project.group), title: 'Go to group', class: 'back-link' do
+ = icon('caret-square-o-left fw')
%span
- Project
- = nav_link(path: 'projects#activity') do
- = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do
- = icon('dashboard fw')
+ Go to group
+ - else
+ = nav_link do
+ = link_to root_path, title: 'Go to dashboard', class: 'back-link' do
+ = icon('caret-square-o-left fw')
%span
- Activity
- - if project_nav_tab? :files
- = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare repositories tags branches releases network)) do
- = link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree' do
- = icon('code fw')
- %span
- Code
+ Go to dashboard
- - if project_nav_tab? :pipelines
- = nav_link(controller: :pipelines) do
- = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do
- = icon('ship fw')
- %span
- Pipelines
+ %li.separate-item
- - if project_nav_tab? :container_registry
- = nav_link(controller: %w(container_registry)) do
- = link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do
- = icon('hdd-o fw')
- %span
- Container Registry
+ = nav_link(path: 'projects#show', html_options: {class: 'home'}) do
+ = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
+ = icon('bookmark fw')
+ %span
+ Project
+ = nav_link(path: 'projects#activity') do
+ = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do
+ = icon('dashboard fw')
+ %span
+ Activity
+ - if project_nav_tab? :files
+ = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do
+ = link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree' do
+ = icon('files-o fw')
+ %span
+ Files
- - if project_nav_tab? :graphs
- = nav_link(controller: %w(graphs)) do
- = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do
- = icon('area-chart fw')
- %span
- Graphs
-
- - if project_nav_tab? :milestones
- = nav_link(controller: :milestones) do
- = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do
- = icon('clock-o fw')
- %span
- Milestones
-
- - if project_nav_tab? :issues
- = nav_link(controller: :issues) do
- = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do
- = icon('exclamation-circle fw')
- %span
- Issues
- - if @project.default_issues_tracker?
- %span.badge.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count)
-
- - if project_nav_tab? :merge_requests
- = nav_link(controller: :merge_requests) do
- = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
- = icon('tasks fw')
- %span
- Merge Requests
- %span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count)
-
- - if project_nav_tab? :labels
- = nav_link(controller: :labels) do
- = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do
- = icon('tags fw')
- %span
- Labels
-
- - if project_nav_tab? :wiki
- = nav_link(controller: :wikis) do
- = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do
- = icon('book fw')
- %span
- Wiki
-
- - if project_nav_tab? :snippets
- = nav_link(controller: :snippets) do
- = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do
- = icon('clipboard fw')
- %span
- Snippets
-
- -# Global shortcut to network page for compatibility
- - if project_nav_tab? :network
- %li.hidden
- = link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network' do
- Network
-
- -# Shortcut to create a new issue
- %li.hidden
- = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'shortcuts-new-issue' do
- Create a new issue
-
- -# Shortcut to builds page
- - if project_nav_tab? :builds
- %li.hidden
- = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do
- Builds
-
- -# Shortcut to commits page
- - if project_nav_tab? :commits
- %li.hidden
- = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do
+ - if project_nav_tab? :commits
+ = nav_link(controller: %w(commit commits compare repositories tags branches releases network)) do
+ = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do
+ = icon('history fw')
+ %span
Commits
- .fade-right
+ - if project_nav_tab? :builds
+ = nav_link(controller: %w(builds)) do
+ = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do
+ = icon('cubes fw')
+ %span
+ Builds
+ %span.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all))
+
+ - if project_nav_tab? :graphs
+ = nav_link(controller: %w(graphs)) do
+ = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do
+ = icon('area-chart fw')
+ %span
+ Graphs
+
+ - if project_nav_tab? :milestones
+ = nav_link(controller: :milestones) do
+ = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do
+ = icon('clock-o fw')
+ %span
+ Milestones
+
+ - if project_nav_tab? :issues
+ = nav_link(controller: :issues) do
+ = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do
+ = icon('exclamation-circle fw')
+ %span
+ Issues
+ - if @project.default_issues_tracker?
+ %span.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count)
+
+ - if project_nav_tab? :merge_requests
+ = nav_link(controller: :merge_requests) do
+ = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
+ = icon('tasks fw')
+ %span
+ Merge Requests
+ %span.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count)
+
+ - if project_nav_tab? :team
+ = nav_link(controller: [:project_members, :teams]) do
+ = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab' do
+ = icon('users fw')
+ %span
+ Members
+
+ - if project_nav_tab? :labels
+ = nav_link(controller: :labels) do
+ = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do
+ = icon('tags fw')
+ %span
+ Labels
+
+ - if project_nav_tab? :wiki
+ = nav_link(controller: :wikis) do
+ = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do
+ = icon('book fw')
+ %span
+ Wiki
+
+ - if project_nav_tab? :forks
+ = nav_link(controller: :forks, action: :index) do
+ = link_to namespace_project_forks_path(@project.namespace, @project), title: 'Forks' do
+ = icon('code-fork fw')
+ %span
+ Forks
+
+ - if project_nav_tab? :snippets
+ = nav_link(controller: :snippets) do
+ = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do
+ = icon('clipboard fw')
+ %span
+ Snippets
+
+ - if project_nav_tab? :settings
+ = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do
+ = link_to edit_project_path(@project), title: 'Settings' do
+ = icon('cogs fw')
+ %span
+ Settings
+
+ -# Global shortcut to network page for compatibility
+ - if project_nav_tab? :network
+ %li.hidden
+ = link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network' do
+ Network
+
+ -# Shortcut to create a new issue
+ %li.hidden
+ = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'shortcuts-new-issue' do
+ Create a new issue
diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml
index 885e78d38c..d429a92846 100644
--- a/app/views/layouts/nav/_project_settings.html.haml
+++ b/app/views/layouts/nav/_project_settings.html.haml
@@ -1,45 +1,63 @@
-- if project_nav_tab? :team
- = nav_link(controller: [:project_members, :teams]) do
- = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab' do
+%ul.nav.nav-sidebar
+ = nav_link do
+ = link_to project_path(@project), title: 'Go to project', class: 'back-link' do
+ = icon('caret-square-o-left fw')
%span
- Members
+ Go to project
-- if @project.allowed_to_share_with_group?
- = nav_link(controller: :group_links) do
- = link_to namespace_project_group_links_path(@project.namespace, @project), title: "Groups" do
- %span
- Groups
-= nav_link(controller: :deploy_keys) do
- = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do
- %span
- Deploy Keys
-= nav_link(controller: :hooks) do
- = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do
- %span
- Webhooks
-= nav_link(controller: :services) do
- = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do
- %span
- Services
-= nav_link(controller: :protected_branches) do
- = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do
- %span
- Protected Branches
+ %li.separate-item
-- if @project.builds_enabled?
- = nav_link(controller: :runners) do
- = link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do
- %span
- Runners
- = nav_link(controller: :variables) do
- = link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do
- %span
- Variables
- = nav_link(controller: :triggers) do
- = link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do
- %span
- Triggers
- = nav_link(controller: :badges) do
- = link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do
- %span
- Badges
+ %ul.sidebar-subnav
+ = nav_link(path: 'projects#edit') do
+ = link_to edit_project_path(@project), title: 'Project Settings' do
+ = icon('pencil-square-o fw')
+ %span
+ Project Settings
+ - if @project.allowed_to_share_with_group?
+ = nav_link(controller: :group_links) do
+ = link_to namespace_project_group_links_path(@project.namespace, @project), title: "Groups" do
+ = icon('share-square-o fw')
+ %span
+ Groups
+ = nav_link(controller: :deploy_keys) do
+ = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do
+ = icon('key fw')
+ %span
+ Deploy Keys
+ = nav_link(controller: :hooks) do
+ = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do
+ = icon('link fw')
+ %span
+ Webhooks
+ = nav_link(controller: :services) do
+ = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do
+ = icon('cogs fw')
+ %span
+ Services
+ = nav_link(controller: :protected_branches) do
+ = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do
+ = icon('lock fw')
+ %span
+ Protected Branches
+
+ - if @project.builds_enabled?
+ = nav_link(controller: :runners) do
+ = link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do
+ = icon('cog fw')
+ %span
+ Runners
+ = nav_link(controller: :variables) do
+ = link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do
+ = icon('code fw')
+ %span
+ Variables
+ = nav_link(controller: :triggers) do
+ = link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do
+ = icon('retweet fw')
+ %span
+ Triggers
+ = nav_link(controller: :badges) do
+ = link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do
+ = icon('star-half-empty fw')
+ %span
+ Badges
diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml
index dde2e2889d..2997f59d94 100644
--- a/app/views/layouts/notify.html.haml
+++ b/app/views/layouts/notify.html.haml
@@ -4,7 +4,6 @@
%title
GitLab
= stylesheet_link_tag 'notify'
- = yield :head
%body
%div.content
= yield
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index 20d6cdf724..6dfe7fbdae 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -1,7 +1,7 @@
- page_title @project.name_with_namespace
- page_description @project.description unless page_description
- header_title project_title(@project) unless header_title
-- nav "project"
+- sidebar "project" unless sidebar
- content_for :scripts_body_top do
- project = @target_project || @project
diff --git a/app/views/layouts/project_settings.html.haml b/app/views/layouts/project_settings.html.haml
index 4bc94bd132..59ce38f67b 100644
--- a/app/views/layouts/project_settings.html.haml
+++ b/app/views/layouts/project_settings.html.haml
@@ -1,4 +1,5 @@
- page_title "Settings"
-- nav "project"
+- header_title project_title(@project, "Settings", edit_project_path(@project))
+- sidebar "project_settings"
= render template: "layouts/project"
diff --git a/app/views/notify/_note_message.html.haml b/app/views/notify/_note_message.html.haml
index e9c6617087..12ded41fbf 100644
--- a/app/views/notify/_note_message.html.haml
+++ b/app/views/notify/_note_message.html.haml
@@ -2,4 +2,4 @@
%div
#{link_to @note.author_name, user_url(@note.author)} wrote:
%div
- = markdown(@note.note, pipeline: :email, author: @note.author)
+ = markdown(@note.note, pipeline: :email)
diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml
index f42b150c0d..ad3ab2525b 100644
--- a/app/views/notify/new_issue_email.html.haml
+++ b/app/views/notify/new_issue_email.html.haml
@@ -2,7 +2,7 @@
%div
#{link_to @issue.author_name, user_url(@issue.author)} wrote:
-if @issue.description
- = markdown(@issue.description, pipeline: :email, author: @issue.author)
+ = markdown(@issue.description, pipeline: :email)
- if @issue.assignee_id.present?
%p
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index 158404de39..23423e7d98 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -9,4 +9,4 @@
Assignee: #{@merge_request.author_name} → #{@merge_request.assignee_name}
-if @merge_request.description
- = markdown(@merge_request.description, pipeline: :email, author: @merge_request.author)
+ = markdown(@merge_request.description, pipeline: :email)
diff --git a/app/views/notify/note_merge_request_email.html.haml b/app/views/notify/note_merge_request_email.html.haml
index a3643a00cf..65f0e4c406 100644
--- a/app/views/notify/note_merge_request_email.html.haml
+++ b/app/views/notify/note_merge_request_email.html.haml
@@ -1,7 +1,7 @@
-- if @note.legacy_diff_note?
+- if @note.diff_file_name
%p.details
New comment on diff for
- = link_to @note.diff_file_path, @target_url
+ = link_to @note.diff_file_name, @target_url
\:
= render 'note_message'
diff --git a/app/views/notify/repository_push_email.html.haml b/app/views/notify/repository_push_email.html.haml
index f1532371b2..f2e405b14f 100644
--- a/app/views/notify/repository_push_email.html.haml
+++ b/app/views/notify/repository_push_email.html.haml
@@ -1,6 +1,3 @@
-= content_for :head do
- = stylesheet_link_tag 'mailers/repository_push_email'
-
%h3
#{@message.author_name} #{@message.action_name} #{@message.ref_type} #{@message.ref_name}
at #{link_to(@message.project_name_with_namespace, namespace_project_url(@message.project_namespace, @message.project))}
@@ -46,38 +43,26 @@
= diff.new_path
- unless @message.disable_diffs?
- - diff_files = @message.diffs
-
- - if @message.compare_timeout
- %h5 The diff was not included because it is too large.
- - else
- %h4 Changes:
- - diff_files.each_with_index do |diff_file, i|
- %li{id: "diff-#{i}"}
- %a{href: @message.target_url + "#diff-#{i}"}<
- - if diff_file.deleted_file
- %strong<
- = diff_file.old_path
- deleted
- - elsif diff_file.renamed_file
- %strong<
- = diff_file.old_path
- →
- %strong<
- = diff_file.new_path
- - else
- %strong<
- = diff_file.new_path
- - if diff_file.too_large?
- The diff for this file was not included because it is too large.
+ %h4 Changes:
+ - @message.diffs.each_with_index do |diff, i|
+ %li{id: "diff-#{i}"}
+ %a{href: @message.target_url + "#diff-#{i}"}
+ - if diff.deleted_file
+ %strong
+ = diff.old_path
+ deleted
+ - elsif diff.renamed_file
+ %strong
+ = diff.old_path
+ →
+ %strong
+ = diff.new_path
- else
- %hr
- - diff_commit = diff_file.deleted_file ? @message.diff_refs.first : @message.diff_refs.last
- - blob = @message.project.repository.blob_for_diff(diff_commit, diff_file)
- - if blob && blob.respond_to?(:text?) && blob_text_viewable?(blob)
- %table.code.white
- - diff_file.highlighted_diff_lines.each do |line|
- = render "projects/diffs/line", {line: line, diff_file: diff_file, line_code: nil, plain: true}
- - else
- No preview for this file type
- %br
+ %strong
+ = diff.new_path
+ %hr
+ = color_email_diff(diff.diff)
+ %br
+
+ - if @message.compare_timeout
+ %h5 Huge diff. To prevent performance issues changes are hidden
diff --git a/app/views/notify/repository_push_email.text.haml b/app/views/notify/repository_push_email.text.haml
index 5ac23aa399..53869e36b2 100644
--- a/app/views/notify/repository_push_email.text.haml
+++ b/app/views/notify/repository_push_email.text.haml
@@ -25,28 +25,24 @@
- else
\- #{diff.new_path}
- unless @message.disable_diffs?
- - if @message.compare_timeout
+ \
+ \
+ Changes:
+ - @message.diffs.each do |diff|
\
- \
- The diff was not included because it is too large.
- - else
- \
- \
- Changes:
- - @message.diffs.each do |diff_file|
- \
- \=====================================
- - if diff_file.deleted_file
- #{diff_file.old_path} deleted
- - elsif diff_file.renamed_file
- #{diff_file.old_path} → #{diff_file.new_path}
- - else
- = diff_file.new_path
- \=====================================
- - if diff_file.too_large?
- The diff for this file was not included because it is too large.
- - else
- != diff_file.diff.diff
+ \=====================================
+ - if diff.deleted_file
+ #{diff.old_path} deleted
+ - elsif diff.renamed_file
+ #{diff.old_path} → #{diff.new_path}
+ - else
+ = diff.new_path
+ \=====================================
+ != diff.diff
+ - if @message.compare_timeout
+ \
+ \
+ Huge diff. To prevent performance issues it was hidden
- if @message.target_url
\
\
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index 01ac816194..afd3d79321 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -70,7 +70,7 @@
- if current_user.can_change_username?
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar
- %h4.prepend-top-0.warning-title
+ %h4.prepend-top-0.change-username-title
Change username
%p
Changing your username will change path to all personal projects!
@@ -94,7 +94,7 @@
- if signup_enabled?
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar
- %h4.prepend-top-0.danger-title
+ %h4.prepend-top-0.remove-account-title
Remove account
.col-lg-9
- if @user.can_be_removed?
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 1b1b16d656..bfe53be685 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -5,7 +5,7 @@
%h4.prepend-top-0
Application theme
%p
- This setting allows you to customize the appearance of the site, e.g. the sidebar.
+ This setting allows you to customize the appearance of the site, ex. sidebar.
.col-lg-9.application-theme
- Gitlab::Themes.each do |theme|
= label_tag do
diff --git a/app/views/projects/_builds_settings.html.haml b/app/views/projects/_builds_settings.html.haml
index 0568c2d305..0de019983c 100644
--- a/app/views/projects/_builds_settings.html.haml
+++ b/app/views/projects/_builds_settings.html.haml
@@ -1,65 +1,74 @@
%fieldset.builds-feature
- %h5.prepend-top-0
- Builds
+ %legend
+ Builds:
+
- unless @repository.gitlab_ci_yml
.form-group
- %p Builds need to be configured before you can begin using Continuous Integration.
- = link_to 'Get started with Builds', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info'
- .form-group
- %p Get recent application code using the following command:
- .radio
- = f.label :build_allow_git_fetch_false do
- = f.radio_button :build_allow_git_fetch, 'false'
- %strong git clone
- %br
- %span.descr Slower but makes sure you have a clean dir before every build
- .radio
- = f.label :build_allow_git_fetch_true do
- = f.radio_button :build_allow_git_fetch, 'true'
- %strong git fetch
- %br
- %span.descr Faster
+ .col-sm-offset-2.col-sm-10
+ %p Builds need to be configured before you can begin using Continuous Integration.
+ = link_to 'Get started with Builds', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info'
+ %hr
.form-group
- = f.label :build_timeout_in_minutes, 'Timeout', class: 'label-light'
- = f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0'
- %p.help-block per build in minutes
- .form-group
- = f.label :build_coverage_regex, "Test coverage parsing", class: 'label-light'
- .input-group
- %span.input-group-addon /
- = f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered'
- %span.input-group-addon /
- %p.help-block
- We will use this regular expression to find test coverage output in build trace.
- Leave blank if you want to disable this feature
- .bs-callout.bs-callout-info
- %p Below are examples of regex for existing tools:
- %ul
- %li
- Simplecov (Ruby) -
- %code \(\d+.\d+\%\) covered
- %li
- pytest-cov (Python) -
- %code \d+\%\s*$
- %li
- phpunit --coverage-text --colors=never (PHP) -
- %code ^\s*Lines:\s*\d+.\d+\%
- %li
- gcovr (C/C++) -
- %code ^TOTAL.*\s+(\d+\%)$
- %li
- tap --coverage-report=text-summary (Node.js) -
- %code ^Statements\s*:\s*([^%]+)
+ .col-sm-offset-2.col-sm-10
+ %p Get recent application code using the following command:
+ .radio
+ = f.label :build_allow_git_fetch_false do
+ = f.radio_button :build_allow_git_fetch, 'false'
+ %strong git clone
+ %br
+ %span.descr Slower but makes sure you have a clean dir before every build
+ .radio
+ = f.label :build_allow_git_fetch_true do
+ = f.radio_button :build_allow_git_fetch, 'true'
+ %strong git fetch
+ %br
+ %span.descr Faster
.form-group
- .checkbox
- = f.label :public_builds do
- = f.check_box :public_builds
- %strong Public builds
- .help-block Allow everyone to access builds for Public and Internal projects
+ = f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label'
+ .col-sm-10
+ = f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0'
+ %p.help-block per build in minutes
+ .form-group
+ = f.label :build_coverage_regex, "Test coverage parsing", class: 'control-label'
+ .col-sm-10
+ .input-group
+ %span.input-group-addon /
+ = f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered'
+ %span.input-group-addon /
+ %p.help-block
+ We will use this regular expression to find test coverage output in build trace.
+ Leave blank if you want to disable this feature
+ .bs-callout.bs-callout-info
+ %p Below are examples of regex for existing tools:
+ %ul
+ %li
+ Simplecov (Ruby) -
+ %code \(\d+.\d+\%\) covered
+ %li
+ pytest-cov (Python) -
+ %code \d+\%\s*$
+ %li
+ phpunit --coverage-text --colors=never (PHP) -
+ %code ^\s*Lines:\s*\d+.\d+\%
+ %li
+ gcovr (C/C++) -
+ %code ^TOTAL.*\s+(\d+\%)$
+ %li
+ tap --coverage-report=text-summary (Node.js) -
+ %code ^Statements\s*:\s*([^%]+)
- .form-group.append-bottom-0
- = f.label :runners_token, "Runners token", class: 'label-light'
- = f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89'
- %p.help-block The secure token used to checkout project.
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :public_builds do
+ = f.check_box :public_builds
+ %strong Public builds
+ .help-block Allow everyone to access builds for Public and Internal projects
+
+ .form-group
+ = f.label :runners_token, "Runners token", class: 'control-label'
+ .col-sm-10
+ = f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89'
+ %p.help-block The secure token used to checkout project.
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 57c3d1b0a6..9b5de17dd3 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -1,37 +1,59 @@
- empty_repo = @project.empty_repo?
.project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)}
- .container-fluid.container-limited
- .row
- .project-image-container
- = project_icon(@project, alt: '', class: 'project-avatar avatar s70')
- .project-info
- .cover-title.project-home-desc
- %h1
- = @project.name
- %span.visibility-icon.has-tooltip{data: { container: 'body' }, title: visibility_icon_description(@project)}
- = visibility_level_icon(@project.visibility_level, fw: false)
+ .project-identicon-holder
+ = project_icon(@project, alt: '', class: 'project-avatar avatar s90')
+ .cover-title.project-home-desc
+ %h1
+ = @project.name
+ %span.visibility-icon.has-tooltip{data: { container: 'body' }, title: visibility_icon_description(@project)}
+ = visibility_level_icon(@project.visibility_level, fw: false)
- - if @project.description.present?
- .cover-desc.project-home-desc
- = markdown(@project.description, pipeline: :description)
+ - if @project.description.present?
+ .cover-desc.project-home-desc
+ = markdown(@project.description, pipeline: :description)
- - if forked_from_project = @project.forked_from_project
- .cover-desc
- Forked from
- = link_to project_path(forked_from_project) do
- = forked_from_project.namespace.try(:name)
+ - if forked_from_project = @project.forked_from_project
+ .cover-desc
+ Forked from
+ = link_to project_path(forked_from_project) do
+ = forked_from_project.namespace.try(:name)
- .project-repo-buttons
- .count-buttons
- = render 'projects/buttons/star'
- = render 'projects/buttons/fork'
+ .cover-controls
+ - if current_user
+ = link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), class: 'btn btn-gray' do
+ = icon('rss')
+ - access = user_max_access_in_project(current_user.id, @project)
+ - can_edit = can?(current_user, :admin_project, @project)
+ - if access || can_edit
+ %span.dropdown.project-settings-dropdown
+ %a.dropdown-new.btn.btn-gray#project-settings-button{href: '#', 'data-toggle' => 'dropdown'}
+ = icon('cog')
+ = icon('angle-down')
+ %ul.dropdown-menu.dropdown-menu-right
+ - if can_edit
+ %li
+ = link_to edit_project_path(@project) do
+ Edit Project
+ - if access
+ %li
+ = link_to leave_namespace_project_project_members_path(@project.namespace, @project),
+ data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do
+ Leave Project
- .project-clone-holder
- = render "shared/clone_panel"
+ .project-repo-buttons
+ .split-one.count-buttons
+ = render 'projects/buttons/star'
+ = render 'projects/buttons/fork'
+
+ .clone-row
+ .project-clone-holder
+ = render "shared/clone_panel"
+
+ .split-repo-buttons
+ .btn-group.pull-left
+ = render "projects/buttons/download"
+ = render 'projects/buttons/dropdown'
- .project-repo-buttons.btn-group.project-right-buttons
- = render "projects/buttons/download"
- = render 'projects/buttons/dropdown'
= render 'projects/buttons/notifications'
:javascript
diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml
index 81afea2c60..8de44a6c91 100644
--- a/app/views/projects/_md_preview.html.haml
+++ b/app/views/projects/_md_preview.html.haml
@@ -8,7 +8,7 @@
%a.js-md-preview-button{ href: "#md-preview-holder", tabindex: -1 }
Preview
%li.pull-right
- %button.zen-control.zen-control-full.js-zen-enter{ type: 'button', tabindex: -1 }
+ %button.zen-cotrol.zen-control-full.js-zen-enter{ type: 'button', tabindex: -1 }
Go full screen
.md-write-holder
diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml
index 413477a2d3..e1e3501396 100644
--- a/app/views/projects/_zen.html.haml
+++ b/app/views/projects/_zen.html.haml
@@ -4,5 +4,5 @@
= f.text_area attr, class: classes, placeholder: placeholder
- else
= text_area_tag attr, nil, class: classes, placeholder: placeholder
- %a.zen-control.zen-control-leave.js-zen-leave{ href: "#" }
+ %a.zen-cotrol.zen-control-leave.js-zen-leave{ href: "#" }
= icon('compress')
diff --git a/app/views/projects/activity.html.haml b/app/views/projects/activity.html.haml
index 3c0f01cbf6..69fa4ad37c 100644
--- a/app/views/projects/activity.html.haml
+++ b/app/views/projects/activity.html.haml
@@ -1,4 +1,5 @@
- page_title "Activity"
+- header_title project_title(@project, "Activity", activity_project_path(@project))
= render 'projects/last_push'
diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml
index ede01dcc1a..49f95ff37d 100644
--- a/app/views/projects/artifacts/browse.html.haml
+++ b/app/views/projects/artifacts/browse.html.haml
@@ -1,4 +1,5 @@
- page_title 'Artifacts', "#{@build.name} (##{@build.id})", 'Builds'
+= render 'projects/builds/header_title'
.top-block.row-content-block.clearfix
.pull-right
diff --git a/app/views/projects/badges/index.html.haml b/app/views/projects/badges/index.html.haml
index ee63bc55a3..c22384ddf4 100644
--- a/app/views/projects/badges/index.html.haml
+++ b/app/views/projects/badges/index.html.haml
@@ -1,5 +1,6 @@
- page_title 'Badges'
- badges_path = namespace_project_badges_path(@project.namespace, @project)
+- header_title project_title(@project, 'Badges', badges_path)
.prepend-top-10
.panel.panel-default
diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml
index 377665b096..5f9a92ff93 100644
--- a/app/views/projects/blame/show.html.haml
+++ b/app/views/projects/blame/show.html.haml
@@ -1,4 +1,5 @@
- page_title "Blame", @blob.path, @ref
+- header_title project_title(@project, "Files", project_files_path(@project))
%h3.page-title Blame view
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 4071b59c00..fefa652a3d 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -16,9 +16,6 @@
.license-selector.js-license-selector.hide
= select_tag :license_type, grouped_options_for_select(licenses_for_select, @project.repository.license_key), include_blank: true, class: 'select2 license-select', data: {placeholder: 'Choose a license template', project: @project.name, fullname: @project.namespace.human_name}
- .gitignore-selector.hidden
- = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { filenames: gitignore_names } } )
-
.encoding-selector
= select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2'
diff --git a/app/views/projects/blob/_header_title.html.haml b/app/views/projects/blob/_header_title.html.haml
new file mode 100644
index 0000000000..78c5ef20a5
--- /dev/null
+++ b/app/views/projects/blob/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Files", project_files_path(@project))
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index e4f04ca776..effcce5a1c 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -1,4 +1,5 @@
- page_title "Edit", @blob.path, @ref
+= render "header_title"
.file-editor
%ul.nav-links.no-bottom.js-edit-mode
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
index c952bc7e5d..0459699432 100644
--- a/app/views/projects/blob/new.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -1,4 +1,5 @@
- page_title "New File", @path.presence, @ref
+= render "header_title"
%h3.page-title
New File
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index ed670dae88..6988039b6c 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -1,4 +1,5 @@
- page_title @blob.path, @ref
+= render "header_title"
= render 'projects/last_push'
diff --git a/app/views/projects/branches/destroy.js.haml b/app/views/projects/branches/destroy.js.haml
new file mode 100644
index 0000000000..a21ddaf493
--- /dev/null
+++ b/app/views/projects/branches/destroy.js.haml
@@ -0,0 +1 @@
+$('.js-totalbranch-count').html("#{@repository.branch_count}")
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index 08148b1a18..ac7790421a 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -1,4 +1,5 @@
- page_title "Branches"
+= render "projects/commits/header_title"
= render "projects/commits/head"
.row-content-block
.pull-right
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index 5a6c8c243f..c659af6338 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -1,4 +1,5 @@
- page_title "New Branch"
+= render "projects/commits/header_title"
- if @error
.alert.alert-danger
diff --git a/app/views/projects/builds/_header_title.html.haml b/app/views/projects/builds/_header_title.html.haml
new file mode 100644
index 0000000000..082dab1f5b
--- /dev/null
+++ b/app/views/projects/builds/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Builds", project_builds_path(@project))
diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml
index 818d5d28f0..2e8015d119 100644
--- a/app/views/projects/builds/index.html.haml
+++ b/app/views/projects/builds/index.html.haml
@@ -1,5 +1,5 @@
- page_title "Builds"
-= render "projects/pipelines/head"
+= render "header_title"
.top-area
%ul.nav-links
@@ -35,6 +35,9 @@
= icon('wrench')
%span CI Lint
+.row-content-block
+ #{(@scope || 'running').capitalize} builds from this project
+
%ul.content-list
- if @builds.blank?
%li
diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
index 16017c994b..c0f7a7686f 100644
--- a/app/views/projects/builds/show.html.haml
+++ b/app/views/projects/builds/show.html.haml
@@ -1,5 +1,5 @@
- page_title "#{@build.name} (##{@build.id})", "Builds"
-- trace_with_state = @build.trace_with_state
+= render "header_title"
.build-page
.row-content-block.top-block
@@ -85,9 +85,7 @@
%pre.trace#build-trace
%code.bash
= preserve do
- = raw trace_with_state[:html]
- - if @build.active?
- %i{:class => "fa fa-refresh fa-spin"}
+ = raw @build.trace_html
%div#down-build-trace
@@ -218,4 +216,4 @@
:javascript
- new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace_with_state[:state]}")
+ new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}")
diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml
index 16b8e1cca9..1e4c46fca2 100644
--- a/app/views/projects/buttons/_dropdown.html.haml
+++ b/app/views/projects/buttons/_dropdown.html.haml
@@ -2,7 +2,7 @@
.btn-group
%a.btn.dropdown-toggle{href: '#', "data-toggle" => "dropdown"}
= icon('plus')
- %ul.dropdown-menu.dropdown-menu-align-right.project-home-dropdown
+ %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
- can_create_issue = can?(current_user, :create_issue, @project)
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
- can_create_snippet = can?(current_user, :create_snippet, @project)
diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml
index 34ad9fe2c4..5fb5fe5af2 100644
--- a/app/views/projects/buttons/_fork.html.haml
+++ b/app/views/projects/buttons/_fork.html.haml
@@ -12,8 +12,7 @@
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has-tooltip' do
= icon('code-fork fw')
Fork
- %div.count-with-arrow
+ = link_to namespace_project_forks_path(@project.namespace, @project), class: 'count-with-arrow' do
%span.arrow
%span.count
- = link_to namespace_project_forks_path(@project.namespace, @project) do
- = @project.forks_count
+ = @project.forks_count
diff --git a/app/views/projects/buttons/_notifications.html.haml b/app/views/projects/buttons/_notifications.html.haml
index 1d05da5058..c1e3e5b73a 100644
--- a/app/views/projects/buttons/_notifications.html.haml
+++ b/app/views/projects/buttons/_notifications.html.haml
@@ -1,11 +1,11 @@
- if @notification_setting
= form_for @notification_setting, url: namespace_project_notification_setting_path(@project.namespace.becomes(Namespace), @project), method: :patch, remote: true, html: { class: 'inline', id: 'notification-form' } do |f|
= f.hidden_field :level
- .dropdown
+ %span.dropdown
%a.dropdown-new.btn.notifications-btn#notifications-button{href: '#', "data-toggle" => "dropdown"}
= icon('bell')
= notification_title(@notification_setting.level)
- = icon('caret-down')
- %ul.dropdown-menu.dropdown-menu-align-right.project-home-dropdown
+ = icon('angle-down')
+ %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
- NotificationSetting.levels.each do |level|
= notification_list_item(level.first, @notification_setting)
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index 5bd6e3f0eb..8e95f04027 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -13,9 +13,7 @@
%strong ##{build.id}
- if build.stuck?
- = icon('warning', class: 'text-warning has-tooltip', title: 'Build is stuck. Check runners.')
- - if defined?(retried) && retried
- = icon('warning', class: 'text-warning has-tooltip', title: 'Build was retried.')
+ %i.fa.fa-warning.text-warning
- if defined?(commit_sha) && commit_sha
%td
@@ -72,11 +70,11 @@
.pull-right
- if can?(current_user, :read_build, build) && build.artifacts?
= link_to download_namespace_project_build_artifacts_path(build.project.namespace, build.project, build), title: 'Download artifacts', class: 'btn btn-build' do
- = icon('download')
+ %i.fa.fa-download
- if can?(current_user, :update_build, build)
- if build.active?
= link_to cancel_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do
- = icon('remove', class: 'cred')
+ %i.fa.fa-remove.cred
- elsif defined?(allow_retry) && allow_retry && build.retryable?
= link_to retry_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do
- = icon('refresh')
+ %i.fa.fa-refresh
diff --git a/app/views/projects/ci/commits/_commit.html.haml b/app/views/projects/ci/commits/_commit.html.haml
deleted file mode 100644
index 5e3a4123a8..0000000000
--- a/app/views/projects/ci/commits/_commit.html.haml
+++ /dev/null
@@ -1,71 +0,0 @@
-- status = commit.status
-%tr.commit
- %td.commit-link
- = link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: "ci-status ci-#{status}" do
- = ci_icon_for_status(status)
- %strong ##{commit.id}
-
- %td
- %div.branch-commit
- - if commit.ref
- = link_to commit.ref, namespace_project_commits_path(@project.namespace, @project, commit.ref), class: "monospace"
- ·
- = link_to commit.short_sha, namespace_project_commit_path(@project.namespace, @project, commit.sha), class: "commit-id monospace"
-
- - if commit.tag?
- %span.label.label-primary tag
- - elsif commit.latest?
- %span.label.label-success.has-tooltip{ title: 'Latest build for this branch' } latest
- - if commit.triggered?
- %span.label.label-primary triggered
- - if commit.yaml_errors.present?
- %span.label.label-danger.has-tooltip{ title: "#{commit.yaml_errors}" } yaml invalid
- - if commit.builds.any?(&:stuck?)
- %span.label.label-warning stuck
-
- %p.commit-title
- - if commit_data = commit.commit_data
- = link_to_gfm truncate(commit_data.title, length: 60), namespace_project_commit_path(@project.namespace, @project, commit_data.id), class: "commit-row-message"
- - else
- Cant find HEAD commit for this branch
-
-
- - stages_status = commit.statuses.stages_status
- - stages.each do |stage|
- %td
- - status = stages_status[stage]
- - tooltip = "#{stage.titleize}: #{status || 'not found'}"
- - if status
- = link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status}", title: tooltip do
- = ci_icon_for_status(status)
- - else
- .light.has-tooltip{ title: tooltip }
- \-
-
- %td
- - if commit.started_at && commit.finished_at
- %p.duration
- #{duration_in_words(commit.finished_at, commit.started_at)}
-
- %td
- .controls.hidden-xs.pull-right
- - artifacts = commit.builds.latest.select { |b| b.artifacts? }
- - if artifacts.present?
- .dropdown.inline.build-artifacts
- %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
- = icon('download')
- %b.caret
- %ul.dropdown-menu.dropdown-menu-align-right
- - artifacts.each do |build|
- %li
- = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, build), rel: 'nofollow' do
- = icon("download")
- %span #{build.name}
-
- - if can?(current_user, :update_pipeline, @project)
- - if commit.retryable?
- = link_to retry_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn has-tooltip', title: "Retry", method: :post do
- = icon("repeat")
- - if commit.cancelable?
- = link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do
- = icon("remove")
diff --git a/app/views/projects/commit/_builds.html.haml b/app/views/projects/commit/_builds.html.haml
index 7f7a15aa21..5c9a319ede 100644
--- a/app/views/projects/commit/_builds.html.haml
+++ b/app/views/projects/commit/_builds.html.haml
@@ -1,2 +1,2 @@
- @ci_commits.each do |ci_commit|
- = render "ci_commit", ci_commit: ci_commit, pipeline_details: true
+ = render "ci_commit", ci_commit: ci_commit
diff --git a/app/views/projects/commit/_ci_commit.html.haml b/app/views/projects/commit/_ci_commit.html.haml
index 32ff4d3097..e849aefb18 100644
--- a/app/views/projects/commit/_ci_commit.html.haml
+++ b/app/views/projects/commit/_ci_commit.html.haml
@@ -1,27 +1,24 @@
.row-content-block.build-content.middle-block
.pull-right
- - if can?(current_user, :update_pipeline, ci_commit.project)
+ - if can?(current_user, :update_build, @project)
- if ci_commit.builds.latest.failed.any?(&:retryable?)
- = link_to "Retry failed", retry_namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), class: 'btn btn-grouped btn-primary', method: :post
+ = link_to "Retry failed", retry_builds_namespace_project_commit_path(@project.namespace, @project, ci_commit.sha), class: 'btn btn-grouped btn-primary', method: :post
- if ci_commit.builds.running_or_pending.any?
- = link_to "Cancel running", cancel_namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
+ = link_to "Cancel running", cancel_builds_namespace_project_commit_path(@project.namespace, @project, ci_commit.sha), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
- .oneline.clearfix
- - if defined?(pipeline_details) && pipeline_details
- Pipeline
- = link_to "##{ci_commit.id}", namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), class: "monospace"
- with
- = pluralize ci_commit.statuses.count(:id), "build"
- - if ci_commit.ref
- for
- = link_to ci_commit.ref, namespace_project_commits_path(ci_commit.project.namespace, ci_commit.project, ci_commit.ref), class: "monospace"
- - if defined?(link_to_commit) && link_to_commit
- for commit
- = link_to ci_commit.short_sha, namespace_project_commit_path(ci_commit.project.namespace, ci_commit.project, ci_commit.sha), class: "monospace"
- - if ci_commit.duration
- in
- = time_interval_in_words ci_commit.duration
+ .oneline
+ = pluralize ci_commit.statuses.count(:id), "build"
+ - if ci_commit.ref
+ for
+ %span.label.label-info
+ = ci_commit.ref
+ - if defined?(link_to_commit) && link_to_commit
+ for commit
+ = link_to ci_commit.short_sha, namespace_project_commit_path(@project.namespace, @project, ci_commit.sha), class: "monospace"
+ - if ci_commit.duration
+ in
+ = time_interval_in_words ci_commit.duration
- if ci_commit.yaml_errors.present?
.bs-callout.bs-callout-danger
@@ -31,7 +28,7 @@
%li= error
You can also test your .gitlab-ci.yml in the #{link_to "Lint", ci_lint_path}
-- if ci_commit.project.builds_enabled? && !ci_commit.ci_yaml_file
+- if @project.builds_enabled? && !ci_commit.ci_yaml_file
.bs-callout.bs-callout-warning
\.gitlab-ci.yml not found in this commit
@@ -41,12 +38,34 @@
%tr
%th Status
%th Build ID
+ %th Stage
%th Name
%th Tags
%th Duration
%th Finished at
- - if ci_commit.project.build_coverage_enabled?
+ - if @project.build_coverage_enabled?
%th Coverage
%th
- - ci_commit.statuses.stages.each do |stage|
- = render 'projects/commit/ci_stage', stage: stage, statuses: ci_commit.statuses.where(stage: stage)
+ - builds = ci_commit.statuses.latest.ordered
+ = render builds, coverage: @project.build_coverage_enabled?, stage: true, ref: false, allow_retry: true
+
+- if ci_commit.retried.any?
+ .row-content-block.second-block
+ Retried builds
+
+ .table-holder
+ %table.table.builds
+ %thead
+ %tr
+ %th Status
+ %th Build ID
+ %th Ref
+ %th Stage
+ %th Name
+ %th Tags
+ %th Duration
+ %th Finished at
+ - if @project.build_coverage_enabled?
+ %th Coverage
+ %th
+ = render ci_commit.retried, coverage: @project.build_coverage_enabled?, stage: true, ref: false
diff --git a/app/views/projects/commit/_ci_stage.html.haml b/app/views/projects/commit/_ci_stage.html.haml
deleted file mode 100644
index ae7bb01223..0000000000
--- a/app/views/projects/commit/_ci_stage.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-%tr
- %th{colspan: 10}
- %strong
- %a{name: stage}
- - status = statuses.latest.status
- %span{class: "ci-status-link ci-status-icon-#{status}"}
- = ci_icon_for_status(status)
- - if stage
-
- = stage.titleize.pluralize
- = render statuses.latest.ordered, coverage: @project.build_coverage_enabled?, stage: false, ref: false, allow_retry: true
- = render statuses.retried.ordered, coverage: @project.build_coverage_enabled?, stage: false, ref: false, retried: true
- %tr
- %td{colspan: 10}
-
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 6674d58417..01163e526b 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -1,35 +1,37 @@
-.commit-info-row.commit-info-row-header
- %span.hidden-xs Authored by
- %strong
- = commit_author_link(@commit, avatar: true, size: 24)
- #{time_ago_with_tooltip(@commit.authored_date)}
-
- .pull-right.commit-action-buttons
- - if defined?(@notes_count) && @notes_count > 0
- %span.btn.disabled.btn-grouped.hidden-xs
- = icon('comment')
+.pull-right.commit-action-buttons
+ %div
+ - if @notes_count > 0
+ %span.btn.disabled.btn-grouped
+ %i.fa.fa-comment
= @notes_count
- = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-grouped hidden-xs hidden-sm" do
- Browse Files
- .dropdown.inline
- %a.btn.btn-default.dropdown-toggle{ data: { toggle: "dropdown" } }
- %span.hidden-xs Options
- %span.caret.commit-options-dropdown-caret
- %ul.dropdown-menu.dropdown-menu-align-right
- %li.visible-xs-block.visible-sm-block
- = link_to namespace_project_tree_path(@project.namespace, @project, @commit) do
- Browse Files
- - unless @commit.has_been_reverted?(current_user)
- %li.clearfix
- = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false)
- %li.clearfix
- = cherry_pick_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false)
- %li.divider
- %li.dropdown-header
- Download
+ .pull-left.btn-group
+ %a.btn.btn-grouped.dropdown-toggle{ data: {toggle: :dropdown} }
+ %i.fa.fa-download
+ Download as
+ %span.caret
+ %ul.dropdown-menu
- unless @commit.parents.length > 1
%li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch)
%li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff)
+ = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-grouped" do
+ = icon('files-o')
+ Browse Files
+ - unless @commit.has_been_reverted?(current_user)
+ = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id))
+ = cherry_pick_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id))
+ %div
+
+%p
+.commit-info-row
+ - if @commit.status
+ = link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id), class: "ci-status ci-#{@commit.status}" do
+ = ci_icon_for_status(@commit.status)
+ build:
+ = ci_label_for_status(@commit.status)
+ %span.light Authored by
+ %strong
+ = commit_author_link(@commit, avatar: true, size: 24)
+ #{time_ago_with_tooltip(@commit.authored_date)}
- if @commit.different_committer?
.commit-info-row
@@ -39,9 +41,8 @@
#{time_ago_with_tooltip(@commit.committed_date)}
.commit-info-row
- %span.hidden-xs.hidden-sm Commit
- = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace hidden-xs hidden-sm"
- = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace visible-xs-inline visible-sm-inline"
+ %span.light Commit
+ = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace"
= clipboard_button(clipboard_text: @commit.id)
%span.cgray= pluralize(@commit.parents.count, "parent")
- @commit.parents.each do |parent|
@@ -50,23 +51,12 @@
%span.commit-info.branches
%i.fa.fa-spinner.fa-spin
-- if @commit.status
- .commit-info-row
- Builds for
- = pluralize(@commit.ci_commits.count, 'pipeline')
- = link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id), class: "ci-status-link ci-status-icon-#{@commit.status}" do
- = ci_icon_for_status(@commit.status)
- = ci_label_for_status(@commit.status)
- - if @commit.ci_commits.duration
- in
- = time_interval_in_words @commit.ci_commits.duration
-
.commit-box.content-block
%h3.commit-title
- = markdown escape_once(@commit.title), pipeline: :single_line, author: @commit.author
+ = markdown escape_once(@commit.title), pipeline: :single_line
- if @commit.description.present?
%pre.commit-description
- = preserve(markdown(escape_once(@commit.description), pipeline: :single_line, author: @commit.author))
+ = preserve(markdown(escape_once(@commit.description), pipeline: :single_line))
:javascript
$(".commit-info.branches").load("#{branches_namespace_project_commit_path(@project.namespace, @project, @commit.id)}");
diff --git a/app/views/projects/commit/builds.html.haml b/app/views/projects/commit/builds.html.haml
index 2f051fb90e..7118a4846c 100644
--- a/app/views/projects/commit/builds.html.haml
+++ b/app/views/projects/commit/builds.html.haml
@@ -1,7 +1,7 @@
- page_title "Builds", "#{@commit.title} (#{@commit.short_id})", "Commits"
-
+= render "projects/commits/header_title"
.prepend-top-default
= render "commit_box"
-
= render "ci_menu"
+
= render "builds"
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index 401cb4f7e3..e5e3d69603 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -1,6 +1,8 @@
- page_title "#{@commit.title} (#{@commit.short_id})", "Commits"
- page_description @commit.description
+= render "projects/commits/header_title"
+
.prepend-top-default
= render "commit_box"
- if @commit.status
diff --git a/app/views/projects/commits/_commit.atom.builder b/app/views/projects/commits/_commit.atom.builder
deleted file mode 100644
index 1657fb4616..0000000000
--- a/app/views/projects/commits/_commit.atom.builder
+++ /dev/null
@@ -1,14 +0,0 @@
-xml.entry do
- xml.id namespace_project_commit_url(@project.namespace, @project, id: commit.id)
- xml.link href: namespace_project_commit_url(@project.namespace, @project, id: commit.id)
- xml.title truncate(commit.title, length: 80)
- xml.updated commit.committed_date.xmlschema
- xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(commit.author_email))
-
- xml.author do |author|
- xml.name commit.author_name
- xml.email commit.author_email
- end
-
- xml.summary markdown(commit.description, pipeline: :single_line)
-end
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 367027182b..c7d8c9a0d1 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -17,14 +17,14 @@
.pull-right
- if commit.status
- = render_commit_status(commit)
+ = render_ci_status(commit)
= clipboard_button(clipboard_text: commit.id)
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
- if commit.description?
.commit-row-description.js-toggle-content
%pre
- = preserve(markdown(escape_once(commit.description), pipeline: :single_line, author: commit.author))
+ = preserve(markdown(escape_once(commit.description), pipeline: :single_line))
.commit-row-info
by
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index 7283a78a64..64e8da9201 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -3,7 +3,7 @@
- commits, hidden = limited_commits(@commits)
-- commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, commits|
+- commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits|
.row.commits-row
.col-md-2.hidden-xs.hidden-sm
%h5.commits-row-date
diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml
index 1c136133ab..d1bd76ab52 100644
--- a/app/views/projects/commits/_head.html.haml
+++ b/app/views/projects/commits/_head.html.haml
@@ -1,11 +1,9 @@
%ul.nav-links
- = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do
- = link_to project_files_path(@project) do
- Files
-
= nav_link(controller: [:commit, :commits]) do
= link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
Commits
+ %span.badge
+ = number_with_delimiter(@repository.commit_count)
= nav_link(controller: %w(network)) do
= link_to namespace_project_network_path(@project.namespace, @project, current_ref) do
@@ -18,7 +16,9 @@
= nav_link(html_options: {class: branches_tab_class}) do
= link_to namespace_project_branches_path(@project.namespace, @project) do
Branches
+ %span.badge.js-totalbranch-count= @repository.branch_count
= nav_link(controller: [:tags, :releases]) do
= link_to namespace_project_tags_path(@project.namespace, @project) do
Tags
+ %span.badge.js-totaltags-count= @repository.tag_count
diff --git a/app/views/projects/commits/_header_title.html.haml b/app/views/projects/commits/_header_title.html.haml
new file mode 100644
index 0000000000..e4385893dd
--- /dev/null
+++ b/app/views/projects/commits/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Commits", project_commits_path(@project))
diff --git a/app/views/projects/commits/show.atom.builder b/app/views/projects/commits/show.atom.builder
index 30bb741207..e310fafd82 100644
--- a/app/views/projects/commits/show.atom.builder
+++ b/app/views/projects/commits/show.atom.builder
@@ -6,5 +6,18 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id namespace_project_commits_url(@project.namespace, @project, @ref)
xml.updated @commits.first.committed_date.xmlschema if @commits.any?
- xml << render(@commits) if @commits.any?
+ @commits.each do |commit|
+ xml.entry do
+ xml.id namespace_project_commit_url(@project.namespace, @project, id: commit.id)
+ xml.link href: namespace_project_commit_url(@project.namespace, @project, id: commit.id)
+ xml.title truncate(commit.title, length: 80)
+ xml.updated commit.committed_date.xmlschema
+ xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(commit.author_email))
+ xml.author do |author|
+ xml.name commit.author_name
+ xml.email commit.author_email
+ end
+ xml.summary markdown(commit.description, pipeline: :single_line)
+ end
+ end
end
diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml
index 2c21923ed4..088eaa2801 100644
--- a/app/views/projects/commits/show.html.haml
+++ b/app/views/projects/commits/show.html.haml
@@ -1,4 +1,5 @@
- page_title "Commits", @ref
+= render "header_title"
= content_for :meta_tags do
- if current_user
= auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits")
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index 0b8ed23b30..5e188dd0f3 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -1,4 +1,5 @@
- page_title "Compare"
+= render "projects/commits/header_title"
= render "projects/commits/head"
.row-content-block
diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml
index cdc34f51d6..6252516823 100644
--- a/app/views/projects/compare/show.html.haml
+++ b/app/views/projects/compare/show.html.haml
@@ -1,4 +1,5 @@
- page_title "#{params[:from]}...#{params[:to]}"
+= render "projects/commits/header_title"
= render "projects/commits/head"
diff --git a/app/views/projects/container_registry/_tag.html.haml b/app/views/projects/container_registry/_tag.html.haml
deleted file mode 100644
index 4e9f936539..0000000000
--- a/app/views/projects/container_registry/_tag.html.haml
+++ /dev/null
@@ -1,21 +0,0 @@
-%tr.tag
- %td
- = escape_once(tag.name)
- = clipboard_button(clipboard_text: "docker pull #{tag.path}")
- %td
- - if layer = tag.layers.first
- %span.has-tooltip{ title: "#{layer.revision}" }
- = layer.short_revision
- - else
- \-
- %td
- = number_to_human_size(tag.total_size)
- ·
- = pluralize(tag.layers.size, "layer")
- %td
- = time_ago_in_words(tag.created_at)
- - if can?(current_user, :update_container_image, @project)
- %td.content
- .controls.hidden-xs.pull-right
- = link_to namespace_project_container_registry_path(@project.namespace, @project, tag.name), class: 'btn btn-remove has-tooltip', title: "Remove", data: { confirm: "Are you sure?" }, method: :delete do
- = icon("trash cred")
diff --git a/app/views/projects/container_registry/index.html.haml b/app/views/projects/container_registry/index.html.haml
deleted file mode 100644
index 993da27310..0000000000
--- a/app/views/projects/container_registry/index.html.haml
+++ /dev/null
@@ -1,39 +0,0 @@
-- page_title "Container Registry"
-
-%hr
-
-%ul.content-list
- %li.light.prepend-top-default
- %p
- A 'container image' is a snapshot of a container.
- You can host your container images with GitLab.
- %br
- To start using container images hosted on GitLab you first need to login:
- %pre
- %code
- docker login #{Gitlab.config.registry.host_port}
- %br
- Then you are free to create and upload a container image with build and push commands:
- %pre
- docker build -t #{escape_once(@project.container_registry_repository_url)} .
- %br
- docker push #{escape_once(@project.container_registry_repository_url)}
-
- - if @tags.blank?
- %li
- .nothing-here-block No images in Container Registry for this project.
-
- - else
- .table-holder
- %table.table.tags
- %thead
- %tr
- %th Name
- %th Image ID
- %th Size
- %th Created
- - if can?(current_user, :update_container_image, @project)
- %th
-
- - @tags.each do |tag|
- = render 'tag', tag: tag
diff --git a/app/views/projects/deploy_keys/index.html.haml b/app/views/projects/deploy_keys/index.html.haml
index 04fbb37d93..e230834e8b 100644
--- a/app/views/projects/deploy_keys/index.html.haml
+++ b/app/views/projects/deploy_keys/index.html.haml
@@ -19,7 +19,7 @@
%ul.well-list
= render @enabled_keys
- else
- .settings-message.text-center
+ .profile-settings-message.text-center
No deploy keys found. Create one with the form above or add existing one below.
%h5.prepend-top-default
Deploy keys from projects you have access to (#{@available_project_keys.size})
@@ -27,7 +27,7 @@
%ul.well-list
= render @available_project_keys
- else
- .settings-message.text-center
+ .profile-settings-message.text-center
No deploy keys from your projects could be found. Create one with the form above or add existing one below.
- if @available_public_keys.any?
%h5.prepend-top-default
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index e5983c5803..0f04fc5d33 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -11,9 +11,11 @@
= link_to "#diff-#{i}" do
- if diff_file.renamed_file
- old_path, new_path = mark_inline_diffs(diff_file.old_path, diff_file.new_path)
- = old_path
+ .filename.old
+ = old_path
→
- = new_path
+ .filename.new
+ = new_path
- else
%span
= diff_file.new_path
@@ -39,7 +41,7 @@
.diff-content.diff-wrap-lines
- # Skip all non non-supported blobs
- - return unless blob.respond_to?(:text?)
+ - return unless blob.respond_to?('text?')
- if diff_file.too_large?
.nothing-here-block This diff could not be displayed because it is too large.
- elsif blob_text_viewable?(blob) && !project.repository.diffable?(blob)
diff --git a/app/views/projects/diffs/_line.html.haml b/app/views/projects/diffs/_line.html.haml
index f1577e8a47..107097ad96 100644
--- a/app/views/projects/diffs/_line.html.haml
+++ b/app/views/projects/diffs/_line.html.haml
@@ -15,7 +15,7 @@
= link_text
- else
= link_to "", "##{line_code}", id: line_code, data: { linenumber: link_text }
- - if !@diff_notes_disabled && can?(current_user, :create_note, @project)
+ - if @comments_allowed && can?(current_user, :create_note, @project)
= link_to_new_diff_note(line_code)
%td.new_line.diff-line-num{ class: type, data: { linenumber: line.new_pos } }
- link_text = type == "old" ? " ".html_safe : line.new_pos
diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml
index 4ecc9528bd..81948513e4 100644
--- a/app/views/projects/diffs/_parallel_view.html.haml
+++ b/app/views/projects/diffs/_parallel_view.html.haml
@@ -16,7 +16,7 @@
- else
%td.old_line.diff-line-num{id: left[:line_code], class: "#{left[:type]} #{'empty-cell' if !left[:number]}"}
= link_to raw(left[:number]), "##{left[:line_code]}", id: left[:line_code]
- - if !@diff_notes_disabled && can?(current_user, :create_note, @project)
+ - if @comments_allowed && can?(current_user, :create_note, @project)
= link_to_new_diff_note(left[:line_code], 'old')
%td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]} #{'empty-cell' if left[:text].empty?}", data: { line_code: left[:line_code] }}= diff_line_content(left[:text])
@@ -29,14 +29,14 @@
%td.new_line.diff-line-num{id: new_line_code, class: "#{new_line_class} #{'empty-cell' if !right[:number]}", data: { linenumber: right[:number] }}
= link_to raw(right[:number]), "##{new_line_code}", id: new_line_code
- - if !@diff_notes_disabled && can?(current_user, :create_note, @project)
- = link_to_new_diff_note(new_line_code, 'new')
+ - if @comments_allowed && can?(current_user, :create_note, @project)
+ = link_to_new_diff_note(right[:line_code], 'new')
%td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code} #{'empty-cell' if right[:text].empty?}", data: { line_code: new_line_code }}= diff_line_content(right[:text])
- - unless @diff_notes_disabled
- - notes_left, notes_right = organize_comments(left, right)
- - if notes_left.present? || notes_right.present?
- = render "projects/notes/diff_notes_with_reply_parallel", notes_left: notes_left, notes_right: notes_right
+ - if @reply_allowed
+ - comments_left, comments_right = organize_comments(left[:type], right[:type], left[:line_code], right[:line_code])
+ - if comments_left.present? || comments_right.present?
+ = render "projects/notes/diff_notes_with_reply_parallel", notes_left: comments_left, notes_right: comments_right
- if diff_file.diff.diff.blank? && diff_file.mode_changed?
.file-mode-changed
diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml
index 068593a7dd..e7169d7b59 100644
--- a/app/views/projects/diffs/_text_file.html.haml
+++ b/app/views/projects/diffs/_text_file.html.haml
@@ -6,15 +6,16 @@
%table.text-file.code.js-syntax-highlight{ class: too_big ? 'hide' : '' }
- last_line = 0
+ - raw_diff_lines = diff_file.diff_lines.to_a
- diff_file.highlighted_diff_lines.each_with_index do |line, index|
- line_code = generate_line_code(diff_file.file_path, line)
- last_line = line.new_pos
= render "projects/diffs/line", {line: line, diff_file: diff_file, line_code: line_code}
- - unless @diff_notes_disabled
- - diff_notes = @grouped_diff_notes[line_code]
- - if diff_notes
- = render "projects/notes/diff_notes_with_reply", notes: diff_notes
+ - if @reply_allowed
+ - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at)
+ - unless comments.empty?
+ = render "projects/notes/diff_notes_with_reply", notes: comments, line: raw_diff_lines[index].text
- if last_line > 0
= render "projects/diffs/match_line", { line: "",
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 18b125ff9d..76a4f41193 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -1,221 +1,251 @@
-.project-edit-container
- .row.prepend-top-default
- .col-lg-3.profile-settings-sidebar
- %h4.prepend-top-0
+.project-edit-container.prepend-top-default
+ .project-edit-errors
+ .project-edit-content
+ .panel.panel-default
+ .panel-heading
Project settings
- .col-lg-9
- = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit-project" }, authenticity_token: true do |f|
- %fieldset.append-bottom-0
- .form-group
- = f.label :name, class: 'label-light' do
- Project name
- = f.text_field :name, class: "form-control", id: "project_name_edit"
- .form-group
- = f.label :description, class: 'label-light' do
- Project description
- %span.light (optional)
- = f.text_area :description, class: "form-control", rows: 3, maxlength: 250
+ .panel-body
+ = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit_project form-horizontal fieldset-form" }, authenticity_token: true do |f|
+
+ %fieldset
+ .form-group.project_name_holder
+ = f.label :name, class: 'control-label' do
+ Project name
+ .col-sm-10
+ = f.text_field :name, class: "form-control", id: "project_name_edit"
+
- - unless @project.empty_repo?
.form-group
- = f.label :default_branch, "Default Branch", class: 'label-light'
- = f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'})
- .form-group.project-visibility-level-holder
- = f.label :visibility_level, class: 'label-light' do
- Visibility Level
- = link_to "(?)", help_page_path("public_access", "public_access")
- - if can_change_visibility_level?(@project, current_user)
- = render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: @project.visibility_level, form_model: @project)
- - else
- .info
- = visibility_level_icon(@project.visibility_level)
- %strong
- = visibility_level_label(@project.visibility_level)
- .light= visibility_level_description(@project.visibility_level, @project)
- .form-group
- = f.label :tag_list, "Tags", class: 'label-light'
- = f.text_field :tag_list, value: @project.tag_list.to_s, maxlength: 2000, class: "form-control"
- %p.help-block Separate tags with commas.
- %hr
- %fieldset.features.append-bottom-0
- %h5.prepend-top-0
- Features
+ = f.label :description, class: 'control-label' do
+ Project description
+ %span.light (optional)
+ .col-sm-10
+ = f.text_area :description, class: "form-control", rows: 3, maxlength: 250
+
+ - unless @project.empty_repo?
+ .form-group
+ = f.label :default_branch, "Default Branch", class: 'control-label'
+ .col-sm-10= f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'})
+
+
+ = render 'shared/visibility_level', f: f, visibility_level: @project.visibility_level, can_change_visibility_level: can_change_visibility_level?(@project, current_user), form_model: @project
+
.form-group
- .checkbox
- = f.label :issues_enabled do
- = f.check_box :issues_enabled
- %strong Issues
- %br
- %span.descr Lightweight issue tracking system for this project
- .form-group
- .checkbox
- = f.label :merge_requests_enabled do
- = f.check_box :merge_requests_enabled
- %strong Merge Requests
- %br
- %span.descr Submit changes to be merged upstream
- .form-group
- .checkbox
- = f.label :builds_enabled do
- = f.check_box :builds_enabled
- %strong Builds
- %br
- %span.descr Test and deploy your changes before merge
- .form-group
- .checkbox
- = f.label :wiki_enabled do
- = f.check_box :wiki_enabled
- %strong Wiki
- %br
- %span.descr Pages for project documentation
- .form-group
- .checkbox
- = f.label :snippets_enabled do
- = f.check_box :snippets_enabled
- %strong Snippets
- %br
- %span.descr Share code pastes with others out of git repository
- - if Gitlab.config.registry.enabled
+ = f.label :tag_list, "Tags", class: 'control-label'
+ .col-sm-10
+ = f.text_field :tag_list, value: @project.tag_list.to_s, maxlength: 2000, class: "form-control"
+ %p.help-block Separate tags with commas.
+
+ %fieldset.features
+ %legend
+ Features:
.form-group
- .checkbox
- = f.label :container_registry_enabled do
- = f.check_box :container_registry_enabled
- %strong Container Registry
- %br
- %span.descr Enable Container Registry for this repository
- %hr
- = render 'builds_settings', f: f
- %hr
- %fieldset.features.append-bottom-default
- %h5.prepend-top-0
- Project avatar
- .form-group
- - if @project.avatar?
- = project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar s160')
- %p.light
- - if @project.avatar_in_git
- Project avatar in repository: #{ @project.avatar_in_git }
- %a.choose-btn.btn.js-choose-project-avatar-button
- Browse file...
- %span.file_name.prepend-left-default.js-avatar-filename No file chosen
- = f.file_field :avatar, class: "js-project-avatar-input hidden"
- .help-block The maximum file size allowed is 200KB.
- - if @project.avatar?
- %hr
- = link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
- = f.submit 'Save changes', class: "btn btn-save"
- .row.prepend-top-default
- %hr
- .row.prepend-top-default
- .col-lg-3
- %h4.prepend-top-0
- Housekeeping
- %p.append-bottom-0
- %p
- Runs a number of housekeeping tasks within the current repository,
- such as compressing file revisions and removing unreachable objects.
- .col-lg-9
- = link_to 'Housekeeping', housekeeping_namespace_project_path(@project.namespace, @project),
- method: :post, class: "btn btn-save"
- %hr
- - if can? current_user, :archive_project, @project
- .row.prepend-top-default
- .col-lg-3
- %h4.warning-title.prepend-top-0
- - if @project.archived?
- Unarchive project
- - else
- Archive project
- %p.append-bottom-0
- - if @project.archived?
- Unarchiving the project will mark its repository as active. The project can be committed to.
- - else
- Archiving the project will mark its repository as read-only. It is hidden from the dashboard and doesn't show up in searches.
- .col-lg-9
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :issues_enabled do
+ = f.check_box :issues_enabled
+ %strong Issues
+ %br
+ %span.descr Lightweight issue tracking system for this project
+
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :merge_requests_enabled do
+ = f.check_box :merge_requests_enabled
+ %strong Merge Requests
+ %br
+ %span.descr Submit changes to be merged upstream
+
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :builds_enabled do
+ = f.check_box :builds_enabled
+ %strong Builds
+ %br
+ %span.descr Test and deploy your changes before merge
+
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :wiki_enabled do
+ = f.check_box :wiki_enabled
+ %strong Wiki
+ %br
+ %span.descr Pages for project documentation
+
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :snippets_enabled do
+ = f.check_box :snippets_enabled
+ %strong Snippets
+ %br
+ %span.descr Share code pastes with others out of git repository
+
+ = render 'builds_settings', f: f
+
+ %fieldset.features
+ %legend
+ Project avatar:
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ - if @project.avatar?
+ = project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar s160')
+ %p.light
+ - if @project.avatar_in_git
+ Project avatar in repository: #{ @project.avatar_in_git }
+ %p.light
+ - if @project.avatar?
+ You can change your project avatar here
+ - else
+ You can upload a project avatar here
+ %a.choose-btn.btn.btn-sm.js-choose-project-avatar-button
+ %i.icon-paper-clip
+ %span Choose File ...
+
+ %span.file_name.js-avatar-filename File name...
+ = f.file_field :avatar, class: "js-project-avatar-input hidden"
+ .light The maximum file size allowed is 200KB.
+ - if @project.avatar?
+ %hr
+ = link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
+
+
+ .form-actions
+ = f.submit 'Save changes', class: "btn btn-save"
+
+
+
+ .danger-settings
+ .panel.panel-default
+ .panel-heading Housekeeping
+ .errors-holder
+ .panel-body
+ %p
+ Runs a number of housekeeping tasks within the current repository,
+ such as compressing file revisions and removing unreachable objects.
+ %br
+
+ .form-actions
+ = link_to 'Housekeeping', housekeeping_namespace_project_path(@project.namespace, @project),
+ method: :post, class: "btn btn-default"
+
+ - if can? current_user, :archive_project, @project
- if @project.archived?
- %p
- %strong Once active this project shows up in the search and on the dashboard.
- = link_to 'Unarchive project', unarchive_namespace_project_path(@project.namespace, @project),
- data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." },
- method: :post, class: "btn btn-success"
+ .panel.panel-success
+ .panel-heading
+ Unarchive project
+ .panel-body
+ %p
+ Unarchiving the project will mark its repository as active.
+ %br
+ The project can be committed to.
+ %br
+ %strong Once active this project shows up in the search and on the dashboard.
+
+ .form-actions
+ = link_to 'Unarchive project', unarchive_namespace_project_path(@project.namespace, @project),
+ data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." },
+ method: :post, class: "btn btn-success"
- else
- %p
- %strong Archived projects cannot be committed to!
- = link_to 'Archive project', archive_namespace_project_path(@project.namespace, @project),
- data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." },
- method: :post, class: "btn btn-warning"
- %hr
- .row.prepend-top-default
- .col-lg-3
- %h4.prepend-top-0.warning-title
- Rename repository
- .col-lg-9
- = form_for([@project.namespace.becomes(Namespace), @project]) do |f|
- .form-group.project_name_holder
- = f.label :name, class: 'label-light' do
- Project name
- .form-group
- = f.text_field :name, class: "form-control"
- .form-group
- = f.label :path, class: 'label-light' do
- %span Path
- .form-group
- .input-group
- .input-group-addon
- #{URI.join(root_url, @project.namespace.path)}/
- = f.text_field :path, class: 'form-control'
- %ul
- %li Be careful. Renaming a project's repository can have unintended side effects.
- %li You will need to update your local repositories to point to the new location.
- = f.submit 'Rename project', class: "btn btn-warning"
- - if can?(current_user, :change_namespace, @project)
- %hr
- .row.prepend-top-default
- .col-lg-3
- %h4.prepend-top-0.danger-title
- Transfer project
- .col-lg-9
- = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_namespace_project_path(@project.namespace, @project), method: :put, remote: true) do |f|
- .form-group
- = label_tag :new_namespace_id, nil, class: 'label-light' do
- %span Namespace
+ .panel.panel-warning
+ .panel-heading
+ Archive project
+ .panel-body
+ %p
+ Archiving the project will mark its repository as read-only.
+ %br
+ It is hidden from the dashboard and doesn't show up in searches.
+ %br
+ %strong Archived projects cannot be committed to!
+
+ .form-actions
+ = link_to 'Archive project', archive_namespace_project_path(@project.namespace, @project),
+ data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." },
+ method: :post, class: "btn btn-warning"
+ - else
+ .nothing-here-block Only the project owner can archive a project
+
+ .panel.panel-default.panel.panel-warning
+ .panel-heading Rename repository
+ .errors-holder
+ .panel-body
+ = form_for([@project.namespace.becomes(Namespace), @project], html: { class: 'form-horizontal' }) do |f|
+ .form-group.project_name_holder
+ = f.label :name, class: 'control-label' do
+ Project name
+ .col-sm-9
+ .form-group
+ = f.text_field :name, class: "form-control"
.form-group
- = select_tag :new_namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace', class: 'select2' }
- %ul
- %li Be careful. Changing the project's namespace can have unintended side effects.
- %li You can only transfer the project to namespaces you manage.
- %li You will need to update your local repositories to point to the new location.
- %li Project visibility level will be changed to match namespace rules when transfering to a group.
- = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) }
- - if @project.forked? && can?(current_user, :remove_fork_project, @project)
- %hr
- .row.prepend-top-default.append-bottom-default
- .col-lg-3
- %h4.prepend-top-0.danger-title
- Remove fork relationship
- %p.append-bottom-0
- %p
- This will remove the fork relationship to source project
- = succeed "." do
- = link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project)
- .col-lg-9
- = form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_namespace_project_path(@project.namespace, @project), method: :delete, remote: true, html: { class: 'transfer-project' }) do |f|
- %p
- %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.
- = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) }
- - if can?(current_user, :remove_project, @project)
- %hr
- .row.prepend-top-default.append-bottom-default
- .col-lg-3
- %h4.prepend-top-0.danger-title
- Remove project
- %p.append-bottom-0
- Removing the project will delete its repository and all related resources including issues, merge requests etc.
- .col-lg-9
- = form_tag(namespace_project_path(@project.namespace, @project), method: :delete) do
- %p
- %strong Removed projects cannot be restored!
- = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) }
+ = f.label :path, class: 'control-label' do
+ %span Path
+ .col-sm-9
+ .form-group
+ .input-group
+ .input-group-addon
+ #{URI.join(root_url, @project.namespace.path)}/
+ = f.text_field :path, class: 'form-control'
+ %ul
+ %li Be careful. Renaming a project's repository can have unintended side effects.
+ %li You will need to update your local repositories to point to the new location.
+ .form-actions
+ = f.submit 'Rename project', class: "btn btn-warning"
+
+ - if can?(current_user, :change_namespace, @project)
+ .panel.panel-default.panel.panel-danger
+ .panel-heading Transfer project
+ .errors-holder
+ .panel-body
+ = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_namespace_project_path(@project.namespace, @project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f|
+ .form-group
+ = label_tag :new_namespace_id, nil, class: 'control-label' do
+ %span Namespace
+ .col-sm-9
+ .form-group
+ = select_tag :new_namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace', class: 'select2' }
+ %ul
+ %li Be careful. Changing the project's namespace can have unintended side effects.
+ %li You can only transfer the project to namespaces you manage.
+ %li You will need to update your local repositories to point to the new location.
+ %li Project visibility level will be changed to match namespace rules when transfering to a group.
+ .form-actions
+ = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) }
+ - else
+ .nothing-here-block Only the project owner can transfer a project
+
+ - if @project.forked?
+ - if can?(current_user, :remove_fork_project, @project)
+ = form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_namespace_project_path(@project.namespace, @project), method: :delete, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f|
+ .panel.panel-default.panel.panel-danger
+ .panel-heading Remove fork relationship
+ .panel-body
+ %p
+ This will remove the fork relationship to source project
+ #{link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project)}.
+ %br
+ %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.
+ .form-actions
+ = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) }
+ - else
+ .nothing-here-block Only the project owner can remove the fork relationship.
+
+ - if can?(current_user, :remove_project, @project)
+ .panel.panel-default.panel.panel-danger
+ .panel-heading Remove project
+ .panel-body
+ = form_tag(namespace_project_path(@project.namespace, @project), method: :delete, class: 'form-horizontal') do
+ %p
+ Removing the project will delete its repository and all related resources including issues, merge requests etc.
+ %br
+ %strong Removed projects cannot be restored!
+ .form-actions
+ = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) }
+ - else
+ .nothing-here-block Only the project owner can remove a project.
+
.save-project-loader.hide
.center
@@ -224,4 +254,5 @@
Saving project.
%p Please wait a moment, this page will automatically refresh when ready.
+
= render 'shared/confirm_modal', phrase: @project.path
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 636beb73ec..1a2e59752f 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -15,14 +15,10 @@
If you already have files you can push them using command line instructions below.
%p
Otherwise you can start with adding a
- = succeed ',' do
- = link_to "README", new_readme_path, class: 'underlined-link'
- a
- = succeed ',' do
- = link_to "LICENSE", add_special_file_path(@project, file_name: 'LICENSE'), class: 'underlined-link'
+ = link_to "README", new_readme_path, class: 'underlined-link'
or a
- = link_to '.gitignore', add_special_file_path(@project, file_name: '.gitignore'), class: 'underlined-link'
- to this project.
+ = link_to "LICENSE", add_special_file_path(@project, file_name: 'LICENSE'), class: 'underlined-link'
+ file to this project.
- if can?(current_user, :push_code, @project)
%div{ class: container_class }
diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml
index 9322c82904..1fe1d98bf1 100644
--- a/app/views/projects/find_file/show.html.haml
+++ b/app/views/projects/find_file/show.html.haml
@@ -1,4 +1,5 @@
- page_title "Find File", @ref
+- header_title project_title(@project, "Files", project_files_path(@project))
.file-finder-holder.tree-holder.clearfix
.nav-block
diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
index 5bc5c71283..f21c864e35 100644
--- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
+++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
@@ -12,9 +12,6 @@
- else
%strong ##{generic_commit_status.id}
- - if defined?(retried) && retried
- = icon('warning', class: 'text-warning has-tooltip', title: 'Status was retried.')
-
- if defined?(commit_sha) && commit_sha
%td
= link_to generic_commit_status.short_sha, namespace_project_commit_path(generic_commit_status.project.namespace, generic_commit_status.project, generic_commit_status.sha), class: "monospace"
@@ -40,13 +37,11 @@
%td
= generic_commit_status.name
- %td
- - if generic_commit_status.tags.any?
- - generic_commit_status.tags.each do |tag|
- %span.label.label-primary
- = tag
- - if defined?(retried) && retried
- %span.label.label-warning retried
+ .pull-right
+ - if generic_commit_status.tags.any?
+ - generic_commit_status.tags.each do |tag|
+ %span.label.label-primary
+ = tag
%td.duration
- if generic_commit_status.duration
diff --git a/app/views/projects/graphs/_head.html.haml b/app/views/projects/graphs/_head.html.haml
index 8becaea246..79a56647c5 100644
--- a/app/views/projects/graphs/_head.html.haml
+++ b/app/views/projects/graphs/_head.html.haml
@@ -1,4 +1,3 @@
-- page_specific_javascripts asset_path("graphs/application.js")
%ul.nav-links
= nav_link(action: :show) do
= link_to 'Contributors', namespace_project_graph_path
diff --git a/app/views/projects/graphs/_header_title.html.haml b/app/views/projects/graphs/_header_title.html.haml
new file mode 100644
index 0000000000..1e2f61cd22
--- /dev/null
+++ b/app/views/projects/graphs/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Graphs", namespace_project_graph_path(@project.namespace, @project, current_ref))
diff --git a/app/views/projects/graphs/ci.html.haml b/app/views/projects/graphs/ci.html.haml
index 19ccc125ea..9f05be9982 100644
--- a/app/views/projects/graphs/ci.html.haml
+++ b/app/views/projects/graphs/ci.html.haml
@@ -1,4 +1,5 @@
- page_title "Continuous Integration", "Graphs"
+= render "header_title"
= render 'head'
.row-content-block.append-bottom-default
.oneline
diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml
index d9b2fb6c06..da9f648cc9 100644
--- a/app/views/projects/graphs/commits.html.haml
+++ b/app/views/projects/graphs/commits.html.haml
@@ -1,4 +1,5 @@
- page_title "Commits", "Graphs"
+= render "header_title"
= render 'head'
.row-content-block.append-bottom-default
diff --git a/app/views/projects/graphs/languages.html.haml b/app/views/projects/graphs/languages.html.haml
index 249c16f470..ebecab1dbf 100644
--- a/app/views/projects/graphs/languages.html.haml
+++ b/app/views/projects/graphs/languages.html.haml
@@ -1,4 +1,5 @@
- page_title "Languages", "Graphs"
+= render "header_title"
= render 'head'
.row-content-block.append-bottom-default
diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml
index 33970e7b90..ad4a932d39 100644
--- a/app/views/projects/graphs/show.html.haml
+++ b/app/views/projects/graphs/show.html.haml
@@ -1,4 +1,5 @@
- page_title "Contributors", "Graphs"
+= render "header_title"
= render 'head'
.row-content-block.append-bottom-default
@@ -18,7 +19,7 @@
.header.clearfix
%h3#date_header.page-title
%p.light
- Commits to #{@ref}, excluding merge commits. Limited to 6,000 commits.
+ Commits to #{@ref}, excluding merge commits. Limited by 6,000 commits
%input#brush_change{:type => "hidden"}
.graphs
#contributors-master
diff --git a/app/views/projects/hooks/_project_hook.html.haml b/app/views/projects/hooks/_project_hook.html.haml
index 8151187d49..62eba5888a 100644
--- a/app/views/projects/hooks/_project_hook.html.haml
+++ b/app/views/projects/hooks/_project_hook.html.haml
@@ -3,7 +3,7 @@
.col-md-8.col-lg-7
%strong.light-header= hook.url
%div
- - %w(push_events tag_push_events issues_events note_events merge_requests_events build_events wiki_page_events).each do |trigger|
+ - %w(push_events tag_push_events issues_events note_events merge_requests_events build_events).each do |trigger|
- if hook.send(trigger)
%span.label.label-gray.deploy-project-label= trigger.titleize
.col-md-4.col-lg-5.text-right-lg.prepend-top-5
diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml
index 917a0b805b..36c1d69f06 100644
--- a/app/views/projects/hooks/index.html.haml
+++ b/app/views/projects/hooks/index.html.haml
@@ -64,13 +64,6 @@
Build events
%p.light
This url will be triggered when the build status changes
- %div
- = f.check_box :wiki_page_events, class: 'pull-left'
- .prepend-left-20
- = f.label :wiki_page_events, class: 'label-light append-bottom-0' do
- Wiki Page events
- %p.light
- This url will be triggered when a wiki page is created/updated
.form-group
= f.label :enable_ssl_verification, "SSL verification", class: "label-light"
%div
@@ -87,5 +80,5 @@
- @hooks.each do |hook|
= render "project_hook", hook: hook
- else
- %p.settings-message.text-center.append-bottom-0
+ %p.profile-settings-message.text-center.append-bottom-0
No webhooks found, add one in the form above.
diff --git a/app/views/projects/issues/_header_title.html.haml b/app/views/projects/issues/_header_title.html.haml
new file mode 100644
index 0000000000..99f03549c4
--- /dev/null
+++ b/app/views/projects/issues/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Issues", namespace_project_issues_path(@project.namespace, @project))
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 78f6415060..9ad86ed71c 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -6,7 +6,7 @@
.issue-title.title
%span.issue-title-text
= confidential_icon(issue)
- = link_to issue.title, issue_path(issue)
+ = link_to_gfm issue.title, issue_path(issue)
%ul.controls
- if issue.closed?
%li
@@ -28,10 +28,16 @@
= downvotes
- note_count = issue.notes.user.nonawards.count
- %li
- = link_to issue_path(issue, anchor: 'notes'), class: ('issue-no-comments' if note_count.zero?) do
- = icon('comments')
- = note_count
+ - if note_count > 0
+ %li
+ = link_to issue_path(issue) + "#notes" do
+ = icon('comments')
+ = note_count
+ - else
+ %li
+ = link_to issue_path(issue) + "#notes", class: "issue-no-comments" do
+ = icon('comments')
+ = note_count
.issue-info
#{issue.to_reference} ·
diff --git a/app/views/projects/issues/_merge_requests.html.haml b/app/views/projects/issues/_merge_requests.html.haml
index 2f9dc867d0..d6b38b327f 100644
--- a/app/views/projects/issues/_merge_requests.html.haml
+++ b/app/views/projects/issues/_merge_requests.html.haml
@@ -7,7 +7,7 @@
%li
%span.merge-request-ci-status
- if merge_request.ci_commit
- = render_pipeline_status(merge_request.ci_commit)
+ = render_ci_status(merge_request.ci_commit)
- elsif has_any_ci
= icon('blank fw')
%span.merge-request-id
@@ -24,8 +24,5 @@
MERGED
- elsif merge_request.closed?
CLOSED
- %li
- = render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count}
- if @closed_by_merge_requests.present?
- %li
- = render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count}
+ = render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count}
diff --git a/app/views/projects/issues/_related_branches.html.haml b/app/views/projects/issues/_related_branches.html.haml
index 5f9d291998..bdfa0c7009 100644
--- a/app/views/projects/issues/_related_branches.html.haml
+++ b/app/views/projects/issues/_related_branches.html.haml
@@ -8,7 +8,7 @@
- ci_commit = @project.ci_commit(sha, branch) if sha
- if ci_commit
%span.related-branch-ci-status
- = render_pipeline_status(ci_commit)
+ = render_ci_status(ci_commit)
%span.related-branch-info
%strong
= link_to namespace_project_compare_path(@project.namespace, @project, from: @project.default_branch, to: branch), class: "label-branch" do
diff --git a/app/views/projects/issues/edit.html.haml b/app/views/projects/issues/edit.html.haml
index 7cf1923456..20216297d2 100644
--- a/app/views/projects/issues/edit.html.haml
+++ b/app/views/projects/issues/edit.html.haml
@@ -1,4 +1,5 @@
- page_title "Edit", "#{@issue.title} (##{@issue.iid})", "Issues"
+= render "header_title"
%h3.page-title
Edit Issue ##{@issue.iid}
diff --git a/app/views/projects/issues/index.atom.builder b/app/views/projects/issues/index.atom.builder
index 7ad7c9c87e..ee8a941465 100644
--- a/app/views/projects/issues/index.atom.builder
+++ b/app/views/projects/issues/index.atom.builder
@@ -6,5 +6,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id namespace_project_issues_url(@project.namespace, @project)
xml.updated @issues.first.created_at.xmlschema if @issues.any?
- xml << render(partial: 'issues/issue', collection: @issues) if @issues.any?
+ @issues.each do |issue|
+ issue_to_atom(xml, issue)
+ end
end
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 19a6f4a91f..efa7642b2d 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -1,4 +1,5 @@
- page_title "Issues"
+= render "header_title"
= content_for :meta_tags do
- if current_user
diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml
index e8aae0f47e..b317a0c1cf 100644
--- a/app/views/projects/issues/new.html.haml
+++ b/app/views/projects/issues/new.html.haml
@@ -1,4 +1,5 @@
- page_title "New Issue"
+= render "header_title"
%h3.page-title
New Issue
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index f3b0469b7d..bde80bbb54 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -1,6 +1,7 @@
- page_title "#{@issue.title} (##{@issue.iid})", "Issues"
- page_description @issue.description
- page_card_attributes @issue.card_attributes
+- header_title project_title(@project, "Issues", namespace_project_issues_path(@project.namespace, @project))
.clearfix.detail-page-header
.issuable-header
@@ -52,12 +53,12 @@
.issue-details.issuable-details
.detail-page-description.content-block
%h2.title
- = markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author
+ = markdown escape_once(@issue.title), pipeline: :single_line
- if @issue.description.present?
.description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' }
.wiki
= preserve do
- = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author)
+ = markdown(@issue.description, cache_key: [@issue, "description"])
%textarea.hidden.js-task-list-field
= @issue.description
= edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago')
diff --git a/app/views/projects/labels/_header_title.html.haml b/app/views/projects/labels/_header_title.html.haml
new file mode 100644
index 0000000000..abe28da483
--- /dev/null
+++ b/app/views/projects/labels/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Labels", namespace_project_labels_path(@project.namespace, @project))
diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml
index 6901ba13ab..675a805e12 100644
--- a/app/views/projects/labels/edit.html.haml
+++ b/app/views/projects/labels/edit.html.haml
@@ -1,4 +1,5 @@
- page_title "Edit", @label.name, "Labels"
+= render "header_title"
%h3.page-title
Edit Label
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index 2557d1a4d5..cc41130a9d 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -1,4 +1,5 @@
- page_title "Labels"
+= render "header_title"
.top-area
.nav-text
@@ -17,6 +18,6 @@
- else
.nothing-here-block
- if can? current_user, :admin_label, @project
- Create a label or #{link_to 'generate a default set of labels', generate_namespace_project_labels_path(@project.namespace, @project), method: :post}.
+ Create first label or #{link_to 'generate', generate_namespace_project_labels_path(@project.namespace, @project), method: :post} default set of labels
- else
No labels created
diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml
index 49ddf90161..e20fd7d689 100644
--- a/app/views/projects/labels/new.html.haml
+++ b/app/views/projects/labels/new.html.haml
@@ -1,4 +1,5 @@
- page_title "New Label"
+= render "header_title"
%h3.page-title
New Label
diff --git a/app/views/projects/merge_requests/_header_title.html.haml b/app/views/projects/merge_requests/_header_title.html.haml
new file mode 100644
index 0000000000..669a9b06bd
--- /dev/null
+++ b/app/views/projects/merge_requests/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Merge Requests", namespace_project_merge_requests_path(@project.namespace, @project))
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index c02f94490a..e740fe8c84 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -1,7 +1,7 @@
%li{ class: mr_css_classes(merge_request) }
.merge-request-title.title
%span.merge-request-title-text
- = link_to merge_request.title, merge_request_path(merge_request)
+ = link_to_gfm merge_request.title, merge_request_path(merge_request)
%ul.controls
- if merge_request.merged?
%li
@@ -13,7 +13,7 @@
- if merge_request.ci_commit
%li
- = render_pipeline_status(merge_request.ci_commit)
+ = render_ci_status(merge_request.ci_commit)
- if merge_request.open? && merge_request.broken?
%li
@@ -36,10 +36,16 @@
= downvotes
- note_count = merge_request.mr_and_commit_notes.user.nonawards.count
- %li
- = link_to merge_request_path(merge_request, anchor: 'notes'), class: ('merge-request-no-comments' if note_count.zero?) do
- = icon('comments')
- = note_count
+ - if note_count > 0
+ %li
+ = link_to merge_request_path(merge_request) + "#notes" do
+ = icon('comments')
+ = note_count
+ - else
+ %li
+ = link_to merge_request_path(merge_request) + "#notes", class: "merge-request-no-comments" do
+ = icon('comments')
+ = note_count
.merge-request-info
#{merge_request.to_reference} ·
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 7af227129e..290753d57c 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -1,6 +1,7 @@
- page_title "#{@merge_request.title} (#{@merge_request.to_reference})", "Merge Requests"
- page_description @merge_request.description
- page_card_attributes @merge_request.card_attributes
+- header_title project_title(@project, "Merge Requests", namespace_project_merge_requests_path(@project.namespace, @project))
- if diff_view == 'parallel'
- fluid_layout true
diff --git a/app/views/projects/merge_requests/dropdowns/_branch.html.haml b/app/views/projects/merge_requests/dropdowns/_branch.html.haml
index a60c445aa5..ba8d9a5835 100644
--- a/app/views/projects/merge_requests/dropdowns/_branch.html.haml
+++ b/app/views/projects/merge_requests/dropdowns/_branch.html.haml
@@ -1,5 +1,5 @@
%ul
- branches.each do |branch|
%li
- %a{ href: '#', class: "#{('is-active' if selected == branch)}", title: branch, data: { id: branch } }
+ %a{ href: '#', class: "#{('is-active' if selected == branch)}", data: { id: branch } }
= branch
diff --git a/app/views/projects/merge_requests/edit.html.haml b/app/views/projects/merge_requests/edit.html.haml
index 03159f123f..b31ea5e532 100644
--- a/app/views/projects/merge_requests/edit.html.haml
+++ b/app/views/projects/merge_requests/edit.html.haml
@@ -1,4 +1,5 @@
- page_title "Edit", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests"
+= render "header_title"
%h3.page-title
Edit Merge Request #{@merge_request.to_reference}
diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml
index b517e874b0..e56a44e0a7 100644
--- a/app/views/projects/merge_requests/index.html.haml
+++ b/app/views/projects/merge_requests/index.html.haml
@@ -1,4 +1,5 @@
- page_title "Merge Requests"
+= render "header_title"
= render 'projects/last_push'
diff --git a/app/views/projects/merge_requests/invalid.html.haml b/app/views/projects/merge_requests/invalid.html.haml
index a00d3128ff..f5bf16ef3a 100644
--- a/app/views/projects/merge_requests/invalid.html.haml
+++ b/app/views/projects/merge_requests/invalid.html.haml
@@ -1,4 +1,5 @@
- page_title "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests"
+= render "header_title"
.merge-request
= render "projects/merge_requests/show/mr_title"
diff --git a/app/views/projects/merge_requests/new.html.haml b/app/views/projects/merge_requests/new.html.haml
index 2e798ce780..d259968030 100644
--- a/app/views/projects/merge_requests/new.html.haml
+++ b/app/views/projects/merge_requests/new.html.haml
@@ -1,4 +1,5 @@
- page_title "New Merge Request"
+= render "header_title"
- if @merge_request.can_be_created && !params[:change_branches]
= render 'new_submit'
diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml
index ebf18f6ac8..a23bd8d18d 100644
--- a/app/views/projects/merge_requests/show/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_box.html.haml
@@ -1,13 +1,13 @@
.detail-page-description.content-block
%h2.title
- = markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author
+ = markdown escape_once(@merge_request.title), pipeline: :single_line
%div
- if @merge_request.description.present?
.description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''}
.wiki
= preserve do
- = markdown(@merge_request.description, cache_key: [@merge_request, "description"], author: @merge_request.author)
+ = markdown(@merge_request.description, cache_key: [@merge_request, "description"])
%textarea.hidden.js-task-list-field
= @merge_request.description
diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml
index 13359abede..55dbae598d 100644
--- a/app/views/projects/merge_requests/widget/_open.html.haml
+++ b/app/views/projects/merge_requests/widget/_open.html.haml
@@ -26,4 +26,4 @@
%i.fa.fa-check
Accepting this merge request will close #{"issue".pluralize(@closes_issues.size)}
= succeed '.' do
- != markdown issues_sentence(@closes_issues), pipeline: :gfm, author: @merge_request.author
+ != markdown issues_sentence(@closes_issues), pipeline: :gfm
diff --git a/app/views/projects/merge_requests/widget/_show.html.haml b/app/views/projects/merge_requests/widget/_show.html.haml
index b79508bdc3..3c68d61c4b 100644
--- a/app/views/projects/merge_requests/widget/_show.html.haml
+++ b/app/views/projects/merge_requests/widget/_show.html.haml
@@ -13,7 +13,7 @@
check_enable: #{@merge_request.unchecked? ? "true" : "false"},
ci_status_url: "#{ci_status_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}",
gitlab_icon: "#{asset_path 'gitlab_logo.png'}",
- ci_status: "#{@merge_request.ci_commit ? @merge_request.ci_commit.status : ''}",
+ ci_status: "",
ci_message: {
normal: "Build {{status}} for \"{{title}}\"",
preparing: "{{status}} build for \"{{title}}\""
@@ -26,10 +26,4 @@
builds_path: "#{builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}"
};
- if (typeof merge_request_widget !== 'undefined') {
- clearInterval(merge_request_widget.fetchBuildStatusInterval);
- merge_request_widget.cancelPolling();
- merge_request_widget.clearEventListeners();
- }
-
merge_request_widget = new MergeRequestWidget(opts);
diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml
index cfdf4edac3..807833741a 100644
--- a/app/views/projects/merge_requests/widget/open/_accept.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml
@@ -25,10 +25,7 @@
- else
= f.button class: "btn btn-create btn-grouped js-merge-button accept_merge_request #{status_class}" do
Accept Merge Request
- - if @merge_request.force_remove_source_branch?
- .accept-control
- The source branch will be removed.
- - elsif @merge_request.can_remove_source_branch?(current_user)
+ - if @merge_request.can_remove_source_branch?(current_user)
.accept-control.checkbox
= label_tag :should_remove_source_branch, class: "remove_source_checkbox" do
= check_box_tag :should_remove_source_branch
diff --git a/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml b/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
index b83ddcab3a..2168294c68 100644
--- a/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_merge_when_build_succeeds.html.haml
@@ -2,16 +2,17 @@
Set by #{link_to_member(@project, @merge_request.merge_user, avatar: true)}
to be merged automatically when the build succeeds.
%div
+ - should_remove_source_branch = @merge_request.merge_params["should_remove_source_branch"].present?
%p
= succeed '.' do
The changes will be merged into
%span.label-branch= @merge_request.target_branch
- - if @merge_request.remove_source_branch?
+ - if should_remove_source_branch
The source branch will be removed.
- else
The source branch will not be removed.
- - remove_source_branch_button = !@merge_request.remove_source_branch? && @merge_request.can_remove_source_branch?(current_user) && @merge_request.merge_user == current_user
+ - remove_source_branch_button = @merge_request.can_remove_source_branch?(current_user) && !should_remove_source_branch && @merge_request.merge_user == current_user
- user_can_cancel_automatic_merge = @merge_request.can_cancel_merge_when_build_succeeds?(current_user)
- if remove_source_branch_button || user_can_cancel_automatic_merge
.clearfix.prepend-top-10
diff --git a/app/views/projects/merge_requests/widget/open/_not_allowed.html.haml b/app/views/projects/merge_requests/widget/open/_not_allowed.html.haml
index 57ce195902..a8145558ca 100644
--- a/app/views/projects/merge_requests/widget/open/_not_allowed.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_not_allowed.html.haml
@@ -1,6 +1,4 @@
-%h4
+%h4
Ready to be merged automatically
%p
Ask someone with write access to this repository to merge this request.
- - if @merge_request.force_remove_source_branch?
- The source branch will be removed.
diff --git a/app/views/projects/milestones/_header_title.html.haml b/app/views/projects/milestones/_header_title.html.haml
new file mode 100644
index 0000000000..5f4b6982a6
--- /dev/null
+++ b/app/views/projects/milestones/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Milestones", namespace_project_milestones_path(@project.namespace, @project))
diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml
index be682226ab..43f8863163 100644
--- a/app/views/projects/milestones/edit.html.haml
+++ b/app/views/projects/milestones/edit.html.haml
@@ -1,4 +1,5 @@
- page_title "Edit", @milestone.title, "Milestones"
+= render "header_title"
%h3.page-title
Edit Milestone ##{@milestone.iid}
diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml
index e6133b22f9..abe567af1d 100644
--- a/app/views/projects/milestones/index.html.haml
+++ b/app/views/projects/milestones/index.html.haml
@@ -1,4 +1,6 @@
- page_title "Milestones"
+= render "header_title"
+
.top-area
= render 'shared/milestones_filter'
diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml
index 7f372b4169..0d016f7831 100644
--- a/app/views/projects/milestones/new.html.haml
+++ b/app/views/projects/milestones/new.html.haml
@@ -1,4 +1,5 @@
- page_title "New Milestone"
+= render "header_title"
%h3.page-title
New Milestone
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 19944e3e02..6ec8466015 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -1,6 +1,8 @@
- page_title @milestone.title, "Milestones"
- page_description @milestone.description
+= render "header_title"
+
.detail-page-header
.status-box{ class: status_box_class(@milestone) }
- if @milestone.closed?
diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml
index 326180ebe4..8065663ca2 100644
--- a/app/views/projects/network/show.html.haml
+++ b/app/views/projects/network/show.html.haml
@@ -1,4 +1,5 @@
- page_title "Network", @ref
+= render "projects/commits/header_title"
= render "projects/commits/head"
= render "head"
.project-network
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index f9ac16b32f..a4c6094c69 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -1,5 +1,5 @@
- page_title 'New Project'
-- header_title "Projects", dashboard_projects_path
+- header_title "Projects", root_path
%h3.page-title
New Project
diff --git a/.vagrant_enabled b/app/views/projects/notes/_commit_discussion.html.haml
similarity index 100%
rename from .vagrant_enabled
rename to app/views/projects/notes/_commit_discussion.html.haml
diff --git a/app/views/projects/notes/_diff_notes_with_reply.html.haml b/app/views/projects/notes/_diff_notes_with_reply.html.haml
index 8144c1ba49..39be072855 100644
--- a/app/views/projects/notes/_diff_notes_with_reply.html.haml
+++ b/app/views/projects/notes/_diff_notes_with_reply.html.haml
@@ -1,8 +1,10 @@
-- note = notes.first
-%tr.notes_holder
- %td.notes_line{ colspan: 2 }
- %td.notes_content
- %ul.notes{ data: { discussion_id: note.discussion_id } }
- = render partial: "projects/notes/note", collection: notes, as: :note
- .discussion-reply-holder
- = link_to_reply_discussion(note)
+- note = notes.first # example note
+-# Check if line want not changed since comment was left
+- if !defined?(line) || line == note.diff_line
+ %tr.notes_holder
+ %td.notes_line{ colspan: 2 }
+ %td.notes_content
+ %ul.notes{ data: { discussion_id: note.discussion_id } }
+ = render notes
+ .discussion-reply-holder
+ = link_to_reply_diff(note)
diff --git a/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml b/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml
index 45986b0d1e..f8aa5e2fa7 100644
--- a/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml
+++ b/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml
@@ -1,27 +1,27 @@
-- note_left = notes_left.present? ? notes_left.first : nil
-- note_right = notes_right.present? ? notes_right.first : nil
+- note1 = notes_left.present? ? notes_left.first : nil
+- note2 = notes_right.present? ? notes_right.first : nil
%tr.notes_holder
- - if note_left
+ - if note1
%td.notes_line.old
%td.notes_content.parallel.old
- %ul.notes{ data: { discussion_id: note_left.discussion_id } }
- = render partial: "projects/notes/note", collection: notes_left, as: :note
+ %ul.notes{ data: { discussion_id: note1.discussion_id } }
+ = render notes_left
.discussion-reply-holder
- = link_to_reply_discussion(note_left, 'old')
+ = link_to_reply_diff(note1, 'old')
- else
%td.notes_line.old= ""
%td.notes_content.parallel.old= ""
- - if note_right
+ - if note2
%td.notes_line.new
%td.notes_content.parallel.new
- %ul.notes{ data: { discussion_id: note_right.discussion_id } }
- = render partial: "projects/notes/note", collection: notes_right, as: :note
+ %ul.notes{ data: { discussion_id: note2.discussion_id } }
+ = render notes_right
.discussion-reply-holder
- = link_to_reply_discussion(note_right, 'new')
+ = link_to_reply_diff(note2, 'new')
- else
%td.notes_line.new= ""
%td.notes_content.parallel.new= ""
diff --git a/app/views/projects/notes/_discussion.html.haml b/app/views/projects/notes/_discussion.html.haml
index 7869d6413d..572b00a38c 100644
--- a/app/views/projects/notes/_discussion.html.haml
+++ b/app/views/projects/notes/_discussion.html.haml
@@ -1,46 +1,13 @@
- note = discussion_notes.first
-- expanded = !note.diff_note? || note.active?
%li.note.note-discussion.timeline-entry
.timeline-entry-inner
.timeline-icon
= link_to user_path(note.author) do
- = image_tag avatar_icon(note.author), class: "avatar s40"
+ = image_tag avatar_icon(note.author_email), class: "avatar s40"
.timeline-content
- .discussion.js-toggle-container{ class: note.discussion_id }
- .discussion-header
- = link_to_member(@project, note.author, avatar: false)
-
- .inline.discussion-headline-light
- = note.author.to_reference
- started a discussion on
-
- - if note.for_commit?
- - commit = note.noteable
- - if commit
- commit
- = link_to commit.short_id, namespace_project_commit_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code), class: 'monospace'
- - else
- a deleted commit
- - else
- - if note.active?
- = link_to diffs_namespace_project_merge_request_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code) do
- the diff
- - else
- an outdated diff
-
- = time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "note-created-ago")
-
- .discussion-actions
- = link_to "#", class: "note-action-button discussion-toggle-button js-toggle-button" do
- - if expanded
- = icon("chevron-up")
- - else
- = icon("chevron-down")
-
- Toggle discussion
-
- .discussion-body.js-toggle-content{ class: ("hide" unless expanded) }
- - if note.diff_note?
- = render "projects/notes/discussions/diff_with_notes", discussion_notes: discussion_notes
- - else
- = render "projects/notes/discussions/notes", discussion_notes: discussion_notes
+ - if note.for_merge_request?
+ - (active_notes, outdated_notes) = discussion_notes.partition(&:active?)
+ = render "projects/notes/discussions/active", discussion_notes: active_notes if active_notes.length > 0
+ = render "projects/notes/discussions/outdated", discussion_notes: outdated_notes if outdated_notes.length > 0
+ - else
+ = render "projects/notes/discussions/commit", discussion_notes: discussion_notes
diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml
index 67ed38a7b2..d0ac380f21 100644
--- a/app/views/projects/notes/_form.html.haml
+++ b/app/views/projects/notes/_form.html.haml
@@ -6,7 +6,6 @@
= f.hidden_field :line_code
= f.hidden_field :noteable_id
= f.hidden_field :noteable_type
- = f.hidden_field :type
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
= render 'projects/zen', f: f, attr: :note, classes: 'note-textarea js-note-text', placeholder: "Write a comment or drag your files here..."
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index f1045bbd8c..aeb7c1d5ee 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -1,8 +1,5 @@
-- return unless note.author
-- return if note.cross_reference_not_visible_for?(current_user)
-
- note_editable = note_editable?(note)
-%li.timeline-entry{ id: dom_id(note), class: ["note", "note-row-#{note.id}", ('system-note' if note.system)], data: {author_id: note.author.id, editable: note_editable} }
+%li.timeline-entry{ id: dom_id(note), class: [dom_class(note), "note-row-#{note.id}", ('system-note' if note.system)], data: {author_id: note.author.id, editable: note_editable} }
.timeline-entry-inner
.timeline-icon
%a{href: user_path(note.author)}
@@ -11,8 +8,8 @@
.note-header
= link_to_member(note.project, note.author, avatar: false)
.inline.note-headline-light
- = note.author.to_reference
- - unless note.system
+ = "#{note.author.to_reference}"
+ - if !note.system
commented
%a{ href: "##{dom_id(note)}" }
= time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago')
@@ -29,7 +26,7 @@
.note-body{class: note_editable ? 'js-task-list-container' : ''}
.note-text
= preserve do
- = markdown(note.note, pipeline: :note, cache_key: [note, "note"], author: note.author)
+ = markdown(note.note, pipeline: :note, cache_key: [note, "note"])
- if note_editable
= render 'projects/notes/edit_form', note: note
= edited_time_ago_with_tooltip(note, placement: 'bottom', html_class: 'note_edited_ago', include_author: true)
diff --git a/app/views/projects/notes/_notes.html.haml b/app/views/projects/notes/_notes.html.haml
index ebf7e8a9cb..62db86fb18 100644
--- a/app/views/projects/notes/_notes.html.haml
+++ b/app/views/projects/notes/_notes.html.haml
@@ -2,9 +2,14 @@
- @discussions.each do |discussion_notes|
- note = discussion_notes.first
- if note_for_main_target?(note)
- = render partial: "projects/notes/note", object: note, as: :note
+ - next if note.cross_reference_not_visible_for?(current_user)
+
+ = render discussion_notes
- else
= render 'projects/notes/discussion', discussion_notes: discussion_notes
- else
- @notes.each do |note|
- = render partial: "projects/notes/note", object: note, as: :note
+ - next unless note.author
+ - next if note.cross_reference_not_visible_for?(current_user)
+
+ = render note
diff --git a/app/views/projects/notes/discussions/_active.html.haml b/app/views/projects/notes/discussions/_active.html.haml
new file mode 100644
index 0000000000..0ea8862a68
--- /dev/null
+++ b/app/views/projects/notes/discussions/_active.html.haml
@@ -0,0 +1,16 @@
+- note = discussion_notes.first
+.discussion.js-toggle-container{ class: note.discussion_id }
+ .discussion-header
+ = link_to_member(@project, note.author, avatar: false)
+ .inline.discussion-headline-light
+ = "#{note.author.to_reference} started a discussion"
+ = link_to diffs_namespace_project_merge_request_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code) do
+ on the diff
+ = time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "discussion_updated_ago")
+ .discussion-actions
+ = link_to "#", class: "discussion-action-button discussion-toggle-button js-toggle-button" do
+ %i.fa.fa-chevron-up
+ Show/hide discussion
+
+ .discussion-body.js-toggle-content
+ = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note
diff --git a/app/views/projects/notes/discussions/_commit.html.haml b/app/views/projects/notes/discussions/_commit.html.haml
new file mode 100644
index 0000000000..2a2ead58ee
--- /dev/null
+++ b/app/views/projects/notes/discussions/_commit.html.haml
@@ -0,0 +1,25 @@
+- note = discussion_notes.first
+- commit = note.noteable
+- commit_description = commit ? 'commit' : 'a deleted commit'
+.discussion.js-toggle-container{ class: note.discussion_id }
+ .discussion-header
+ = link_to_member(@project, note.author, avatar: false)
+ .inline.discussion-headline-light
+ = "#{note.author.to_reference} started a discussion on #{commit_description}"
+ - if commit
+ = link_to(commit.short_id, namespace_project_commit_path(note.project.namespace, note.project, note.noteable), class: 'monospace')
+ = time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "discussion_updated_ago")
+ .discussion-actions
+ = link_to "#", class: "note-action-button discussion-toggle-button js-toggle-button" do
+ %i.fa.fa-chevron-up
+ Show/hide discussion
+ .discussion-body.js-toggle-content
+ - if note.for_diff_line?
+ = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note
+ - else
+ .panel.panel-default
+ .notes{ data: { discussion_id: discussion_notes.first.discussion_id } }
+ %ul.notes.timeline
+ = render discussion_notes
+ .discussion-reply-holder
+ = link_to_reply_diff(discussion_notes.first)
diff --git a/app/views/projects/notes/discussions/_diff.html.haml b/app/views/projects/notes/discussions/_diff.html.haml
new file mode 100644
index 0000000000..d46aab000c
--- /dev/null
+++ b/app/views/projects/notes/discussions/_diff.html.haml
@@ -0,0 +1,28 @@
+- diff = note.diff
+- if diff
+ .diff-file
+ .diff-header
+ %span
+ - if diff.deleted_file
+ = diff.old_path
+ - else
+ = diff.new_path
+ - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
+ %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
+ .diff-content.code.js-syntax-highlight
+ %table
+ - note.truncated_diff_lines.each do |line|
+ - type = line.type
+ - line_code = generate_line_code(note.file_path, line)
+ %tr.line_holder{ id: line_code, class: "#{type}" }
+ - if type == "match"
+ %td.old_line.diff-line-num= "..."
+ %td.new_line.diff-line-num= "..."
+ %td.line_content.match= line.text
+ - else
+ %td.old_line.diff-line-num{ data: { linenumber: type == "new" ? " ".html_safe : line.old_pos } }
+ %td.new_line.diff-line-num{ data: { linenumber: type == "old" ? " ".html_safe : line.new_pos } }
+ %td.line_content{ class: ['noteable_line', type, line_code], line_code: line_code }= diff_line_content(line.text, type)
+
+ - if line_code == note.line_code
+ = render "projects/notes/diff_notes_with_reply", notes: discussion_notes
diff --git a/app/views/projects/notes/discussions/_diff_with_notes.html.haml b/app/views/projects/notes/discussions/_diff_with_notes.html.haml
deleted file mode 100644
index 6401245bf7..0000000000
--- a/app/views/projects/notes/discussions/_diff_with_notes.html.haml
+++ /dev/null
@@ -1,30 +0,0 @@
-- note = discussion_notes.first
-- diff = note.diff
-- return unless diff
-
-.diff-file
- .diff-header
- %span
- - if diff.deleted_file
- = diff.old_path
- - else
- = diff.new_path
- - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
- %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
- .diff-content.code.js-syntax-highlight
- %table
- - note.truncated_diff_lines.each do |line|
- - type = line.type
- - line_code = generate_line_code(note.diff_file_path, line)
- %tr.line_holder{ id: line_code, class: "#{type}" }
- - if type == "match"
- %td.old_line.diff-line-num= "..."
- %td.new_line.diff-line-num= "..."
- %td.line_content.match= line.text
- - else
- %td.old_line.diff-line-num{ data: { linenumber: type == "new" ? " ".html_safe : line.old_pos } }
- %td.new_line.diff-line-num{ data: { linenumber: type == "old" ? " ".html_safe : line.new_pos } }
- %td.line_content{ class: ['noteable_line', type, line_code], line_code: line_code }= diff_line_content(line.text, type)
-
- - if line_code == note.line_code
- = render "projects/notes/diff_notes_with_reply", notes: discussion_notes
diff --git a/app/views/projects/notes/discussions/_notes.html.haml b/app/views/projects/notes/discussions/_notes.html.haml
deleted file mode 100644
index e598e3c7c6..0000000000
--- a/app/views/projects/notes/discussions/_notes.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-- note = discussion_notes.first
-.panel.panel-default
- .notes{ data: { discussion_id: note.discussion_id } }
- %ul.notes.timeline
- = render partial: "projects/notes/note", collection: discussion_notes, as: :note
- .discussion-reply-holder
- = link_to_reply_discussion(note)
diff --git a/app/views/projects/notes/discussions/_outdated.html.haml b/app/views/projects/notes/discussions/_outdated.html.haml
new file mode 100644
index 0000000000..45141bcd1d
--- /dev/null
+++ b/app/views/projects/notes/discussions/_outdated.html.haml
@@ -0,0 +1,14 @@
+- note = discussion_notes.first
+.discussion.js-toggle-container{ class: note.discussion_id }
+ .discussion-header
+ = link_to_member(@project, note.author, avatar: false)
+ .inline.discussion-headline-light
+ = "#{note.author.to_reference} started a discussion"
+ on the outdated diff
+ = time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "discussion_updated_ago")
+ .discussion-actions
+ = link_to "#", class: "note-action-button discussion-toggle-button js-toggle-button" do
+ %i.fa.fa-chevron-down
+ Show/hide discussion
+ .discussion-body.js-toggle-content.hide
+ = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note
diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml
deleted file mode 100644
index 6e757df541..0000000000
--- a/app/views/projects/pipelines/_head.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-%ul.nav-links
- - if project_nav_tab? :pipelines
- = nav_link(controller: :pipelines) do
- = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do
- %span
- Pipelines
- %span.badge.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count)
-
- - if project_nav_tab? :builds
- = nav_link(controller: %w(builds)) do
- = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do
- %span
- Builds
- %span.badge.count.builds_counter= number_with_delimiter(@project.running_or_pending_build_count)
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
deleted file mode 100644
index 8289aefcde..0000000000
--- a/app/views/projects/pipelines/_info.html.haml
+++ /dev/null
@@ -1,37 +0,0 @@
-%p
-.commit-info-row
- Pipeline
- = link_to "##{@pipeline.id}", namespace_project_pipeline_path(@project.namespace, @project, @pipeline.id), class: "monospace"
- with
- = pluralize @pipeline.statuses.count(:id), "build"
- - if @pipeline.ref
- for
- = link_to @pipeline.ref, namespace_project_commits_path(@project.namespace, @project, @pipeline.ref), class: "monospace"
- - if @pipeline.duration
- in
- = time_interval_in_words @pipeline.duration
-
- .pull-right
- = link_to namespace_project_pipeline_path(@project.namespace, @project, @pipeline), class: "ci-status ci-#{@pipeline.status}" do
- = ci_icon_for_status(@pipeline.status)
- = ci_label_for_status(@pipeline.status)
-
-- if @commit
- .commit-info-row
- %span.light Authored by
- %strong
- = commit_author_link(@commit, avatar: true, size: 24)
- #{time_ago_with_tooltip(@commit.authored_date)}
-
-.commit-info-row
- %span.light Commit
- = link_to @pipeline.sha, namespace_project_commit_path(@project.namespace, @project, @pipeline.sha), class: "monospace"
- = clipboard_button(clipboard_text: @pipeline.sha)
-
-- if @commit
- .commit-box.content-block
- %h3.commit-title
- = markdown escape_once(@commit.title), pipeline: :single_line
- - if @commit.description.present?
- %pre.commit-description
- = preserve(markdown(escape_once(@commit.description), pipeline: :single_line))
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
deleted file mode 100644
index 453767920b..0000000000
--- a/app/views/projects/pipelines/index.html.haml
+++ /dev/null
@@ -1,58 +0,0 @@
-- page_title "Pipelines"
-= render "projects/pipelines/head"
-
-.top-area
- %ul.nav-links
- %li{class: ('active' if @scope.nil?)}
- = link_to project_pipelines_path(@project) do
- All
- %span.badge.js-totalbuilds-count
- = number_with_delimiter(@pipelines_count)
-
- %li{class: ('active' if @scope == 'running')}
- = link_to project_pipelines_path(@project, scope: :running) do
- Running
- %span.badge.js-running-count
- = number_with_delimiter(@running_or_pending_count)
-
- %li{class: ('active' if @scope == 'branches')}
- = link_to project_pipelines_path(@project, scope: :branches) do
- Branches
-
- %li{class: ('active' if @scope == 'tags')}
- = link_to project_pipelines_path(@project, scope: :tags) do
- Tags
-
- .nav-controls
- - if can? current_user, :create_pipeline, @project
- = link_to new_namespace_project_pipeline_path(@project.namespace, @project), class: 'btn btn-create' do
- = icon('plus')
- New pipeline
-
- - unless @repository.gitlab_ci_yml
- = link_to 'Get started with Pipelines', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info'
-
- = link_to ci_lint_path, class: 'btn btn-default' do
- = icon('wrench')
- %span CI Lint
-
-%ul.content-list.pipelines
- - stages = @pipelines.stages
- - if @pipelines.blank?
- %li
- .nothing-here-block No pipelines to show
- - else
- .table-holder
- %table.table.builds
- %tbody
- %th ID
- %th Commit
- - stages.each do |stage|
- %th.stage
- %span.has-tooltip{ title: "#{stage.titleize}" }
- = stage.titleize.pluralize
- %th Duration
- %th
- = render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages
-
- = paginate @pipelines, theme: 'gitlab'
diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml
deleted file mode 100644
index 5f4ec2e40c..0000000000
--- a/app/views/projects/pipelines/new.html.haml
+++ /dev/null
@@ -1,21 +0,0 @@
-- page_title "New Pipeline"
-
-%h3.page-title
- New Pipeline
-%hr
-
-= form_for @pipeline, as: :pipeline, url: namespace_project_pipelines_path(@project.namespace, @project), html: { id: "new-pipeline-form", class: "form-horizontal js-new-pipeline-form js-requires-input" } do |f|
- = form_errors(@pipeline)
- .form-group
- = f.label :ref, 'Create for', class: 'control-label'
- .col-sm-10
- = f.text_field :ref, required: true, tabindex: 2, class: 'form-control'
- .help-block Existing branch name, tag
- .form-actions
- = f.submit 'Create pipeline', class: 'btn btn-create', tabindex: 3
- = link_to 'Cancel', namespace_project_pipelines_path(@project.namespace, @project), class: 'btn btn-cancel'
-
-:javascript
- var availableRefs = #{@project.repository.ref_names.to_json};
-
- new NewBranchForm($('.js-new-pipeline-form'), availableRefs)
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
deleted file mode 100644
index 2aad560241..0000000000
--- a/app/views/projects/pipelines/show.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-- page_title "Pipeline"
-
-.prepend-top-default
- - if @commit
- = render "projects/pipelines/info"
- %div.block-connector
-
-= render "projects/commit/ci_commit", ci_commit: @pipeline
diff --git a/app/views/projects/project_members/_header_title.html.haml b/app/views/projects/project_members/_header_title.html.haml
new file mode 100644
index 0000000000..a31f0a37fa
--- /dev/null
+++ b/app/views/projects/project_members/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Members", namespace_project_project_members_path(@project.namespace, @project))
diff --git a/app/views/projects/project_members/import.html.haml b/app/views/projects/project_members/import.html.haml
index eef97107d7..189906498c 100644
--- a/app/views/projects/project_members/import.html.haml
+++ b/app/views/projects/project_members/import.html.haml
@@ -1,4 +1,5 @@
- page_title "Import members"
+= render "header_title"
%h3.page-title
Import members from another project
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 15dc064e7e..ebcfc907eb 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -1,4 +1,5 @@
- page_title "Members"
+= render "header_title"
.project-members-page.prepend-top-default
- if can?(current_user, :admin_project_member, @project)
diff --git a/app/views/projects/protected_branches/_branches_list.html.haml b/app/views/projects/protected_branches/_branches_list.html.haml
index 565905cbe7..b9e9dd8aae 100644
--- a/app/views/projects/protected_branches/_branches_list.html.haml
+++ b/app/views/projects/protected_branches/_branches_list.html.haml
@@ -1,7 +1,7 @@
%h5.prepend-top-0
Already Protected (#{@branches.size})
- if @branches.empty?
- %p.settings-message.text-center
+ %p.profile-settings-message.text-center
No branches are protected, protect a branch with the form above.
- else
- can_admin_project = can?(current_user, :admin_project, @project)
diff --git a/app/views/projects/releases/edit.html.haml b/app/views/projects/releases/edit.html.haml
index 835398b6f9..0d59cec322 100644
--- a/app/views/projects/releases/edit.html.haml
+++ b/app/views/projects/releases/edit.html.haml
@@ -1,4 +1,5 @@
- page_title "Edit", @tag.name, "Tags"
+= render "projects/commits/header_title"
= render "projects/commits/head"
.row-content-block
diff --git a/app/views/projects/repositories/_feed.html.haml b/app/views/projects/repositories/_feed.html.haml
index 43a6fdfd10..6ca919f7f8 100644
--- a/app/views/projects/repositories/_feed.html.haml
+++ b/app/views/projects/repositories/_feed.html.haml
@@ -12,7 +12,7 @@
= link_to namespace_project_commits_path(@project.namespace, @project, commit.id) do
%code= commit.short_id
= image_tag avatar_icon(commit.author_email), class: "", width: 16, alt: ''
- = markdown escape_once(truncate(commit.title, length: 40)), pipeline: :single_line, author: commit.author
+ = markdown escape_once(truncate(commit.title, length: 40)), pipeline: :single_line
%td
%span.pull-right.cgray
= time_ago_with_tooltip(commit.committed_date)
diff --git a/app/views/projects/runners/_form.html.haml b/app/views/projects/runners/_form.html.haml
deleted file mode 100644
index d62f5c8f13..0000000000
--- a/app/views/projects/runners/_form.html.haml
+++ /dev/null
@@ -1,32 +0,0 @@
-= form_for runner, url: runner_form_url, html: { class: 'form-horizontal' } do |f|
- = form_errors(runner)
- .form-group
- = label :active, "Active", class: 'control-label'
- .col-sm-10
- .checkbox
- = f.check_box :active
- %span.light Paused runners don't accept new builds
- .form-group
- = label :run_untagged, 'Run untagged jobs', class: 'control-label'
- .col-sm-10
- .checkbox
- = f.check_box :run_untagged
- %span.light Indicates whether this runner can pick jobs without tags
- .form-group
- = label_tag :token, class: 'control-label' do
- Token
- .col-sm-10
- = f.text_field :token, class: 'form-control', readonly: true
- .form-group
- = label_tag :description, class: 'control-label' do
- Description
- .col-sm-10
- = f.text_field :description, class: 'form-control'
- .form-group
- = label_tag :tag_list, class: 'control-label' do
- Tags
- .col-sm-10
- = f.text_field :tag_list, value: runner.tag_list.to_s, class: 'form-control'
- .help-block You can setup jobs to only use runners with specific tags
- .form-actions
- = f.submit 'Save changes', class: 'btn btn-save'
diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml
index 96e2aac451..47ec420189 100644
--- a/app/views/projects/runners/_runner.html.haml
+++ b/app/views/projects/runners/_runner.html.haml
@@ -5,7 +5,7 @@
- if @runners.include?(runner)
= link_to runner.short_sha, runner_path(runner)
%small
- = link_to edit_namespace_project_runner_path(@project.namespace, @project, runner) do
+ =link_to edit_namespace_project_runner_path(@project.namespace, @project, runner) do
%i.fa.fa-edit.btn
- else
= runner.short_sha
diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml
index 8ae9f0d95f..30cd1263a1 100644
--- a/app/views/projects/runners/_specific_runners.html.haml
+++ b/app/views/projects/runners/_specific_runners.html.haml
@@ -8,7 +8,7 @@
Install GitLab Runner software.
Checkout the #{link_to 'GitLab Runner section', 'https://about.gitlab.com/gitlab-ci/#gitlab-runner', target: '_blank'} to install it
%li
- Specify the following URL during runner setup:
+ Specify following URL during runner setup:
%code #{ci_root_url(only_path: false)}
%li
Use the following registration token during setup:
diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml
index 9570688865..eba03028af 100644
--- a/app/views/projects/runners/edit.html.haml
+++ b/app/views/projects/runners/edit.html.haml
@@ -1,6 +1,29 @@
- page_title "Edit", "#{@runner.description} ##{@runner.id}", "Runners"
%h4 Runner ##{@runner.id}
-
%hr
- = render 'form', runner: @runner, runner_form_url: runner_path(@runner)
+= form_for @runner, url: runner_path(@runner), html: { class: 'form-horizontal' } do |f|
+ .form-group
+ = label :active, "Active", class: 'control-label'
+ .col-sm-10
+ .checkbox
+ = f.check_box :active
+ %span.light Paused runners don't accept new builds
+ .form-group
+ = label_tag :token, class: 'control-label' do
+ Token
+ .col-sm-10
+ = f.text_field :token, class: 'form-control', readonly: true
+ .form-group
+ = label_tag :description, class: 'control-label' do
+ Description
+ .col-sm-10
+ = f.text_field :description, class: 'form-control'
+ .form-group
+ = label_tag :tag_list, class: 'control-label' do
+ Tags
+ .col-sm-10
+ = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control'
+ .help-block You can setup jobs to only use runners with specific tags
+ .form-actions
+ = f.submit 'Save changes', class: 'btn btn-save'
diff --git a/app/views/projects/runners/show.html.haml b/app/views/projects/runners/show.html.haml
index f24e1b9144..5bf4c09ca2 100644
--- a/app/views/projects/runners/show.html.haml
+++ b/app/views/projects/runners/show.html.haml
@@ -17,39 +17,50 @@
%th Property Name
%th Value
%tr
- %td Active
- %td= @runner.active? ? 'Yes' : 'No'
- %tr
- %td Can run untagged jobs
- %td= @runner.run_untagged? ? 'Yes' : 'No'
- %tr
- %td Tags
+ %td
+ Tags
%td
- @runner.tag_list.each do |tag|
%span.label.label-primary
= tag
%tr
- %td Name
- %td= @runner.name
+ %td
+ Name
+ %td
+ = @runner.name
%tr
- %td Version
- %td= @runner.version
+ %td
+ Version
+ %td
+ = @runner.version
%tr
- %td Revision
- %td= @runner.revision
+ %td
+ Revision
+ %td
+ = @runner.revision
%tr
- %td Platform
- %td= @runner.platform
+ %td
+ Platform
+ %td
+ = @runner.platform
%tr
- %td Architecture
- %td= @runner.architecture
+ %td
+ Architecture
+ %td
+ = @runner.architecture
%tr
- %td Description
- %td= @runner.description
+ %td
+ Description
+ %td
+ = @runner.description
%tr
- %td Last contact
+ %td
+ Last contact
%td
- if @runner.contacted_at
#{time_ago_in_words(@runner.contacted_at)} ago
- else
Never
+
+
+
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index 1f13ea28b4..1b70880043 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -1,16 +1,18 @@
-.row.prepend-top-default.append-bottom-default
- .col-lg-3
- %h4.prepend-top-0
- = @service.title
- = boolean_to_icon @service.activated?
+%h3.page-title
+ = @service.title
+ = boolean_to_icon @service.activated?
- %p= @service.description
- .col-lg-9
- = form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form|
- = render 'shared/service_settings', form: form
- = form.submit 'Save changes', class: 'btn btn-save'
-
- - if @service.valid? && @service.activated?
- - disabled = @service.can_test? ? '':'disabled'
- = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}"
- = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel"
+%p= @service.description
+
+%hr
+
+= form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form|
+ = render 'shared/service_settings', form: form
+
+ .form-actions
+ = form.submit 'Save changes', class: 'btn btn-save'
+
+ - if @service.valid? && @service.activated?
+ - disabled = @service.can_test? ? '':'disabled'
+ = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}"
+ = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel"
diff --git a/app/views/projects/services/index.html.haml b/app/views/projects/services/index.html.haml
index 4a33a5bc6f..c1356f6db0 100644
--- a/app/views/projects/services/index.html.haml
+++ b/app/views/projects/services/index.html.haml
@@ -1,32 +1,24 @@
- page_title "Services"
+%h3.page-title Project services
+%p.light Project services allow you to integrate GitLab with other applications
-.row.prepend-top-default.append-bottom-default
- .col-lg-3
- %h4.prepend-top-0
- Project services
- %p Project services allow you to integrate GitLab with other applications
- .col-lg-9
- %table.table
- %colgroup
- %col
- %col
- %col.hidden-xs
- %col{ width: "120" }
- %thead
- %tr
- %th
- %th Service
- %th.hidden-xs Description
- %th Last edit
- - @services.sort_by(&:title).each do |service|
- %tr
- %td
- = boolean_to_icon service.activated?
- %td
- = link_to edit_namespace_project_service_path(@project.namespace, @project, service.to_param) do
- %strong= service.title
- %td.hidden-xs
- = service.description
- %td.light
- = time_ago_in_words service.updated_at
- ago
+.table-holder
+ %table.table
+ %thead
+ %tr
+ %th
+ %th Service
+ %th Description
+ %th Last edit
+ - @services.sort_by(&:title).each do |service|
+ %tr
+ %td
+ = boolean_to_icon service.activated?
+ %td
+ = link_to edit_namespace_project_service_path(@project.namespace, @project, service.to_param) do
+ %strong= service.title
+ %td
+ = service.description
+ %td.light
+ = time_ago_in_words service.updated_at
+ ago
diff --git a/app/views/projects/show.atom.builder b/app/views/projects/show.atom.builder
index 11310d5e1e..9b3d3f069d 100644
--- a/app/views/projects/show.atom.builder
+++ b/app/views/projects/show.atom.builder
@@ -6,5 +6,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id namespace_project_url(@project.namespace, @project)
xml.updated @events[0].updated_at.xmlschema if @events[0]
- xml << render(@events) if @events.any?
+ @events.each do |event|
+ event_to_atom(xml, event)
+ end
end
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index a19c7c406a..74feb9e328 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -13,50 +13,50 @@
= render "home_panel"
.project-stats.row-content-block.second-block
- .container-fluid.container-limited
- %ul.nav
+ %ul.nav
+ %li
+ = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
+ = pluralize(number_with_delimiter(@project.commit_count), 'commit')
+ %li
+ = link_to namespace_project_branches_path(@project.namespace, @project) do
+ = pluralize(number_with_delimiter(@repository.branch_names.count), 'branch')
+ %li
+ = link_to namespace_project_tags_path(@project.namespace, @project) do
+ = pluralize(number_with_delimiter(@repository.tag_names.count), 'tag')
+
+ %li
+ = link_to project_files_path(@project) do
+ = repository_size
+
+ - if default_project_view != 'readme' && @repository.readme
%li
- = link_to project_files_path(@project) do
- Files (#{repository_size})
+ = link_to 'Readme', readme_path(@project)
+
+ - if @repository.changelog
%li
- = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
- #{'Commit'.pluralize(@project.commit_count)} (#{number_with_delimiter(@project.commit_count)})
+ = link_to 'Changelog', changelog_path(@project)
+
+ - if @repository.license_blob
%li
- = link_to namespace_project_branches_path(@project.namespace, @project) do
- #{'Branch'.pluralize(@repository.branch_names.count)} (#{number_with_delimiter(@repository.branch_names.count)})
+ = link_to license_short_name(@project), license_path(@project)
+
+ - if @repository.contribution_guide
%li
- = link_to namespace_project_tags_path(@project.namespace, @project) do
- #{'Tag'.pluralize(@repository.tag_names.count)} (#{number_with_delimiter(@repository.tag_names.count)})
+ = link_to 'Contribution guide', contribution_guide_path(@project)
- - if default_project_view != 'readme' && @repository.readme
- %li
- = link_to 'Readme', readme_path(@project)
-
- - if @repository.changelog
- %li
- = link_to 'Changelog', changelog_path(@project)
-
- - if @repository.license_blob
- %li
- = link_to license_short_name(@project), license_path(@project)
-
- - if @repository.contribution_guide
- %li
- = link_to 'Contribution guide', contribution_guide_path(@project)
-
- - if current_user && can_push_branch?(@project, @project.default_branch)
- - unless @repository.changelog
- %li.missing
- = link_to add_special_file_path(@project, file_name: 'CHANGELOG') do
- Add Changelog
- - unless @repository.license_blob
- %li.missing
- = link_to add_special_file_path(@project, file_name: 'LICENSE') do
- Add License
- - unless @repository.contribution_guide
- %li.missing
- = link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do
- Add Contribution guide
+ - if current_user && can_push_branch?(@project, @project.default_branch)
+ - unless @repository.changelog
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: 'CHANGELOG') do
+ Add Changelog
+ - unless @repository.license_blob
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: 'LICENSE') do
+ Add License
+ - unless @repository.contribution_guide
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do
+ Add Contribution guide
- if @repository.commit
.content-block.second-block.white
diff --git a/app/views/projects/snippets/_actions.html.haml b/app/views/projects/snippets/_actions.html.haml
index bf57beb9d0..4a51546942 100644
--- a/app/views/projects/snippets/_actions.html.haml
+++ b/app/views/projects/snippets/_actions.html.haml
@@ -1,27 +1,11 @@
-.hidden-xs
- = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped btn-create new-snippet-link', title: "New Snippet" do
- = icon('plus')
- New Snippet
- - if can?(current_user, :update_project_snippet, @snippet)
- = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-grouped snippable-edit" do
- Edit
- - if can?(current_user, :update_project_snippet, @snippet)
- = link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-warning", title: 'Delete Snippet' do
- Delete
-.visible-xs-block.dropdown
- %button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
- Options
- %span.caret
- .dropdown-menu.dropdown-menu-full-width
- %ul
- %li
- = link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "New Snippet" do
- New Snippet
- - if can?(current_user, :update_project_snippet, @snippet)
- %li
- = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet) do
- Edit
- - if can?(current_user, :update_project_snippet, @snippet)
- %li
- = link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do
- Delete
+= link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped new-snippet-link', title: "New Snippet" do
+ = icon('plus')
+ New Snippet
+- if can?(current_user, :admin_project_snippet, @snippet)
+ = link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-remove", title: 'Delete Snippet' do
+ = icon('trash-o')
+ Delete
+- if can?(current_user, :update_project_snippet, @snippet)
+ = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-grouped snippable-edit" do
+ = icon('pencil-square-o')
+ Edit
diff --git a/app/views/projects/snippets/_header_title.html.haml b/app/views/projects/snippets/_header_title.html.haml
new file mode 100644
index 0000000000..04f0bbe985
--- /dev/null
+++ b/app/views/projects/snippets/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Snippets", namespace_project_snippets_path(@project.namespace, @project))
diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml
index 216f70f560..dc3ea1fcf1 100644
--- a/app/views/projects/snippets/edit.html.haml
+++ b/app/views/projects/snippets/edit.html.haml
@@ -1,4 +1,5 @@
- page_title "Edit", @snippet.title, "Snippets"
+= render "header_title"
%h3.page-title
Edit Snippet
diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml
index 96fee3b17b..103ff44746 100644
--- a/app/views/projects/snippets/index.html.haml
+++ b/app/views/projects/snippets/index.html.haml
@@ -1,4 +1,5 @@
- page_title "Snippets"
+= render "header_title"
.row-content-block.top-block
.pull-right
diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml
index 772a594269..e57237991b 100644
--- a/app/views/projects/snippets/new.html.haml
+++ b/app/views/projects/snippets/new.html.haml
@@ -1,4 +1,5 @@
- page_title "New Snippets"
+= render "header_title"
%h3.page-title
New Snippet
diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml
index bae4d8f349..7c599563ce 100644
--- a/app/views/projects/snippets/show.html.haml
+++ b/app/views/projects/snippets/show.html.haml
@@ -1,15 +1,18 @@
- page_title @snippet.title, "Snippets"
+= render "header_title"
.snippet-holder
= render 'shared/snippets/header'
- %article.file-holder.file-holder-no-border.snippet-file-content
- .file-title.file-title-clear
+ %article.file-holder
+ .file-title
= blob_icon 0, @snippet.file_name
- = @snippet.file_name
+ %strong
+ = @snippet.file_name
.file-actions.hidden-xs
= clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']")
= link_to 'Raw', raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank"
+
= render 'shared/snippets/blob'
%div#notes= render "projects/notes/notes_with_form"
diff --git a/app/views/projects/tags/destroy.js.haml b/app/views/projects/tags/destroy.js.haml
index e4a78fadbe..ffeacb5a00 100644
--- a/app/views/projects/tags/destroy.js.haml
+++ b/app/views/projects/tags/destroy.js.haml
@@ -1,2 +1,3 @@
+$('.js-totaltags-count').html("#{@repository.tags.size}");
- if @repository.tags.empty?
$('.tags').load(document.URL + ' .nothing-here-block').hide().fadeIn(1000)
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 8f381663e6..dc6ece30dd 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -1,4 +1,5 @@
- page_title "Tags"
+= render "projects/commits/header_title"
= render "projects/commits/head"
.row-content-block
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index 3a097750d6..b40a6e5cb2 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -1,4 +1,5 @@
- page_title "New Tag"
+= render "projects/commits/header_title"
- if @error
.alert.alert-danger
@@ -22,7 +23,7 @@
.form-group
= label_tag :message, nil, class: 'control-label'
.col-sm-10
- = text_area_tag :message, nil, required: false, tabindex: 3, class: 'form-control', rows: 5
+ = text_field_tag :message, nil, required: false, tabindex: 3, class: 'form-control'
.help-block Optionally, enter a message to create an annotated tag.
%hr
.form-group
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index b7d7d5c538..9c916fd02d 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -1,4 +1,5 @@
- page_title @tag.name, "Tags"
+= render "projects/commits/header_title"
= render "projects/commits/head"
.row-content-block
@@ -18,13 +19,15 @@
%i.fa.fa-trash-o
.title
%span.item-title= @tag.name
+ - if @tag.message.present?
+ %span.light
+
+ = strip_gpg_signature(@tag.message)
- if @commit
= render 'projects/branches/commit', commit: @commit, project: @project
- else
Cant find HEAD commit for this tag
- - if @tag.message.present?
- %pre.body
- = strip_gpg_signature(@tag.message)
+
.append-bottom-default.prepend-top-default
- if @release.description.present?
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index 59f60c4687..91fb2a4459 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -1,9 +1,9 @@
- page_title @path.presence || "Files", @ref
+- header_title project_title(@project, "Files", project_files_path(@project))
= content_for :meta_tags do
- if current_user
= auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits")
= render 'projects/last_push'
-= render "projects/commits/head"
.tree-controls
= render 'projects/find_file_link'
diff --git a/app/views/projects/triggers/index.html.haml b/app/views/projects/triggers/index.html.haml
index 7f3de47d7d..f91885b216 100644
--- a/app/views/projects/triggers/index.html.haml
+++ b/app/views/projects/triggers/index.html.haml
@@ -5,7 +5,7 @@
%h4.prepend-top-0
= page_title
%p
- Triggers can force a specific branch or tag to rebuild with an API call.
+ Triggers can be used to force a rebuild of a specific branch or tag with an API call.
.col-lg-9
%h5.prepend-top-0
Your triggers
@@ -18,8 +18,8 @@
%th
= render partial: 'trigger', collection: @triggers, as: :trigger
- else
- %p.settings-message.text-center.append-bottom-default
- No triggers have been created yet. Add one using the button below.
+ %p.profile-settings-message.text-center.append-bottom-default
+ There are no triggers to use, add one by the button below.
= form_for @trigger, url: url_for(controller: 'projects/triggers', action: 'create') do |f|
= f.submit "Add Trigger", class: 'btn btn-success'
@@ -28,7 +28,8 @@
Use CURL
%p.light
- Copy the token above, set your branch or tag name, and that reference will be rebuilt.
+ Copy the token above and set your branch or tag name. This is the reference that will be rebuild.
+
%pre
:plain
@@ -40,10 +41,10 @@
Use .gitlab-ci.yml
%p.light
- In the
- %code .gitlab-ci.yml
- of the dependent project, include the following snippet.
- The project will rebuild at the end of the build.
+ Copy the snippet to
+ %i .gitlab-ci.yml
+ of dependent project.
+ At the end of your build it will trigger this project to rebuilt.
%pre
:plain
@@ -56,8 +57,9 @@
%p.light
Add
- %code variables[VARIABLE]=VALUE
- to an API request. Variable values can be used to distinguish between triggered builds and normal builds.
+ %strong variables[VARIABLE]=VALUE
+ to API request.
+ The value of variable could then be used to distinguish triggered build from normal one.
%pre.append-bottom-0
:plain
diff --git a/app/views/projects/variables/_content.html.haml b/app/views/projects/variables/_content.html.haml
deleted file mode 100644
index 0249e0c1bf..0000000000
--- a/app/views/projects/variables/_content.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-%h4.prepend-top-0
- Secret Variables
-%p
- These variables will be set to environment by the runner.
-%p
- So you can use them for passwords, secret keys or whatever you want.
-%p
- The value of the variable can be visible in build log if explicitly asked to do so.
diff --git a/app/views/projects/variables/_form.html.haml b/app/views/projects/variables/_form.html.haml
deleted file mode 100644
index a5bae83e0c..0000000000
--- a/app/views/projects/variables/_form.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-= form_for [@project.namespace.becomes(Namespace), @project, @variable] do |f|
- = form_errors(@variable)
-
- .form-group
- = f.label :key, "Key", class: "label-light"
- = f.text_field :key, class: "form-control", placeholder: "PROJECT_VARIABLE", required: true
- .form-group
- = f.label :value, "Value", class: "label-light"
- = f.text_area :value, class: "form-control", placeholder: "PROJECT_VARIABLE", required: true
- = f.submit btn_text, class: "btn btn-save"
diff --git a/app/views/projects/variables/_table.html.haml b/app/views/projects/variables/_table.html.haml
deleted file mode 100644
index 6c43f822db..0000000000
--- a/app/views/projects/variables/_table.html.haml
+++ /dev/null
@@ -1,25 +0,0 @@
-.table-responsive.variables-table
- %table.table
- %colgroup
- %col
- %col
- %col{ width: 100 }
- %thead
- %th Key
- %th Value
- %th
- %tbody
- - @project.variables.each do |variable|
- - if variable.id?
- %tr
- %td= variable.key
- %td= variable.value
- %td
- = link_to namespace_project_variable_path(@project.namespace, @project, variable), class: "btn btn-transparent btn-variable-edit" do
- %span.sr-only
- Update
- = icon("pencil")
- = link_to namespace_project_variable_path(@project.namespace, @project, variable), class: "btn btn-transparent btn-variable-delete", method: :delete, data: { confirm: "Are you sure?" } do
- %span.sr-only
- Remove
- = icon("trash")
diff --git a/app/views/projects/variables/index.html.haml b/app/views/projects/variables/index.html.haml
deleted file mode 100644
index 09bb54600a..0000000000
--- a/app/views/projects/variables/index.html.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-- page_title "Variables"
-
-.row.prepend-top-default.append-bottom-default
- .col-lg-3
- = render "content"
- .col-lg-9
- %h5.prepend-top-0
- Add a variable
- = render "form", btn_text: "Add new variable"
- %hr
- %h5.prepend-top-0
- Your variables (#{@project.variables.size})
- - if @project.variables.empty?
- %p.settings-message.text-center.append-bottom-0
- No variables found, add one with the form above.
- - else
- = render "table"
diff --git a/app/views/projects/variables/show.html.haml b/app/views/projects/variables/show.html.haml
index 297a53ca98..ca284b84d3 100644
--- a/app/views/projects/variables/show.html.haml
+++ b/app/views/projects/variables/show.html.haml
@@ -1,9 +1,36 @@
- page_title "Variables"
+%h3.page-title
+ Secret Variables
-.row.prepend-top-default.append-bottom-default
- .col-lg-3
- = render "content"
- .col-lg-9
- %h5.prepend-top-0
- Update variable
- = render "form", btn_text: "Save variable"
+%p.light
+ These variables will be set to environment by the runner.
+ %br
+ So you can use them for passwords, secret keys or whatever you want.
+ %br
+ The value of the variable can be visible in build log if explicitly asked to do so.
+
+%hr
+
+
+= nested_form_for @project, url: url_for(controller: 'projects/variables', action: 'update'), html: { class: 'form-horizontal' } do |f|
+ = form_errors(@project)
+
+ = f.fields_for :variables do |variable_form|
+ .form-group
+ = variable_form.label :key, 'Key', class: 'control-label'
+ .col-sm-10
+ = variable_form.text_field :key, class: 'form-control', placeholder: "PROJECT_VARIABLE"
+
+ .form-group
+ = variable_form.label :value, 'Value', class: 'control-label'
+ .col-sm-10
+ = variable_form.text_area :value, class: 'form-control', rows: 2, placeholder: ""
+
+ = variable_form.link_to_remove "Remove this variable", class: 'btn btn-danger pull-right prepend-top-10'
+ %hr
+ %p
+ .clearfix
+ = f.link_to_add "Add a variable", :variables, class: 'btn btn-success pull-right'
+
+ .form-actions
+ = f.submit 'Save changes', class: 'btn btn-save', return_to: request.original_url
diff --git a/app/views/projects/wikis/_header_title.html.haml b/app/views/projects/wikis/_header_title.html.haml
new file mode 100644
index 0000000000..408adc36ca
--- /dev/null
+++ b/app/views/projects/wikis/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, 'Wiki', get_project_wiki_path(@project))
diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml
index aaa15dd3bb..4dd818c7f6 100644
--- a/app/views/projects/wikis/edit.html.haml
+++ b/app/views/projects/wikis/edit.html.haml
@@ -1,4 +1,5 @@
- page_title "Edit", @page.title.capitalize, "Wiki"
+= render "header_title"
= render 'nav'
.top-area
diff --git a/app/views/projects/wikis/empty.html.haml b/app/views/projects/wikis/empty.html.haml
index 7dfa405d06..c7e490c3cd 100644
--- a/app/views/projects/wikis/empty.html.haml
+++ b/app/views/projects/wikis/empty.html.haml
@@ -1,4 +1,5 @@
- page_title "Wiki"
+= render "header_title"
%h3.page-title Empty page
%hr
diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml
index ccceab6155..ba3f2cadc4 100644
--- a/app/views/projects/wikis/git_access.html.haml
+++ b/app/views/projects/wikis/git_access.html.haml
@@ -1,4 +1,5 @@
- page_title "Git Access", "Wiki"
+= render "header_title"
= render 'nav'
.row-content-block
diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml
index 45460ed9f4..dcaddae2b0 100644
--- a/app/views/projects/wikis/history.html.haml
+++ b/app/views/projects/wikis/history.html.haml
@@ -1,4 +1,5 @@
- page_title "History", @page.title.capitalize, "Wiki"
+= render "header_title"
= render 'nav'
.top-area
diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml
index 2f6162fa3c..92b494a513 100644
--- a/app/views/projects/wikis/pages.html.haml
+++ b/app/views/projects/wikis/pages.html.haml
@@ -1,4 +1,5 @@
- page_title "Pages", "Wiki"
+= render "header_title"
= render 'nav'
diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml
index 1cb48a1e85..067fb7f8f5 100644
--- a/app/views/projects/wikis/show.html.haml
+++ b/app/views/projects/wikis/show.html.haml
@@ -1,4 +1,5 @@
- page_title @page.title.capitalize, "Wiki"
+= render "header_title"
= render 'nav'
.top-area
diff --git a/app/views/search/results/_issue.html.haml b/app/views/search/results/_issue.html.haml
index 8f68d6d1b8..640890fbe9 100644
--- a/app/views/search/results/_issue.html.haml
+++ b/app/views/search/results/_issue.html.haml
@@ -7,7 +7,7 @@
- if issue.description.present?
.description.term
= preserve do
- = search_md_sanitize(markdown(truncate(issue.description, length: 200, separator: " "), { project: issue.project, author: issue.author }))
+ = search_md_sanitize(markdown(truncate(issue.description, length: 200, separator: " "), { project: issue.project }))
%span.light
#{issue.project.name_with_namespace}
- if issue.closed?
diff --git a/app/views/search/results/_merge_request.html.haml b/app/views/search/results/_merge_request.html.haml
index 6331c2bd6b..333f653321 100644
--- a/app/views/search/results/_merge_request.html.haml
+++ b/app/views/search/results/_merge_request.html.haml
@@ -6,7 +6,7 @@
- if merge_request.description.present?
.description.term
= preserve do
- = search_md_sanitize(markdown(merge_request.description, { project: merge_request.project, author: merge_request.author }))
+ = search_md_sanitize(markdown(merge_request.description, { project: merge_request.project }))
%span.light
#{merge_request.project.name_with_namespace}
.pull-right
diff --git a/app/views/search/results/_note.html.haml b/app/views/search/results/_note.html.haml
index 8163aff43b..d9400b1d9f 100644
--- a/app/views/search/results/_note.html.haml
+++ b/app/views/search/results/_note.html.haml
@@ -19,4 +19,4 @@
.note-search-result
.term
= preserve do
- = search_md_sanitize(markdown(note.note, {no_header_anchors: true, author: note.author}))
+ = search_md_sanitize(markdown(note.note, {no_header_anchors: true}))
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index 84b3f44c0a..974751d997 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -5,7 +5,7 @@
%a#clone-dropdown.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'}
%span
= default_clone_protocol.upcase
- = icon('caret-down')
+ = icon('angle-down')
%ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown
%li
= ssh_clone_button(project)
diff --git a/app/views/shared/_event_filter.html.haml b/app/views/shared/_event_filter.html.haml
index 3005500221..c38d9313db 100644
--- a/app/views/shared/_event_filter.html.haml
+++ b/app/views/shared/_event_filter.html.haml
@@ -1,7 +1,5 @@
-%ul.nav-links.event-filter.scrolling-tabs
- .fade-left
+%ul.nav-links.event-filter
= event_filter_link EventFilter.push, 'Push events'
= event_filter_link EventFilter.merged, 'Merge events'
= event_filter_link EventFilter.comments, 'Comments'
= event_filter_link EventFilter.team, 'Team'
- .fade-right
diff --git a/app/views/shared/_sort_dropdown.html.haml b/app/views/shared/_sort_dropdown.html.haml
index 1e0f075b30..d327bd0a96 100644
--- a/app/views/shared/_sort_dropdown.html.haml
+++ b/app/views/shared/_sort_dropdown.html.haml
@@ -6,7 +6,7 @@
- else
= sort_title_recently_created
%b.caret
- %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort
+ %ul.dropdown-menu.dropdown-menu-align-right
%li
= link_to page_filter_path(sort: sort_value_recently_created) do
= sort_title_recently_created
diff --git a/app/views/shared/groups/_list.html.haml b/app/views/shared/groups/_list.html.haml
index 427595c47a..1aa7ed1f2e 100644
--- a/app/views/shared/groups/_list.html.haml
+++ b/app/views/shared/groups/_list.html.haml
@@ -3,4 +3,4 @@
- groups.each_with_index do |group, i|
= render "shared/groups/group", group: group
- else
- .nothing-here-block No groups found
+ %h3 No groups found
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
index cedff4af2e..9474462cbd 100644
--- a/app/views/shared/issuable/_filter.html.haml
+++ b/app/views/shared/issuable/_filter.html.haml
@@ -1,8 +1,6 @@
.issues-filters
.issues-details-filters.row-content-block.second-block
- = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name, :issue_search]), method: :get, class: 'filter-form js-filter-form' do
- - if params[:issue_search].present?
- = hidden_field_tag :issue_search, params[:issue_search]
+ = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name]), method: :get, class: 'filter-form' do
- if controller.controller_name == 'issues' && can?(current_user, :admin_issue, @project)
.check-all-holder
= check_box_tag "check_all_issues", nil, false,
@@ -12,7 +10,7 @@
- if params[:author_id].present?
= hidden_field_tag(:author_id, params[:author_id])
= dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit",
- placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author], field_name: "author_id", default_label: "Author" } })
+ placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: "author_id", default_label: "Author" } })
.filter-item.inline
- if params[:assignee_id].present?
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index b430251dbf..5c52cc6d1d 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -44,53 +44,45 @@
This issue is confidential and should only be visible to team members
- if can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project)
- - has_due_date = issuable.has_attribute?(:due_date)
%hr
- .row
- %div{ class: (has_due_date ? "col-lg-6" : "col-sm-12") }
- .form-group.issue-assignee
- = f.label :assignee_id, "Assignee", class: "control-label #{"col-lg-4" if has_due_date}"
- .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .form-group
+ .issue-assignee
+ = f.label :assignee_id, "Assignee", class: 'control-label'
+ .col-sm-10
+ .issuable-form-select-holder
+ = users_select_tag("#{issuable.class.model_name.param_key}[assignee_id]",
+ placeholder: 'Select assignee', class: 'custom-form-control', null_user: true,
+ selected: issuable.assignee_id, project: @target_project || @project,
+ first_user: true, current_user: true, include_blank: true)
+
+ = link_to 'Assign to me', '#', class: 'btn assign-to-me-link'
+ .form-group
+ .issue-milestone
+ = f.label :milestone_id, "Milestone", class: 'control-label'
+ .col-sm-10
+ - if milestone_options(issuable).present?
.issuable-form-select-holder
- = users_select_tag("#{issuable.class.model_name.param_key}[assignee_id]",
- placeholder: 'Select assignee', class: 'custom-form-control', null_user: true,
- selected: issuable.assignee_id, project: @target_project || @project,
- first_user: true, current_user: true, include_blank: true)
- %div
- = link_to 'Assign to me', '#', class: 'assign-to-me-link prepend-top-5 inline'
- .form-group.issue-milestone
- = f.label :milestone_id, "Milestone", class: "control-label #{"col-lg-4" if has_due_date}"
- .col-sm-10{ class: ("col-lg-8" if has_due_date) }
- - if milestone_options(issuable).present?
- .issuable-form-select-holder
- = f.select(:milestone_id, milestone_options(issuable),
- { include_blank: true }, { class: 'select2', data: { placeholder: 'Select milestone' } })
- - else
- .prepend-top-10
- %span.light No open milestones available.
- - if can? current_user, :admin_milestone, issuable.project
- %div
- = link_to 'Create new milestone', new_namespace_project_milestone_path(issuable.project.namespace, issuable.project), target: :blank, class: "prepend-top-5 inline"
- .form-group
- - has_labels = issuable.project.labels.any?
- = f.label :label_ids, "Labels", class: "control-label #{"col-lg-4" if has_due_date}"
- .col-sm-10{ class: "#{"col-lg-8" if has_due_date} #{'issuable-form-padding-top' if !has_labels}" }
- - if has_labels
- .issuable-form-select-holder
- = f.collection_select :label_ids, issuable.project.labels.all, :id, :name,
- { selected: issuable.label_ids }, multiple: true, class: 'select2', data: { placeholder: "Select labels" }
- - else
- %span.light No labels yet.
- - if can? current_user, :admin_label, issuable.project
- %div
- = link_to 'Create new label', new_namespace_project_label_path(issuable.project.namespace, issuable.project), target: :blank, class: "prepend-top-5 inline"
- - if has_due_date
- .col-lg-6
- .form-group
- = f.label :due_date, "Due date", class: "control-label"
- = f.hidden_field :due_date, id: "issuable-due-date"
- .col-sm-10
- .datepicker
+ = f.select(:milestone_id, milestone_options(issuable),
+ { include_blank: true }, { class: 'select2', data: { placeholder: 'Select milestone' } })
+ - else
+ .prepend-top-10
+ %span.light No open milestones available.
+
+ - if can? current_user, :admin_milestone, issuable.project
+ = link_to 'Create new milestone', new_namespace_project_milestone_path(issuable.project.namespace, issuable.project), target: :blank
+ .form-group
+ - has_labels = issuable.project.labels.any?
+ = f.label :label_ids, "Labels", class: 'control-label'
+ .col-sm-10{ class: ('issuable-form-padding-top' if !has_labels) }
+ - if has_labels
+ .issuable-form-select-holder
+ = f.collection_select :label_ids, issuable.project.labels.all, :id, :name,
+ { selected: issuable.label_ids }, multiple: true, class: 'select2', data: { placeholder: "Select labels" }
+ - else
+ %span.light No labels yet.
+
+ - if can? current_user, :admin_label, issuable.project
+ = link_to 'Create new label', new_namespace_project_label_path(issuable.project.namespace, issuable.project), target: :blank
- if issuable.can_move?(current_user)
%hr
@@ -98,7 +90,9 @@
= label_tag :move_to_project_id, 'Move', class: 'control-label'
.col-sm-10
.issuable-form-select-holder
- = hidden_field_tag :move_to_project_id, nil, class: 'js-move-dropdown', data: { placeholder: 'Select project', projects_url: autocomplete_projects_path(project_id: @project.id) }
+ - projects = project_options(issuable, current_user, ability: :admin_issue)
+ = select_tag(:move_to_project_id, projects, include_blank: true,
+ class: 'select2', data: { placeholder: 'Select project' })
%span{ data: { toggle: 'tooltip', placement: 'auto top' }, style: 'cursor: default',
title: 'Moving an issue will copy the discussion to a different project and close it here. All participants will be notified of the new location.' }
@@ -120,13 +114,6 @@
- if @merge_request.new_record?
= link_to 'Change branches', mr_change_branches_path(@merge_request)
- - if @merge_request.can_remove_source_branch?(current_user)
- .form-group
- .col-sm-10.col-sm-offset-2
- .checkbox
- = label_tag 'merge_request[force_remove_source_branch]' do
- = check_box_tag 'merge_request[force_remove_source_branch]', '1', @merge_request.force_remove_source_branch?
- Remove source branch when merge request is accepted.
- is_footer = !(issuable.is_a?(MergeRequest) && issuable.new_record?)
.row-content-block{class: (is_footer ? "footer-block" : "middle-block")}
diff --git a/app/views/shared/issuable/_search_form.html.haml b/app/views/shared/issuable/_search_form.html.haml
index 186963b32b..afad48499b 100644
--- a/app/views/shared/issuable/_search_form.html.haml
+++ b/app/views/shared/issuable/_search_form.html.haml
@@ -1,2 +1,8 @@
= form_tag(path, method: :get, id: "issue_search_form", class: 'issue-search-form') do
= search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by name ...', class: 'form-control issue_search search-text-input input-short', spellcheck: false }
+ = hidden_field_tag :state, params['state']
+ = hidden_field_tag :scope, params['scope']
+ = hidden_field_tag :assignee_id, params['assignee_id']
+ = hidden_field_tag :author_id, params['author_id']
+ = hidden_field_tag :milestone_id, params['milestone_id']
+ = hidden_field_tag :label_id, params['label_id']
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index d6552ae7f1..ed1b8a8da2 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -87,16 +87,10 @@
- if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
= link_to 'Edit', '#', class: 'edit-link pull-right'
.value.bold.hide-collapsed
- %span.value-content
- - if issuable.due_date
- = issuable.due_date.to_s(:medium)
- - else
- None
- - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
- %span.light.js-remove-due-date-holder{ class: ("hidden" if issuable.due_date.nil?) }
- \-
- %a.js-remove-due-date{ href: "#", role: "button" }
- remove due date
+ - if issuable.due_date
+ = issuable.due_date.to_s(:medium)
+ - else
+ .light None
- if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
.selectbox.hide-collapsed
= f.hidden_field :due_date, value: issuable.due_date
@@ -114,20 +108,20 @@
.sidebar-collapsed-icon
= icon('tags')
%span
- = issuable.labels_array.size
+ = issuable.labels.count
.title.hide-collapsed
Labels
= icon('spinner spin', class: 'block-loading')
- if can_edit_issuable
= link_to 'Edit', '#', class: 'edit-link pull-right'
- .value.bold.issuable-show-labels.hide-collapsed{ class: ("has-labels" if issuable.labels_array.any?) }
- - if issuable.labels_array.any?
- - issuable.labels_array.each do |label|
+ .value.bold.issuable-show-labels.hide-collapsed{ class: ("has-labels" if issuable.labels.any?) }
+ - if issuable.labels.any?
+ - issuable.labels.each do |label|
= link_to_label(label, type: issuable.to_ability_name)
- else
.light None
.selectbox.hide-collapsed
- - issuable.labels_array.each do |label|
+ - issuable.labels.each do |label|
= hidden_field_tag "#{issuable.to_ability_name}[label_names][]", label.id, id: nil
.dropdown
%button.dropdown-menu-toggle.js-label-select.js-multiselect{type: "button", data: {toggle: "dropdown", field_name: "#{issuable.to_ability_name}[label_names][]", ability_name: issuable.to_ability_name, show_no: "true", show_any: "true", project_id: (@project.id if @project), issue_update: issuable_json_path(issuable), labels: (namespace_project_labels_path(@project.namespace, @project, :json) if @project)}}
diff --git a/app/views/shared/milestones/_participants_tab.html.haml b/app/views/shared/milestones/_participants_tab.html.haml
index 549d2e2f61..67ae85ac27 100644
--- a/app/views/shared/milestones/_participants_tab.html.haml
+++ b/app/views/shared/milestones/_participants_tab.html.haml
@@ -3,6 +3,6 @@
%li
= link_to user, title: user.name, class: "darken" do
= image_tag avatar_icon(user, 32), class: "avatar s32"
- %strong= truncate(user.name, length: 40)
+ %strong= truncate(user.name, lenght: 40)
%br
%small.cgray= user.username
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index b8b66d08db..ab8b022411 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -12,9 +12,12 @@
%li.project-row{ class: css_class }
= cache(cache_key) do
.controls
+ - if project.main_language
+ %span
+ = project.main_language
- if project.commit.try(:status)
%span
- = render_commit_status(project.commit)
+ = render_ci_status(project.commit)
- if forks
%span
= icon('code-fork')
diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml
index af75349626..e65b181487 100644
--- a/app/views/shared/snippets/_header.html.haml
+++ b/app/views/shared/snippets/_header.html.haml
@@ -1,24 +1,25 @@
-.detail-page-header.clearfix
- .snippet-box.has-tooltip.inline.append-right-5{ title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: "body" } }
- %span.sr-only
- = visibility_level_label(@snippet.visibility_level)
+.detail-page-header
+ .snippet-box.has-tooltip{class: visibility_level_color(@snippet.visibility_level), title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: 'body' }}
= visibility_level_icon(@snippet.visibility_level, fw: false)
- %strong.item-title
- Snippet #{@snippet.to_reference}
+ = visibility_level_label(@snippet.visibility_level)
+ %span.identifier
+ Snippet ##{@snippet.id}
%span.creator
- created by #{link_to_member(@project, @snippet.author, size: 24, author_class: "author item-title")}
+ · created by #{link_to_member(@project, @snippet.author, size: 24)}
+ ·
= time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago')
- if @snippet.updated_at != @snippet.created_at
%span
+ ·
= icon('edit', title: 'edited')
= time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago')
- .snippet-actions
+ .pull-right
- if @snippet.project_id?
= render "projects/snippets/actions"
- else
= render "snippets/actions"
-.content-block.second-block
- %h2.snippet-title.prepend-top-0.append-bottom-0
- = markdown escape_once(@snippet.title), pipeline: :single_line, author: @snippet.author
+.detail-page-description.row-content-block.second-block
+ %h2.title
+ = markdown escape_once(@snippet.title), pipeline: :single_line
diff --git a/app/views/snippets/_actions.html.haml b/app/views/snippets/_actions.html.haml
index a7769654b6..1979ae6d5b 100644
--- a/app/views/snippets/_actions.html.haml
+++ b/app/views/snippets/_actions.html.haml
@@ -1,27 +1,11 @@
-.hidden-xs
- = link_to new_snippet_path, class: "btn btn-grouped btn-create new-snippet-link", title: "New Snippet" do
- = icon('plus')
- New Snippet
- - if can?(current_user, :update_personal_snippet, @snippet)
- = link_to edit_snippet_path(@snippet), class: "btn btn-grouped snippable-edit" do
- Edit
- - if can?(current_user, :admin_personal_snippet, @snippet)
- = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-warning", title: 'Delete Snippet' do
- Delete
-.visible-xs-block.dropdown
- %button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
- Options
- %span.caret
- .dropdown-menu.dropdown-menu-full-width
- %ul
- %li
- = link_to new_snippet_path, title: "New Snippet" do
- New Snippet
- - if can?(current_user, :update_personal_snippet, @snippet)
- %li
- = link_to edit_snippet_path(@snippet) do
- Edit
- - if can?(current_user, :admin_personal_snippet, @snippet)
- %li
- = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do
- Delete
+= link_to new_snippet_path, class: 'btn btn-grouped new-snippet-link', title: "New Snippet" do
+ = icon('plus')
+ New Snippet
+- if can?(current_user, :update_personal_snippet, @snippet)
+ = link_to edit_snippet_path(@snippet), class: "btn btn-grouped snippable-edit" do
+ = icon('pencil-square-o')
+ Edit
+- if can?(current_user, :admin_personal_snippet, @snippet)
+ = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-remove", title: 'Delete Snippet' do
+ = icon('trash-o')
+ Delete
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index ed3992650d..a2b3656877 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -3,10 +3,11 @@
.snippet-holder
= render 'shared/snippets/header'
- %article.file-holder.file-holder-no-border.snippet-file-content
- .file-title.file-title-clear
+ %article.file-holder
+ .file-title
= blob_icon 0, @snippet.file_name
- = @snippet.file_name
+ %strong
+ = @snippet.file_name
.file-actions.hidden-xs
= clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']")
= link_to 'Raw', raw_snippet_path(@snippet), class: "btn btn-sm", target: "_blank"
diff --git a/app/views/users/calendar.html.haml b/app/views/users/calendar.html.haml
index 77f2ddefb1..1de71f37d1 100644
--- a/app/views/users/calendar.html.haml
+++ b/app/views/users/calendar.html.haml
@@ -1,9 +1,10 @@
-.clearfix.calendar
- .js-contrib-calendar
- .calendar-hint
- Summary of issues, merge requests, and push events
-:javascript
- new Calendar(
- #{@timestamps.to_json},
- '#{user_calendar_activities_path}'
- );
+#cal-heatmap.calendar
+ :javascript
+ new Calendar(
+ #{@timestamps.to_json},
+ #{@starting_year},
+ #{@starting_month},
+ '#{user_calendar_activities_path}'
+ );
+
+.calendar-hint Summary of issues, merge requests, and push events
diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml
index 630d97e339..027a93a75f 100644
--- a/app/views/users/calendar_activities.html.haml
+++ b/app/views/users/calendar_activities.html.haml
@@ -1,27 +1,23 @@
%h4.prepend-top-20
- Contributions for
+ %span.light Contributions for
%strong #{@calendar_date.to_s(:short)}
-- if @events.any?
- %ul.bordered-list
- - @events.sort_by(&:created_at).each do |event|
- %li
- %span.light
- %i.fa.fa-clock-o
- = event.created_at.to_s(:time)
- - if event.push?
- #{event.action_name} #{event.ref_type} #{event.ref_name}
- - else
- = event_action_name(event)
- - if event.target
- %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target]
+%ul.bordered-list
+ - @events.sort_by(&:created_at).each do |event|
+ %li
+ %span.light
+ %i.fa.fa-clock-o
+ = event.created_at.to_s(:time)
+ - if event.push?
+ #{event.action_name} #{event.ref_type} #{event.ref_name}
+ - else
+ = event_action_name(event)
+ - if event.target
+ %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target]
- at
- %strong
- - if event.project
- = link_to_project event.project
- - else
- = event.project_name
-- else
- %p
- No contributions found for #{@calendar_date.to_s(:short)}
+ at
+ %strong
+ - if event.project
+ = link_to_project event.project
+ - else
+ = event.project_name
diff --git a/app/views/users/show.atom.builder b/app/views/users/show.atom.builder
index 6c85e5f9fb..e9e466c635 100644
--- a/app/views/users/show.atom.builder
+++ b/app/views/users/show.atom.builder
@@ -6,5 +6,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id user_url(@user)
xml.updated @events[0].updated_at.xmlschema if @events[0]
- xml << render(@events) if @events.any?
+ @events.each do |event|
+ event_to_atom(xml, event)
+ end
end
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 8268380daf..3c0b89c674 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -1,6 +1,5 @@
- page_title @user.name
- page_description @user.bio
-- page_specific_javascripts asset_path("users/application.js")
- header_title @user.name, user_path(@user)
- @no_container = true
@@ -82,17 +81,15 @@
%li.projects-tab
= link_to user_projects_path, data: {target: 'div#projects', action: 'projects', toggle: 'tab'} do
Personal projects
- %li.snippets-tab
- = link_to user_snippets_path, data: {target: 'div#snippets', action: 'snippets', toggle: 'tab'} do
- Snippets
%div{ class: container_class }
.tab-content
#activity.tab-pane
.row-content-block.calender-block.white.second-block.hidden-xs
- .user-calendar{data: {href: user_calendar_path}}
- %h4.center.light
- %i.fa.fa-spinner.fa-spin
+ %div{ class: container_class }
+ .user-calendar{data: {href: user_calendar_path}}
+ %h4.center.light
+ %i.fa.fa-spinner.fa-spin
.user-calendar-activities
.content_list{ data: {href: user_path} }
@@ -107,9 +104,6 @@
#projects.tab-pane
- # This tab is always loaded via AJAX
- #snippets.tab-pane
- - # This tab is always loaded via AJAX
-
.loading-status
= spinner
diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb
index 971f969e25..c4d8595d45 100644
--- a/app/workers/emails_on_push_worker.rb
+++ b/app/workers/emails_on_push_worker.rb
@@ -1,9 +1,6 @@
class EmailsOnPushWorker
include Sidekiq::Worker
- sidekiq_options queue: :mailers
- attr_reader :email, :skip_premailer
-
def perform(project_id, recipients, push_data, options = {})
options.symbolize_keys!
options.reverse_merge!(
@@ -28,18 +25,15 @@ class EmailsOnPushWorker
:push
end
- diff_refs = nil
compare = nil
reverse_compare = false
if action == :push
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha)
- diff_refs = [project.merge_base_commit(before_sha, after_sha), project.commit(after_sha)]
return false if compare.same
if compare.commits.empty?
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, after_sha, before_sha)
- diff_refs = [project.merge_base_commit(after_sha, before_sha), project.commit(before_sha)]
reverse_compare = true
@@ -47,42 +41,26 @@ class EmailsOnPushWorker
end
end
- recipients.split.each do |recipient|
+ recipients.split(" ").each do |recipient|
begin
- send_email(
- recipient,
+ Notify.repository_push_email(
project_id,
- author_id: author_id,
- ref: ref,
- action: action,
- compare: compare,
- reverse_compare: reverse_compare,
- diff_refs: diff_refs,
- send_from_committer_email: send_from_committer_email,
- disable_diffs: disable_diffs
- )
-
+ recipient,
+ author_id: author_id,
+ ref: ref,
+ action: action,
+ compare: compare,
+ reverse_compare: reverse_compare,
+ send_from_committer_email: send_from_committer_email,
+ disable_diffs: disable_diffs
+ ).deliver_now
# These are input errors and won't be corrected even if Sidekiq retries
rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e
logger.info("Failed to send e-mail for project '#{project.name_with_namespace}' to #{recipient}: #{e}")
end
end
ensure
- @email = nil
compare = nil
GC.start
end
-
- private
-
- def send_email(recipient, project_id, options)
- # Generating the body of this email can be expensive, so only do it once
- @skip_premailer ||= email.present?
- @email ||= Notify.repository_push_email(project_id, options)
-
- email.to = recipient
- email.add_message_id
- email.header[:skip_premailer] = true if skip_premailer
- email.deliver_now
- end
end
diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb
index d947f10551..f9e3233798 100644
--- a/app/workers/repository_fork_worker.rb
+++ b/app/workers/repository_fork_worker.rb
@@ -15,7 +15,8 @@ class RepositoryForkWorker
result = gitlab_shell.fork_repository(source_path, target_path)
unless result
logger.error("Unable to fork project #{project_id} for repository #{source_path} -> #{target_path}")
- project.mark_import_as_failed('The project could not be forked.')
+ project.update(import_error: "The project could not be forked.")
+ project.import_fail
return
end
@@ -23,7 +24,8 @@ class RepositoryForkWorker
unless project.valid_repo?
logger.error("Project #{project_id} had an invalid repository after fork")
- project.mark_import_as_failed('The forked repository is invalid.')
+ project.update(import_error: "The forked repository is invalid.")
+ project.import_fail
return
end
diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb
index 7d819fe78f..2937493c61 100644
--- a/app/workers/repository_import_worker.rb
+++ b/app/workers/repository_import_worker.rb
@@ -13,7 +13,8 @@ class RepositoryImportWorker
result = Projects::ImportService.new(project, current_user).execute
if result[:status] == :error
- project.mark_import_as_failed(result[:message])
+ project.update(import_error: result[:message])
+ project.import_fail
return
end
diff --git a/config/application.rb b/config/application.rb
index 49d4d3ba55..b602e2b616 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -1,32 +1,23 @@
require File.expand_path('../boot', __FILE__)
require 'rails/all'
-
+require 'devise'
+I18n.config.enforce_available_locales = false
Bundler.require(:default, Rails.env)
+require_relative '../lib/gitlab/redis'
module Gitlab
class Application < Rails::Application
- require_dependency Rails.root.join('lib/gitlab/redis')
-
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
- # Sidekiq uses eager loading, but directories not in the standard Rails
- # directories must be added to the eager load paths:
- # https://github.com/mperham/sidekiq/wiki/FAQ#why-doesnt-sidekiq-autoload-my-rails-application-code
- # Also, there is no need to add `lib` to autoload_paths since autoloading is
- # configured to check for eager loaded paths:
- # https://github.com/rails/rails/blob/v4.2.6/railties/lib/rails/engine.rb#L687
- # This is a nice reference article on autoloading/eager loading:
- # http://blog.arkency.com/2014/11/dont-forget-about-eager-load-when-extending-autoload
- config.eager_load_paths.push(*%W(#{config.root}/lib
- #{config.root}/app/models/ci
- #{config.root}/app/models/hooks
- #{config.root}/app/models/members
- #{config.root}/app/models/project_services))
-
- config.generators.templates.push("#{config.root}/generator_templates")
+ # Custom directories with classes and modules you want to be autoloadable.
+ config.autoload_paths.push(*%W(#{config.root}/lib
+ #{config.root}/app/models/hooks
+ #{config.root}/app/models/concerns
+ #{config.root}/app/models/project_services
+ #{config.root}/app/models/members))
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
@@ -41,7 +32,7 @@ module Gitlab
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
- #
+ #
# Parameters filtered:
# - Password (:password, :password_confirmation)
# - Private tokens (:private_token)
@@ -80,9 +71,6 @@ module Gitlab
config.assets.precompile << "*.png"
config.assets.precompile << "print.css"
config.assets.precompile << "notify.css"
- config.assets.precompile << "mailers/*.css"
- config.assets.precompile << "graphs/application.js"
- config.assets.precompile << "users/application.js"
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
diff --git a/config/boot.rb b/config/boot.rb
index f2830ae316..4489e58688 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -3,4 +3,4 @@ require 'rubygems'
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
-require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
+require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 8cca0039b4..4f39016bfa 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -39,7 +39,6 @@ Rails.application.configure do
config.action_mailer.delivery_method = :letter_opener_web
# Don't make a mess when bootstrapping a development environment
config.action_mailer.perform_deliveries = (ENV['BOOTSTRAP'] != '1')
- config.action_mailer.preview_path = 'spec/mailers/previews'
config.eager_load = false
end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index fb25d3a8b1..a703c0934f 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -20,7 +20,7 @@ Rails.application.configure do
config.action_dispatch.show_exceptions = false
# Disable request forgery protection in test environment
- config.action_controller.allow_forgery_protection = false
+ config.action_controller.allow_forgery_protection = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 0510e7df59..e682bcb976 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -98,7 +98,6 @@ production: &base
wiki: true
snippets: false
builds: true
- container_registry: true
## Webhook settings
# Number of seconds to wait for HTTP response after sending webhook HTTP POST request (default: 10)
@@ -176,15 +175,6 @@ production: &base
repository_archive_cache_worker:
cron: "0 * * * *"
- registry:
- # enabled: true
- # host: registry.example.com
- # port: 5005
- # api_url: http://localhost:5000/ # internal address to the registry, will be used by GitLab to directly communicate with API
- # key_path: config/registry.key
- # path: shared/registry
- # issuer: gitlab-issuer
-
#
# 2. GitLab CI settings
# ==========================
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 436751b9d1..8db2c05fe4 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -1,4 +1,4 @@
-require_dependency Rails.root.join('lib/gitlab') # Load Gitlab as soon as possible
+require 'gitlab' # Load lib/gitlab.rb as soon as possible
class Settings < Settingslogic
source ENV.fetch('GITLAB_CONFIG') { "#{Rails.root}/config/gitlab.yml" }
@@ -52,7 +52,7 @@ class Settings < Settingslogic
# check that values in `current` (string or integer) is a contant in `modul`.
def verify_constant_array(modul, current, default)
values = default || []
- unless current.nil?
+ if !current.nil?
values = []
current.each do |constant|
values.push(verify_constant(modul, constant, nil))
@@ -126,7 +126,7 @@ end
Settings['omniauth'] ||= Settingslogic.new({})
-Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil?
+Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil?
Settings.omniauth['auto_sign_in_with_provider'] = false if Settings.omniauth['auto_sign_in_with_provider'].nil?
Settings.omniauth['allow_single_sign_on'] = false if Settings.omniauth['allow_single_sign_on'].nil?
Settings.omniauth['external_providers'] = [] if Settings.omniauth['external_providers'].nil?
@@ -134,7 +134,7 @@ Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block
Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil?
Settings.omniauth['auto_link_saml_user'] = false if Settings.omniauth['auto_link_saml_user'].nil?
-Settings.omniauth['providers'] ||= []
+Settings.omniauth['providers'] ||= []
Settings.omniauth['cas3'] ||= Settingslogic.new({})
Settings.omniauth.cas3['session_duration'] ||= 8.hours
Settings.omniauth['session_tickets'] ||= Settingslogic.new({})
@@ -168,7 +168,7 @@ end
Settings['shared'] ||= Settingslogic.new({})
Settings.shared['path'] = File.expand_path(Settings.shared['path'] || "shared", Rails.root)
-Settings['issues_tracker'] ||= {}
+Settings['issues_tracker'] ||= {}
#
# GitLab
@@ -183,7 +183,7 @@ Settings.gitlab['ssh_host'] ||= Settings.gitlab.host
Settings.gitlab['https'] = false if Settings.gitlab['https'].nil?
Settings.gitlab['port'] ||= Settings.gitlab.https ? 443 : 80
Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || ''
-Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http"
+Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http"
Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].nil?
Settings.gitlab['email_from'] ||= ENV['GITLAB_EMAIL_FROM'] || "gitlab@#{Settings.gitlab.host}"
Settings.gitlab['email_display_name'] ||= ENV['GITLAB_EMAIL_DISPLAY_NAME'] || 'GitLab'
@@ -196,7 +196,7 @@ Settings.gitlab['user_home'] ||= begin
rescue ArgumentError # no user configured
'/home/' + Settings.gitlab['user']
end
-Settings.gitlab['time_zone'] ||= nil
+Settings.gitlab['time_zone'] ||= nil
Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil?
Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil?
Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
@@ -206,13 +206,12 @@ Settings.gitlab['default_projects_features'] ||= {}
Settings.gitlab['webhook_timeout'] ||= 10
Settings.gitlab['max_attachment_size'] ||= 10
Settings.gitlab['session_expire_delay'] ||= 10080
-Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil?
-Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil?
-Settings.gitlab.default_projects_features['wiki'] = true if Settings.gitlab.default_projects_features['wiki'].nil?
-Settings.gitlab.default_projects_features['snippets'] = false if Settings.gitlab.default_projects_features['snippets'].nil?
-Settings.gitlab.default_projects_features['builds'] = true if Settings.gitlab.default_projects_features['builds'].nil?
-Settings.gitlab.default_projects_features['container_registry'] = true if Settings.gitlab.default_projects_features['container_registry'].nil?
-Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE)
+Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil?
+Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil?
+Settings.gitlab.default_projects_features['wiki'] = true if Settings.gitlab.default_projects_features['wiki'].nil?
+Settings.gitlab.default_projects_features['snippets'] = false if Settings.gitlab.default_projects_features['snippets'].nil?
+Settings.gitlab.default_projects_features['builds'] = true if Settings.gitlab.default_projects_features['builds'].nil?
+Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE)
Settings.gitlab['repository_downloads_path'] = File.join(Settings.shared['path'], 'cache/archive') if Settings.gitlab['repository_downloads_path'].nil?
Settings.gitlab['restricted_signup_domains'] ||= []
Settings.gitlab['import_sources'] ||= ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git']
@@ -226,8 +225,8 @@ Settings['gitlab_ci'] ||= Settingslogic.new({})
Settings.gitlab_ci['shared_runners_enabled'] = true if Settings.gitlab_ci['shared_runners_enabled'].nil?
Settings.gitlab_ci['all_broken_builds'] = true if Settings.gitlab_ci['all_broken_builds'].nil?
Settings.gitlab_ci['add_pusher'] = false if Settings.gitlab_ci['add_pusher'].nil?
+Settings.gitlab_ci['url'] ||= Settings.send(:build_gitlab_ci_url)
Settings.gitlab_ci['builds_path'] = File.expand_path(Settings.gitlab_ci['builds_path'] || "builds/", Rails.root)
-Settings.gitlab_ci['url'] ||= Settings.send(:build_gitlab_ci_url)
#
# Reply by email
@@ -241,20 +240,7 @@ Settings.incoming_email['enabled'] = false if Settings.incoming_email['enabled']
Settings['artifacts'] ||= Settingslogic.new({})
Settings.artifacts['enabled'] = true if Settings.artifacts['enabled'].nil?
Settings.artifacts['path'] = File.expand_path(Settings.artifacts['path'] || File.join(Settings.shared['path'], "artifacts"), Rails.root)
-Settings.artifacts['max_size'] ||= 100 # in megabytes
-
-#
-# Registry
-#
-Settings['registry'] ||= Settingslogic.new({})
-Settings.registry['enabled'] ||= false
-Settings.registry['host'] ||= "example.com"
-Settings.registry['port'] ||= nil
-Settings.registry['api_url'] ||= "http://localhost:5000/"
-Settings.registry['key'] ||= nil
-Settings.registry['issuer'] ||= nil
-Settings.registry['host_port'] ||= [Settings.registry['host'], Settings.registry['port']].compact.join(':')
-Settings.registry['path'] = File.expand_path(Settings.registry['path'] || File.join(Settings.shared['path'], 'registry'), Rails.root)
+Settings.artifacts['max_size'] ||= 100 # in megabytes
#
# Git LFS
@@ -312,7 +298,7 @@ Settings['backup'] ||= Settingslogic.new({})
Settings.backup['keep_time'] ||= 0
Settings.backup['pg_schema'] = nil
Settings.backup['path'] = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root)
-Settings.backup['archive_permissions'] ||= 0600
+Settings.backup['archive_permissions'] ||= 0600
Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil })
# Convert upload connection settings to use symbol keys, to make Fog happy
if Settings.backup['upload']['connection']
diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
index e026151a03..80d641d73a 100644
--- a/config/initializers/5_backend.rb
+++ b/config/initializers/5_backend.rb
@@ -1,11 +1,11 @@
# GIT over HTTP
-require_dependency Rails.root.join('lib/gitlab/backend/grack_auth')
+require Rails.root.join("lib", "gitlab", "backend", "grack_auth")
# GIT over SSH
-require_dependency Rails.root.join('lib/gitlab/backend/shell')
+require Rails.root.join("lib", "gitlab", "backend", "shell")
# GitLab shell adapter
-require_dependency Rails.root.join('lib/gitlab/backend/shell_adapter')
+require Rails.root.join("lib", "gitlab", "backend", "shell_adapter")
required_version = Gitlab::VersionInfo.parse(Gitlab::Shell.version_required)
current_version = Gitlab::VersionInfo.parse(Gitlab::Shell.new.version)
diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb
index 1933afcbfb..df28d30d75 100644
--- a/config/initializers/carrierwave.rb
+++ b/config/initializers/carrierwave.rb
@@ -2,7 +2,7 @@ CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
aws_file = Rails.root.join('config', 'aws.yml')
-if File.exist?(aws_file)
+if File.exists?(aws_file)
AWS_CONFIG = YAML.load(File.read(aws_file))[Rails.env]
CarrierWave.configure do |config|
@@ -20,7 +20,7 @@ if File.exist?(aws_file)
config.fog_public = false
# optional, defaults to {}
- config.fog_attributes = { 'Cache-Control' => 'max-age=315576000' }
+ config.fog_attributes = { 'Cache-Control'=>'max-age=315576000' }
# optional time (in seconds) that authenticated urls will be valid.
# when fog_public is false and provider is AWS or Google, defaults to 600
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 021bdb1125..31dceaebca 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -243,7 +243,7 @@ Devise.setup do |config|
when Hash
# Add procs for handling SLO
if provider['name'] == 'cas3'
- provider['args'][:on_single_sign_out] = lambda do |request|
+ provider['args'][:on_single_sign_out] = lambda do |request|
ticket = request.params[:session_index]
raise "Service Ticket not found." unless Gitlab::OAuth::Session.valid?(:cas3, ticket)
Gitlab::OAuth::Session.destroy(:cas3, ticket)
diff --git a/config/initializers/devise_async.rb b/config/initializers/devise_async.rb
new file mode 100644
index 0000000000..05a1852cdb
--- /dev/null
+++ b/config/initializers/devise_async.rb
@@ -0,0 +1 @@
+Devise::Async.backend = :sidekiq
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index 7bd1310504..66ac88e9f4 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -52,7 +52,7 @@ Doorkeeper.configure do
# For more information go to
# https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
default_scopes :api
- # optional_scopes :write, :update
+ #optional_scopes :write, :update
# Change the way client credentials are retrieved from the request object.
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
@@ -71,7 +71,7 @@ Doorkeeper.configure do
# The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL
# (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
#
- native_redirect_uri nil # 'urn:ietf:wg:oauth:2.0:oob'
+ native_redirect_uri nil#'urn:ietf:wg:oauth:2.0:oob'
# Specify what grant flows are enabled in array of Strings. The valid
# strings and the flows they enable are:
diff --git a/config/initializers/health_check.rb b/config/initializers/health_check.rb
deleted file mode 100644
index 79e2d23ab2..0000000000
--- a/config/initializers/health_check.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-HealthCheck.setup do |config|
- config.standard_checks = ['database', 'migrations', 'cache']
-end
diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb
index 0c78871471..b2d08d87ba 100644
--- a/config/initializers/metrics.rb
+++ b/config/initializers/metrics.rb
@@ -12,7 +12,6 @@ if Gitlab::Metrics.enabled?
Gitlab::Application.configure do |config|
config.middleware.use(Gitlab::Metrics::RackMiddleware)
- config.middleware.use(Gitlab::Middleware::RailsQueueDuration)
end
Sidekiq.configure_server do |config|
@@ -119,8 +118,6 @@ if Gitlab::Metrics.enabled?
# Instrument the classes used for checking if somebody has push access.
config.instrument_instance_methods(Gitlab::GitAccess)
config.instrument_instance_methods(Gitlab::GitAccessWiki)
-
- config.instrument_instance_methods(API::Helpers)
end
GC::Profiler.enable
diff --git a/config/initializers/monkey_patch.rb b/config/initializers/monkey_patch.rb
new file mode 100644
index 0000000000..62b05a5528
--- /dev/null
+++ b/config/initializers/monkey_patch.rb
@@ -0,0 +1,48 @@
+## This patch is from rails 4.2-stable. Remove it when 4.2.6 is released
+## https://github.com/rails/rails/issues/21108
+
+module ActiveRecord
+ module ConnectionAdapters
+ class AbstractMysqlAdapter < AbstractAdapter
+ # SHOW VARIABLES LIKE 'name'
+ def show_variable(name)
+ variables = select_all("select @@#{name} as 'Value'", 'SCHEMA')
+ variables.first['Value'] unless variables.empty?
+ rescue ActiveRecord::StatementInvalid
+ nil
+ end
+
+
+ # MySQL is too stupid to create a temporary table for use subquery, so we have
+ # to give it some prompting in the form of a subsubquery. Ugh!
+ def subquery_for(key, select)
+ subsubselect = select.clone
+ subsubselect.projections = [key]
+
+ subselect = Arel::SelectManager.new(select.engine)
+ subselect.project Arel.sql(key.name)
+ # Materialized subquery by adding distinct
+ # to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on'
+ subselect.from subsubselect.distinct.as('__active_record_temp')
+ end
+ end
+ end
+end
+
+module ActiveRecord
+ module ConnectionAdapters
+ class MysqlAdapter < AbstractMysqlAdapter
+ ADAPTER_NAME = 'MySQL'.freeze
+
+ # Get the client encoding for this database
+ def client_encoding
+ return @client_encoding if @client_encoding
+
+ result = exec_query(
+ "select @@character_set_client",
+ 'SCHEMA')
+ @client_encoding = ENCODINGS[result.rows.last.last]
+ end
+ end
+ end
+end
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
index 26c30e523a..4c164119ff 100644
--- a/config/initializers/omniauth.rb
+++ b/config/initializers/omniauth.rb
@@ -13,7 +13,7 @@ end
OmniAuth.config.full_host = Settings.gitlab['base_url']
OmniAuth.config.allowed_request_methods = [:post]
-# In case of auto sign-in, the GET method is used (users don't get to click on a button)
+#In case of auto sign-in, the GET method is used (users don't get to click on a button)
OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present?
OmniAuth.config.before_request_phase do |env|
OmniAuth::RequestForgeryProtection.call(env)
diff --git a/config/initializers/premailer.rb b/config/initializers/premailer.rb
index cb00d3cfe9..b9176688bc 100644
--- a/config/initializers/premailer.rb
+++ b/config/initializers/premailer.rb
@@ -3,6 +3,6 @@ Premailer::Rails.config.merge!(
generate_text_part: false,
preserve_styles: true,
remove_comments: true,
- remove_ids: false,
+ remove_ids: true,
remove_scripts: false
)
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index 0d9d87bac0..599dabb9e5 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -23,6 +23,6 @@ else
secure: Gitlab.config.gitlab.https,
httponly: true,
expires_in: Settings.gitlab['session_expire_delay'] * 60,
- path: Rails.application.config.relative_url_root.nil? ? '/' : Gitlab::Application.config.relative_url_root
+ path: (Rails.application.config.relative_url_root.nil?) ? '/' : Gitlab::Application.config.relative_url_root
)
end
diff --git a/config/routes.rb b/config/routes.rb
index 428302d0fd..dafecc9464 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -56,7 +56,6 @@ Rails.application.routes.draw do
# Autocomplete
get '/autocomplete/users' => 'autocomplete#users'
get '/autocomplete/users/:id' => 'autocomplete#user'
- get '/autocomplete/projects' => 'autocomplete#projects'
# Emojis
resources :emojis, only: :index
@@ -65,9 +64,6 @@ Rails.application.routes.draw do
get 'search' => 'search#show'
get 'search/autocomplete' => 'search#autocomplete', as: :search_autocomplete
- # JSON Web Token
- get 'jwt/auth' => 'jwt#auth'
-
# API
API::API.logger Rails.logger
mount API::API => '/api'
@@ -77,9 +73,6 @@ Rails.application.routes.draw do
mount Sidekiq::Web, at: '/admin/sidekiq', as: :sidekiq
end
- # Health check
- get 'health_check(/:checks)' => 'health_check#index', as: :health_check
-
# Enable Grack support
mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\//.match(request.path_info) }, via: [:get, :post, :put]
@@ -87,7 +80,7 @@ Rails.application.routes.draw do
get 'help' => 'help#index'
get 'help/:category/:file' => 'help#show', as: :help_page, constraints: { category: /.*/, file: /[^\/\.]+/ }
get 'help/shortcuts'
- get 'help/ui' => 'help#ui'
+ get 'help/ui' => 'help#ui'
#
# Global snippets
@@ -98,8 +91,7 @@ Rails.application.routes.draw do
end
end
- get '/s/:username', to: redirect('/u/%{username}/snippets'),
- constraints: { username: /[a-zA-Z.0-9_\-]+(? 'snippets#index', as: :user_snippets, constraints: { username: /.*/ }
#
# Invites
@@ -261,7 +253,6 @@ Rails.application.routes.draw do
end
resource :logs, only: [:show]
- resource :health_check, controller: 'health_check', only: [:show]
resource :background_jobs, controller: 'background_jobs', only: [:show]
resources :namespaces, path: '/projects', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do
@@ -293,7 +284,6 @@ Rails.application.routes.draw do
resource :application_settings, only: [:show, :update] do
resources :services
put :reset_runners_token
- put :reset_health_check_token
put :clear_repository_check_states
end
@@ -352,18 +342,23 @@ Rails.application.routes.draw do
end
end
- scope(path: 'u/:username',
- as: :user,
- constraints: { username: /[a-zA-Z.0-9_\-]+(? 'users#calendar', as: :user_calendar,
+ constraints: { username: /.*/ }
+
+ get 'u/:username/calendar_activities' => 'users#calendar_activities', as: :user_calendar_activities,
+ constraints: { username: /.*/ }
+
+ get 'u/:username/groups' => 'users#groups', as: :user_groups,
+ constraints: { username: /.*/ }
+
+ get 'u/:username/projects' => 'users#projects', as: :user_projects,
+ constraints: { username: /.*/ }
+
+ get 'u/:username/contributed' => 'users#contributed', as: :user_contributed_projects,
+ constraints: { username: /.*/ }
+
+ get '/u/:username' => 'users#show', as: :user,
+ constraints: { username: /[a-zA-Z.0-9_\-]+(? 'omniauth_callbacks#omniauth_error', as: :omniauth_error
@@ -668,16 +659,9 @@ Rails.application.routes.draw do
end
resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
- resources :variables, only: [:index, :show, :update, :create, :destroy]
+ resource :variables, only: [:show, :update]
resources :triggers, only: [:index, :create, :destroy]
- resources :pipelines, only: [:index, :new, :create, :show] do
- member do
- post :cancel
- post :retry
- end
- end
-
resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do
collection do
post :cancel_all
@@ -688,7 +672,6 @@ Rails.application.routes.draw do
post :cancel
post :retry
post :erase
- get :trace
get :raw
end
@@ -705,8 +688,6 @@ Rails.application.routes.draw do
end
end
- resources :container_registry, only: [:index, :destroy], constraints: { id: Gitlab::Regex.container_registry_reference_regex }
-
resources :milestones, constraints: { id: /\d+/ } do
member do
put :sort_issues
@@ -793,7 +774,7 @@ Rails.application.routes.draw do
end
# Get all keys of user
- get ':username.keys' => 'profiles/keys#get_keys', constraints: { username: /.*/ }
+ get ':username.keys' => 'profiles/keys#get_keys' , constraints: { username: /.*/ }
get ':id' => 'namespaces#show', constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
end
diff --git a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
index 6aed0fe03d..8a351cf27a 100644
--- a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
+++ b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
@@ -24,11 +24,11 @@ class RemoveWrongImportUrlFromProjects < ActiveRecord::Migration
def process_projects_with_wrong_url
projects_with_wrong_import_url.each do |project|
begin
- import_url = Gitlab::UrlSanitizer.new(project["import_url"])
+ import_url = Gitlab::ImportUrl.new(project["import_url"])
update_import_url(import_url, project)
update_import_data(import_url, project)
- rescue Addressable::URI::InvalidURIError
+ rescue URI::InvalidURIError
nullify_import_url(project)
end
end
diff --git a/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb b/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb
index 72b862d67d..75de5f70fa 100644
--- a/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb
+++ b/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb
@@ -7,9 +7,7 @@ class AddDefaultGroupVisibilityToApplicationSettings < ActiveRecord::Migration
add_column :application_settings, :default_group_visibility, :integer
# Unfortunately, this can't be a `default`, since we don't want the configuration specific
# `allowed_visibility_level` to end up in schema.rb
-
- visibility_level = allowed_visibility_level || Gitlab::VisibilityLevel::PRIVATE
- execute("UPDATE application_settings SET default_group_visibility = #{visibility_level}")
+ execute("UPDATE application_settings SET default_group_visibility = #{allowed_visibility_level}")
end
def down
diff --git a/db/migrate/20160407120251_add_images_enabled_for_project.rb b/db/migrate/20160407120251_add_images_enabled_for_project.rb
deleted file mode 100644
index 47f0ca8e8d..0000000000
--- a/db/migrate/20160407120251_add_images_enabled_for_project.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddImagesEnabledForProject < ActiveRecord::Migration
- def change
- add_column :projects, :container_registry_enabled, :boolean
- end
-end
diff --git a/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb b/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb
deleted file mode 100644
index facd33875b..0000000000
--- a/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddDisabledOauthSignInSourcesToApplicationSettings < ActiveRecord::Migration
- def change
- add_column :application_settings, :disabled_oauth_sign_in_sources, :text
- end
-end
diff --git a/db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb b/db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb
deleted file mode 100644
index 84e5e4eabe..0000000000
--- a/db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class AddRunUntaggedToCiRunner < ActiveRecord::Migration
- include Gitlab::Database::MigrationHelpers
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:ci_runners, :run_untagged, :boolean,
- default: true, allow_null: false)
- end
-
- def down
- remove_column(:ci_runners, :run_untagged)
- end
-end
diff --git a/db/migrate/20160508215820_add_type_to_notes.rb b/db/migrate/20160508215820_add_type_to_notes.rb
deleted file mode 100644
index 58944d4e65..0000000000
--- a/db/migrate/20160508215820_add_type_to_notes.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddTypeToNotes < ActiveRecord::Migration
- def change
- add_column :notes, :type, :string
- end
-end
diff --git a/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb b/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb
deleted file mode 100644
index c3f23d89d5..0000000000
--- a/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class SetTypeOnLegacyDiffNotes < ActiveRecord::Migration
- def change
- execute "UPDATE notes SET type = 'LegacyDiffNote' WHERE line_code IS NOT NULL"
- end
-end
diff --git a/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb b/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb
deleted file mode 100644
index 9d729fec18..0000000000
--- a/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class AddHealthCheckAccessTokenToApplicationSettings < ActiveRecord::Migration
- def change
- add_column :application_settings, :health_check_access_token, :string
- end
-end
diff --git a/db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb b/db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb
deleted file mode 100644
index c34e7ba540..0000000000
--- a/db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class AddSendUserConfirmationEmailToApplicationSettings < ActiveRecord::Migration
- def up
- add_column :application_settings, :send_user_confirmation_email, :boolean, default: false
-
- #Sets confirmation email to true by default on existing installations.
- execute "UPDATE application_settings SET send_user_confirmation_email=true"
- end
-
- def down
- remove_column :application_settings, :send_user_confirmation_email
- end
-end
diff --git a/db/migrate/20160525205328_remove_main_language_from_projects.rb b/db/migrate/20160525205328_remove_main_language_from_projects.rb
deleted file mode 100644
index 0f9d60c385..0000000000
--- a/db/migrate/20160525205328_remove_main_language_from_projects.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class RemoveMainLanguageFromProjects < ActiveRecord::Migration
- include Gitlab::Database::MigrationHelpers
-
- # When using the methods "add_concurrent_index" or "add_column_with_default"
- # you must disable the use of transactions as these methods can not run in an
- # existing transaction. When using "add_concurrent_index" make sure that this
- # method is the _only_ method called in the migration, any other changes
- # should go in a separate migration. This ensures that upon failure _only_ the
- # index creation fails and can be retried or reverted easily.
- #
- # To disable transactions uncomment the following line and remove these
- # comments:
- # disable_ddl_transaction!
-
- def change
- remove_column :projects, :main_language
- end
-end
diff --git a/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb b/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb
deleted file mode 100644
index 7910120b4e..0000000000
--- a/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class RemoveNotificationSettingsForDeletedProjects < ActiveRecord::Migration
- def up
- execute <<-SQL
- DELETE FROM notification_settings
- WHERE notification_settings.source_type = 'Project'
- AND NOT EXISTS (
- SELECT *
- FROM projects
- WHERE projects.id = notification_settings.source_id
- )
- SQL
- end
-end
diff --git a/db/migrate/20160528043124_add_users_state_index.rb b/db/migrate/20160528043124_add_users_state_index.rb
deleted file mode 100644
index e77a546073..0000000000
--- a/db/migrate/20160528043124_add_users_state_index.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class AddUsersStateIndex < ActiveRecord::Migration
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- def change
- add_concurrent_index :users, :state
- end
-end
diff --git a/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb b/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb
deleted file mode 100644
index e21376bd57..0000000000
--- a/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# This is ONLINE migration
-
-class AddContainerRegistryTokenExpireDelayToApplicationSettings < ActiveRecord::Migration
- include Gitlab::Database::MigrationHelpers
-
- def change
- add_column :application_settings, :container_registry_token_expire_delay, :integer, default: 5
- end
-end
diff --git a/db/schema.rb b/db/schema.rb
index b2af810f60..71d953afe3 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160530150109) do
+ActiveRecord::Schema.define(version: 20160508194200) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -43,47 +43,43 @@ ActiveRecord::Schema.define(version: 20160530150109) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "home_page_url"
- t.integer "default_branch_protection", default: 2
+ t.integer "default_branch_protection", default: 2
t.text "restricted_visibility_levels"
- t.boolean "version_check_enabled", default: true
- t.integer "max_attachment_size", default: 10, null: false
+ t.boolean "version_check_enabled", default: true
+ t.integer "max_attachment_size", default: 10, null: false
t.integer "default_project_visibility"
t.integer "default_snippet_visibility"
t.text "restricted_signup_domains"
- t.boolean "user_oauth_applications", default: true
+ t.boolean "user_oauth_applications", default: true
t.string "after_sign_out_path"
- t.integer "session_expire_delay", default: 10080, null: false
+ t.integer "session_expire_delay", default: 10080, null: false
t.text "import_sources"
t.text "help_page_text"
t.string "admin_notification_email"
- t.boolean "shared_runners_enabled", default: true, null: false
- t.integer "max_artifacts_size", default: 100, null: false
+ t.boolean "shared_runners_enabled", default: true, null: false
+ t.integer "max_artifacts_size", default: 100, null: false
t.string "runners_registration_token"
- t.boolean "require_two_factor_authentication", default: false
- t.integer "two_factor_grace_period", default: 48
- t.boolean "metrics_enabled", default: false
- t.string "metrics_host", default: "localhost"
- t.integer "metrics_pool_size", default: 16
- t.integer "metrics_timeout", default: 10
- t.integer "metrics_method_call_threshold", default: 10
- t.boolean "recaptcha_enabled", default: false
+ t.boolean "require_two_factor_authentication", default: false
+ t.integer "two_factor_grace_period", default: 48
+ t.boolean "metrics_enabled", default: false
+ t.string "metrics_host", default: "localhost"
+ t.integer "metrics_pool_size", default: 16
+ t.integer "metrics_timeout", default: 10
+ t.integer "metrics_method_call_threshold", default: 10
+ t.boolean "recaptcha_enabled", default: false
t.string "recaptcha_site_key"
t.string "recaptcha_private_key"
- t.integer "metrics_port", default: 8089
- t.boolean "akismet_enabled", default: false
+ t.integer "metrics_port", default: 8089
+ t.boolean "akismet_enabled", default: false
t.string "akismet_api_key"
- t.integer "metrics_sample_interval", default: 15
- t.boolean "sentry_enabled", default: false
+ t.integer "metrics_sample_interval", default: 15
+ t.boolean "sentry_enabled", default: false
t.string "sentry_dsn"
- t.boolean "email_author_in_body", default: false
+ t.boolean "email_author_in_body", default: false
t.integer "default_group_visibility"
- t.boolean "repository_checks_enabled", default: false
+ t.boolean "repository_checks_enabled", default: false
t.text "shared_runners_text"
- t.integer "metrics_packet_size", default: 1
- t.text "disabled_oauth_sign_in_sources"
- t.string "health_check_access_token"
- t.boolean "send_user_confirmation_email", default: false
- t.integer "container_registry_token_expire_delay", default: 5
+ t.integer "metrics_packet_size", default: 1
end
create_table "audit_events", force: :cascade do |t|
@@ -271,7 +267,6 @@ ActiveRecord::Schema.define(version: 20160530150109) do
t.string "revision"
t.string "platform"
t.string "architecture"
- t.boolean "run_untagged", default: true, null: false
end
add_index "ci_runners", ["description"], name: "index_ci_runners_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
@@ -639,7 +634,6 @@ ActiveRecord::Schema.define(version: 20160530150109) do
t.text "st_diff"
t.integer "updated_by_id"
t.boolean "is_award", default: false, null: false
- t.string "type"
end
add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree
@@ -761,10 +755,10 @@ ActiveRecord::Schema.define(version: 20160530150109) do
t.integer "build_timeout", default: 3600, null: false
t.boolean "pending_delete", default: false
t.boolean "public_builds", default: true, null: false
+ t.string "main_language"
t.integer "pushes_since_gc", default: 0
t.boolean "last_repository_check_failed"
t.datetime "last_repository_check_at"
- t.boolean "container_registry_enabled"
end
add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree
@@ -1001,7 +995,6 @@ ActiveRecord::Schema.define(version: 20160530150109) do
add_index "users", ["name"], name: "index_users_on_name", using: :btree
add_index "users", ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
- add_index "users", ["state"], name: "index_users_on_state", using: :btree
add_index "users", ["username"], name: "index_users_on_username", using: :btree
add_index "users", ["username"], name: "index_users_on_username_trigram", using: :gin, opclasses: {"username"=>"gin_trgm_ops"}
diff --git a/doc/README.md b/doc/README.md
index d1345ab249..e358da1c42 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -13,7 +13,6 @@
- [Profile Settings](profile/README.md)
- [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat.
- [Public access](public_access/public_access.md) Learn how you can allow public and internal access to projects.
-- [Container Registry](container_registry/README.md) Learn how to use GitLab Container Registry.
- [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects.
- [Webhooks](web_hooks/web_hooks.md) Let GitLab notify you when new code has been pushed to your project.
- [Workflow](workflow/README.md) Using GitLab functionality and importing projects from GitHub and SVN.
@@ -42,10 +41,8 @@
- [Git LFS configuration](workflow/lfs/lfs_administration.md)
- [Housekeeping](administration/housekeeping.md) Keep your Git repository tidy and fast.
- [GitLab Performance Monitoring](monitoring/performance/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics
-- [Monitoring uptime](monitoring/health_check.md) Check the server status using the health check endpoint
- [Sidekiq Troubleshooting](administration/troubleshooting/sidekiq.md) Debug when Sidekiq appears hung and is not processing jobs
- [High Availability](administration/high_availability/README.md) Configure multiple servers for scaling or high availability
-- [Container Registry](administration/container_registry.md) Configure Docker Registry with GitLab
## Contributor documentation
diff --git a/doc/administration/container_registry.md b/doc/administration/container_registry.md
deleted file mode 100644
index caf9a5bef2..0000000000
--- a/doc/administration/container_registry.md
+++ /dev/null
@@ -1,375 +0,0 @@
-# GitLab Container Registry Administration
-
-> **Note:**
-This feature was [introduced][ce-4040] in GitLab 8.8.
-
-With the Docker Container Registry integrated into GitLab, every project can
-have its own space to store its Docker images.
-
-You can read more about Docker Registry at https://docs.docker.com/registry/introduction/.
-
----
-
-
-
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Enable the Container Registry](#enable-the-container-registry)
-- [Container Registry domain configuration](#container-registry-domain-configuration)
- - [Configure Container Registry under an existing GitLab domain](#configure-container-registry-under-an-existing-gitlab-domain)
- - [Configure Container Registry under its own domain](#configure-container-registry-under-its-own-domain)
-- [Disable Container Registry site-wide](#disable-container-registry-site-wide)
-- [Disable Container Registry per project](#disable-container-registry-per-project)
-- [Disable Container Registry for new projects site-wide](#disable-container-registry-for-new-projects-site-wide)
-- [Container Registry storage path](#container-registry-storage-path)
-- [Storage limitations](#storage-limitations)
-- [Changelog](#changelog)
-
-
-
-## Enable the Container Registry
-
-**Omnibus GitLab installations**
-
-All you have to do is configure the domain name under which the Container
-Registry will listen to. Read [#container-registry-domain-configuration](#container-registry-domain-configuration)
-and pick one of the two options that fits your case.
-
->**Note:**
-The container Registry works under HTTPS by default. Using HTTP is possible
-but not recommended and out of the scope of this document.
-Read the [insecure Registry documentation][docker-insecure] if you want to
-implement this.
-
----
-
-**Installations from source**
-
-If you have installed GitLab from source:
-
-1. You will have to [install Docker Registry][registry-deploy] by yourself.
-1. After the installation is complete, you will have to configure the Registry's
- settings in `gitlab.yml` in order to enable it.
-1. Use the sample NGINX configuration file that is found under
- [`lib/support/nginx/registry-ssl`][registry-ssl] and edit it to match the
- `host`, `port` and TLS certs paths.
-
-The contents of `gitlab.yml` are:
-
-```
-registry:
- enabled: true
- host: registry.gitlab.example.com
- port: 5005
- api_url: http://localhost:5000/
- key_path: config/registry.key
- path: shared/registry
- issuer: gitlab-issuer
-```
-
-where:
-
-| Parameter | Description |
-| --------- | ----------- |
-| `enabled` | `true` or `false`. Enables the Registry in GitLab. By default this is `false`. |
-| `host` | The host URL under which the Registry will run and the users will be able to use. |
-| `port` | The port under which the external Registry domain will listen on. |
-| `api_url` | The internal API URL under which the Registry is exposed to. It defaults to `http://localhost:5000`. |
-| `key_path`| The private key location that is a pair of Registry's `rootcertbundle`. Read the [token auth configuration documentation][token-config]. |
-| `path` | This should be the same directory like specified in Registry's `rootdirectory`. Read the [storage configuration documentation][storage-config]. This path needs to be readable by the GitLab user, the web-server user and the Registry user. Read more in [#container-registry-storage-path](#container-registry-storage-path). |
-| `issuer` | This should be the same value as configured in Registry's `issuer`. Read the [token auth configuration documentation][token-config]. |
-
->**Note:**
-GitLab does not ship with a Registry init file. Hence, [restarting GitLab][restart gitlab]
-will not restart the Registry should you modify its settings. Read the upstream
-documentation on how to achieve that.
-
-## Container Registry domain configuration
-
-There are two ways you can configure the Registry's external domain.
-
-- Either [use the existing GitLab domain][existing-domain] where in that case
- the Registry will have to listen on a port and reuse GitLab's TLS certificate,
-- or [use a completely separate domain][new-domain] with a new TLS certificate
- for that domain.
-
-Since the container Registry requires a TLS certificate, in the end it all boils
-down to how easy or pricey is to get a new one.
-
-Please take this into consideration before configuring the Container Registry
-for the first time.
-
-### Configure Container Registry under an existing GitLab domain
-
-If the Registry is configured to use the existing GitLab domain, you can
-expose the Registry on a port so that you can reuse the existing GitLab TLS
-certificate.
-
-Assuming that the GitLab domain is `https://gitlab.example.com` and the port the
-Registry is exposed to the outside world is `4567`, here is what you need to set
-in `gitlab.rb` or `gitlab.yml` if you are using Omnibus GitLab or installed
-GitLab from source respectively.
-
----
-
-**Omnibus GitLab installations**
-
-1. Your `/etc/gitlab/gitlab.rb` should contain the Registry URL as well as the
- path to the existing TLS certificate and key used by GitLab:
-
- ```ruby
- registry_external_url 'https://gitlab.example.com:4567'
- ```
-
- Note how the `registry_external_url` is listening on HTTPS under the
- existing GitLab URL, but on a different port.
-
- If your TLS certificate is not in `/etc/gitlab/ssl/gitlab.example.com.crt`
- and key not in `/etc/gitlab/ssl/gitlab.example.com.key` uncomment the lines
- below:
-
- ```ruby
- registry_nginx['ssl_certificate'] = "/path/to/certificate.pem"
- registry_nginx['ssl_certificate_key'] = "/path/to/certificate.key"
- ```
-
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
-
----
-
-**Installations from source**
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
- configure it with the following settings:
-
- ```
- registry:
- enabled: true
- host: gitlab.example.com
- port: 4567
- ```
-
-1. Save the file and [restart GitLab][] for the changes to take effect.
-1. Make the relevant changes in NGINX as well (domain, port, TLS certificates path).
-
----
-
-Users should now be able to login to the Container Registry with their GitLab
-credentials using:
-
-```bash
-docker login gitlab.example.com:4567
-```
-
-### Configure Container Registry under its own domain
-
-If the Registry is configured to use its own domain, you will need a TLS
-certificate for that specific domain (e.g., `registry.example.com`) or maybe
-a wildcard certificate if hosted under a subdomain of your existing GitLab
-domain (e.g., `registry.gitlab.example.com`).
-
-Let's assume that you want the container Registry to be accessible at
-`https://registry.gitlab.example.com`.
-
----
-
-**Omnibus GitLab installations**
-
-1. Place your TLS certificate and key in
- `/etc/gitlab/ssl/registry.gitlab.example.com.crt` and
- `/etc/gitlab/ssl/registry.gitlab.example.com.key` and make sure they have
- correct permissions:
-
- ```bash
- chmod 600 /etc/gitlab/ssl/registry.gitlab.example.com.*
- ```
-
-1. Once the TLS certificate is in place, edit `/etc/gitlab/gitlab.rb` with:
-
- ```ruby
- registry_external_url 'https://registry.gitlab.example.com'
- ```
-
- Note how the `registry_external_url` is listening on HTTPS.
-
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
-
-> **Note:**
-If you have a [wildcard certificate][], you need to specify the path to the
-certificate in addition to the URL, in this case `/etc/gitlab/gitlab.rb` will
-look like:
->
-```ruby
-registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/certificate.pem"
-registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key"
-```
-
----
-
-**Installations from source**
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
- configure it with the following settings:
-
- ```
- registry:
- enabled: true
- host: registry.gitlab.example.com
- ```
-
-1. Save the file and [restart GitLab][] for the changes to take effect.
-1. Make the relevant changes in NGINX as well (domain, port, TLS certificates path).
-
----
-
-Users should now be able to login to the Container Registry using their GitLab
-credentials:
-
-```bash
-docker login registry.gitlab.example.com
-```
-
-## Disable Container Registry site-wide
-
->**Note:**
-Disabling the Registry in the Rails GitLab application as set by the following
-steps, will not remove any existing Docker images. This is handled by the
-Registry application itself.
-
-**Omnibus GitLab**
-
-1. Open `/etc/gitlab/gitlab.rb` and set `registry['enable']` to `false`:
-
- ```ruby
- registry['enable'] = false
- ```
-
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
-
----
-
-**Installations from source**
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
- set `enabled` to `false`:
-
- ```
- registry:
- enabled: false
- ```
-
-1. Save the file and [restart GitLab][] for the changes to take effect.
-
-## Disable Container Registry per project
-
-If Registry is enabled in your GitLab instance, but you don't need it for your
-project, you can disable it from your project's settings. Read the user guide
-on how to achieve that.
-
-## Disable Container Registry for new projects site-wide
-
-If the Container Registry is enabled, then it will be available on all new
-projects. To disable this function and let the owners of a project to enable
-the Container Registry by themselves, follow the steps below.
-
----
-
-**Omnibus GitLab installations**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
-
- ```ruby
- gitlab_rails['gitlab_default_projects_features_container_registry'] = false
- ```
-
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
-
----
-
-**Installations from source**
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, find the `default_projects_features`
- entry and configure it so that `container_registry` is set to `false`:
-
- ```
- ## Default project features settings
- default_projects_features:
- issues: true
- merge_requests: true
- wiki: true
- snippets: false
- builds: true
- container_registry: false
- ```
-
-1. Save the file and [restart GitLab][] for the changes to take effect.
-
-## Container Registry storage path
-
-To change the storage path where Docker images will be stored, follow the
-steps below.
-
-This path is accessible to:
-
-- the user running the Container Registry daemon,
-- the user running GitLab
-
-> **Warning** You should confirm that all GitLab, Registry and web server users
-have access to this directory.
-
----
-
-**Omnibus GitLab installations**
-
-The default location where images are stored in Omnibus, is
-`/var/opt/gitlab/gitlab-rails/shared/registry`. To change it:
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['registry_path'] = "/path/to/registry/storage"
- ```
-
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
-
----
-
-**Installations from source**
-
-The default location where images are stored in source installations, is
-`/home/git/gitlab/shared/registry`. To change it:
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
- change the `path` setting:
-
- ```
- registry:
- path: shared/registry
- ```
-
-1. Save the file and [restart GitLab][] for the changes to take effect.
-
-## Storage limitations
-
-Currently, there is no storage limitation, which means a user can upload an
-infinite amount of Docker images with arbitrary sizes. This setting will be
-configurable in future releases.
-
-## Changelog
-
-**GitLab 8.8 ([source docs][8-8-docs])**
-
-- GitLab Container Registry feature was introduced.
-
-[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure
-[restart gitlab]: restart_gitlab.md#installations-from-source
-[wildcard certificate]: https://en.wikipedia.org/wiki/Wildcard_certificate
-[ce-4040]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4040
-[docker-insecure]: https://docs.docker.com/registry/insecure/
-[registry-deploy]: https://docs.docker.com/registry/deploying/
-[storage-config]: https://docs.docker.com/registry/configuration/#storage
-[token-config]: https://docs.docker.com/registry/configuration/#token
-[8-8-docs]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/doc/administration/container_registry.md
-[registry-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/nginx/registry-ssl
-[existing-domain]: #configure-container-registry-under-an-existing-gitlab-domain
-[new-domain]: #configure-container-registry-under-its-own-domain
diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md
index 7f53915a4d..43ab153d76 100644
--- a/doc/administration/environment_variables.md
+++ b/doc/administration/environment_variables.md
@@ -58,4 +58,4 @@ to the naming scheme `GITLAB_#{name in 1_settings.rb in upper case}`.
It's possible to preconfigure the GitLab docker image by adding the environment
variable `GITLAB_OMNIBUS_CONFIG` to the `docker run` command.
-For more information see the ['preconfigure-docker-container' section in the Omnibus documentation](http://docs.gitlab.com/omnibus/docker/#preconfigure-docker-container).
+For more information see the ['preconfigure-docker-container' section in the Omnibus documentation](http://doc.gitlab.com/omnibus/docker/#preconfigure-docker-container).
diff --git a/doc/administration/high_availability/README.md b/doc/administration/high_availability/README.md
index d74a786ac2..43d85ffb77 100644
--- a/doc/administration/high_availability/README.md
+++ b/doc/administration/high_availability/README.md
@@ -19,8 +19,6 @@ Components/Servers Required:
- 2 servers/virtual machines (one active/one passive)
-
-
### Active/Active
This architecture scales easily because all application servers handle
@@ -28,8 +26,6 @@ user requests simultaneously. The database, Redis, and GitLab application are
all deployed on separate servers. The configuration is **only** highly-available
if the database, Redis and storage are also configured as such.
-
-
**Steps to configure active/active:**
1. [Configure the database](database.md)
diff --git a/doc/administration/high_availability/load_balancer.md b/doc/administration/high_availability/load_balancer.md
index 136f570ac2..b1fe34ed9a 100644
--- a/doc/administration/high_availability/load_balancer.md
+++ b/doc/administration/high_availability/load_balancer.md
@@ -60,4 +60,4 @@ Read more on high-availability configuration:
configure custom domains with custom SSL, which would not be possible
if SSL was terminated at the load balancer.
-[gitlab-pages]: http://docs.gitlab.com/ee/pages/administration.html
+[gitlab-pages]: http://doc.gitlab.com/ee/pages/administration.html
diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md
index 537f4f3501..e4e124e200 100644
--- a/doc/administration/high_availability/nfs.md
+++ b/doc/administration/high_availability/nfs.md
@@ -2,8 +2,8 @@
## Required NFS Server features
-**File locking**: GitLab **requires** advisory file locking, which is only
-supported natively in NFS version 4. NFSv3 also supports locking as long as
+**File locking**: GitLab **requires** file locking which is only supported
+natively in NFS version 4. NFSv3 also supports locking as long as
Linux Kernel 2.6.5+ is used. We recommend using version 4 and do not
specifically test NFSv3.
@@ -113,4 +113,4 @@ Read more on high-availability configuration:
1. [Configure the GitLab application servers](gitlab.md)
1. [Configure the load balancers](load_balancer.md)
-[udp-log-shipping]: http://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only "UDP log shipping"
+[udp-log-shipping]: http://doc.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only "UDP log shipping"
diff --git a/doc/administration/high_availability/redis.md b/doc/administration/high_availability/redis.md
index f6153216f3..d89a1e582c 100644
--- a/doc/administration/high_availability/redis.md
+++ b/doc/administration/high_availability/redis.md
@@ -26,7 +26,7 @@ that runs Redis.
```ruby
external_url 'https://gitlab.example.com'
- # Disable all components except Redis
+ # Disable all components except PostgreSQL
redis['enable'] = true
bootstrap['enable'] = false
nginx['enable'] = false
diff --git a/doc/administration/img/high_availability/active-active-diagram.png b/doc/administration/img/high_availability/active-active-diagram.png
deleted file mode 100644
index 81259e0ae9..0000000000
Binary files a/doc/administration/img/high_availability/active-active-diagram.png and /dev/null differ
diff --git a/doc/administration/img/high_availability/active-passive-diagram.png b/doc/administration/img/high_availability/active-passive-diagram.png
deleted file mode 100644
index f69ff1d035..0000000000
Binary files a/doc/administration/img/high_availability/active-passive-diagram.png and /dev/null differ
diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md
index 4172b604ce..3411e4af6a 100644
--- a/doc/administration/repository_checks.md
+++ b/doc/administration/repository_checks.md
@@ -5,7 +5,7 @@ This feature was [introduced][ce-3232] in GitLab 8.7. It is OFF by
default because it still causes too many false alarms.
Git has a built-in mechanism, [git fsck][git-fsck], to verify the
-integrity of all data committed to a repository. GitLab administrators
+integrity of all data commited to a repository. GitLab administrators
can trigger such a check for a project via the project page under the
admin panel. The checks run asynchronously so it may take a few minutes
before the check result is visible on the project admin page. If the
@@ -41,4 +41,4 @@ alarms you can choose to clear ALL repository check states from the
---
[ce-3232]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3232 "Auto git fsck"
-[git-fsck]: https://www.kernel.org/pub/software/scm/git/docs/git-fsck.html "git fsck documentation"
+[git-fsck]: https://www.kernel.org/pub/software/scm/git/docs/git-fsck.html "git fsck documentation"
\ No newline at end of file
diff --git a/doc/administration/troubleshooting/sidekiq.md b/doc/administration/troubleshooting/sidekiq.md
index a776cd3f05..134a758376 100644
--- a/doc/administration/troubleshooting/sidekiq.md
+++ b/doc/administration/troubleshooting/sidekiq.md
@@ -150,14 +150,6 @@ To output a backtrace from all threads at once:
apply all thread bt
```
-Once you're done debugging with `gdb`, be sure to detach from the process and
-exit:
-
-```
-detach
-exit
-```
-
## Check for blocking queries
Sometimes the speed at which Sidekiq processes jobs can be so fast that it can
diff --git a/doc/api/README.md b/doc/api/README.md
index 27c5962dec..ff039f1886 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -33,7 +33,7 @@ following locations:
- [Build triggers](build_triggers.md)
- [Build Variables](build_variables.md)
- [Runners](runners.md)
-- [Open source license templates](licenses.md)
+- [Licenses](licenses.md)
## Authentication
diff --git a/doc/api/build_triggers.md b/doc/api/build_triggers.md
index 0881a7d7a9..4a12e962b6 100644
--- a/doc/api/build_triggers.md
+++ b/doc/api/build_triggers.md
@@ -101,18 +101,8 @@ DELETE /projects/:id/triggers/:token
| Attribute | Type | required | Description |
|-----------|---------|----------|--------------------------|
| `id` | integer | yes | The ID of a project |
-| `token` | string | yes | The `token` of a trigger |
+| `token` | string | yes | The `token` of a project |
```
curl -X DELETE -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers/7b9148c158980bbd9bcea92c17522d"
```
-
-```json
-{
- "created_at": "2015-12-23T16:25:56.760Z",
- "deleted_at": "2015-12-24T12:32:20.100Z",
- "last_used": null,
- "token": "7b9148c158980bbd9bcea92c17522d",
- "updated_at": "2015-12-24T12:32:20.100Z"
-}
-```
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 1ccb9715e9..2821bc21b8 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -265,6 +265,7 @@ GET /groups/:id/members
{
"id": 1,
"username": "raymond_smith",
+ "email": "ray@smith.org",
"name": "Raymond Smith",
"state": "active",
"created_at": "2012-10-22T14:13:35Z",
@@ -273,6 +274,7 @@ GET /groups/:id/members
{
"id": 2,
"username": "john_doe",
+ "email": "joh@doe.org",
"name": "John Doe",
"state": "active",
"created_at": "2012-10-22T14:13:35Z",
diff --git a/doc/api/issues.md b/doc/api/issues.md
index fc7a7ae0c0..3e78149f44 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -77,8 +77,7 @@ Example response:
"created_at" : "2016-01-04T15:31:51.081Z",
"iid" : 6,
"labels" : [],
- "subscribed" : false,
- "user_notes_count": 1
+ "subscribed" : false
}
]
```
@@ -155,8 +154,7 @@ Example response:
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z",
"created_at" : "2016-01-04T15:31:46.176Z",
- "subscribed" : false,
- "user_notes_count": 1
+ "subscribed" : false
}
]
```
@@ -218,8 +216,7 @@ Example response:
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z",
"created_at" : "2016-01-04T15:31:46.176Z",
- "subscribed": false,
- "user_notes_count": 1
+ "subscribed": false
}
```
@@ -274,8 +271,7 @@ Example response:
"description" : null,
"updated_at" : "2016-01-07T12:44:33.959Z",
"milestone" : null,
- "subscribed" : true,
- "user_notes_count": 0
+ "subscribed" : true
}
```
@@ -333,8 +329,7 @@ Example response:
"id" : 85,
"assignee" : null,
"milestone" : null,
- "subscribed" : true,
- "user_notes_count": 0
+ "subscribed" : true
}
```
diff --git a/doc/api/labels.md b/doc/api/labels.md
index a181c0f57a..3730c07c5a 100644
--- a/doc/api/labels.md
+++ b/doc/api/labels.md
@@ -39,7 +39,7 @@ Example response:
{
"name" : "critical",
"color" : "#d9534f",
- "description": "Critical issue. Need fix ASAP",
+ "description": "Criticalissue. Need fix ASAP",
"open_issues_count": 1,
"closed_issues_count": 3,
"open_merge_requests_count": 1
@@ -165,73 +165,3 @@ Example response:
"description": "Documentation"
}
```
-
-## Subscribe to a label
-
-Subscribes the authenticated user to a label to receive notifications. If the
-operation is successful, status code `201` together with the updated label is
-returned. If the user is already subscribed to the label, the status code `304`
-is returned. If the project or label is not found, status code `404` is
-returned.
-
-```
-POST /projects/:id/labels/:label_id/subscription
-```
-
-| Attribute | Type | Required | Description |
-| ---------- | ----------------- | -------- | ------------------------------------ |
-| `id` | integer | yes | The ID of a project |
-| `label_id` | integer or string | yes | The ID or title of a project's label |
-
-```bash
-curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscription
-```
-
-Example response:
-
-```json
-{
- "name": "Docs",
- "color": "#cc0033",
- "description": "",
- "open_issues_count": 0,
- "closed_issues_count": 0,
- "open_merge_requests_count": 0,
- "subscribed": true
-}
-```
-
-## Unsubscribe from a label
-
-Unsubscribes the authenticated user from a label to not receive notifications
-from it. If the operation is successful, status code `200` together with the
-updated label is returned. If the user is not subscribed to the label, the
-status code `304` is returned. If the project or label is not found, status code
-`404` is returned.
-
-```
-DELETE /projects/:id/labels/:label_id/subscription
-```
-
-| Attribute | Type | Required | Description |
-| ---------- | ----------------- | -------- | ------------------------------------ |
-| `id` | integer | yes | The ID of a project |
-| `label_id` | integer or string | yes | The ID or title of a project's label |
-
-```bash
-curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscription
-```
-
-Example response:
-
-```json
-{
- "name": "Docs",
- "color": "#cc0033",
- "description": "",
- "open_issues_count": 0,
- "closed_issues_count": 0,
- "open_merge_requests_count": 0,
- "subscribed": false
-}
-```
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 8217e30fe2..2057f9d77a 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -67,8 +67,7 @@ Parameters:
},
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : false,
- "user_notes_count": 1
+ "subscribed" : false
}
]
```
@@ -131,8 +130,7 @@ Parameters:
},
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
- "user_notes_count": 1
+ "subscribed" : true
}
```
@@ -232,7 +230,6 @@ Parameters:
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
- "user_notes_count": 1,
"changes": [
{
"old_path": "VERSION",
@@ -311,8 +308,7 @@ Parameters:
},
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
- "user_notes_count": 0
+ "subscribed" : true
}
```
@@ -382,8 +378,7 @@ Parameters:
},
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
- "user_notes_count": 1
+ "subscribed" : true
}
```
@@ -477,8 +472,7 @@ Parameters:
},
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
- "user_notes_count": 1
+ "subscribed" : true
}
```
@@ -543,8 +537,7 @@ Parameters:
},
"merge_when_build_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
- "user_notes_count": 1
+ "subscribed" : true
}
```
@@ -609,8 +602,7 @@ Example response:
"title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.",
"created_at" : "2016-01-04T15:31:51.081Z",
"iid" : 6,
- "labels" : [],
- "user_notes_count": 1
+ "labels" : []
},
]
```
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 7aa1c2155b..a6b5b1787f 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -15,7 +15,7 @@ GET /projects/:id/issues/:issue_id/notes
Parameters:
- `id` (required) - The ID of a project
-- `issue_id` (required) - The ID of an issue
+- `issue_id` (required) - The IID of an issue (not ID)
```json
[
@@ -73,7 +73,7 @@ GET /projects/:id/issues/:issue_id/notes/:note_id
Parameters:
- `id` (required) - The ID of a project
-- `issue_id` (required) - The ID of a project issue
+- `issue_id` (required) - The IID of a project issue (not ID)
- `note_id` (required) - The ID of an issue note
### Create new issue note
@@ -87,7 +87,7 @@ POST /projects/:id/issues/:issue_id/notes
Parameters:
- `id` (required) - The ID of a project
-- `issue_id` (required) - The ID of an issue
+- `issue_id` (required) - The IID of an issue (not ID)
- `body` (required) - The content of a note
- `created_at` (optional) - Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z
@@ -102,7 +102,7 @@ PUT /projects/:id/issues/:issue_id/notes/:note_id
Parameters:
- `id` (required) - The ID of a project
-- `issue_id` (required) - The ID of an issue
+- `issue_id` (required) - The IID of an issue (not ID)
- `note_id` (required) - The ID of a note
- `body` (required) - The content of a note
@@ -120,7 +120,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of an issue |
+| `issue_id` | integer | yes | The IID of an issue |
| `note_id` | integer | yes | The ID of a note |
```bash
diff --git a/doc/api/projects.md b/doc/api/projects.md
index f5f195b97d..de1faadebf 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -424,7 +424,6 @@ Parameters:
- `builds_enabled` (optional)
- `wiki_enabled` (optional)
- `snippets_enabled` (optional)
-- `container_registry_enabled` (optional)
- `public` (optional) - if `true` same as setting visibility_level = 20
- `visibility_level` (optional)
- `import_url` (optional)
@@ -448,7 +447,6 @@ Parameters:
- `builds_enabled` (optional)
- `wiki_enabled` (optional)
- `snippets_enabled` (optional)
-- `container_registry_enabled` (optional)
- `public` (optional) - if `true` same as setting visibility_level = 20
- `visibility_level` (optional)
- `import_url` (optional)
@@ -474,7 +472,6 @@ Parameters:
- `builds_enabled` (optional)
- `wiki_enabled` (optional)
- `snippets_enabled` (optional)
-- `container_registry_enabled` (optional)
- `public` (optional) - if `true` same as setting visibility_level = 20
- `visibility_level` (optional)
- `public_builds` (optional)
diff --git a/doc/api/runners.md b/doc/api/runners.md
index ddfa298f79..cc6c6b7cb2 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -275,7 +275,7 @@ POST /projects/:id/runners
| `runner_id` | integer | yes | The ID of a runner |
```
-curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/9/runners" -F "runner_id=9"
+curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/project/9/runners" -F "runner_id=9"
```
Example response:
@@ -306,7 +306,7 @@ DELETE /projects/:id/runners/:runner_id
| `runner_id` | integer | yes | The ID of a runner |
```
-curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/9/runners/9"
+curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/project/9/runners/9"
```
Example response:
diff --git a/doc/api/services.md b/doc/api/services.md
index ccfc0fccb7..7d45b2cf46 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -16,8 +16,8 @@ PUT /projects/:id/services/asana
Parameters:
-- `api_key` (**required**) - User API token. User must have access to task, all comments will be attributed to this user.
-- `restrict_to_branch` (optional) - Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches.
+- `api_key` (**required**) - User API token. User must have access to task,all comments will be attributed to this user.
+- `restrict_to_branch` (optional) - Comma-separated list of branches which will beautomatically inspected. Leave blank to include all branches.
### Delete Asana service
@@ -491,7 +491,7 @@ Jira issue tracker
Set JIRA service for a project.
-> Setting `project_url`, `issues_url` and `new_issue_url` will allow a user to easily navigate to the Jira issue tracker. See the [integration doc](http://docs.gitlab.com/ce/integration/external-issue-tracker.html) for details. Support for referencing commits and automatic closing of Jira issues directly from GitLab is [available in GitLab EE.](http://docs.gitlab.com/ee/integration/jira.html)
+> Setting `project_url`, `issues_url` and `new_issue_url` will allow a user to easily navigate to the Jira issue tracker. See the [integration doc](http://doc.gitlab.com/ce/integration/external-issue-tracker.html) for details. Support for referencing commits and automatic closing of Jira issues directly from GitLab is [available in GitLab EE.](http://doc.gitlab.com/ee/integration/jira.html)
```
PUT /projects/:id/services/jira
@@ -503,8 +503,6 @@ Parameters:
- `project_url` (**required**) - Project url
- `issues_url` (**required**) - Issue url
- `description` (optional) - Jira issue tracker
-- `username` (optional) - Jira username
-- `password` (optional) - Jira password
### Delete JIRA service
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 43a0fe35e4..1e745115dc 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -37,8 +37,7 @@ Example response:
"created_at" : "2016-01-04T15:44:55.176Z",
"default_project_visibility" : 0,
"gravatar_enabled" : true,
- "sign_in_text" : null,
- "container_registry_token_expire_delay": 5
+ "sign_in_text" : null
}
```
@@ -65,7 +64,6 @@ PUT /application/settings
| `restricted_signup_domains` | array of strings | no | Force people to use only corporate emails for sign-up. Default is null, meaning there is no restriction. |
| `user_oauth_applications` | boolean | no | Allow users to register any application to use GitLab as an OAuth provider |
| `after_sign_out_path` | string | no | Where to redirect users after logout |
-| `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes |
```bash
curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings?signup_enabled=false&default_project_visibility=1
@@ -92,7 +90,6 @@ Example response:
"default_snippet_visibility": 0,
"restricted_signup_domains": [],
"user_oauth_applications": true,
- "after_sign_out_path": "",
- "container_registry_token_expire_delay": 5
+ "after_sign_out_path": ""
}
```
diff --git a/doc/ci/examples/deployment/README.md b/doc/ci/deployment/README.md
similarity index 100%
rename from doc/ci/examples/deployment/README.md
rename to doc/ci/deployment/README.md
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index 386b8e29fc..6a42a935ab 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -212,8 +212,8 @@ If you want to receive e-mail notifications about the result status of the
builds, you should explicitly enable the **Builds Emails** service under your
project's settings.
-For more information read the
-[Builds emails service documentation](../../project_services/builds_emails.md).
+For more information read the [Builds emails service documentation]
+(../../project_services/builds_emails.md).
## Builds badge
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index b42d7a62eb..a06650b338 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -125,13 +125,7 @@ shared runners will only run the jobs they are equipped to run.
For instance, at GitLab we have runners tagged with "rails" if they contain
the appropriate dependencies to run Rails test suites.
-### Prevent runner with tags from picking jobs without tags
-
-You can configure a runner to prevent it from picking jobs with tags when
-the runnner does not have tags assigned. This setting is available on each
-runner in *Project Settings* > *Runners*.
-
-### Be careful with sensitive information
+### Be Careful with Sensitive Information
If you can run a build on a runner, you can get access to any code it runs
and get the token of the runner. With shared runners, this means that anyone
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index 5c316510d0..79ed512aab 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -33,7 +33,7 @@ POST /projects/:id/trigger/builds
The required parameters are the trigger's `token` and the Git `ref` on which
the trigger will be performed. Valid refs are the branch, the tag or the commit
-SHA. The `:id` of a project can be found by [querying the API](../../api/projects.md)
+SHA. The `:id` of a project can be found by [querying the API](../api/projects.md)
or by visiting the **Triggers** page which provides self-explanatory examples.
When a rebuild is triggered, the information is exposed in GitLab's UI under
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index a3481f58c6..7e9bced761 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -128,7 +128,7 @@ builds, including deploy builds. This can be an array or a multi-line string.
### after_script
>**Note:**
-Introduced in GitLab 8.7 and requires Gitlab Runner v1.2 (not yet released)
+Introduced in GitLab 8.7 and GitLab Runner v1.2.
`after_script` is used to define the command that will be run after for all
builds. This has to be an array or a multi-line string.
@@ -348,7 +348,7 @@ job_name:
| allow_failure | no | Allow build to fail. Failed build doesn't contribute to commit status |
| when | no | Define when to run build. Can be `on_success`, `on_failure` or `always` |
| dependencies | no | Define other builds that a build depends on so that you can pass artifacts between them|
-| artifacts | no | Define list of build artifacts |
+| artifacts | no | Define list build artifacts |
| cache | no | Define list of files that should be cached between subsequent runs |
| before_script | no | Override a set of commands that are executed before build |
| after_script | no | Override a set of commands that are executed after build |
diff --git a/doc/container_registry/README.md b/doc/container_registry/README.md
deleted file mode 100644
index 4df24ef13c..0000000000
--- a/doc/container_registry/README.md
+++ /dev/null
@@ -1,113 +0,0 @@
-# GitLab Container Registry
-
-> **Note:**
-This feature was [introduced][ce-4040] in GitLab 8.8.
-
-> **Note:**
-This document is about the user guide. To learn how to enable GitLab Container
-Registry across your GitLab instance, visit the
-[administrator documentation](../administration/container_registry.md).
-
-With the Docker Container Registry integrated into GitLab, every project can
-have its own space to store its Docker images.
-
-You can read more about Docker Registry at https://docs.docker.com/registry/introduction/.
-
----
-
-## Enable the Container Registry for your project
-
-1. First, ask your system administrator to enable GitLab Container Registry
- following the [administration documentation](../administration/container_registry.md).
- If you are using GitLab.com, this is enabled by default so you can start using
- the Registry immediately.
-
-1. Go to your project's settings and enable the **Container Registry** feature
- on your project. For new projects this might be enabled by default. For
- existing projects you will have to explicitly enable it.
-
- 
-
-## Build and push images
-
-After you save your project's settings, you should see a new link in the
-sidebar called **Container Registry**. Following this link will get you to
-your project's Registry panel where you can see how to login to the Container
-Registry using your GitLab credentials.
-
-For example if the Registry's URL is `registry.example.com`, the you should be
-able to login with:
-
-```
-docker login registry.example.com
-```
-
-Building and publishing images should be a straightforward process. Just make
-sure that you are using the Registry URL with the namespace and project name
-that is hosted on GitLab:
-
-```
-docker build -t registry.example.com/group/project .
-docker push registry.example.com/group/project
-```
-
-## Use images from GitLab Container Registry
-
-To download and run a container from images hosted in GitLab Container Registry,
-use `docker run`:
-
-```
-docker run [options] registry.example.com/group/project [arguments]
-```
-
-For more information on running Docker containers, visit the
-[Docker documentation][docker-docs].
-
-## Control Container Registry from within GitLab
-
-GitLab offers a simple Container Registry management panel. Go to your project
-and click **Container Registry** in the left sidebar.
-
-This view will show you all tags in your project and will easily allow you to
-delete them.
-
-
-
-## Build and push images using GitLab CI
-
-> **Note:**
-This feature requires GitLab 8.8 and GitLab Runner 1.2.
-
-Make sure that your GitLab Runner is configured to allow building docker images.
-You have to check the [Using Docker Build documentation](../../ci/docker/using_docker_build.md).
-
-You can use [docker:dind](https://hub.docker.com/_/docker/) to build your images,
-and this is how `.gitlab-ci.yml` should look like:
-
-```
- build_image:
- image: docker:git
- services:
- - docker:dind
- stage: build
- script:
- - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com
- - docker build -t registry.example.com/group/project:latest .
- - docker push registry.example.com/group/project:latest
-```
-
-You have to use the credentials of the special `gitlab-ci-token` user with its
-password stored in `$CI_BUILD_TOKEN` in order to push to the Registry connected
-to your project. This allows you to automated building and deployment of your
-Docker images.
-
-## Limitations
-
-In order to use a container image from your private project as an `image:` in
-your `.gitlab-ci.yml`, you have to follow the
-[Using a private Docker Registry][private-docker]
-documentation. This workflow will be simplified in the future.
-
-[ce-4040]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4040
-[docker-docs]: https://docs.docker.com/engine/userguide/intro/
-[private-docker]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry
diff --git a/doc/container_registry/img/container_registry.png b/doc/container_registry/img/container_registry.png
deleted file mode 100644
index e9505a73b4..0000000000
Binary files a/doc/container_registry/img/container_registry.png and /dev/null differ
diff --git a/doc/container_registry/img/project_feature.png b/doc/container_registry/img/project_feature.png
deleted file mode 100644
index 57a73d253c..0000000000
Binary files a/doc/container_registry/img/project_feature.png and /dev/null differ
diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md
index 8292b39375..187ec9e7b7 100644
--- a/doc/development/doc_styleguide.md
+++ b/doc/development/doc_styleguide.md
@@ -127,7 +127,7 @@ Inside the document:
```
If the document you are editing resides in a place other than the GitLab CE/EE
`doc/` directory, instead of the relative link, use the full path:
- `http://docs.gitlab.com/ce/administration/restart_gitlab.html`.
+ `http://doc.gitlab.com/ce/administration/restart_gitlab.html`.
Replace `reconfigure` with `restart` where appropriate.
## Installation guide
@@ -266,5 +266,5 @@ curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" -d "restricted_signup_domai
[cURL]: http://curl.haxx.se/ "cURL website"
[single spaces]: http://www.slate.com/articles/technology/technology/2011/01/space_invaders.html
-[gfm]: http://docs.gitlab.com/ce/markdown/markdown.html#newlines "GitLab flavored markdown documentation"
+[gfm]: http://doc.gitlab.com/ce/markdown/markdown.html#newlines "GitLab flavored markdown documentation"
[doc-restart]: ../administration/restart_gitlab.md "GitLab restart documentation"
diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md
index 9168c70945..c1cf2e77c2 100644
--- a/doc/development/instrumentation.md
+++ b/doc/development/instrumentation.md
@@ -1,125 +1,12 @@
# Instrumenting Ruby Code
-GitLab Performance Monitoring allows instrumenting of both methods and custom
-blocks of Ruby code. Method instrumentation is the primary form of
-instrumentation with block-based instrumentation only being used when we want to
-drill down to specific regions of code within a method.
+GitLab Performance Monitoring allows instrumenting of custom blocks of Ruby
+code. This can be used to measure the time spent in a specific part of a larger
+chunk of code. The resulting data is stored as a field in the transaction that
+executed the block.
-## Instrumenting Methods
-
-Instrumenting methods is done by using the `Gitlab::Metrics::Instrumentation`
-module. This module offers a few different methods that can be used to
-instrument code:
-
-* `instrument_method`: instruments a single class method.
-* `instrument_instance_method`: instruments a single instance method.
-* `instrument_class_hierarchy`: given a Class this method will recursively
- instrument all sub-classes (both class and instance methods).
-* `instrument_methods`: instruments all public class methods of a Module.
-* `instrument_instance_methods`: instruments all public instance methods of a
- Module.
-
-To remove the need for typing the full `Gitlab::Metrics::Instrumentation`
-namespace you can use the `configure` class method. This method simply yields
-the supplied block while passing `Gitlab::Metrics::Instrumentation` as its
-argument. An example:
-
-```
-Gitlab::Metrics::Instrumentation.configure do |conf|
- conf.instrument_method(Foo, :bar)
- conf.instrument_method(Foo, :baz)
-end
-```
-
-Using this method is in general preferred over directly calling the various
-instrumentation methods.
-
-Method instrumentation should be added in the initializer
-`config/initializers/metrics.rb`.
-
-### Examples
-
-Instrumenting a single method:
-
-```
-Gitlab::Metrics::Instrumentation.configure do |conf|
- conf.instrument_method(User, :find_by)
-end
-```
-
-Instrumenting an entire class hierarchy:
-
-```
-Gitlab::Metrics::Instrumentation.configure do |conf|
- conf.instrument_class_hierarchy(ActiveRecord::Base)
-end
-```
-
-Instrumenting all public class methods:
-
-```
-Gitlab::Metrics::Instrumentation.configure do |conf|
- conf.instrument_methods(User)
-end
-```
-
-### Checking Instrumented Methods
-
-The easiest way to check if a method has been instrumented is to check its
-source location. For example:
-
-```
-method = Rugged::TagCollection.instance_method(:[])
-
-method.source_location
-```
-
-If the source location points to `lib/gitlab/metrics/instrumentation.rb` you
-know the method has been instrumented.
-
-If you're using Pry you can use the `$` command to display the source code of a
-method (along with its source location), this is easier than running the above
-Ruby code. In case of the above snippet you'd run the following:
-
-```
-$ Rugged::TagCollection#[]
-```
-
-This will print out something along the lines of:
-
-```
-From: /path/to/your/gitlab/lib/gitlab/metrics/instrumentation.rb @ line 148:
-Owner: #
-Visibility: public
-Number of lines: 21
-
-def #{name}(#{args_signature})
- trans = Gitlab::Metrics::Instrumentation.transaction
-
- if trans
- start = Time.now
- retval = super
- duration = (Time.now - start) * 1000.0
-
- if duration >= Gitlab::Metrics.method_call_threshold
- trans.increment(:method_duration, duration)
-
- trans.add_metric(Gitlab::Metrics::Instrumentation::SERIES,
- { duration: duration },
- method: #{label.inspect})
- end
-
- retval
- else
- super
- end
-end
-```
-
-## Instrumenting Ruby Blocks
-
-Measuring blocks of Ruby code is done by calling `Gitlab::Metrics.measure` and
-passing it a block. For example:
+To start measuring a block of Ruby code you should use `Gitlab::Metrics.measure`
+and give it a name:
```ruby
Gitlab::Metrics.measure(:foo) do
@@ -127,10 +14,6 @@ Gitlab::Metrics.measure(:foo) do
end
```
-The block is executed and the execution time is stored as a set of fields in the
-currently running transaction. If no transaction is present the block is yielded
-without measuring anything.
-
3 values are measured for a block:
1. The real time elapsed, stored in NAME_real_time.
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 02e024ca15..28dedf3978 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -8,10 +8,7 @@ In addition, having to take a server offline for a an upgrade small or big is
a big burden for most organizations. For this reason it is important that your
migrations are written carefully, can be applied online and adhere to the style guide below.
-Migrations should not require GitLab installations to be taken offline unless
-_absolutely_ necessary. If a migration requires downtime this should be
-clearly mentioned during the review process as well as being documented in the
-monthly release post.
+It's advised to have offline migrations only in major GitLab releases.
When writing your migrations, also consider that databases might have stale data
or inconsistencies and guard for that. Try to make as little assumptions as possible
@@ -61,45 +58,6 @@ remove_index :namespaces, column: :name if index_exists?(:namespaces, :name)
If you need to add an unique index please keep in mind there is possibility of existing duplicates. If it is possible write a separate migration for handling this situation. It can be just removing or removing with overwriting all references to these duplicates depend on situation.
-When adding an index make sure to use the method `add_concurrent_index` instead
-of the regular `add_index` method. The `add_concurrent_index` method
-automatically creates concurrent indexes when using PostgreSQL, removing the
-need for downtime. To use this method you must disable transactions by calling
-the method `disable_ddl_transaction!` in the body of your migration class like
-so:
-
-```
-class MyMigration < ActiveRecord::Migration
- disable_ddl_transaction!
-
- def change
-
- end
-end
-```
-
-## Adding Columns With Default Values
-
-When adding columns with default values you should use the method
-`add_column_with_default`. This method ensures the table is updated without
-requiring downtime. This method is not reversible so you must manually define
-the `up` and `down` methods in your migration class.
-
-For example, to add the column `foo` to the `projects` table with a default
-value of `10` you'd write the following:
-
-```
-class MyMigration < ActiveRecord::Migration
- def up
- add_column_with_default(:projects, :foo, :integer, 10)
- end
-
- def down
- remove_column(:projects, :foo)
- end
-end
-```
-
## Testing
Make sure that your migration works with MySQL and PostgreSQL with data. An empty database does not guarantee that your migration is correct.
@@ -116,7 +74,7 @@ Example with Arel:
users = Arel::Table.new(:users)
users.group(users[:user_id]).having(users[:id].count.gt(5))
-#update other tables with these results
+#updtae other tables with this results
```
Example with plain SQL and `quote_string` helper:
@@ -131,4 +89,4 @@ select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(i
execute("UPDATE taggings SET tag_id = #{origin_tag_id} WHERE tag_id IN(#{duplicate_ids.join(",")})")
execute("DELETE FROM tags WHERE id IN(#{duplicate_ids.join(",")})")
end
-```
+```
\ No newline at end of file
diff --git a/doc/development/testing.md b/doc/development/testing.md
index 513457d203..33eed29ba5 100644
--- a/doc/development/testing.md
+++ b/doc/development/testing.md
@@ -65,7 +65,7 @@ the command line via `bundle exec teaspoon`, or via a web browser at
- Use `context` to test branching logic.
- Don't `describe` symbols (see [Gotchas](gotchas.md#dont-describe-symbols)).
- Don't supply the `:each` argument to hooks since it's the default.
-- Prefer `not_to` to `to_not` (_this is enforced by Rubocop_).
+- Prefer `not_to` to `to_not`.
- Try to match the ordering of tests to the ordering within the class.
- Try to follow the [Four-Phase Test][four-phase-test] pattern, using newlines
to separate phases.
diff --git a/doc/development/ui_guide.md b/doc/development/ui_guide.md
index 23760a14b3..a3e260a5f8 100644
--- a/doc/development/ui_guide.md
+++ b/doc/development/ui_guide.md
@@ -6,51 +6,3 @@ We created a page inside GitLab where you can check commonly used html and css e
When you run GitLab instance locally - just visit http://localhost:3000/help/ui page to see UI examples
you can use during GitLab development.
-
-## Design repository
-
-All design files are stored in the [gitlab-design](https://gitlab.com/gitlab-org/gitlab-design)
-repository and maintained by GitLab UX designers.
-
-## Navigation
-
-GitLab's layout contains 2 sections: the left sidebar and the content. The left sidebar contains a static navigation menu.
-This menu will be visible regardless of what page you visit. The left sidebar also contains the GitLab logo
-and the current user's profile picture. The content section contains a header and the content itself.
-The header describes the current GitLab page and what navigation is
-available to user in this area. Depending on the area (project, group, profile setting) the header name and navigation may change. For example when user visits one of the
-project pages the header will contain a project name and navigation for that project. When the user visits a group page it will contain a group name and navigation related to this group.
-
-### Adding new tab to header navigation
-
-We try to keep the amount of tabs in the header navigation between 5 and 10 so that it fits on a typical laptop screen. We also try not to confuse the user with too many options. Ideally each
-tab should represent separate functionality. Everything related to the issue
-tracker should be under the 'Issues' tab while everything related to the wiki should
-be under 'Wiki' tab and so on and so forth.
-
-## Mobile screen size
-
-We want GitLab to work well on small mobile screens as well. Size limitations make it is impossible to fit everything on a mobile screen. In this case it is OK to hide
-part of the UI for smaller resolutions in favor of a better user experience.
-However core functionality like browsing files, creating issues, writing comments, should
-be available on all resolutions.
-
-## Icons
-
-* `trash` icon for button or link that does destructive action like removing
-information from database or file system
-* `x` icon for closing/hiding UI element. For example close modal window
-* `pencil` icon for edit button or link
-* `eye` icon for subscribe action
-* `rss` for rss/atom feed
-* `plus` for link or dropdown that lead to page where you create new object (For example new issue page)
-
-
-## Buttons
-
-* Button should contain icon or text. Exceptions should be approved by UX designer.
-* Use gray button on white background or white button on gray background.
-* Use red button for destructive actions (not revertable). For example removing issue.
-* Use green or blue button for primary action. Primary button should be only one.
-Do not use both green and blue button in one form.
-
diff --git a/doc/gitlab-basics/create-issue.md b/doc/gitlab-basics/create-issue.md
index 5221d85b66..87f078def0 100644
--- a/doc/gitlab-basics/create-issue.md
+++ b/doc/gitlab-basics/create-issue.md
@@ -24,4 +24,4 @@ You may assign the Issue to a user, add a milestone and add labels (they are all

-Your Issue will now be added to the Issue Tracker and will be ready to be reviewed. You can comment on it and mention the people involved. You can also link Issues to the Merge Requests where the Issues are solved. To do this, you can use an [Issue closing pattern](http://docs.gitlab.com/ce/customization/issue_closing.html).
+Your Issue will now be added to the Issue Tracker and will be ready to be reviewed. You can comment on it and mention the people involved. You can also link Issues to the Merge Requests where the Issues are solved. To do this, you can use an [Issue closing pattern](http://doc.gitlab.com/ce/customization/issue_closing.html).
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index f737dffc02..b545d62549 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -14,7 +14,7 @@ Fill out the required information:
1. Select a [visibility level](https://gitlab.com/help/public_access/public_access)
-1. You can also [import your existing projects](http://docs.gitlab.com/ce/workflow/importing/README.html)
+1. You can also [import your existing projects](http://doc.gitlab.com/ce/workflow/importing/README.html)
1. Click on "create project"
diff --git a/doc/hooks/custom_hooks.md b/doc/hooks/custom_hooks.md
index 820934f97f..dcdf49d337 100644
--- a/doc/hooks/custom_hooks.md
+++ b/doc/hooks/custom_hooks.md
@@ -2,7 +2,7 @@
**Note: Custom git hooks must be configured on the filesystem of the GitLab
server. Only GitLab server administrators will be able to complete these tasks.
-Please explore [webhooks](../web_hooks/web_hooks.md) as an option if you do not have filesystem access. For a user configurable Git Hooks interface, please see [GitLab Enterprise Edition Git Hooks](http://docs.gitlab.com/ee/git_hooks/git_hooks.html).**
+Please explore [webhooks](../web_hooks/web_hooks.md) as an option if you do not have filesystem access. For a user configurable Git Hooks interface, please see [GitLab Enterprise Edition Git Hooks](http://doc.gitlab.com/ee/git_hooks/git_hooks.html).**
Git natively supports hooks that are executed on different actions.
Examples of server-side git hooks include pre-receive, post-receive, and update.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 1318b3d1fa..e3af302226 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -6,7 +6,7 @@ Since an installation from source is a lot of work and error prone we strongly r
One reason the Omnibus package is more reliable is its use of Runit to restart any of the GitLab processes in case one crashes.
On heavily used GitLab instances the memory usage of the Sidekiq background worker will grow over time.
-Omnibus packages solve this by [letting the Sidekiq terminate gracefully](http://docs.gitlab.com/ce/operations/sidekiq_memory_killer.html) if it uses too much memory.
+Omnibus packages solve this by [letting the Sidekiq terminate gracefully](http://doc.gitlab.com/ce/operations/sidekiq_memory_killer.html) if it uses too much memory.
After this termination Runit will detect Sidekiq is not running and will start it.
Since installations from source don't have Runit, Sidekiq can't be terminated and its memory usage will grow over time.
@@ -269,9 +269,9 @@ sudo usermod -aG redis git
### Clone the Source
# Clone GitLab repository
- sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-8-stable gitlab
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-7-stable gitlab
-**Note:** You can change `8-8-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+**Note:** You can change `8-7-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
@@ -394,7 +394,7 @@ GitLab Shell is an SSH access and repository management software developed speci
cd /home/git
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git
cd gitlab-workhorse
- sudo -u git -H git checkout v0.7.4
+ sudo -u git -H git checkout v0.7.1
sudo -u git -H make
### Initialize Database and Activate Advanced Features
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index 44d2a14f36..0245febfcd 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -132,5 +132,5 @@ To disable the relative URL:
1. Follow the same as above starting from 2. and set up the
GitLab URL to one that doesn't contain a relative path.
-[omnibus-rel]: http://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab "How to setup relative URL in Omnibus GitLab"
+[omnibus-rel]: http://doc.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab "How to setup relative URL in Omnibus GitLab"
[restart gitlab]: ../administration/restart_gitlab.md#installations-from-source "How to restart GitLab"
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 09c6211b3a..df8e8bdc47 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -81,7 +81,7 @@ errors during usage.
- More users? Run it on [multiple application servers](https://about.gitlab.com/high-availability/)
We recommend having at least 1GB of swap on your server, even if you currently have
-enough available RAM. Having swap will help reduce the chance of errors occurring
+enough available RAM. Having swap will help reduce the chance of errors occuring
if your available memory changes.
Notice: The 25 workers of Sidekiq will show up as separate processes in your process overview (such as top or htop) but they share the same RAM allocation since Sidekiq is a multithreaded application. Please see the section below about Unicorn workers for information about many you need of those.
@@ -150,4 +150,3 @@ On a very active server (10,000 active users) the Sidekiq process can use 1GB+ o
- Safari 7+ (known problem: required fields in html5 do not work)
- Opera (Latest released version)
- Internet Explorer (IE) 11+ but please make sure that you have the `Compatibility View` mode disabled.
-- Edge (Latest stable version)
diff --git a/doc/integration/README.md b/doc/integration/README.md
index fd330dd7a7..6fe04aa2a0 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -19,7 +19,7 @@ See the documentation below for details on how to configure these services.
GitLab Enterprise Edition contains [advanced Jenkins support][jenkins].
-[jenkins]: http://docs.gitlab.com/ee/integration/jenkins.html
+[jenkins]: http://doc.gitlab.com/ee/integration/jenkins.html
## Project services
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index e34e306f9a..e6b2071f19 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -27,18 +27,17 @@ To enable the CAS OmniAuth provider you must register your application with your
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name"=> "cas3",
- "label"=> "cas",
- "args"=> {
- "url"=> 'CAS_SERVER',
- "login_url"=> '/CAS_PATH/login',
- "service_validate_url"=> '/CAS_PATH/p3/serviceValidate',
- "logout_url"=> '/CAS_PATH/logout'
- }
+ name: "cas3",
+ label: "cas",
+ args: {
+ url: 'CAS_SERVER',
+ login_url: '/CAS_PATH/login',
+ service_validate_url: '/CAS_PATH/p3/serviceValidate',
+ logout_url: '/CAS_PATH/logout'} }
+ }
}
]
```
-
For installations from source:
@@ -58,8 +57,6 @@ To enable the CAS OmniAuth provider you must register your application with your
1. Save the configuration file.
-1. Run `gitlab-ctl reconfigure` for the omnibus package.
-
1. Restart GitLab for the changes to take effect.
On the sign in page there should now be a CAS tab in the sign in form.
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 82978b68a3..f9a20dd840 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -11,9 +11,9 @@ To enable the Google OAuth2 OmniAuth provider you must register your application
- Project ID: Must be unique to all Google Developer registered applications. Google provides a randomly generated Project ID by default. You can use the randomly generated ID or choose a new one.
1. Refresh the page. You should now see your new project in the list. Click on the project.
-1. Select the "Google APIs" tab in the Overview.
+1. Select "APIs & auth" in the left menu.
-1. Select and enable the following Google APIs - listed under "Popular APIs"
+1. Select "APIs" in the submenu.
- Enable `Contacts API`
- Enable `Google+ API`
diff --git a/doc/integration/img/enabled-oauth-sign-in-sources.png b/doc/integration/img/enabled-oauth-sign-in-sources.png
deleted file mode 100644
index 95f8bbdcd2..0000000000
Binary files a/doc/integration/img/enabled-oauth-sign-in-sources.png and /dev/null differ
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 820f40f81a..cab329c0de 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -11,7 +11,6 @@ of the configured mechanisms.
- [Supported Providers](#supported-providers)
- [Enable OmniAuth for an Existing User](#enable-omniauth-for-an-existing-user)
- [OmniAuth configuration sample when using Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master#omniauth-google-twitter-github-login)
-- [Enable or disable Sign In with an OmniAuth provider without disabling import sources](#enable-or-disable-sign-in-with-an-omniauth-provider-without-disabling-import-sources)
## Supported Providers
@@ -192,17 +191,3 @@ experience [in the public Wiki](https://github.com/gitlabhq/gitlab-public-wiki/w
While we can't officially support every possible authentication mechanism out there,
we'd like to at least help those with specific needs.
-
-## Enable or disable Sign In with an OmniAuth provider without disabling import sources
-
->**Note:**
-This setting was introduced with version 8.8 of GitLab.
-
-Administrators are able to enable or disable Sign In via some OmniAuth providers.
-
->**Note:**
-By default Sign In is enabled via all the OAuth Providers that have been configured in `config/gitlab.yml`.
-
-In order to enable/disable an OmniAuth provider, go to Admin Area -> Settings -> Sign-in Restrictions section -> Enabled OAuth Sign-In sources and select the providers you want to enable or disable.
-
-
diff --git a/doc/intro/README.md b/doc/intro/README.md
index 382d10aaf4..ab298d3808 100644
--- a/doc/intro/README.md
+++ b/doc/intro/README.md
@@ -39,4 +39,4 @@ Install and update your GitLab installation.
- [Install GitLab](https://about.gitlab.com/installation/)
- [Update GitLab](https://about.gitlab.com/update/)
-- [Explore Omnibus GitLab configuration options](http://docs.gitlab.com/omnibus/settings/configuration.html)
+- [Explore Omnibus GitLab configuration options](http://doc.gitlab.com/omnibus/settings/configuration.html)
diff --git a/doc/logs/logs.md b/doc/logs/logs.md
index f84060b8d0..27937e5176 100644
--- a/doc/logs/logs.md
+++ b/doc/logs/logs.md
@@ -1,6 +1,6 @@
## Log system
-GitLab has an advanced log system where everything is logged so that you can analyze your instance using various system log files.
-In addition to system log files, GitLab Enterprise Edition comes with Audit Events. Find more about them [in Audit Events documentation](http://docs.gitlab.com/ee/administration/audit_events.html)
+GitLab has advanced log system so everything is logging and you can analize your instance using various system log files.
+In addition to system log files, GitLab Enterprise Edition comes with Audit Events. Find more about them [in Audit Events documentation](http://doc.gitlab.com/ee/administration/audit_events.html)
System log files are typically plain text in a standard log file format. This guide talks about how to read and use these system log files.
@@ -67,13 +67,13 @@ gitlab-shell is using by Gitlab for executing git commands and provide ssh acces
```
I, [2015-02-13T06:17:00.671315 #9291] INFO -- : Adding project root/example.git at .
-I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and symlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git.
+I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and simlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git.
```
#### unicorn_stderr.log
This file lives in `/var/log/gitlab/unicorn/unicorn_stderr.log` for omnibus package or in `/home/git/gitlab/log/unicorn_stderr.log` for installations from the source.
-Unicorn is a high-performance forking Web server which is used for serving the GitLab application. You can look at this log if, for example, your application does not respond. This log contains all information about the state of unicorn processes at any given time.
+Unicorn is a high-performance forking Web server which is used for serving GitLab application. You can look at this log, for example, if your application does not respond. This log cantains all information about state of unicorn processes at any given time.
```
I, [2015-02-13T06:14:46.680381 #9047] INFO -- : Refreshing Gem list
diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md
index 236eb7b12c..4f199b6af6 100644
--- a/doc/markdown/markdown.md
+++ b/doc/markdown/markdown.md
@@ -8,7 +8,6 @@
* [Multiple underscores in words](#multiple-underscores-in-words)
* [URL auto-linking](#url-auto-linking)
* [Code and Syntax Highlighting](#code-and-syntax-highlighting)
-* [Inline Diff](#inline-diff)
* [Emoji](#emoji)
* [Special GitLab references](#special-gitlab-references)
* [Task lists](#task-lists)
@@ -154,19 +153,6 @@ s = "There is no highlighting for this."
But let's throw in a tag.
```
-## Inline Diff
-
-With inline diffs tags you can display {+ additions +} or [- deletions -].
-
-The wrapping tags can be either curly braces or square brackets [+ additions +] or {- deletions -}.
-
-However the wrapping tags cannot be mixed as such:
-
-- {+ additions +]
-- [+ additions +}
-- {- deletions -]
-- [- deletions -}
-
## Emoji
Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you:
@@ -199,23 +185,20 @@ GFM will turn that reference into a link so you can navigate between them easily
GFM will recognize the following:
-| input | references |
-|:-----------------------|:--------------------------- |
-| `@user_name` | specific user |
-| `@group_name` | specific group |
-| `@all` | entire team |
-| `#123` | issue |
-| `!123` | merge request |
-| `$123` | snippet |
-| `~123` | label by ID |
-| `~bug` | one-word label by name |
-| `~"feature request"` | multi-word label by name |
-| `%123` | milestone by ID |
-| `%v1.23` | one-word milestone by name |
-| `%"release candidate"` | multi-word milestone by name |
-| `9ba12248` | specific commit |
-| `9ba12248...b19a04f5` | commit range comparison |
-| `[README](doc/README)` | repository file references |
+| input | references |
+|:-----------------------|:---------------------------|
+| `@user_name` | specific user |
+| `@group_name` | specific group |
+| `@all` | entire team |
+| `#123` | issue |
+| `!123` | merge request |
+| `$123` | snippet |
+| `~123` | label by ID |
+| `~bug` | one-word label by name |
+| `~"feature request"` | multi-word label by name |
+| `9ba12248` | specific commit |
+| `9ba12248...b19a04f5` | commit range comparison |
+| `[README](doc/README)` | repository file references |
GFM also recognizes certain cross-project references:
@@ -223,7 +206,6 @@ GFM also recognizes certain cross-project references:
|:----------------------------------------|:------------------------|
| `namespace/project#123` | issue |
| `namespace/project!123` | merge request |
-| `namespace/project%123` | milestone |
| `namespace/project$123` | snippet |
| `namespace/project@9ba12248` | specific commit |
| `namespace/project@9ba12248...b19a04f5` | commit range comparison |
@@ -420,7 +402,7 @@ There are two ways to create links, inline-style and reference-style.
[I'm a reference-style link][Arbitrary case-insensitive reference text]
-[I'm a relative reference to a repository file](LICENSE)[^1]
+[I'm a relative reference to a repository file](LICENSE)
[You can use numbers for reference-style link definitions][1]
@@ -612,4 +594,3 @@ By including colons in the header row, you can align the text within that column
[rouge]: http://rouge.jneen.net/ "Rouge website"
[redcarpet]: https://github.com/vmg/redcarpet "Redcarpet website"
-[^1]: This link will be broken if you see this document from the Help page or docs.gitlab.com
diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md
index 8f9ef05494..5ec0a2069b 100644
--- a/doc/migrate_ci_to_ce/README.md
+++ b/doc/migrate_ci_to_ce/README.md
@@ -355,7 +355,7 @@ sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
```
#### Problems when importing CI database to GitLab
-If you were migrating CI database from MySQL to PostgreSQL manually you can see errors during import about missing sequences:
+If you were migrating CI database from MySQL to PostgreSQL manually you can see errros during import about missing sequences:
```
ALTER SEQUENCE
ERROR: relation "ci_builds_id_seq" does not exist
diff --git a/doc/monitoring/health_check.md b/doc/monitoring/health_check.md
deleted file mode 100644
index 0d17799372..0000000000
--- a/doc/monitoring/health_check.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# Health Check
-
->**Note:** This feature was [introduced][ce-3888] in GitLab 8.8.
-
-GitLab provides a health check endpoint for uptime monitoring on the `health_check` web
-endpoint. The health check reports on the overall system status based on the status of
-the database connection, the state of the database migrations, and the ability to write
-and access the cache. This endpoint can be provided to uptime monitoring services like
-[Pingdom][pingdom], [Nagios][nagios-health], and [NewRelic][newrelic-health].
-
-## Access Token
-
-An access token needs to be provided while accessing the health check endpoint. The current
-accepted token can be found on the `admin/health_check` page of your GitLab instance.
-
-
-
-The access token can be passed as a URL parameter:
-
-```
-https://gitlab.example.com/health_check.json?token=ACCESS_TOKEN
-```
-
-or as an HTTP header:
-
-```bash
-curl -H "TOKEN: ACCESS_TOKEN" https://gitlab.example.com/health_check.json
-```
-
-## Using the Endpoint
-
-Once you have the access token, health information can be retrieved as plain text, JSON,
-or XML using the `health_check` endpoint:
-
-- `https://gitlab.example.com/health_check?token=ACCESS_TOKEN`
-- `https://gitlab.example.com/health_check.json?token=ACCESS_TOKEN`
-- `https://gitlab.example.com/health_check.xml?token=ACCESS_TOKEN`
-
-You can also ask for the status of specific services:
-
-- `https://gitlab.example.com/health_check/cache.json?token=ACCESS_TOKEN`
-- `https://gitlab.example.com/health_check/database.json?token=ACCESS_TOKEN`
-- `https://gitlab.example.com/health_check/migrations.json?token=ACCESS_TOKEN`
-
-For example, the JSON output of the following health check:
-
-```bash
-curl -H "TOKEN: ACCESS_TOKEN" https://gitlab.example.com/health_check.json
-```
-
-would be like:
-
-```
-{"healthy":true,"message":"success"}
-```
-
-## Status
-
-On failure, the endpoint will return a `500` HTTP status code. On success, the endpoint
-will return a valid successful HTTP status code, and a `success` message. Ideally your
-uptime monitoring should look for the success message.
-
-[ce-3888]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3888
-[pingdom]: https://www.pingdom.com
-[nagios-health]: https://nagios-plugins.org/doc/man/check_http.html
-[newrelic-health]: https://docs.newrelic.com/docs/alerts/alert-policies/downtime-alerts/availability-monitoring
diff --git a/doc/monitoring/img/health_check_token.png b/doc/monitoring/img/health_check_token.png
deleted file mode 100644
index 2daf8606b0..0000000000
Binary files a/doc/monitoring/img/health_check_token.png and /dev/null differ
diff --git a/doc/operations/moving_repositories.md b/doc/operations/moving_repositories.md
index 54adb99386..39086b7a25 100644
--- a/doc/operations/moving_repositories.md
+++ b/doc/operations/moving_repositories.md
@@ -134,7 +134,7 @@ sudo -u git sh -c '
cat /var/opt/gitlab/transfer-logs/* | sort | uniq -u |\
/usr/bin/env JOBS=10 \
/opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
- /var/opt/gitlab/transfer-logs/success-$(date +%s).log \
+ /var/opt/gitlab/transfer-logs/succes-$(date +%s).log \
/var/opt/gitlab/git-data/repositories \
/mnt/gitlab/repositories
'
@@ -145,7 +145,7 @@ sudo -u git -H sh -c '
cat /home/git/transfer-logs/* | sort | uniq -u |\
/usr/bin/env JOBS=10 \
bin/parallel-rsync-repos \
- /home/git/transfer-logs/success-$(date +%s).log \
+ /home/git/transfer-logs/succes-$(date +%s).log \
/home/git/repositories \
/mnt/gitlab/repositories
`
@@ -164,7 +164,7 @@ sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
sudo -u git \
/usr/bin/env JOBS=10 \
/opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
- success-$(date +%s).log \
+ succes-$(date +%s).log \
/var/opt/gitlab/git-data/repositories \
/mnt/gitlab/repositories
@@ -174,7 +174,7 @@ sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
sudo -u git -H \
/usr/bin/env JOBS=10 \
bin/parallel-rsync-repos \
- success-$(date +%s).log \
+ succes-$(date +%s).log \
/home/git/repositories \
/mnt/gitlab/repositories
```
diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md
index b76ce31cba..6219693b8a 100644
--- a/doc/permissions/permissions.md
+++ b/doc/permissions/permissions.md
@@ -27,7 +27,6 @@ documentation](../workflow/add-user/add-user.md).
| Manage issue tracker | | ✓ | ✓ | ✓ | ✓ |
| Manage labels | | ✓ | ✓ | ✓ | ✓ |
| See a commit status | | ✓ | ✓ | ✓ | ✓ |
-| See a container registry | | ✓ | ✓ | ✓ | ✓ |
| Manage merge requests | | | ✓ | ✓ | ✓ |
| Create new merge request | | | ✓ | ✓ | ✓ |
| Create new branches | | | ✓ | ✓ | ✓ |
@@ -38,8 +37,6 @@ documentation](../workflow/add-user/add-user.md).
| Write a wiki | | | ✓ | ✓ | ✓ |
| Cancel and retry builds | | | ✓ | ✓ | ✓ |
| Create or update commit status | | | ✓ | ✓ | ✓ |
-| Update a container registry | | | ✓ | ✓ | ✓ |
-| Remove a container registry image | | | ✓ | ✓ | ✓ |
| Create new milestones | | | | ✓ | ✓ |
| Add new team members | | | | ✓ | ✓ |
| Push to protected branches | | | | ✓ | ✓ |
diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md
index a49c43b8ef..6be954ad68 100644
--- a/doc/raketasks/README.md
+++ b/doc/raketasks/README.md
@@ -8,4 +8,4 @@
- [User management](user_management.md)
- [Webhooks](web_hooks.md)
- [Import](import.md) of git repositories in bulk
-- [Rebuild authorized_keys file](http://docs.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators
+- [Rebuild authorized_keys file](http://doc.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators
diff --git a/doc/security/README.md b/doc/security/README.md
index 38706e48ec..4cd0fdd409 100644
--- a/doc/security/README.md
+++ b/doc/security/README.md
@@ -8,4 +8,3 @@
- [User File Uploads](user_file_uploads.md)
- [How we manage the CRIME vulnerability](crime_vulnerability.md)
- [Enforce Two-factor authentication](two_factor_authentication.md)
-- [Send email confirmation on sign-up](user_email_confirmation.md)
diff --git a/doc/security/user_email_confirmation.md b/doc/security/user_email_confirmation.md
deleted file mode 100644
index 4293944ae8..0000000000
--- a/doc/security/user_email_confirmation.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# User email confirmation at sign-up
-
-Gitlab admin can enable email confirmation on sign-up, if you want to confirm all
-user emails before they are able to sign-in.
-
-In the Admin area under **Settings** (`/admin/application_settings`), go to section
-**Sign-in Restrictions** and look for **Send confirmation email on sign-up** option.
diff --git a/doc/update/8.6-to-8.7.md b/doc/update/8.6-to-8.7.md
index bb463d43a7..4a2c6ea91d 100644
--- a/doc/update/8.6-to-8.7.md
+++ b/doc/update/8.6-to-8.7.md
@@ -86,14 +86,6 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
### 7. Update configuration files
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-6-stable:config/gitlab.yml.example origin/8-7-stable:config/gitlab.yml.example
-```
-
#### Git configuration
Disable `git gc --auto` because GitLab runs `git gc` for us already.
diff --git a/doc/update/8.7-to-8.8.md b/doc/update/8.7-to-8.8.md
deleted file mode 100644
index 32906650f6..0000000000
--- a/doc/update/8.7-to-8.8.md
+++ /dev/null
@@ -1,162 +0,0 @@
-# From 8.7 to 8.8
-
-Make sure you view this update guide from the tag (version) of GitLab you would
-like to install. In most cases this should be the highest numbered production
-tag (without rc in it). You can select the tag in the version dropdown at the
-top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
- sudo service gitlab stop
-
-### 2. Backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Get latest code
-
-```bash
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-```
-
-For GitLab Community Edition:
-
-```bash
-sudo -u git -H git checkout 8-8-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-sudo -u git -H git checkout 8-8-stable-ee
-```
-
-### 4. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v2.7.2
-```
-
-### 5. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. This requires
-[Go 1.5](https://golang.org/dl) which should already be on your system from
-GitLab 8.1.
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch --all
-sudo -u git -H git checkout v0.7.1
-sudo -u git -H make
-```
-
-### 6. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
-
-```
-
-### 7. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-git diff origin/8-7-stable:config/gitlab.yml.example origin/8-8-stable:config/gitlab.yml.example
-```
-
-#### Git configuration
-
-Disable `git gc --auto` because GitLab runs `git gc` for us already.
-
-```sh
-sudo -u git -H git config --global gc.auto 0
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-# For HTTPS configurations
-git diff origin/8-7-stable:lib/support/nginx/gitlab-ssl origin/8-8-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/8-7-stable:lib/support/nginx/gitlab origin/8-8-stable:lib/support/nginx/gitlab
-```
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/lib/support/init.d/gitlab.default.example#L37
-
-#### Init script
-
-Ensure you're still up-to-date with the latest init script changes:
-
- sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
-### 8. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-### 9. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-
-To make sure you didn't miss anything run a more thorough check:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (8.7)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 8.6 to 8.7](8.6-to-8.7.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
diff --git a/doc/update/README.md b/doc/update/README.md
index 975d72164b..a770633c9b 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -29,7 +29,7 @@ Based on your installation, choose a section below that fits your needs.
## Omnibus Packages
-- The [Omnibus update guide](http://docs.gitlab.com/omnibus/update/README.html)
+- The [Omnibus update guide](http://doc.gitlab.com/omnibus/update/README.html)
contains the steps needed to update an Omnibus GitLab package.
## Installation from source
@@ -86,10 +86,10 @@ possible.
information about configuring GitLab to work with a MySQL database.
- [Restoring from backup after a failed upgrade](restore_after_failure.md)
-[omnidocker]: http://docs.gitlab.com/omnibus/docker/README.html
+[omnidocker]: http://doc.gitlab.com/omnibus/docker/README.html
[source-ee]: https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc/update
[source-ce]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update
[ee-ce]: ../downgrade_ee_to_ce/README.md
[ce]: https://about.gitlab.com/features/#community
[ee]: https://about.gitlab.com/features/#enterprise
-[omni-ce-ee]: http://docs.gitlab.com/omnibus/update/README.html#from-community-edition-to-enterprise-edition
+[omni-ce-ee]: http://doc.gitlab.com/omnibus/update/README.html#from-community-edition-to-enterprise-edition
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index 60729316cd..b4283a526f 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -57,10 +57,10 @@ sudo -u git -H make
cd /home/git/gitlab
# PostgreSQL
-sudo -u git -H bundle install --without development test mysql --deployment
+sudo -u git -H bundle install --without development test mysql --with postgres --deployment
# MySQL
-sudo -u git -H bundle install --without development test postgres --deployment
+sudo -u git -H bundle install --without development test postgres --with mysql --deployment
# Optional: clean up old gems
sudo -u git -H bundle clean
diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md
index 8559b67af0..c1c51302e7 100644
--- a/doc/web_hooks/web_hooks.md
+++ b/doc/web_hooks/web_hooks.md
@@ -13,19 +13,6 @@ You can configure webhooks to listen for specific events like pushes, issues or
Webhooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
-## Webhook endpoint tips
-
-If you are writing your own endpoint (web server) that will receive
-GitLab webhooks keep in mind the following things:
-
-- Your endpoint should send its HTTP response as fast as possible. If
- you wait too long, GitLab may decide the hook failed and retry it.
-- Your endpoint should ALWAYS return a valid HTTP response. If you do
- not do this then GitLab will think the hook failed and retry it.
- Most HTTP libraries take care of this for you automatically but if
- you are writing a low-level hook this is important to remember.
-- GitLab ignores the HTTP status code returned by your endpoint.
-
## SSL Verification
By default, the SSL certificate of the webhook endpoint is verified based on
@@ -695,61 +682,6 @@ X-Gitlab-Event: Merge Request Hook
}
```
-## Wiki Page events
-
-Triggered when a wiki page is created or edited.
-
-**Request Header**:
-
-```
-X-Gitlab-Event: Wiki Page Hook
-```
-
-**Request Body**:
-
-```json
-{
- "object_kind": "wiki_page",
- "user": {
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon"
- },
- "project": {
- "name": "awesome-project",
- "description": "This is awesome",
- "web_url": "http://example.com/root/awesome-project",
- "avatar_url": null,
- "git_ssh_url": "git@example.com:root/awesome-project.git",
- "git_http_url": "http://example.com/root/awesome-project.git",
- "namespace": "root",
- "visibility_level": 0,
- "path_with_namespace": "root/awesome-project",
- "default_branch": "master",
- "homepage": "http://example.com/root/awesome-project",
- "url": "git@example.com:root/awesome-project.git",
- "ssh_url": "git@example.com:root/awesome-project.git",
- "http_url": "http://example.com/root/awesome-project.git"
- },
- "wiki": {
- "web_url": "http://example.com/root/awesome-project/wikis/home",
- "git_ssh_url": "git@example.com:root/awesome-project.wiki.git",
- "git_http_url": "http://example.com/root/awesome-project.wiki.git",
- "path_with_namespace": "root/awesome-project.wiki",
- "default_branch": "master"
- },
- "object_attributes": {
- "title": "Awesome",
- "content": "awesome content goes here",
- "format": "markdown",
- "message": "adding an awesome page to the wiki",
- "slug": "awesome",
- "url": "http://example.com/root/awesome-project/wikis/awesome",
- "action": "create"
- }
-}
-```
-
#### Example webhook receiver
If you want to see GitLab's webhooks in action for testing purposes you can use
diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md
index 2b2f140f8b..1b354bcc0f 100644
--- a/doc/workflow/gitlab_flow.md
+++ b/doc/workflow/gitlab_flow.md
@@ -131,7 +131,7 @@ When you feel comfortable with it to be merged you assign it to the person that
There is room for more feedback and after the assigned person feels comfortable with the result the branch is merged.
If the assigned person does not feel comfortable they can close the merge request without merging.
-In GitLab it is common to protect the long-lived branches (e.g. the master branch) so that normal developers [can't modify these protected branches](http://docs.gitlab.com/ce/permissions/permissions.html).
+In GitLab it is common to protect the long-lived branches (e.g. the master branch) so that normal developers [can't modify these protected branches](http://doc.gitlab.com/ce/permissions/permissions.html).
So if you want to merge it into a protected branch you assign it to someone with master authorizations.
## Issues with GitLab flow
@@ -187,7 +187,7 @@ If you have an issue that spans across multiple repositories, the best thing is

With git you can use an interactive rebase (`rebase -i`) to squash multiple commits into one and reorder them.
-In GitLab EE and .com you can also [rebase before merge](http://docs.gitlab.com/ee/workflow/rebase_before_merge.html) from the web interface.
+In GitLab EE and .com you can also [rebase before merge](http://doc.gitlab.com/ee/workflow/rebase_before_merge.html) from the web interface.
This functionality is useful if you made a couple of commits for small changes during development and want to replace them with a single commit or if you want to make the order more logical.
However you should never rebase commits you have pushed to a remote server.
Somebody can have referred to the commits or cherry-picked them.
diff --git a/doc/workflow/groups.md b/doc/workflow/groups.md
index 34ada1774d..52bf611dc5 100644
--- a/doc/workflow/groups.md
+++ b/doc/workflow/groups.md
@@ -54,7 +54,7 @@ If necessary, you can increase the access level of an individual user for a spec
## Managing group memberships via LDAP
In GitLab Enterprise Edition it is possible to manage GitLab group memberships using LDAP groups.
-See [the GitLab Enterprise Edition documentation](http://docs.gitlab.com/ee/integration/ldap.html) for more information.
+See [the GitLab Enterprise Edition documentation](http://doc.gitlab.com/ee/integration/ldap.html) for more information.
## Allowing only admins to create groups
diff --git a/doc/workflow/importing/import_projects_from_github.md b/doc/workflow/importing/import_projects_from_github.md
index a7dfac2c12..e670e415c7 100644
--- a/doc/workflow/importing/import_projects_from_github.md
+++ b/doc/workflow/importing/import_projects_from_github.md
@@ -44,5 +44,5 @@ case the namespace is taken, the project will be imported on the user's
namespace.
[gh-import]: ../../integration/github.md "GitHub integration"
-[ee-gh]: http://docs.gitlab.com/ee/integration/github.html "GitHub integration for GitLab EE"
+[ee-gh]: http://doc.gitlab.com/ee/integration/github.html "GitHub integration for GitLab EE"
[new-project]: ../../gitlab-basics/create-project.md "How to create a new project in GitLab"
diff --git a/doc/workflow/importing/import_projects_from_gitlab_com.md b/doc/workflow/importing/import_projects_from_gitlab_com.md
index dcc00074b7..1117db98e7 100644
--- a/doc/workflow/importing/import_projects_from_gitlab_com.md
+++ b/doc/workflow/importing/import_projects_from_gitlab_com.md
@@ -2,7 +2,7 @@
You can import your existing GitLab.com projects to your GitLab instance. But keep in mind that it is possible only if
GitLab support is enabled on your GitLab instance.
-You can read more about GitLab support [here](http://docs.gitlab.com/ce/integration/gitlab.html)
+You can read more about GitLab support [here](http://doc.gitlab.com/ce/integration/gitlab.html)
To get to the importer page you need to go to "New project" page.

diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
index 9fe065fa68..31620044b1 100644
--- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
+++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
@@ -4,7 +4,7 @@ Managing large files such as audio, video and graphics files has always been one
of the shortcomings of Git. The general recommendation is to not have Git repositories
larger than 1GB to preserve performance.
-GitLab already supports [managing large files with git annex](http://docs.gitlab.com/ee/workflow/git_annex.html)
+GitLab already supports [managing large files with git annex](http://doc.gitlab.com/ee/workflow/git_annex.html)
(EE only), however in certain environments it is not always convenient to use
different commands to differentiate between the large files and regular ones.
@@ -127,7 +127,7 @@ To prevent this from happening, set the lfs url in project Git config:
```bash
-git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs"
+git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs/objects/batch"
```
### Credentials are always required when pushing an object
@@ -152,4 +152,4 @@ If you are using OS X you can use `osxkeychain` to store and encrypt your creden
For Windows, you can use `wincred` or Microsoft's [Git Credential Manager for Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases).
More details about various methods of storing the user credentials can be found
-on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage).
+on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage).
\ No newline at end of file
diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md
index cbca94c0b5..80817c98d2 100644
--- a/doc/workflow/notifications.md
+++ b/doc/workflow/notifications.md
@@ -69,7 +69,7 @@ In all of the below cases, the notification will be sent to:
...with notification level "Participating" or higher
-- Watchers: users with notification level "Watch"
+- Watchers: project members with notification level "Watch"
- Subscribers: anyone who manually subscribed to the issue/merge request
| Event | Sent to |
diff --git a/features/project/active_tab.feature b/features/project/active_tab.feature
index 26e6750302..2fd097d100 100644
--- a/features/project/active_tab.feature
+++ b/features/project/active_tab.feature
@@ -10,9 +10,14 @@ Feature: Project Active Tab
Then the active main tab should be Home
And no other main tabs should be active
- Scenario: On Project Code
+ Scenario: On Project Files
Given I visit my project's files page
- Then the active main tab should be Code
+ Then the active main tab should be Files
+ And no other main tabs should be active
+
+ Scenario: On Project Commits
+ Given I visit my project's commits page
+ Then the active main tab should be Commits
And no other main tabs should be active
Scenario: On Project Issues
@@ -25,6 +30,11 @@ Feature: Project Active Tab
Then the active main tab should be Merge Requests
And no other main tabs should be active
+ Scenario: On Project Members
+ Given I visit my project's members page
+ Then the active main tab should be Members
+ And no other main tabs should be active
+
Scenario: On Project Wiki
Given I visit my project's wiki page
Then the active main tab should be Wiki
@@ -39,6 +49,13 @@ Feature: Project Active Tab
# Sub Tabs: Settings
+ Scenario: On Project Settings/Edit
+ Given I visit my project's settings page
+ And I click the "Edit" tab
+ Then the active sub nav should be Edit
+ And no other sub navs should be active
+ And the active main tab should be Settings
+
Scenario: On Project Settings/Hooks
Given I visit my project's settings page
And I click the "Hooks" tab
@@ -53,52 +70,40 @@ Feature: Project Active Tab
And no other sub navs should be active
And the active main tab should be Settings
- Scenario: On Project Members
- Given I visit my project's members page
- Then the active sub nav should be Members
- And no other sub navs should be active
- And the active main tab should be Settings
+ # Sub Tabs: Commits
- # Sub Tabs: Code
-
- Scenario: On Project Code/Files
- Given I visit my project's files page
- Then the active sub tab should be Files
- And no other sub tabs should be active
- And the active main tab should be Code
-
- Scenario: On Project Code/Commits
+ Scenario: On Project Commits/Commits
Given I visit my project's commits page
Then the active sub tab should be Commits
And no other sub tabs should be active
- And the active main tab should be Code
+ And the active main tab should be Commits
- Scenario: On Project Code/Network
+ Scenario: On Project Commits/Network
Given I visit my project's network page
Then the active sub tab should be Network
And no other sub tabs should be active
- And the active main tab should be Code
+ And the active main tab should be Commits
- Scenario: On Project Code/Compare
+ Scenario: On Project Commits/Compare
Given I visit my project's commits page
And I click the "Compare" tab
Then the active sub tab should be Compare
And no other sub tabs should be active
- And the active main tab should be Code
+ And the active main tab should be Commits
- Scenario: On Project Code/Branches
+ Scenario: On Project Commits/Branches
Given I visit my project's commits page
And I click the "Branches" tab
Then the active sub tab should be Branches
And no other sub tabs should be active
- And the active main tab should be Code
+ And the active main tab should be Commits
- Scenario: On Project Code/Tags
+ Scenario: On Project Commits/Tags
Given I visit my project's commits page
And I click the "Tags" tab
Then the active sub tab should be Tags
And no other sub tabs should be active
- And the active main tab should be Code
+ And the active main tab should be Commits
Scenario: On Project Issues/Browse
Given I visit my project's issues page
diff --git a/features/project/builds/summary.feature b/features/project/builds/summary.feature
index 550ebccf0d..3c029a973d 100644
--- a/features/project/builds/summary.feature
+++ b/features/project/builds/summary.feature
@@ -24,4 +24,3 @@ Feature: Project Builds Summary
Then recent build has been erased
And recent build summary does not have artifacts widget
And recent build summary contains information saying that build has been erased
- And the build count cache is updated
diff --git a/features/project/commits/tags.feature b/features/project/commits/tags.feature
new file mode 100644
index 0000000000..a4be39b2d4
--- /dev/null
+++ b/features/project/commits/tags.feature
@@ -0,0 +1,46 @@
+@project_commits
+Feature: Project Commits Tags
+ Background:
+ Given I sign in as a user
+ And I own project "Shop"
+ Given I visit project tags page
+
+ Scenario: I can see all git tags
+ Then I should see "Shop" all tags list
+
+ Scenario: I create a tag
+ And I click new tag link
+ And I submit new tag form
+ Then I should see new tag created
+
+ Scenario: I create a tag with release notes
+ Given I click new tag link
+ And I submit new tag form with release notes
+ Then I should see new tag created
+ And I should see tag release notes
+
+ Scenario: I create a tag with invalid name
+ And I click new tag link
+ And I submit new tag form with invalid name
+ Then I should see new an error that tag is invalid
+
+ Scenario: I create a tag with invalid reference
+ And I click new tag link
+ And I submit new tag form with invalid reference
+ Then I should see new an error that tag ref is invalid
+
+ Scenario: I create a tag that already exists
+ And I click new tag link
+ And I submit new tag form with tag that already exists
+ Then I should see new an error that tag already exists
+
+ Scenario: I delete a tag
+ Given I visit tag 'v1.1.0' page
+ Given I delete tag 'v1.1.0'
+ Then I should not see tag 'v1.1.0'
+
+ Scenario: I add release notes to the tag
+ Given I visit tag 'v1.1.0' page
+ When I click edit tag link
+ And I fill release notes and submit form
+ Then I should see tag release notes
diff --git a/features/project/create.feature b/features/project/create.feature
index 67336d73bf..27136798e3 100644
--- a/features/project/create.feature
+++ b/features/project/create.feature
@@ -6,9 +6,21 @@ Feature: Project Create
@javascript
Scenario: User create a project
+ Given I sign in as a user
+ When I visit new project page
+ And I have an ssh key
+ And fill project form with valid data
+ Then I should see project page
+ And I should see empty project instuctions
+
+ @javascript
+ Scenario: Empty project instructions
Given I sign in as a user
And I have an ssh key
When I visit new project page
And fill project form with valid data
- Then I should see project page
- And I should see empty project instructions
+ Then I see empty project instuctions
+ And I click on HTTP
+ Then Remote url should update to http link
+ And If I click on SSH
+ Then Remote url should update to ssh link
diff --git a/features/project/project.feature b/features/project/project.feature
index aa22401c88..f1f3ed2606 100644
--- a/features/project/project.feature
+++ b/features/project/project.feature
@@ -18,6 +18,15 @@ Feature: Project
Then I should see the default project avatar
And I should not see the "Remove avatar" button
+ Scenario: I should have back to group button
+ And project "Shop" belongs to group
+ And I visit project "Shop" page
+ Then I should see back to group button
+
+ Scenario: I should have back to group button
+ And I visit project "Shop" page
+ Then I should see back to dashboard button
+
Scenario: I should have readme on page
And I visit project "Shop" page
Then I should see project "Shop" README
diff --git a/features/project/shortcuts.feature b/features/project/shortcuts.feature
index c73d0b3233..10e7c23461 100644
--- a/features/project/shortcuts.feature
+++ b/features/project/shortcuts.feature
@@ -8,21 +8,19 @@ Feature: Project Shortcuts
@javascript
Scenario: Navigate to files tab
Given I press "g" and "f"
- Then the active main tab should be Code
- Then the active sub tab should be Files
+ Then the active main tab should be Files
@javascript
Scenario: Navigate to commits tab
Given I visit my project's files page
Given I press "g" and "c"
- Then the active main tab should be Code
- Then the active sub tab should be Commits
+ Then the active main tab should be Commits
@javascript
Scenario: Navigate to network tab
Given I press "g" and "n"
Then the active sub tab should be Network
- And the active main tab should be Code
+ And the active main tab should be Commits
@javascript
Scenario: Navigate to graphs tab
diff --git a/features/steps/admin/active_tab.rb b/features/steps/admin/active_tab.rb
index f2db180138..90d13abdb1 100644
--- a/features/steps/admin/active_tab.rb
+++ b/features/steps/admin/active_tab.rb
@@ -1,7 +1,7 @@
class Spinach::Features::AdminActiveTab < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
- include SharedSidebarActiveTab
+ include SharedActiveTab
step 'the active main tab should be Home' do
ensure_active_main_tab('Overview')
@@ -34,12 +34,4 @@ class Spinach::Features::AdminActiveTab < Spinach::FeatureSteps
step 'the active main tab should be Messages' do
ensure_active_main_tab('Messages')
end
-
- step 'no other main tabs should be active' do
- expect(page).to have_selector('.nav-sidebar > li.active', count: 1)
- end
-
- def ensure_active_main_tab(content)
- expect(find('.nav-sidebar > li.active')).to have_content(content)
- end
end
diff --git a/features/steps/admin/users.rb b/features/steps/admin/users.rb
index 8fb8a86d58..4bc290b6bd 100644
--- a/features/steps/admin/users.rb
+++ b/features/steps/admin/users.rb
@@ -158,7 +158,7 @@ class Spinach::Features::AdminUsers < Spinach::FeatureSteps
step 'I should not see twitter details' do
expect(page).to have_content 'Pete'
- expect(page).not_to have_content 'twitter'
+ expect(page).to_not have_content 'twitter'
end
step 'click on ssh keys tab' do
diff --git a/features/steps/dashboard/active_tab.rb b/features/steps/dashboard/active_tab.rb
index 04fe96cef2..0e2c04fb29 100644
--- a/features/steps/dashboard/active_tab.rb
+++ b/features/steps/dashboard/active_tab.rb
@@ -1,5 +1,9 @@
class Spinach::Features::DashboardActiveTab < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
- include SharedSidebarActiveTab
+ include SharedActiveTab
+
+ step 'the active main tab should be Help' do
+ ensure_active_main_tab('Help')
+ end
end
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
index 80ed4c6d64..b5980b3510 100644
--- a/features/steps/dashboard/dashboard.rb
+++ b/features/steps/dashboard/dashboard.rb
@@ -13,7 +13,7 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps
end
step 'I should see "Shop" project CI status' do
- expect(page).to have_link "Commit: skipped"
+ expect(page).to have_link "Build skipped"
end
step 'I should see last push widget' do
diff --git a/features/steps/dashboard/issues.rb b/features/steps/dashboard/issues.rb
index 8706f0e8e7..e21af72a77 100644
--- a/features/steps/dashboard/issues.rb
+++ b/features/steps/dashboard/issues.rb
@@ -74,7 +74,7 @@ class Spinach::Features::DashboardIssues < Spinach::FeatureSteps
def project
@project ||= begin
- project = create :project
+ project =create :project
project.team << [current_user, :master]
project
end
diff --git a/features/steps/dashboard/merge_requests.rb b/features/steps/dashboard/merge_requests.rb
index 06db36c701..a2adc87f8e 100644
--- a/features/steps/dashboard/merge_requests.rb
+++ b/features/steps/dashboard/merge_requests.rb
@@ -100,7 +100,7 @@ class Spinach::Features::DashboardMergeRequests < Spinach::FeatureSteps
def project
@project ||= begin
- project = create :project
+ project =create :project
project.team << [current_user, :master]
project
end
diff --git a/features/steps/dashboard/shortcuts.rb b/features/steps/dashboard/shortcuts.rb
index 118d27888d..a9083850b5 100644
--- a/features/steps/dashboard/shortcuts.rb
+++ b/features/steps/dashboard/shortcuts.rb
@@ -2,6 +2,5 @@ class Spinach::Features::DashboardShortcuts < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedProject
- include SharedSidebarActiveTab
- include SharedShortcuts
+ include SharedActiveTab
end
diff --git a/features/steps/dashboard/todos.rb b/features/steps/dashboard/todos.rb
index bd8a270202..2b23df6764 100644
--- a/features/steps/dashboard/todos.rb
+++ b/features/steps/dashboard/todos.rb
@@ -20,7 +20,7 @@ class Spinach::Features::DashboardTodos < Spinach::FeatureSteps
step 'I have todos' do
create(:todo, user: current_user, project: project, author: mary_jane, target: issue, action: Todo::MENTIONED)
create(:todo, user: current_user, project: project, author: john_doe, target: issue, action: Todo::ASSIGNED)
- note = create(:note, author: john_doe, noteable: issue, note: "#{current_user.to_reference} Wdyt?", project: project)
+ note = create(:note, author: john_doe, noteable: issue, note: "#{current_user.to_reference} Wdyt?")
create(:todo, user: current_user, project: project, author: john_doe, target: issue, action: Todo::MENTIONED, note: note)
create(:todo, user: current_user, project: project, author: john_doe, target: merge_request, action: Todo::ASSIGNED)
end
@@ -106,7 +106,7 @@ class Spinach::Features::DashboardTodos < Spinach::FeatureSteps
if pending
expect(page).to have_link 'Done'
else
- expect(page).not_to have_link 'Done'
+ expect(page).to_not have_link 'Done'
end
end
end
diff --git a/features/steps/profile/active_tab.rb b/features/steps/profile/active_tab.rb
index 4724a32627..3b59089a09 100644
--- a/features/steps/profile/active_tab.rb
+++ b/features/steps/profile/active_tab.rb
@@ -22,4 +22,8 @@ class Spinach::Features::ProfileActiveTab < Spinach::FeatureSteps
step 'the active main tab should be Audit Log' do
ensure_active_main_tab('Audit Log')
end
+
+ def ensure_active_main_tab(content)
+ expect(find('.layout-nav li.active')).to have_content(content)
+ end
end
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
index b1a87b96ef..909de31a47 100644
--- a/features/steps/profile/profile.rb
+++ b/features/steps/profile/profile.rb
@@ -166,7 +166,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
end
step 'I have group with projects' do
- @group = create(:group)
+ @group = create(:group)
@group.add_owner(current_user)
@project = create(:project, namespace: @group)
@event = create(:closed_issue_event, project: @project)
diff --git a/features/steps/project/active_tab.rb b/features/steps/project/active_tab.rb
index 745fd3471c..19d81453d8 100644
--- a/features/steps/project/active_tab.rb
+++ b/features/steps/project/active_tab.rb
@@ -16,14 +16,12 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
end
step 'I click the "Snippets" tab' do
- page.within('.layout-nav') do
- click_link('Snippets')
- end
+ click_link('Snippets')
end
- step 'I click the "Edit Project"' do
- page.within '.layout-nav .controls' do
- click_link('Edit Project')
+ step 'I click the "Edit" tab' do
+ page.within '.sidebar-subnav' do
+ click_link('Project Settings')
end
end
@@ -35,10 +33,14 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
click_link('Deploy Keys')
end
- step 'the active sub nav should be Members' do
+ step 'the active sub nav should be Team' do
ensure_active_sub_nav('Members')
end
+ step 'the active sub nav should be Edit' do
+ ensure_active_sub_nav('Project')
+ end
+
step 'the active sub nav should be Hooks' do
ensure_active_sub_nav('Webhooks')
end
@@ -54,15 +56,17 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
end
step 'I click the "Branches" tab' do
- page.within '.content' do
- click_link('Branches')
- end
+ click_link('Branches')
end
step 'I click the "Tags" tab' do
click_link('Tags')
end
+ step 'the active sub tab should be Commits' do
+ ensure_active_sub_tab('Commits')
+ end
+
step 'the active sub tab should be Compare' do
ensure_active_sub_tab('Compare')
end
@@ -78,15 +82,11 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
# Sub Tabs: Issues
step 'I click the "Milestones" tab' do
- page.within('.layout-nav') do
- click_link('Milestones')
- end
+ click_link('Milestones')
end
step 'I click the "Labels" tab' do
- page.within('.layout-nav') do
- click_link('Labels')
- end
+ click_link('Labels')
end
step 'the active sub tab should be Issues' do
diff --git a/features/steps/project/builds/summary.rb b/features/steps/project/builds/summary.rb
index 374eb0b0e0..e9e2359146 100644
--- a/features/steps/project/builds/summary.rb
+++ b/features/steps/project/builds/summary.rb
@@ -36,8 +36,4 @@ class Spinach::Features::ProjectBuildsSummary < Spinach::FeatureSteps
expect(page).to have_content 'Build has been erased'
end
end
-
- step 'the build count cache is updated' do
- expect(@build.project.running_or_pending_build_count).to eq @build.project.builds.running_or_pending.count(:all)
- end
end
diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb
index e1b29f1e57..93c37bf507 100644
--- a/features/steps/project/commits/commits.rb
+++ b/features/steps/project/commits/commits.rb
@@ -105,7 +105,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
end
step 'I should not see button to create a new merge request' do
- expect(page).not_to have_link 'Create Merge Request'
+ expect(page).to_not have_link 'Create Merge Request'
end
step 'I should see button to the merge request' do
@@ -173,7 +173,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
end
step 'I see commit ci info' do
- expect(page).to have_content "Builds for 1 pipeline pending"
+ expect(page).to have_content "build: pending"
end
step 'I click status link' do
@@ -181,7 +181,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
end
step 'I see builds list' do
- expect(page).to have_content "Builds for 1 pipeline pending"
+ expect(page).to have_content "build: pending"
expect(page).to have_content "1 build"
end
diff --git a/features/steps/project/commits/tags.rb b/features/steps/project/commits/tags.rb
new file mode 100644
index 0000000000..912ba580ef
--- /dev/null
+++ b/features/steps/project/commits/tags.rb
@@ -0,0 +1,90 @@
+class Spinach::Features::ProjectCommitsTags < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+
+ step 'I should see "Shop" all tags list' do
+ expect(page).to have_content "Tags"
+ expect(page).to have_content "v1.0.0"
+ end
+
+ step 'I click new tag link' do
+ click_link 'New tag'
+ end
+
+ step 'I submit new tag form' do
+ fill_in 'tag_name', with: 'v7.0'
+ fill_in 'ref', with: 'master'
+ click_button 'Create tag'
+ end
+
+ step 'I submit new tag form with release notes' do
+ fill_in 'tag_name', with: 'v7.0'
+ fill_in 'ref', with: 'master'
+ fill_in 'release_description', with: 'Awesome release notes'
+ click_button 'Create tag'
+ end
+
+ step 'I fill release notes and submit form' do
+ fill_in 'release_description', with: 'Awesome release notes'
+ click_button 'Save changes'
+ end
+
+ step 'I submit new tag form with invalid name' do
+ fill_in 'tag_name', with: 'v 1.0'
+ fill_in 'ref', with: 'master'
+ click_button 'Create tag'
+ end
+
+ step 'I submit new tag form with invalid reference' do
+ fill_in 'tag_name', with: 'foo'
+ fill_in 'ref', with: 'foo'
+ click_button 'Create tag'
+ end
+
+ step 'I submit new tag form with tag that already exists' do
+ fill_in 'tag_name', with: 'v1.0.0'
+ fill_in 'ref', with: 'master'
+ click_button 'Create tag'
+ end
+
+ step 'I should see new tag created' do
+ expect(page).to have_content 'v7.0'
+ end
+
+ step 'I should see new an error that tag is invalid' do
+ expect(page).to have_content 'Tag name invalid'
+ end
+
+ step 'I should see new an error that tag ref is invalid' do
+ expect(page).to have_content 'Target foo is invalid'
+ end
+
+ step 'I should see new an error that tag already exists' do
+ expect(page).to have_content 'Tag v1.0.0 already exists'
+ end
+
+ step "I visit tag 'v1.1.0' page" do
+ click_link 'v1.1.0'
+ end
+
+ step "I delete tag 'v1.1.0'" do
+ page.within('.content') do
+ first('.btn-remove').click
+ end
+ end
+
+ step "I should not see tag 'v1.1.0'" do
+ page.within '.tags' do
+ expect(page).not_to have_link 'v1.1.0'
+ end
+ end
+
+ step 'I click edit tag link' do
+ click_link 'Edit release notes'
+ end
+
+ step 'I should see tag release notes' do
+ expect(page).to have_content 'Awesome release notes'
+ end
+end
diff --git a/features/steps/project/create.rb b/features/steps/project/create.rb
index 5f5f806df3..422b151eaa 100644
--- a/features/steps/project/create.rb
+++ b/features/steps/project/create.rb
@@ -13,9 +13,33 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps
expect(current_path).to eq namespace_project_path(Project.last.namespace, Project.last)
end
- step 'I should see empty project instructions' do
+ step 'I should see empty project instuctions' do
expect(page).to have_content "git init"
expect(page).to have_content "git remote"
expect(page).to have_content Project.last.url_to_repo
end
+
+ step 'I see empty project instuctions' do
+ expect(page).to have_content "git init"
+ expect(page).to have_content "git remote"
+ expect(page).to have_content Project.last.url_to_repo
+ end
+
+ step 'I click on HTTP' do
+ find('#clone-dropdown').click
+ find('.http-selector').click
+ end
+
+ step 'Remote url should update to http link' do
+ expect(page).to have_content "git remote add origin #{Project.last.http_url_to_repo}"
+ end
+
+ step 'If I click on SSH' do
+ find('#clone-dropdown').click
+ find('.ssh-selector').click
+ end
+
+ step 'Remote url should update to ssh link' do
+ expect(page).to have_content "git remote add origin #{Project.last.url_to_repo}"
+ end
end
diff --git a/features/steps/project/fork.rb b/features/steps/project/fork.rb
index 8abeb5ee24..527f7853da 100644
--- a/features/steps/project/fork.rb
+++ b/features/steps/project/fork.rb
@@ -36,7 +36,7 @@ class Spinach::Features::ProjectFork < Spinach::FeatureSteps
end
step 'I goto the Merge Requests page' do
- page.within '.layout-nav' do
+ page.within '.page-sidebar-expanded' do
click_link "Merge Requests"
end
end
diff --git a/features/steps/project/hooks.rb b/features/steps/project/hooks.rb
index 13c0713669..b1ffe7f7b4 100644
--- a/features/steps/project/hooks.rb
+++ b/features/steps/project/hooks.rb
@@ -59,7 +59,7 @@ class Spinach::Features::ProjectHooks < Spinach::FeatureSteps
step 'hook should be triggered' do
expect(current_path).to eq namespace_project_hooks_path(current_project.namespace, current_project)
expect(page).to have_selector '.flash-notice',
- text: 'Hook executed successfully: HTTP 200'
+ text: 'Hook successfully executed.'
end
step 'I should see hook error message' do
diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb
index 1b14659b4d..c5d45709b4 100644
--- a/features/steps/project/issues/award_emoji.rb
+++ b/features/steps/project/issues/award_emoji.rb
@@ -39,8 +39,8 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps
step 'I can see the activity and food categories' do
page.within '.emoji-menu' do
- expect(page).not_to have_selector 'Activity'
- expect(page).not_to have_selector 'Food'
+ expect(page).to_not have_selector 'Activity'
+ expect(page).to_not have_selector 'Food'
end
end
diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb
index 5cd431e05d..fc12843ea5 100644
--- a/features/steps/project/issues/issues.rb
+++ b/features/steps/project/issues/issues.rb
@@ -216,7 +216,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
page.within 'li.issue:nth-child(3)' do
expect(page).to have_content 'Bugfix'
- expect(page).not_to have_content '0 0'
+ expect(page).to_not have_content '0 0'
end
end
end
@@ -235,7 +235,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
page.within 'li.issue:nth-child(3)' do
expect(page).to have_content 'Bugfix'
- expect(page).not_to have_content '0 0'
+ expect(page).to_not have_content '0 0'
end
end
end
@@ -348,7 +348,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
step 'another user adds a comment with text "Yay!" to issue "Release 0.4"' do
issue = Issue.find_by!(title: 'Release 0.4')
- create(:note_on_issue, noteable: issue, project: project, note: 'Yay!')
+ create(:note_on_issue, noteable: issue, note: 'Yay!')
end
step 'I should see a new comment with text "Yay!"' do
diff --git a/features/steps/project/issues/labels.rb b/features/steps/project/issues/labels.rb
index 8d87f6a7a5..0ca2d6257c 100644
--- a/features/steps/project/issues/labels.rb
+++ b/features/steps/project/issues/labels.rb
@@ -24,8 +24,8 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps
step 'I should see labels help message' do
page.within '.labels' do
- expect(page).to have_content 'Create a label or generate a default set '\
- 'of labels'
+ expect(page).to have_content 'Create first label or generate default set of '\
+ 'labels'
end
end
diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb
index b30346790e..3b1a00f628 100644
--- a/features/steps/project/merge_requests.rb
+++ b/features/steps/project/merge_requests.rb
@@ -203,7 +203,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
page.within 'li.merge-request:nth-child(3)' do
expect(page).to have_content 'Bug NS-05'
- expect(page).not_to have_content '0 0'
+ expect(page).to_not have_content '0 0'
end
end
end
@@ -222,7 +222,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
page.within 'li.merge-request:nth-child(3)' do
expect(page).to have_content 'Bug NS-05'
- expect(page).not_to have_content '0 0'
+ expect(page).to_not have_content '0 0'
end
end
end
@@ -273,7 +273,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
step 'user "John Doe" leaves a comment like "Line is wrong" on diff' do
mr = MergeRequest.find_by(title: "Bug NS-05")
create(:note_on_merge_request_diff, project: project,
- noteable: mr,
+ noteable_id: mr.id,
author: user_exists("John Doe"),
line_code: sample_commit.line_code,
note: 'Line is wrong')
@@ -525,7 +525,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
step 'I should see merge request "Bug NS-05" with CI status' do
page.within ".mr-list" do
- expect(page).to have_link "Pipeline: pending"
+ expect(page).to have_link "Build pending"
end
end
@@ -567,7 +567,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
click_diff_line(sample_compare.changes[1][:line_code])
end
- def have_visible_content(text)
+ def have_visible_content (text)
have_css("*", text: text, visible: true)
end
diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb
index a1785311c2..ef185861e0 100644
--- a/features/steps/project/project.rb
+++ b/features/steps/project/project.rb
@@ -114,9 +114,7 @@ class Spinach::Features::Project < Spinach::FeatureSteps
end
step 'I should not see "Snippets" button' do
- page.within '.content' do
- expect(page).not_to have_link 'Snippets'
- end
+ expect(page).not_to have_link 'Snippets'
end
step 'project "Shop" belongs to group' do
@@ -125,6 +123,14 @@ class Spinach::Features::Project < Spinach::FeatureSteps
@project.save!
end
+ step 'I should see back to dashboard button' do
+ expect(page).to have_content 'Go to dashboard'
+ end
+
+ step 'I should see back to group button' do
+ expect(page).to have_content 'Go to group'
+ end
+
step 'I click notifications drop down button' do
click_link 'notifications-button'
end
diff --git a/features/steps/project/project_find_file.rb b/features/steps/project/project_find_file.rb
index 47de4b91df..8c1d09d6cc 100644
--- a/features/steps/project/project_find_file.rb
+++ b/features/steps/project/project_find_file.rb
@@ -13,12 +13,12 @@ class Spinach::Features::ProjectFindFile < Spinach::FeatureSteps
end
step 'I should see "find file" page' do
- ensure_active_main_tab('Code')
+ ensure_active_main_tab('Files')
expect(page).to have_selector('.file-finder-holder', count: 1)
end
step 'I fill in Find by path with "git"' do
- ensure_active_main_tab('Code')
+ ensure_active_main_tab('Files')
expect(page).to have_selector('.file-finder-holder', count: 1)
end
diff --git a/features/steps/project/project_milestone.rb b/features/steps/project/project_milestone.rb
index 1864b3a2b5..2508c09e36 100644
--- a/features/steps/project/project_milestone.rb
+++ b/features/steps/project/project_milestone.rb
@@ -52,7 +52,7 @@ class Spinach::Features::ProjectMilestone < Spinach::FeatureSteps
end
step 'I click link "Labels"' do
- page.within('.layout-nav .nav-links') do
+ page.within('.nav-links') do
page.find(:xpath, "//a[@href='#tab-labels']").click
end
end
diff --git a/features/steps/project/project_shortcuts.rb b/features/steps/project/project_shortcuts.rb
index 8143b01ca4..49e9c5520b 100644
--- a/features/steps/project/project_shortcuts.rb
+++ b/features/steps/project/project_shortcuts.rb
@@ -3,7 +3,6 @@ class Spinach::Features::ProjectShortcuts < Spinach::FeatureSteps
include SharedPaths
include SharedProject
include SharedProjectTab
- include SharedShortcuts
step 'I press "g" and "f"' do
find('body').native.send_key('g')
diff --git a/features/steps/project/snippets.rb b/features/steps/project/snippets.rb
index beb8ecfc79..786a0cad97 100644
--- a/features/steps/project/snippets.rb
+++ b/features/steps/project/snippets.rb
@@ -43,12 +43,12 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps
step 'I click link "Edit"' do
page.within ".detail-page-header" do
- first(:link, "Edit").click
+ click_link "Edit"
end
end
step 'I click link "Delete"' do
- first(:link, "Delete").click
+ click_link "Delete"
end
step 'I submit new snippet "Snippet three"' do
diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb
index 2c0498de3b..c26d7a1521 100644
--- a/features/steps/project/source/browse_files.rb
+++ b/features/steps/project/source/browse_files.rb
@@ -337,15 +337,13 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
end
step 'I should see buttons for allowed commands' do
- page.within '.content' do
- expect(page).to have_content 'Raw'
- expect(page).to have_content 'History'
- expect(page).to have_content 'Permalink'
- expect(page).not_to have_content 'Edit'
- expect(page).not_to have_content 'Blame'
- expect(page).to have_content 'Delete'
- expect(page).to have_content 'Replace'
- end
+ expect(page).to have_content 'Raw'
+ expect(page).to have_content 'History'
+ expect(page).to have_content 'Permalink'
+ expect(page).not_to have_content 'Edit'
+ expect(page).not_to have_content 'Blame'
+ expect(page).to have_content 'Delete'
+ expect(page).to have_content 'Replace'
end
step 'I should see a notice about a new fork having been created' do
diff --git a/features/steps/project/team_management.rb b/features/steps/project/team_management.rb
index c6ced74737..3fbcf770b6 100644
--- a/features/steps/project/team_management.rb
+++ b/features/steps/project/team_management.rb
@@ -126,7 +126,7 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps
step 'I share project with group "OpenSource"' do
project = Project.find_by(name: 'Shop')
- os_group = create(:group, name: 'OpenSource')
+ os_group = create(:group, name: 'OpenSource')
create(:project, group: os_group)
@os_user1 = create(:user)
@os_user2 = create(:user)
diff --git a/features/steps/shared/active_tab.rb b/features/steps/shared/active_tab.rb
index ace717b990..0bee91d758 100644
--- a/features/steps/shared/active_tab.rb
+++ b/features/steps/shared/active_tab.rb
@@ -2,7 +2,7 @@ module SharedActiveTab
include Spinach::DSL
def ensure_active_main_tab(content)
- expect(find('.layout-nav li.active')).to have_content(content)
+ expect(find('.nav-sidebar > li.active')).to have_content(content)
end
def ensure_active_sub_tab(content)
@@ -10,11 +10,11 @@ module SharedActiveTab
end
def ensure_active_sub_nav(content)
- expect(find('.layout-nav .controls li.active')).to have_content(content)
+ expect(find('.sidebar-subnav > li.active')).to have_content(content)
end
step 'no other main tabs should be active' do
- expect(page).to have_selector('.layout-nav .nav-links > li.active', count: 1)
+ expect(page).to have_selector('.nav-sidebar > li.active', count: 1)
end
step 'no other sub tabs should be active' do
@@ -22,6 +22,26 @@ module SharedActiveTab
end
step 'no other sub navs should be active' do
- expect(page).to have_selector('.layout-nav .controls li.active', count: 1)
+ expect(page).to have_selector('.sidebar-subnav > li.active', count: 1)
+ end
+
+ step 'the active main tab should be Home' do
+ ensure_active_main_tab('Projects')
+ end
+
+ step 'the active main tab should be Projects' do
+ ensure_active_main_tab('Projects')
+ end
+
+ step 'the active main tab should be Issues' do
+ ensure_active_main_tab('Issues')
+ end
+
+ step 'the active main tab should be Merge Requests' do
+ ensure_active_main_tab('Merge Requests')
+ end
+
+ step 'the active main tab should be Help' do
+ ensure_active_main_tab('Help')
end
end
diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb
index e8b1e4b487..e846c52d47 100644
--- a/features/steps/shared/diff_note.rb
+++ b/features/steps/shared/diff_note.rb
@@ -23,7 +23,7 @@ module SharedDiffNote
page.within(diff_file_selector) do
click_diff_line(sample_commit.line_code)
- page.within("form[id$='#{sample_commit.line_code}-true']") do
+ page.within("form[id$='#{sample_commit.line_code}']") do
fill_in "note[note]", with: "Typo, please fix"
find(".js-comment-button").trigger("click")
sleep 0.05
@@ -33,7 +33,7 @@ module SharedDiffNote
step 'I leave a diff comment in a parallel view on the left side like "Old comment"' do
click_parallel_diff_line(sample_commit.line_code, 'old')
- page.within("#{diff_file_selector} form[id$='#{sample_commit.line_code}-true']") do
+ page.within("#{diff_file_selector} form[id$='#{sample_commit.line_code}']") do
fill_in "note[note]", with: "Old comment"
find(".js-comment-button").trigger("click")
end
@@ -41,7 +41,7 @@ module SharedDiffNote
step 'I leave a diff comment in a parallel view on the right side like "New comment"' do
click_parallel_diff_line(sample_commit.line_code, 'new')
- page.within("#{diff_file_selector} form[id$='#{sample_commit.line_code}-true']") do
+ page.within("#{diff_file_selector} form[id$='#{sample_commit.line_code}']") do
fill_in "note[note]", with: "New comment"
find(".js-comment-button").trigger("click")
end
@@ -51,7 +51,7 @@ module SharedDiffNote
page.within(diff_file_selector) do
click_diff_line(sample_commit.line_code)
- page.within("form[id$='#{sample_commit.line_code}-true']") do
+ page.within("form[id$='#{sample_commit.line_code}']") do
fill_in "note[note]", with: "Should fix it :smile:"
find('.js-md-preview-button').click
end
@@ -62,7 +62,7 @@ module SharedDiffNote
page.within(diff_file_selector) do
click_diff_line(sample_commit.del_line_code)
- page.within("form[id$='#{sample_commit.del_line_code}-true']") do
+ page.within("form[id$='#{sample_commit.del_line_code}']") do
fill_in "note[note]", with: "DRY this up"
find('.js-md-preview-button').click
end
@@ -91,7 +91,7 @@ module SharedDiffNote
page.within(diff_file_selector) do
click_diff_line(sample_commit.line_code)
- page.within("form[id$='#{sample_commit.line_code}-true']") do
+ page.within("form[id$='#{sample_commit.line_code}']") do
fill_in 'note[note]', with: ':smile:'
click_button('Comment')
end
diff --git a/features/steps/shared/issuable.rb b/features/steps/shared/issuable.rb
index 733e80b727..a58b3cb7e1 100644
--- a/features/steps/shared/issuable.rb
+++ b/features/steps/shared/issuable.rb
@@ -111,7 +111,7 @@ module SharedIssuable
step 'I sort the list by "Oldest updated"' do
find('button.dropdown-toggle.btn').click
- page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
+ page.within('ul.dropdown-menu.dropdown-menu-align-right li') do
click_link "Oldest updated"
end
end
@@ -119,7 +119,7 @@ module SharedIssuable
step 'I sort the list by "Least popular"' do
find('button.dropdown-toggle.btn').click
- page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
+ page.within('ul.dropdown-menu.dropdown-menu-align-right li') do
click_link 'Least popular'
end
end
@@ -127,13 +127,13 @@ module SharedIssuable
step 'I sort the list by "Most popular"' do
find('button.dropdown-toggle.btn').click
- page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
+ page.within('ul.dropdown-menu.dropdown-menu-align-right li') do
click_link 'Most popular'
end
end
step 'The list should be sorted by "Oldest updated"' do
- page.within('.content div.dropdown.inline.prepend-left-10') do
+ page.within('div.dropdown.inline.prepend-left-10') do
expect(page.find('button.dropdown-toggle.btn')).to have_content('Oldest updated')
end
end
diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb
index 3d7c6ef9d2..a3c3887ab4 100644
--- a/features/steps/shared/note.rb
+++ b/features/steps/shared/note.rb
@@ -107,7 +107,7 @@ module SharedNote
end
step 'I should see no notes at all' do
- expect(page).not_to have_css('.note')
+ expect(page).to_not have_css('.note')
end
# Markdown
diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb
index ce9ea7ee18..ea5f958030 100644
--- a/features/steps/shared/project.rb
+++ b/features/steps/shared/project.rb
@@ -95,7 +95,7 @@ module SharedProject
step 'I should see project settings' do
expect(current_path).to eq edit_namespace_project_path(@project.namespace, @project)
expect(page).to have_content("Project name")
- expect(page).to have_content("Features")
+ expect(page).to have_content("Features:")
end
def current_project
diff --git a/features/steps/shared/project_tab.rb b/features/steps/shared/project_tab.rb
index bfee879330..4fc2ece79f 100644
--- a/features/steps/shared/project_tab.rb
+++ b/features/steps/shared/project_tab.rb
@@ -8,8 +8,12 @@ module SharedProjectTab
ensure_active_main_tab('Project')
end
- step 'the active main tab should be Code' do
- ensure_active_main_tab('Code')
+ step 'the active main tab should be Files' do
+ ensure_active_main_tab('Files')
+ end
+
+ step 'the active main tab should be Commits' do
+ ensure_active_main_tab('Commits')
end
step 'the active main tab should be Graphs' do
@@ -37,7 +41,9 @@ module SharedProjectTab
end
step 'the active main tab should be Settings' do
- expect(page).to have_selector('.layout-nav .nav-links > li.active', count: 0)
+ page.within '.nav-sidebar' do
+ expect(page).to have_content('Go to project')
+ end
end
step 'the active main tab should be Activity' do
@@ -47,12 +53,4 @@ module SharedProjectTab
step 'the active sub tab should be Network' do
ensure_active_sub_tab('Network')
end
-
- step 'the active sub tab should be Files' do
- ensure_active_sub_tab('Files')
- end
-
- step 'the active sub tab should be Commits' do
- ensure_active_sub_tab('Commits')
- end
end
diff --git a/features/steps/shared/shortcuts.rb b/features/steps/shared/shortcuts.rb
index a75a8474d2..bbb7afec0a 100644
--- a/features/steps/shared/shortcuts.rb
+++ b/features/steps/shared/shortcuts.rb
@@ -1,4 +1,4 @@
-module SharedShortcuts
+module SharedActiveTab
include Spinach::DSL
step 'I press "g" and "p"' do
diff --git a/features/steps/shared/sidebar_active_tab.rb b/features/steps/shared/sidebar_active_tab.rb
deleted file mode 100644
index 5c47238777..0000000000
--- a/features/steps/shared/sidebar_active_tab.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-module SharedSidebarActiveTab
- include Spinach::DSL
-
- step 'the active main tab should be Help' do
- ensure_active_main_tab('Help')
- end
-
- step 'no other main tabs should be active' do
- expect(page).to have_selector('.nav-sidebar > li.active', count: 1)
- end
-
- def ensure_active_main_tab(content)
- expect(find('.nav-sidebar li.active')).to have_content(content)
- end
-
- step 'the active main tab should be Home' do
- ensure_active_main_tab('Projects')
- end
-
- step 'the active main tab should be Projects' do
- ensure_active_main_tab('Projects')
- end
-
- step 'the active main tab should be Issues' do
- ensure_active_main_tab('Issues')
- end
-
- step 'the active main tab should be Merge Requests' do
- ensure_active_main_tab('Merge Requests')
- end
-
- step 'the active main tab should be Help' do
- ensure_active_main_tab('Help')
- end
-end
diff --git a/features/steps/snippets/snippets.rb b/features/steps/snippets/snippets.rb
index 19366b1107..023032e679 100644
--- a/features/steps/snippets/snippets.rb
+++ b/features/steps/snippets/snippets.rb
@@ -14,12 +14,12 @@ class Spinach::Features::Snippets < Spinach::FeatureSteps
step 'I click link "Edit"' do
page.within ".detail-page-header" do
- first(:link, "Edit").click
+ click_link "Edit"
end
end
step 'I click link "Delete"' do
- first(:link, "Delete").click
+ click_link "Delete"
end
step 'I submit new snippet "Personal snippet three"' do
diff --git a/features/steps/user.rb b/features/steps/user.rb
index 59385a6ab5..b1d088f07f 100644
--- a/features/steps/user.rb
+++ b/features/steps/user.rb
@@ -34,7 +34,7 @@ class Spinach::Features::User < Spinach::FeatureSteps
end
step 'I should see contributions calendar' do
- expect(page).to have_css('.js-contrib-calendar')
+ expect(page).to have_css('.cal-heatmap-container')
end
def contributed_project
diff --git a/generator_templates/active_record/migration/create_table_migration.rb b/generator_templates/active_record/migration/create_table_migration.rb
deleted file mode 100644
index 27acc75dcc..0000000000
--- a/generator_templates/active_record/migration/create_table_migration.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class <%= migration_class_name %> < ActiveRecord::Migration
- include Gitlab::Database::MigrationHelpers
-
- # When using the methods "add_concurrent_index" or "add_column_with_default"
- # you must disable the use of transactions as these methods can not run in an
- # existing transaction. When using "add_concurrent_index" make sure that this
- # method is the _only_ method called in the migration, any other changes
- # should go in a separate migration. This ensures that upon failure _only_ the
- # index creation fails and can be retried or reverted easily.
- #
- # To disable transactions uncomment the following line and remove these
- # comments:
- # disable_ddl_transaction!
-
- def change
- create_table :<%= table_name %> do |t|
-<% attributes.each do |attribute| -%>
-<% if attribute.password_digest? -%>
- t.string :password_digest<%= attribute.inject_options %>
-<% else -%>
- t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
-<% end -%>
-<% end -%>
-<% if options[:timestamps] %>
- t.timestamps null: false
-<% end -%>
- end
-<% attributes_with_index.each do |attribute| -%>
- add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
-<% end -%>
- end
-end
diff --git a/generator_templates/active_record/migration/migration.rb b/generator_templates/active_record/migration/migration.rb
deleted file mode 100644
index 06bdea1136..0000000000
--- a/generator_templates/active_record/migration/migration.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class <%= migration_class_name %> < ActiveRecord::Migration
- include Gitlab::Database::MigrationHelpers
-
- # When using the methods "add_concurrent_index" or "add_column_with_default"
- # you must disable the use of transactions as these methods can not run in an
- # existing transaction. When using "add_concurrent_index" make sure that this
- # method is the _only_ method called in the migration, any other changes
- # should go in a separate migration. This ensures that upon failure _only_ the
- # index creation fails and can be retried or reverted easily.
- #
- # To disable transactions uncomment the following line and remove these
- # comments:
- # disable_ddl_transaction!
-
-<%- if migration_action == 'add' -%>
- def change
-<% attributes.each do |attribute| -%>
- <%- if attribute.reference? -%>
- add_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %>
- <%- else -%>
- add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %>
- <%- if attribute.has_index? -%>
- add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
- <%- end -%>
- <%- end -%>
-<%- end -%>
- end
-<%- elsif migration_action == 'join' -%>
- def change
- create_join_table :<%= join_tables.first %>, :<%= join_tables.second %> do |t|
- <%- attributes.each do |attribute| -%>
- <%= '# ' unless attribute.has_index? -%>t.index <%= attribute.index_name %><%= attribute.inject_index_options %>
- <%- end -%>
- end
- end
-<%- else -%>
- def change
-<% attributes.each do |attribute| -%>
-<%- if migration_action -%>
- <%- if attribute.reference? -%>
- remove_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %>
- <%- else -%>
- <%- if attribute.has_index? -%>
- remove_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
- <%- end -%>
- remove_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %>
- <%- end -%>
-<%- end -%>
-<%- end -%>
- end
-<%- end -%>
-end
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 6cd909f611..cc1004f800 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -1,3 +1,5 @@
+Dir["#{Rails.root}/lib/api/*.rb"].each {|file| require file}
+
module API
class API < Grape::API
include APIGuard
@@ -23,41 +25,38 @@ module API
format :json
content_type :txt, "text/plain"
- # Ensure the namespace is right, otherwise we might load Grape::API::Helpers
- helpers ::API::Helpers
+ helpers Helpers
- mount ::API::Groups
- mount ::API::GroupMembers
- mount ::API::Users
- mount ::API::Projects
- mount ::API::Repositories
- mount ::API::Issues
- mount ::API::Milestones
- mount ::API::Session
- mount ::API::MergeRequests
- mount ::API::Notes
- mount ::API::Internal
- mount ::API::SystemHooks
- mount ::API::ProjectSnippets
- mount ::API::ProjectMembers
- mount ::API::DeployKeys
- mount ::API::ProjectHooks
- mount ::API::Services
- mount ::API::Files
- mount ::API::Commits
- mount ::API::CommitStatuses
- mount ::API::Namespaces
- mount ::API::Branches
- mount ::API::Labels
- mount ::API::Settings
- mount ::API::Keys
- mount ::API::Tags
- mount ::API::Triggers
- mount ::API::Builds
- mount ::API::Variables
- mount ::API::Runners
- mount ::API::Licenses
- mount ::API::Subscriptions
- mount ::API::Gitignores
+ mount Groups
+ mount GroupMembers
+ mount Users
+ mount Projects
+ mount Repositories
+ mount Issues
+ mount Milestones
+ mount Session
+ mount MergeRequests
+ mount Notes
+ mount Internal
+ mount SystemHooks
+ mount ProjectSnippets
+ mount ProjectMembers
+ mount DeployKeys
+ mount ProjectHooks
+ mount Services
+ mount Files
+ mount Commits
+ mount CommitStatus
+ mount Namespaces
+ mount Branches
+ mount Labels
+ mount Settings
+ mount Keys
+ mount Tags
+ mount Triggers
+ mount Builds
+ mount Variables
+ mount Runners
+ mount Licenses
end
end
diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
index 7e67edb203..b9994fcefd 100644
--- a/lib/api/api_guard.rb
+++ b/lib/api/api_guard.rb
@@ -2,175 +2,171 @@
require 'rack/oauth2'
-module API
- module APIGuard
- extend ActiveSupport::Concern
+module APIGuard
+ extend ActiveSupport::Concern
- included do |base|
- # OAuth2 Resource Server Authentication
- use Rack::OAuth2::Server::Resource::Bearer, 'The API' do |request|
- # The authenticator only fetches the raw token string
+ included do |base|
+ # OAuth2 Resource Server Authentication
+ use Rack::OAuth2::Server::Resource::Bearer, 'The API' do |request|
+ # The authenticator only fetches the raw token string
- # Must yield access token to store it in the env
- request.access_token
- end
-
- helpers HelperMethods
-
- install_error_responders(base)
+ # Must yield access token to store it in the env
+ request.access_token
end
- # Helper Methods for Grape Endpoint
- module HelperMethods
- # Invokes the doorkeeper guard.
- #
- # If token is presented and valid, then it sets @current_user.
- #
- # If the token does not have sufficient scopes to cover the requred scopes,
- # then it raises InsufficientScopeError.
- #
- # If the token is expired, then it raises ExpiredError.
- #
- # If the token is revoked, then it raises RevokedError.
- #
- # If the token is not found (nil), then it raises TokenNotFoundError.
- #
- # Arguments:
- #
- # scopes: (optional) scopes required for this guard.
- # Defaults to empty array.
- #
- def doorkeeper_guard!(scopes: [])
- if (access_token = find_access_token).nil?
- raise TokenNotFoundError
+ helpers HelperMethods
- else
- case validate_access_token(access_token, scopes)
- when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
- raise InsufficientScopeError.new(scopes)
- when Oauth2::AccessTokenValidationService::EXPIRED
- raise ExpiredError
- when Oauth2::AccessTokenValidationService::REVOKED
- raise RevokedError
- when Oauth2::AccessTokenValidationService::VALID
- @current_user = User.find(access_token.resource_owner_id)
- end
- end
- end
-
- def doorkeeper_guard(scopes: [])
- if access_token = find_access_token
- case validate_access_token(access_token, scopes)
- when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
- raise InsufficientScopeError.new(scopes)
-
- when Oauth2::AccessTokenValidationService::EXPIRED
- raise ExpiredError
-
- when Oauth2::AccessTokenValidationService::REVOKED
- raise RevokedError
-
- when Oauth2::AccessTokenValidationService::VALID
- @current_user = User.find(access_token.resource_owner_id)
- end
- end
- end
-
- def current_user
- @current_user
- end
-
- private
-
- def find_access_token
- @access_token ||= Doorkeeper.authenticate(doorkeeper_request, Doorkeeper.configuration.access_token_methods)
- end
-
- def doorkeeper_request
- @doorkeeper_request ||= ActionDispatch::Request.new(env)
- end
-
- def validate_access_token(access_token, scopes)
- Oauth2::AccessTokenValidationService.validate(access_token, scopes: scopes)
- end
- end
-
- module ClassMethods
- # Installs the doorkeeper guard on the whole Grape API endpoint.
- #
- # Arguments:
- #
- # scopes: (optional) scopes required for this guard.
- # Defaults to empty array.
- #
- def guard_all!(scopes: [])
- before do
- guard! scopes: scopes
- end
- end
-
- private
-
- def install_error_responders(base)
- error_classes = [ MissingTokenError, TokenNotFoundError,
- ExpiredError, RevokedError, InsufficientScopeError]
-
- base.send :rescue_from, *error_classes, oauth2_bearer_token_error_handler
- end
-
- def oauth2_bearer_token_error_handler
- Proc.new do |e|
- response =
- case e
- when MissingTokenError
- Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new
-
- when TokenNotFoundError
- Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
- :invalid_token,
- "Bad Access Token.")
-
- when ExpiredError
- Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
- :invalid_token,
- "Token is expired. You can either do re-authorization or token refresh.")
-
- when RevokedError
- Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
- :invalid_token,
- "Token was revoked. You have to re-authorize from the user.")
-
- when InsufficientScopeError
- # FIXME: ForbiddenError (inherited from Bearer::Forbidden of Rack::Oauth2)
- # does not include WWW-Authenticate header, which breaks the standard.
- Rack::OAuth2::Server::Resource::Bearer::Forbidden.new(
- :insufficient_scope,
- Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION[:insufficient_scope],
- { scope: e.scopes })
- end
-
- response.finish
- end
- end
- end
+ install_error_responders(base)
+ end
+ # Helper Methods for Grape Endpoint
+ module HelperMethods
+ # Invokes the doorkeeper guard.
#
- # Exceptions
+ # If token is presented and valid, then it sets @current_user.
#
+ # If the token does not have sufficient scopes to cover the requred scopes,
+ # then it raises InsufficientScopeError.
+ #
+ # If the token is expired, then it raises ExpiredError.
+ #
+ # If the token is revoked, then it raises RevokedError.
+ #
+ # If the token is not found (nil), then it raises TokenNotFoundError.
+ #
+ # Arguments:
+ #
+ # scopes: (optional) scopes required for this guard.
+ # Defaults to empty array.
+ #
+ def doorkeeper_guard!(scopes: [])
+ if (access_token = find_access_token).nil?
+ raise TokenNotFoundError
- class MissingTokenError < StandardError; end
+ else
+ case validate_access_token(access_token, scopes)
+ when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
+ raise InsufficientScopeError.new(scopes)
+ when Oauth2::AccessTokenValidationService::EXPIRED
+ raise ExpiredError
+ when Oauth2::AccessTokenValidationService::REVOKED
+ raise RevokedError
+ when Oauth2::AccessTokenValidationService::VALID
+ @current_user = User.find(access_token.resource_owner_id)
+ end
+ end
+ end
- class TokenNotFoundError < StandardError; end
+ def doorkeeper_guard(scopes: [])
+ if access_token = find_access_token
+ case validate_access_token(access_token, scopes)
+ when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
+ raise InsufficientScopeError.new(scopes)
- class ExpiredError < StandardError; end
+ when Oauth2::AccessTokenValidationService::EXPIRED
+ raise ExpiredError
- class RevokedError < StandardError; end
+ when Oauth2::AccessTokenValidationService::REVOKED
+ raise RevokedError
- class InsufficientScopeError < StandardError
- attr_reader :scopes
- def initialize(scopes)
- @scopes = scopes
+ when Oauth2::AccessTokenValidationService::VALID
+ @current_user = User.find(access_token.resource_owner_id)
+ end
+ end
+ end
+
+ def current_user
+ @current_user
+ end
+
+ private
+ def find_access_token
+ @access_token ||= Doorkeeper.authenticate(doorkeeper_request, Doorkeeper.configuration.access_token_methods)
+ end
+
+ def doorkeeper_request
+ @doorkeeper_request ||= ActionDispatch::Request.new(env)
+ end
+
+ def validate_access_token(access_token, scopes)
+ Oauth2::AccessTokenValidationService.validate(access_token, scopes: scopes)
+ end
+ end
+
+ module ClassMethods
+ # Installs the doorkeeper guard on the whole Grape API endpoint.
+ #
+ # Arguments:
+ #
+ # scopes: (optional) scopes required for this guard.
+ # Defaults to empty array.
+ #
+ def guard_all!(scopes: [])
+ before do
+ guard! scopes: scopes
+ end
+ end
+
+ private
+ def install_error_responders(base)
+ error_classes = [ MissingTokenError, TokenNotFoundError,
+ ExpiredError, RevokedError, InsufficientScopeError]
+
+ base.send :rescue_from, *error_classes, oauth2_bearer_token_error_handler
+ end
+
+ def oauth2_bearer_token_error_handler
+ Proc.new do |e|
+ response =
+ case e
+ when MissingTokenError
+ Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new
+
+ when TokenNotFoundError
+ Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
+ :invalid_token,
+ "Bad Access Token.")
+
+ when ExpiredError
+ Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
+ :invalid_token,
+ "Token is expired. You can either do re-authorization or token refresh.")
+
+ when RevokedError
+ Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
+ :invalid_token,
+ "Token was revoked. You have to re-authorize from the user.")
+
+ when InsufficientScopeError
+ # FIXME: ForbiddenError (inherited from Bearer::Forbidden of Rack::Oauth2)
+ # does not include WWW-Authenticate header, which breaks the standard.
+ Rack::OAuth2::Server::Resource::Bearer::Forbidden.new(
+ :insufficient_scope,
+ Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION[:insufficient_scope],
+ { scope: e.scopes })
+ end
+
+ response.finish
end
end
end
+
+ #
+ # Exceptions
+ #
+
+ class MissingTokenError < StandardError; end
+
+ class TokenNotFoundError < StandardError; end
+
+ class ExpiredError < StandardError; end
+
+ class RevokedError < StandardError; end
+
+ class InsufficientScopeError < StandardError
+ attr_reader :scopes
+ def initialize(scopes)
+ @scopes = scopes
+ end
+ end
end
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
index 9bcd33ff19..7388ed2f4e 100644
--- a/lib/api/commit_statuses.rb
+++ b/lib/api/commit_statuses.rb
@@ -2,7 +2,7 @@ require 'mime/types'
module API
# Project commit statuses API
- class CommitStatuses < Grape::API
+ class CommitStatus < Grape::API
resource :projects do
before { authenticate! }
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index 4a11c8e362..93a3a5ce08 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -107,8 +107,6 @@ module API
break if opts[:line_code]
end
-
- opts[:type] = LegacyDiffNote.name if opts[:line_code]
end
note = ::Notes::CreateService.new(user_project, current_user, opts).execute
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 790a1869f7..716ca6f7ed 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -66,8 +66,7 @@ module API
expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
expose :name, :name_with_namespace
expose :path, :path_with_namespace
- expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :builds_enabled, :snippets_enabled, :container_registry_enabled
- expose :created_at, :last_activity_at
+ expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :builds_enabled, :snippets_enabled, :created_at, :last_activity_at
expose :shared_runners_enabled
expose :creator_id
expose :namespace
@@ -171,10 +170,10 @@ module API
expose :label_names, as: :labels
expose :milestone, using: Entities::Milestone
expose :assignee, :author, using: Entities::UserBasic
+
expose :subscribed do |issue, options|
issue.subscribed?(options[:current_user])
end
- expose :user_notes_count
end
class MergeRequest < ProjectEntity
@@ -188,10 +187,10 @@ module API
expose :milestone, using: Entities::Milestone
expose :merge_when_build_succeeds
expose :merge_status
+
expose :subscribed do |merge_request, options|
merge_request.subscribed?(options[:current_user])
end
- expose :user_notes_count
end
class MergeRequestChanges < MergeRequest
@@ -228,9 +227,9 @@ module API
class CommitNote < Grape::Entity
expose :note
- expose(:path) { |note| note.diff_file_path if note.legacy_diff_note? }
- expose(:line) { |note| note.diff_new_line if note.legacy_diff_note? }
- expose(:line_type) { |note| note.diff_line_type if note.legacy_diff_note? }
+ expose(:path) { |note| note.diff_file_name }
+ expose(:line) { |note| note.diff_new_line }
+ expose(:line_type) { |note| note.diff_line_type }
expose :author, using: Entities::UserBasic
expose :created_at
end
@@ -308,10 +307,6 @@ module API
class Label < Grape::Entity
expose :name, :color, :description
expose :open_issues_count, :closed_issues_count, :open_merge_requests_count
-
- expose :subscribed do |label, options|
- label.subscribed?(options[:current_user])
- end
end
class Compare < Grape::Entity
@@ -362,7 +357,6 @@ module API
expose :restricted_signup_domains
expose :user_oauth_applications
expose :after_sign_out_path
- expose :container_registry_token_expire_delay
end
class Release < Grape::Entity
@@ -409,7 +403,6 @@ module API
class RunnerDetails < Runner
expose :tag_list
- expose :run_untagged
expose :version, :revision, :platform, :architecture
expose :contacted_at
expose :token, if: lambda { |runner, options| options[:current_user].is_admin? || !runner.is_shared? }
@@ -458,13 +451,5 @@ module API
expose(:limitations) { |license| license.meta['limitations'] }
expose :content
end
-
- class GitignoresList < Grape::Entity
- expose :name
- end
-
- class Gitignore < Grape::Entity
- expose :name, :content
- end
end
end
diff --git a/lib/api/gitignores.rb b/lib/api/gitignores.rb
deleted file mode 100644
index 270c9501dd..0000000000
--- a/lib/api/gitignores.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-module API
- class Gitignores < Grape::API
-
- # Get the list of the available gitignore templates
- #
- # Example Request:
- # GET /gitignores
- get 'gitignores' do
- present Gitlab::Gitignore.all, with: Entities::GitignoresList
- end
-
- # Get the text for a specific gitignore
- #
- # Parameters:
- # name (required) - The name of a license
- #
- # Example Request:
- # GET /gitignores/Elixir
- #
- get 'gitignores/:name' do
- required_attributes! [:name]
-
- gitignore = Gitlab::Gitignore.find(params[:name])
- not_found!('.gitignore') unless gitignore
-
- present gitignore, with: Entities::Gitignore
- end
- end
-end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 9d8b8d737a..91e420832f 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -95,7 +95,8 @@ module API
# GET /groups/:id/projects
get ":id/projects" do
group = find_group(params[:id])
- projects = GroupProjectsFinder.new(group).execute(current_user)
+ projects = group.projects
+ projects = filter_projects(projects)
projects = paginate projects
present projects, with: Entities::Project
end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 2aaa0557ea..40c967453f 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -2,7 +2,7 @@ module API
module Helpers
PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN"
PRIVATE_TOKEN_PARAM = :private_token
- SUDO_HEADER = "HTTP_SUDO"
+ SUDO_HEADER ="HTTP_SUDO"
SUDO_PARAM = :sudo
def parse_boolean(value)
@@ -29,7 +29,7 @@ module API
@current_user
end
- def sudo_identifier
+ def sudo_identifier()
identifier ||= params[SUDO_PARAM] || env[SUDO_HEADER]
# Regex for integers
@@ -95,17 +95,6 @@ module API
end
end
- def find_project_label(id)
- label = user_project.labels.find_by_id(id) || user_project.labels.find_by_title(id)
- label || not_found!('Label')
- end
-
- def find_project_issue(id)
- issue = user_project.issues.find(id)
- not_found! unless can?(current_user, :read_issue, issue)
- issue
- end
-
def paginate(relation)
relation.page(params[:page]).per(params[:per_page].to_i).tap do |data|
add_pagination_headers(data)
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index f59a4d6c01..4092874948 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -103,7 +103,8 @@ module API
# Example Request:
# GET /projects/:id/issues/:issue_id
get ":id/issues/:issue_id" do
- @issue = find_project_issue(params[:issue_id])
+ @issue = user_project.issues.find(params[:issue_id])
+ not_found! unless can?(current_user, :read_issue, @issue)
present @issue, with: Entities::Issue, current_user: current_user
end
@@ -233,6 +234,42 @@ module API
authorize!(:destroy_issue, issue)
issue.destroy
end
+
+ # Subscribes to a project issue
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # issue_id (required) - The ID of a project issue
+ # Example Request:
+ # POST /projects/:id/issues/:issue_id/subscription
+ post ':id/issues/:issue_id/subscription' do
+ issue = user_project.issues.find(params[:issue_id])
+
+ if issue.subscribed?(current_user)
+ not_modified!
+ else
+ issue.toggle_subscription(current_user)
+ present issue, with: Entities::Issue, current_user: current_user
+ end
+ end
+
+ # Unsubscribes from a project issue
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # issue_id (required) - The ID of a project issue
+ # Example Request:
+ # DELETE /projects/:id/issues/:issue_id/subscription
+ delete ':id/issues/:issue_id/subscription' do
+ issue = user_project.issues.find(params[:issue_id])
+
+ if issue.subscribed?(current_user)
+ issue.unsubscribe(current_user)
+ present issue, with: Entities::Issue, current_user: current_user
+ else
+ not_modified!
+ end
+ end
end
end
end
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
index c806829d69..4af6bef0fa 100644
--- a/lib/api/labels.rb
+++ b/lib/api/labels.rb
@@ -11,7 +11,7 @@ module API
# Example Request:
# GET /projects/:id/labels
get ':id/labels' do
- present user_project.labels, with: Entities::Label, current_user: current_user
+ present user_project.labels, with: Entities::Label
end
# Creates a new label
@@ -36,7 +36,7 @@ module API
label = user_project.labels.create(attrs)
if label.valid?
- present label, with: Entities::Label, current_user: current_user
+ present label, with: Entities::Label
else
render_validation_error!(label)
end
@@ -90,7 +90,7 @@ module API
attrs[:name] = attrs.delete(:new_name) if attrs.key?(:new_name)
if label.update(attrs)
- present label, with: Entities::Label, current_user: current_user
+ present label, with: Entities::Label
else
render_validation_error!(label)
end
diff --git a/lib/api/licenses.rb b/lib/api/licenses.rb
index be0e113fbc..187d2c0470 100644
--- a/lib/api/licenses.rb
+++ b/lib/api/licenses.rb
@@ -2,15 +2,15 @@ module API
# Licenses API
class Licenses < Grape::API
PROJECT_TEMPLATE_REGEX =
- /[\<\{\[]
- (project|description|
- one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here
- [\>\}\]]/xi.freeze
+ /[\<\{\[]
+ (project|description|
+ one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here
+ [\>\}\]]/xi.freeze
YEAR_TEMPLATE_REGEX = /[<{\[](year|yyyy)[>}\]]/i.freeze
FULLNAME_TEMPLATE_REGEX =
- /[\<\{\[]
- (fullname|name\sof\s(author|copyright\sowner))
- [\>\}\]]/xi.freeze
+ /[\<\{\[]
+ (fullname|name\sof\s(author|copyright\sowner))
+ [\>\}\]]/xi.freeze
# Get the list of the available license templates
#
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 4e7de8867b..7e78609ecb 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -327,6 +327,42 @@ module API
issues = ::Kaminari.paginate_array(merge_request.closes_issues(current_user))
present paginate(issues), with: Entities::Issue, current_user: current_user
end
+
+ # Subscribes to a merge request
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # merge_request_id (required) - The ID of a merge request
+ # Example Request:
+ # POST /projects/:id/issues/:merge_request_id/subscription
+ post "#{path}/subscription" do
+ merge_request = user_project.merge_requests.find(params[:merge_request_id])
+
+ if merge_request.subscribed?(current_user)
+ not_modified!
+ else
+ merge_request.toggle_subscription(current_user)
+ present merge_request, with: Entities::MergeRequest, current_user: current_user
+ end
+ end
+
+ # Unsubscribes from a merge request
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # merge_request_id (required) - The ID of a merge request
+ # Example Request:
+ # DELETE /projects/:id/merge_requests/:merge_request_id/subscription
+ delete "#{path}/subscription" do
+ merge_request = user_project.merge_requests.find(params[:merge_request_id])
+
+ if merge_request.subscribed?(current_user)
+ merge_request.unsubscribe(current_user)
+ present merge_request, with: Entities::MergeRequest, current_user: current_user
+ else
+ not_modified!
+ end
+ end
end
end
end
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index d4fcfd3d4d..71a53e6f0d 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -19,24 +19,20 @@ module API
# GET /projects/:id/issues/:noteable_id/notes
# GET /projects/:id/snippets/:noteable_id/notes
get ":id/#{noteables_str}/:#{noteable_id_str}/notes" do
- @noteable = user_project.send(noteables_str.to_sym).find(params[noteable_id_str.to_sym])
+ @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"])
- if can?(current_user, noteable_read_ability_name(@noteable), @noteable)
- # We exclude notes that are cross-references and that cannot be viewed
- # by the current user. By doing this exclusion at this level and not
- # at the DB query level (which we cannot in that case), the current
- # page can have less elements than :per_page even if
- # there's more than one page.
- notes =
- # paginate() only works with a relation. This could lead to a
- # mismatch between the pagination headers info and the actual notes
- # array returned, but this is really a edge-case.
- paginate(@noteable.notes).
- reject { |n| n.cross_reference_not_visible_for?(current_user) }
- present notes, with: Entities::Note
- else
- not_found!("Notes")
- end
+ # We exclude notes that are cross-references and that cannot be viewed
+ # by the current user. By doing this exclusion at this level and not
+ # at the DB query level (which we cannot in that case), the current
+ # page can have less elements than :per_page even if
+ # there's more than one page.
+ notes =
+ # paginate() only works with a relation. This could lead to a
+ # mismatch between the pagination headers info and the actual notes
+ # array returned, but this is really a edge-case.
+ paginate(@noteable.notes).
+ reject { |n| n.cross_reference_not_visible_for?(current_user) }
+ present notes, with: Entities::Note
end
# Get a single +noteable+ note
@@ -49,14 +45,13 @@ module API
# GET /projects/:id/issues/:noteable_id/notes/:note_id
# GET /projects/:id/snippets/:noteable_id/notes/:note_id
get ":id/#{noteables_str}/:#{noteable_id_str}/notes/:note_id" do
- @noteable = user_project.send(noteables_str.to_sym).find(params[noteable_id_str.to_sym])
+ @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"])
@note = @noteable.notes.find(params[:note_id])
- can_read_note = can?(current_user, noteable_read_ability_name(@noteable), @noteable) && !@note.cross_reference_not_visible_for?(current_user)
- if can_read_note
- present @note, with: Entities::Note
- else
+ if @note.cross_reference_not_visible_for?(current_user)
not_found!("Note")
+ else
+ present @note, with: Entities::Note
end
end
@@ -141,11 +136,5 @@ module API
end
end
end
-
- helpers do
- def noteable_read_ability_name(noteable)
- "read_#{noteable.class.to_s.underscore.downcase}".to_sym
- end
- end
end
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 5a22d14988..cc2c7a0c50 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -44,7 +44,7 @@ module API
# Example Request:
# GET /projects/starred
get '/starred' do
- @projects = current_user.viewable_starred_projects
+ @projects = current_user.starred_projects
@projects = filter_projects(@projects)
@projects = paginate @projects
present @projects, with: Entities::Project
@@ -94,7 +94,6 @@ module API
# builds_enabled (optional)
# wiki_enabled (optional)
# snippets_enabled (optional)
- # container_registry_enabled (optional)
# shared_runners_enabled (optional)
# namespace_id (optional) - defaults to user namespace
# public (optional) - if true same as setting visibility_level = 20
@@ -113,7 +112,6 @@ module API
:builds_enabled,
:wiki_enabled,
:snippets_enabled,
- :container_registry_enabled,
:shared_runners_enabled,
:namespace_id,
:public,
@@ -145,7 +143,6 @@ module API
# builds_enabled (optional)
# wiki_enabled (optional)
# snippets_enabled (optional)
- # container_registry_enabled (optional)
# shared_runners_enabled (optional)
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional)
@@ -209,7 +206,6 @@ module API
# builds_enabled (optional)
# wiki_enabled (optional)
# snippets_enabled (optional)
- # container_registry_enabled (optional)
# shared_runners_enabled (optional)
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional) - visibility level of a project
@@ -226,7 +222,6 @@ module API
:builds_enabled,
:wiki_enabled,
:snippets_enabled,
- :container_registry_enabled,
:shared_runners_enabled,
:public,
:visibility_level,
diff --git a/lib/api/runners.rb b/lib/api/runners.rb
index 4faba9dc87..8ec91485b2 100644
--- a/lib/api/runners.rb
+++ b/lib/api/runners.rb
@@ -49,7 +49,7 @@ module API
runner = get_runner(params[:id])
authenticate_update_runner!(runner)
- attrs = attributes_for_keys [:description, :active, :tag_list, :run_untagged]
+ attrs = attributes_for_keys [:description, :active, :tag_list]
if runner.update(attrs)
present runner, with: Entities::RunnerDetails, current_user: current_user
else
diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb
deleted file mode 100644
index c49e2a21b8..0000000000
--- a/lib/api/subscriptions.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-module API
- class Subscriptions < Grape::API
- before { authenticate! }
-
- subscribable_types = {
- 'merge_request' => proc { |id| user_project.merge_requests.find(id) },
- 'merge_requests' => proc { |id| user_project.merge_requests.find(id) },
- 'issues' => proc { |id| find_project_issue(id) },
- 'labels' => proc { |id| find_project_label(id) },
- }
-
- resource :projects do
- subscribable_types.each do |type, finder|
- type_singularized = type.singularize
- type_id_str = :"#{type_singularized}_id"
- entity_class = Entities.const_get(type_singularized.camelcase)
-
- # Subscribe to a resource
- #
- # Parameters:
- # id (required) - The ID of a project
- # subscribable_id (required) - The ID of a resource
- # Example Request:
- # POST /projects/:id/labels/:subscribable_id/subscription
- # POST /projects/:id/issues/:subscribable_id/subscription
- # POST /projects/:id/merge_requests/:subscribable_id/subscription
- post ":id/#{type}/:#{type_id_str}/subscription" do
- resource = instance_exec(params[type_id_str], &finder)
-
- if resource.subscribed?(current_user)
- not_modified!
- else
- resource.subscribe(current_user)
- present resource, with: entity_class, current_user: current_user
- end
- end
-
- # Unsubscribe from a resource
- #
- # Parameters:
- # id (required) - The ID of a project
- # subscribable_id (required) - The ID of a resource
- # Example Request:
- # DELETE /projects/:id/labels/:subscribable_id/subscription
- # DELETE /projects/:id/issues/:subscribable_id/subscription
- # DELETE /projects/:id/merge_requests/:subscribable_id/subscription
- delete ":id/#{type}/:#{type_id_str}/subscription" do
- resource = instance_exec(params[type_id_str], &finder)
-
- if !resource.subscribed?(current_user)
- not_modified!
- else
- resource.unsubscribe(current_user)
- present resource, with: entity_class, current_user: current_user
- end
- end
- end
- end
- end
-end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 8a376d3c2a..ea6fa2dc8a 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -76,7 +76,7 @@ module API
required_attributes! [:email, :password, :name, :username]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :location, :can_create_group, :admin, :confirm, :external]
admin = attrs.delete(:admin)
- confirm = !(attrs.delete(:confirm) =~ /(false|f|no|0)$/i)
+ confirm = !(attrs.delete(:confirm) =~ (/(false|f|no|0)$/i))
user = User.build_user(attrs)
user.admin = admin unless admin.nil?
user.skip_confirmation! unless confirm
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 660ca8c292..4962f5e53c 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -1,8 +1,5 @@
module Backup
class Manager
- ARCHIVES_TO_BACKUP = %w[uploads builds artifacts lfs registry]
- FOLDERS_TO_BACKUP = %w[repositories db]
-
def pack
# Make sure there is a connection
ActiveRecord::Base.connection.reconnect!
@@ -48,7 +45,7 @@ module Backup
end
connection = ::Fog::Storage.new(connection_settings)
- directory = connection.directories.create(key: remote_directory)
+ directory = connection.directories.get(remote_directory)
if directory.files.create(key: tar_file, body: File.open(tar_file), public: false,
multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size,
@@ -150,7 +147,7 @@ module Backup
end
def skipped?(item)
- settings[:skipped] && settings[:skipped].include?(item) || disabled_features.include?(item)
+ settings[:skipped] && settings[:skipped].include?(item)
end
private
@@ -160,17 +157,11 @@ module Backup
end
def archives_to_backup
- ARCHIVES_TO_BACKUP.map{ |name| (name + ".tar.gz") unless skipped?(name) }.compact
+ %w{uploads builds artifacts lfs}.map{ |name| (name + ".tar.gz") unless skipped?(name) }.compact
end
def folders_to_backup
- FOLDERS_TO_BACKUP.reject{ |name| skipped?(name) }
- end
-
- def disabled_features
- features = []
- features << 'registry' unless Gitlab.config.registry.enabled
- features
+ %w{repositories db}.reject{ |name| skipped?(name) }
end
def settings
diff --git a/lib/backup/registry.rb b/lib/backup/registry.rb
deleted file mode 100644
index 67fe023108..0000000000
--- a/lib/backup/registry.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'backup/files'
-
-module Backup
- class Registry < Files
- def initialize
- super('registry', Settings.registry.path)
- end
-
- def create_files_dir
- Dir.mkdir(app_files_dir, 0700)
- end
- end
-end
diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb
index db95d7c908..b8962379cb 100644
--- a/lib/banzai/filter/abstract_reference_filter.rb
+++ b/lib/banzai/filter/abstract_reference_filter.rb
@@ -18,6 +18,10 @@ module Banzai
@object_sym ||= object_name.to_sym
end
+ def self.data_reference
+ @data_reference ||= "data-#{object_name.dasherize}"
+ end
+
def self.object_class_title
@object_title ||= object_class.name.titleize
end
@@ -41,6 +45,10 @@ module Banzai
end
end
+ def self.referenced_by(node)
+ { object_sym => LazyReference.new(object_class, node.attr(data_reference)) }
+ end
+
def object_class
self.class.object_class
end
@@ -228,9 +236,7 @@ module Banzai
if cache.key?(key)
cache[key]
else
- value = yield
- cache[key] = value if key.present?
- value
+ cache[key] = yield
end
end
end
diff --git a/lib/banzai/filter/commit_range_reference_filter.rb b/lib/banzai/filter/commit_range_reference_filter.rb
index bbb88c979c..b469ea0f62 100644
--- a/lib/banzai/filter/commit_range_reference_filter.rb
+++ b/lib/banzai/filter/commit_range_reference_filter.rb
@@ -4,8 +4,6 @@ module Banzai
#
# This filter supports cross-project references.
class CommitRangeReferenceFilter < AbstractReferenceFilter
- self.reference_type = :commit_range
-
def self.object_class
CommitRange
end
@@ -16,18 +14,34 @@ module Banzai
end
end
+ def self.referenced_by(node)
+ project = Project.find(node.attr("data-project")) rescue nil
+ return unless project
+
+ id = node.attr("data-commit-range")
+ range = find_object(project, id)
+
+ return unless range
+
+ { commit_range: range }
+ end
+
def initialize(*args)
super
@commit_map = {}
end
- def find_object(project, id)
+ def self.find_object(project, id)
range = CommitRange.new(id, project)
range.valid_commits? ? range : nil
end
+ def find_object(*args)
+ self.class.find_object(*args)
+ end
+
def url_for_object(range, project)
h = Gitlab::Routing.url_helpers
h.namespace_project_compare_url(project.namespace, project,
diff --git a/lib/banzai/filter/commit_reference_filter.rb b/lib/banzai/filter/commit_reference_filter.rb
index 2ce1816672..bd88207326 100644
--- a/lib/banzai/filter/commit_reference_filter.rb
+++ b/lib/banzai/filter/commit_reference_filter.rb
@@ -4,8 +4,6 @@ module Banzai
#
# This filter supports cross-project references.
class CommitReferenceFilter < AbstractReferenceFilter
- self.reference_type = :commit
-
def self.object_class
Commit
end
@@ -16,12 +14,28 @@ module Banzai
end
end
- def find_object(project, id)
+ def self.referenced_by(node)
+ project = Project.find(node.attr("data-project")) rescue nil
+ return unless project
+
+ id = node.attr("data-commit")
+ commit = find_object(project, id)
+
+ return unless commit
+
+ { commit: commit }
+ end
+
+ def self.find_object(project, id)
if project && project.valid_repo?
project.commit(id)
end
end
+ def find_object(*args)
+ self.class.find_object(*args)
+ end
+
def url_for_object(commit, project)
h = Gitlab::Routing.url_helpers
h.namespace_project_commit_url(project.namespace, project, commit,
diff --git a/lib/banzai/filter/external_issue_reference_filter.rb b/lib/banzai/filter/external_issue_reference_filter.rb
index eaa702952c..37344b9057 100644
--- a/lib/banzai/filter/external_issue_reference_filter.rb
+++ b/lib/banzai/filter/external_issue_reference_filter.rb
@@ -4,8 +4,6 @@ module Banzai
# References are ignored if the project doesn't use an external issue
# tracker.
class ExternalIssueReferenceFilter < ReferenceFilter
- self.reference_type = :external_issue
-
# Public: Find `JIRA-123` issue references in text
#
# ExternalIssueReferenceFilter.references_in(text) do |match, issue|
@@ -23,6 +21,18 @@ module Banzai
end
end
+ def self.referenced_by(node)
+ project = Project.find(node.attr("data-project")) rescue nil
+ return unless project
+
+ id = node.attr("data-external-issue")
+ external_issue = ExternalIssue.new(id, project)
+
+ return unless external_issue
+
+ { external_issue: external_issue }
+ end
+
def call
# Early return if the project isn't using an external tracker
return doc if project.nil? || default_issues_tracker?
diff --git a/lib/banzai/filter/inline_diff_filter.rb b/lib/banzai/filter/inline_diff_filter.rb
deleted file mode 100644
index beb21b19ab..0000000000
--- a/lib/banzai/filter/inline_diff_filter.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-module Banzai
- module Filter
- class InlineDiffFilter < HTML::Pipeline::Filter
- IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set
-
- def call
- search_text_nodes(doc).each do |node|
- next if has_ancestor?(node, IGNORED_ANCESTOR_TAGS)
-
- content = node.to_html
- html_content = inline_diff_filter(content)
-
- next if content == html_content
-
- node.replace(html_content)
- end
- doc
- end
-
- def inline_diff_filter(text)
- html_content = text.gsub(/(?:\[\-(.*?)\-\]|\{\-(.*?)\-\})/, '\1\2')
- html_content.gsub(/(?:\[\+(.*?)\+\]|\{\+(.*?)\+\})/, '\1\2')
- end
- end
- end
-end
diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb
index 2496e70400..2732e0b514 100644
--- a/lib/banzai/filter/issue_reference_filter.rb
+++ b/lib/banzai/filter/issue_reference_filter.rb
@@ -5,12 +5,15 @@ module Banzai
#
# This filter supports cross-project references.
class IssueReferenceFilter < AbstractReferenceFilter
- self.reference_type = :issue
-
def self.object_class
Issue
end
+ def self.user_can_see_reference?(user, node, context)
+ issue = Issue.find(node.attr('data-issue')) rescue nil
+ Ability.abilities.allowed?(user, :read_issue, issue)
+ end
+
def find_object(project, id)
project.get_issue(id)
end
diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb
index e4d3f87d0a..8488a493b5 100644
--- a/lib/banzai/filter/label_reference_filter.rb
+++ b/lib/banzai/filter/label_reference_filter.rb
@@ -2,8 +2,6 @@ module Banzai
module Filter
# HTML filter that replaces label references with links.
class LabelReferenceFilter < AbstractReferenceFilter
- self.reference_type = :label
-
def self.object_class
Label
end
diff --git a/lib/banzai/filter/merge_request_reference_filter.rb b/lib/banzai/filter/merge_request_reference_filter.rb
index ac5216d9cf..cad38a5185 100644
--- a/lib/banzai/filter/merge_request_reference_filter.rb
+++ b/lib/banzai/filter/merge_request_reference_filter.rb
@@ -5,8 +5,6 @@ module Banzai
#
# This filter supports cross-project references.
class MergeRequestReferenceFilter < AbstractReferenceFilter
- self.reference_type = :merge_request
-
def self.object_class
MergeRequest
end
diff --git a/lib/banzai/filter/milestone_reference_filter.rb b/lib/banzai/filter/milestone_reference_filter.rb
index ca686c87d9..4cb8217802 100644
--- a/lib/banzai/filter/milestone_reference_filter.rb
+++ b/lib/banzai/filter/milestone_reference_filter.rb
@@ -2,8 +2,6 @@ module Banzai
module Filter
# HTML filter that replaces milestone references with links.
class MilestoneReferenceFilter < AbstractReferenceFilter
- self.reference_type = :milestone
-
def self.object_class
Milestone
end
@@ -12,53 +10,11 @@ module Banzai
project.milestones.find_by(iid: id)
end
- def references_in(text, pattern = Milestone.reference_pattern)
- # We'll handle here the references that follow the `reference_pattern`.
- # Other patterns (for example, the link pattern) are handled by the
- # default implementation.
- return super(text, pattern) if pattern != Milestone.reference_pattern
-
- text.gsub(pattern) do |match|
- milestone = find_milestone($~[:project], $~[:milestone_iid], $~[:milestone_name])
-
- if milestone
- yield match, milestone.iid, $~[:project], $~
- else
- match
- end
- end
- end
-
- def find_milestone(project_ref, milestone_id, milestone_name)
- project = project_from_ref(project_ref)
- return unless project
-
- milestone_params = milestone_params(milestone_id, milestone_name)
- project.milestones.find_by(milestone_params)
- end
-
- def milestone_params(iid, name)
- if name
- { name: name.tr('"', '') }
- else
- { iid: iid.to_i }
- end
- end
-
- def url_for_object(milestone, project)
+ def url_for_object(issue, project)
h = Gitlab::Routing.url_helpers
h.namespace_project_milestone_url(project.namespace, project, milestone,
only_path: context[:only_path])
end
-
- def object_link_text(object, matches)
- if context[:project] == object.project
- super
- else
- "#{escape_once(super)} in #{escape_once(object.project.path_with_namespace)}".
- html_safe
- end
- end
end
end
end
diff --git a/lib/banzai/filter/redactor_filter.rb b/lib/banzai/filter/redactor_filter.rb
index c753a84a20..e589b5df6e 100644
--- a/lib/banzai/filter/redactor_filter.rb
+++ b/lib/banzai/filter/redactor_filter.rb
@@ -7,11 +7,8 @@ module Banzai
#
class RedactorFilter < HTML::Pipeline::Filter
def call
- nodes = Querying.css(doc, 'a.gfm[data-reference-type]')
- visible = nodes_visible_to_user(nodes)
-
- nodes.each do |node|
- unless visible.include?(node)
+ Querying.css(doc, 'a.gfm').each do |node|
+ unless user_can_see_reference?(node)
# The reference should be replaced by the original text,
# which is not always the same as the rendered text.
text = node.attr('data-original') || node.text
@@ -24,30 +21,20 @@ module Banzai
private
- def nodes_visible_to_user(nodes)
- per_type = Hash.new { |h, k| h[k] = [] }
- visible = Set.new
+ def user_can_see_reference?(node)
+ if node.has_attribute?('data-reference-filter')
+ reference_type = node.attr('data-reference-filter')
+ reference_filter = Banzai::Filter.const_get(reference_type)
- nodes.each do |node|
- per_type[node.attr('data-reference-type')] << node
+ reference_filter.user_can_see_reference?(current_user, node, context)
+ else
+ true
end
-
- per_type.each do |type, nodes|
- parser = Banzai::ReferenceParser[type].new(project, current_user)
-
- visible.merge(parser.nodes_visible_to_user(current_user, nodes))
- end
-
- visible
end
def current_user
context[:current_user]
end
-
- def project
- context[:project]
- end
end
end
end
diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb
index 41ae0e1f9c..31386cf851 100644
--- a/lib/banzai/filter/reference_filter.rb
+++ b/lib/banzai/filter/reference_filter.rb
@@ -8,8 +8,24 @@ module Banzai
# :project (required) - Current project, ignored if reference is cross-project.
# :only_path - Generate path-only links.
class ReferenceFilter < HTML::Pipeline::Filter
- class << self
- attr_accessor :reference_type
+ def self.user_can_see_reference?(user, node, context)
+ if node.has_attribute?('data-project')
+ project_id = node.attr('data-project').to_i
+ return true if project_id == context[:project].try(:id)
+
+ project = Project.find(project_id) rescue nil
+ Ability.abilities.allowed?(user, :read_project, project)
+ else
+ true
+ end
+ end
+
+ def self.user_can_reference?(user, node, context)
+ true
+ end
+
+ def self.referenced_by(node)
+ raise NotImplementedError, "#{self} does not implement #{__method__}"
end
# Returns a data attribute String to attach to a reference link
@@ -27,9 +43,7 @@ module Banzai
#
# Returns a String
def data_attribute(attributes = {})
- attributes = attributes.reject { |_, v| v.nil? }
-
- attributes[:reference_type] = self.class.reference_type
+ attributes[:reference_filter] = self.class.name.demodulize
attributes.delete(:original) if context[:no_original_data]
attributes.map { |key, value| %Q(data-#{key.to_s.dasherize}="#{escape_once(value)}") }.join(" ")
end
diff --git a/lib/banzai/filter/reference_gatherer_filter.rb b/lib/banzai/filter/reference_gatherer_filter.rb
new file mode 100644
index 0000000000..96fdb06304
--- /dev/null
+++ b/lib/banzai/filter/reference_gatherer_filter.rb
@@ -0,0 +1,65 @@
+module Banzai
+ module Filter
+ # HTML filter that gathers all referenced records that the current user has
+ # permission to view.
+ #
+ # Expected to be run in its own post-processing pipeline.
+ #
+ class ReferenceGathererFilter < HTML::Pipeline::Filter
+ def initialize(*)
+ super
+
+ result[:references] ||= Hash.new { |hash, type| hash[type] = [] }
+ end
+
+ def call
+ Querying.css(doc, 'a.gfm').each do |node|
+ gather_references(node)
+ end
+
+ load_lazy_references unless ReferenceExtractor.lazy?
+
+ doc
+ end
+
+ private
+
+ def gather_references(node)
+ return unless node.has_attribute?('data-reference-filter')
+
+ reference_type = node.attr('data-reference-filter')
+ reference_filter = Banzai::Filter.const_get(reference_type)
+
+ return if context[:reference_filter] && reference_filter != context[:reference_filter]
+
+ return if author && !reference_filter.user_can_reference?(author, node, context)
+
+ return unless reference_filter.user_can_see_reference?(current_user, node, context)
+
+ references = reference_filter.referenced_by(node)
+ return unless references
+
+ references.each do |type, values|
+ Array.wrap(values).each do |value|
+ result[:references][type] << value
+ end
+ end
+ end
+
+ def load_lazy_references
+ refs = result[:references]
+ refs.each do |type, values|
+ refs[type] = ReferenceExtractor.lazily(values)
+ end
+ end
+
+ def current_user
+ context[:current_user]
+ end
+
+ def author
+ context[:author]
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb
index ca80aac5a0..42dbab9d27 100644
--- a/lib/banzai/filter/sanitization_filter.rb
+++ b/lib/banzai/filter/sanitization_filter.rb
@@ -63,7 +63,7 @@ module Banzai
begin
uri = Addressable::URI.parse(node['href'])
- uri.scheme = uri.scheme.strip.downcase if uri.scheme
+ uri.scheme.strip! if uri.scheme
node.remove_attribute('href') if UNSAFE_PROTOCOLS.include?(uri.scheme)
rescue Addressable::URI::InvalidURIError
diff --git a/lib/banzai/filter/snippet_reference_filter.rb b/lib/banzai/filter/snippet_reference_filter.rb
index 212a0bbf2a..d507eb5ebe 100644
--- a/lib/banzai/filter/snippet_reference_filter.rb
+++ b/lib/banzai/filter/snippet_reference_filter.rb
@@ -5,8 +5,6 @@ module Banzai
#
# This filter supports cross-project references.
class SnippetReferenceFilter < AbstractReferenceFilter
- self.reference_type = :snippet
-
def self.object_class
Snippet
end
diff --git a/lib/banzai/filter/upload_link_filter.rb b/lib/banzai/filter/upload_link_filter.rb
index c0f503c9af..7edfe5ade2 100644
--- a/lib/banzai/filter/upload_link_filter.rb
+++ b/lib/banzai/filter/upload_link_filter.rb
@@ -8,8 +8,6 @@ module Banzai
#
class UploadLinkFilter < HTML::Pipeline::Filter
def call
- return doc unless project
-
doc.search('a').each do |el|
process_link_attr el.attribute('href')
end
@@ -33,11 +31,7 @@ module Banzai
end
def build_url(uri)
- File.join(Gitlab.config.gitlab.url, project.path_with_namespace, uri)
- end
-
- def project
- context[:project]
+ File.join(Gitlab.config.gitlab.url, context[:project].path_with_namespace, uri)
end
# Ensure that a :project key exists in context
diff --git a/lib/banzai/filter/user_reference_filter.rb b/lib/banzai/filter/user_reference_filter.rb
index 331d800725..eea3af842b 100644
--- a/lib/banzai/filter/user_reference_filter.rb
+++ b/lib/banzai/filter/user_reference_filter.rb
@@ -4,8 +4,6 @@ module Banzai
#
# A special `@all` reference is also supported.
class UserReferenceFilter < ReferenceFilter
- self.reference_type = :user
-
# Public: Find `@user` user references in text
#
# UserReferenceFilter.references_in(text) do |match, username|
@@ -23,6 +21,43 @@ module Banzai
end
end
+ def self.referenced_by(node)
+ if node.has_attribute?('data-group')
+ group = Group.find(node.attr('data-group')) rescue nil
+ return unless group
+
+ { user: group.users }
+ elsif node.has_attribute?('data-user')
+ { user: LazyReference.new(User, node.attr('data-user')) }
+ elsif node.has_attribute?('data-project')
+ project = Project.find(node.attr('data-project')) rescue nil
+ return unless project
+
+ { user: project.team.members.flatten }
+ end
+ end
+
+ def self.user_can_see_reference?(user, node, context)
+ if node.has_attribute?('data-group')
+ group = Group.find(node.attr('data-group')) rescue nil
+ Ability.abilities.allowed?(user, :read_group, group)
+ else
+ super
+ end
+ end
+
+ def self.user_can_reference?(user, node, context)
+ # Only team members can reference `@all`
+ if node.has_attribute?('data-project')
+ project = Project.find(node.attr('data-project')) rescue nil
+ return false unless project
+
+ user && project.team.member?(user)
+ else
+ super
+ end
+ end
+
def call
return doc if project.nil?
@@ -79,12 +114,9 @@ module Banzai
def link_to_all(link_text: nil)
project = context[:project]
- author = context[:author]
-
url = urls.namespace_project_url(project.namespace, project,
only_path: context[:only_path])
-
- data = data_attribute(project: project.id, author: author.try(:id))
+ data = data_attribute(project: project.id)
text = link_text || User.reference_prefix + 'all'
link_tag(url, data, text)
diff --git a/lib/banzai/filter/wiki_link_filter.rb b/lib/banzai/filter/wiki_link_filter.rb
index 7dc771afd7..06d10c9850 100644
--- a/lib/banzai/filter/wiki_link_filter.rb
+++ b/lib/banzai/filter/wiki_link_filter.rb
@@ -25,7 +25,7 @@ module Banzai
end
def process_link_attr(html_attr)
- return if html_attr.blank? || file_reference?(html_attr) || hierarchical_link?(html_attr)
+ return if html_attr.blank? || file_reference?(html_attr)
uri = URI(html_attr.value)
if uri.relative? && uri.path.present?
@@ -40,17 +40,12 @@ module Banzai
uri
end
- def project_wiki
- context[:project_wiki]
- end
-
def file_reference?(html_attr)
!File.extname(html_attr.value).blank?
end
- # Of the form `./link`, `../link`, or similar
- def hierarchical_link?(html_attr)
- html_attr.value[0] == '.'
+ def project_wiki
+ context[:project_wiki]
end
def project_wiki_base_path
diff --git a/lib/banzai/lazy_reference.rb b/lib/banzai/lazy_reference.rb
new file mode 100644
index 0000000000..1095b4debc
--- /dev/null
+++ b/lib/banzai/lazy_reference.rb
@@ -0,0 +1,25 @@
+module Banzai
+ class LazyReference
+ def self.load(refs)
+ lazy_references, values = refs.partition { |ref| ref.is_a?(self) }
+
+ lazy_values = lazy_references.group_by(&:klass).flat_map do |klass, refs|
+ ids = refs.flat_map(&:ids)
+ klass.where(id: ids)
+ end
+
+ values + lazy_values
+ end
+
+ attr_reader :klass, :ids
+
+ def initialize(klass, ids)
+ @klass = klass
+ @ids = Array.wrap(ids).map(&:to_i)
+ end
+
+ def load
+ self.klass.where(id: self.ids)
+ end
+ end
+end
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index b27ecf3c92..ed3cfd6b02 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -23,8 +23,7 @@ module Banzai
Filter::LabelReferenceFilter,
Filter::MilestoneReferenceFilter,
- Filter::TaskListFilter,
- Filter::InlineDiffFilter
+ Filter::TaskListFilter
]
end
diff --git a/lib/banzai/pipeline/reference_extraction_pipeline.rb b/lib/banzai/pipeline/reference_extraction_pipeline.rb
new file mode 100644
index 0000000000..919998380e
--- /dev/null
+++ b/lib/banzai/pipeline/reference_extraction_pipeline.rb
@@ -0,0 +1,11 @@
+module Banzai
+ module Pipeline
+ class ReferenceExtractionPipeline < BasePipeline
+ def self.filters
+ FilterArray[
+ Filter::ReferenceGathererFilter
+ ]
+ end
+ end
+ end
+end
diff --git a/lib/banzai/reference_extractor.rb b/lib/banzai/reference_extractor.rb
index bf366962ae..f4079538ec 100644
--- a/lib/banzai/reference_extractor.rb
+++ b/lib/banzai/reference_extractor.rb
@@ -1,6 +1,28 @@
module Banzai
# Extract possible GFM references from an arbitrary String for further processing.
class ReferenceExtractor
+ class << self
+ LAZY_KEY = :banzai_reference_extractor_lazy
+
+ def lazy?
+ Thread.current[LAZY_KEY]
+ end
+
+ def lazily(values = nil, &block)
+ return (values || block.call).uniq if lazy?
+
+ begin
+ Thread.current[LAZY_KEY] = true
+
+ values ||= block.call
+
+ Banzai::LazyReference.load(values.uniq).uniq
+ ensure
+ Thread.current[LAZY_KEY] = false
+ end
+ end
+ end
+
def initialize
@texts = []
end
@@ -9,21 +31,23 @@ module Banzai
@texts << Renderer.render(text, context)
end
- def references(type, project, current_user = nil)
- processor = Banzai::ReferenceParser[type].
- new(project, current_user)
+ def references(type, context = {})
+ filter = Banzai::Filter["#{type}_reference"]
- processor.process(html_documents)
- end
+ context.merge!(
+ pipeline: :reference_extraction,
- private
+ # ReferenceGathererFilter
+ reference_filter: filter
+ )
- def html_documents
- # This ensures that we don't memoize anything until we have a number of
- # text blobs to parse.
- return [] if @texts.empty?
-
- @html_documents ||= @texts.map { |html| Nokogiri::HTML.fragment(html) }
+ self.class.lazily do
+ @texts.flat_map do |html|
+ text_context = context.dup
+ result = Renderer.render_result(html, text_context)
+ result[:references][type]
+ end.uniq
+ end
end
end
end
diff --git a/lib/banzai/reference_parser.rb b/lib/banzai/reference_parser.rb
deleted file mode 100644
index 557bec4316..0000000000
--- a/lib/banzai/reference_parser.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-module Banzai
- module ReferenceParser
- # Returns the reference parser class for the given type
- #
- # Example:
- #
- # Banzai::ReferenceParser['issue']
- #
- # This would return the `Banzai::ReferenceParser::IssueParser` class.
- def self.[](name)
- const_get("#{name.to_s.camelize}Parser")
- end
- end
-end
diff --git a/lib/banzai/reference_parser/base_parser.rb b/lib/banzai/reference_parser/base_parser.rb
deleted file mode 100644
index 3d7b9c4a02..0000000000
--- a/lib/banzai/reference_parser/base_parser.rb
+++ /dev/null
@@ -1,204 +0,0 @@
-module Banzai
- module ReferenceParser
- # Base class for reference parsing classes.
- #
- # Each parser should also specify its reference type by calling
- # `self.reference_type = ...` in the body of the class. The value of this
- # method should be a symbol such as `:issue` or `:merge_request`. For
- # example:
- #
- # class IssueParser < BaseParser
- # self.reference_type = :issue
- # end
- #
- # The reference type is used to determine what nodes to pass to the
- # `referenced_by` method.
- #
- # Parser classes should either implement the instance method
- # `references_relation` or overwrite `referenced_by`. The
- # `references_relation` method is supposed to return an
- # ActiveRecord::Relation used as a base relation for retrieving the objects
- # referenced in a set of HTML nodes.
- #
- # Each class can implement two additional methods:
- #
- # * `nodes_user_can_reference`: returns an Array of nodes the given user can
- # refer to.
- # * `nodes_visible_to_user`: returns an Array of nodes that are visible to
- # the given user.
- #
- # You only need to overwrite these methods if you want to tweak who can see
- # which references. For example, the IssueParser class defines its own
- # `nodes_visible_to_user` method so it can ensure users can only see issues
- # they have access to.
- class BaseParser
- class << self
- attr_accessor :reference_type
- end
-
- # Returns the attribute name containing the value for every object to be
- # parsed by the current parser.
- #
- # For example, for a parser class that returns "Animal" objects this
- # attribute would be "data-animal".
- def self.data_attribute
- @data_attribute ||= "data-#{reference_type.to_s.dasherize}"
- end
-
- def initialize(project = nil, current_user = nil)
- @project = project
- @current_user = current_user
- end
-
- # Returns all the nodes containing references that the user can refer to.
- def nodes_user_can_reference(user, nodes)
- nodes
- end
-
- # Returns all the nodes that are visible to the given user.
- def nodes_visible_to_user(user, nodes)
- projects = lazy { projects_for_nodes(nodes) }
- project_attr = 'data-project'
-
- nodes.select do |node|
- if node.has_attribute?(project_attr)
- node_id = node.attr(project_attr).to_i
-
- if project && project.id == node_id
- true
- else
- can?(user, :read_project, projects[node_id])
- end
- else
- true
- end
- end
- end
-
- # Returns an Array of objects referenced by any of the given HTML nodes.
- def referenced_by(nodes)
- ids = unique_attribute_values(nodes, self.class.data_attribute)
-
- references_relation.where(id: ids)
- end
-
- # Returns the ActiveRecord::Relation to use for querying references in the
- # DB.
- def references_relation
- raise NotImplementedError,
- "#{self.class} does not implement #{__method__}"
- end
-
- # Returns a Hash containing attribute values per project ID.
- #
- # The returned Hash uses the following format:
- #
- # { project id => [value1, value2, ...] }
- #
- # nodes - An Array of HTML nodes to process.
- # attribute - The name of the attribute (as a String) for which to gather
- # values.
- #
- # Returns a Hash.
- def gather_attributes_per_project(nodes, attribute)
- per_project = Hash.new { |hash, key| hash[key] = Set.new }
-
- nodes.each do |node|
- project_id = node.attr('data-project').to_i
- id = node.attr(attribute)
-
- per_project[project_id] << id if id
- end
-
- per_project
- end
-
- # Returns a Hash containing objects for an attribute grouped per their
- # IDs.
- #
- # The returned Hash uses the following format:
- #
- # { id value => row }
- #
- # nodes - An Array of HTML nodes to process.
- #
- # collection - The model or ActiveRecord relation to use for retrieving
- # rows from the database.
- #
- # attribute - The name of the attribute containing the primary key values
- # for every row.
- #
- # Returns a Hash.
- def grouped_objects_for_nodes(nodes, collection, attribute)
- return {} if nodes.empty?
-
- ids = unique_attribute_values(nodes, attribute)
-
- collection.where(id: ids).each_with_object({}) do |row, hash|
- hash[row.id] = row
- end
- end
-
- # Returns an Array containing all unique values of an attribute of the
- # given nodes.
- def unique_attribute_values(nodes, attribute)
- values = Set.new
-
- nodes.each do |node|
- if node.has_attribute?(attribute)
- values << node.attr(attribute)
- end
- end
-
- values.to_a
- end
-
- # Processes the list of HTML documents and returns an Array containing all
- # the references.
- def process(documents)
- type = self.class.reference_type
-
- nodes = documents.flat_map do |document|
- Querying.css(document, "a[data-reference-type='#{type}'].gfm").to_a
- end
-
- gather_references(nodes)
- end
-
- # Gathers the references for the given HTML nodes.
- def gather_references(nodes)
- nodes = nodes_user_can_reference(current_user, nodes)
- nodes = nodes_visible_to_user(current_user, nodes)
-
- referenced_by(nodes)
- end
-
- # Returns a Hash containing the projects for a given list of HTML nodes.
- #
- # The returned Hash uses the following format:
- #
- # { project ID => project }
- #
- def projects_for_nodes(nodes)
- @projects_for_nodes ||=
- grouped_objects_for_nodes(nodes, Project, 'data-project')
- end
-
- def can?(user, permission, subject)
- Ability.abilities.allowed?(user, permission, subject)
- end
-
- def find_projects_for_hash_keys(hash)
- Project.where(id: hash.keys)
- end
-
- private
-
- attr_reader :current_user, :project
-
- def lazy(&block)
- Gitlab::Lazy.new(&block)
- end
- end
- end
-end
diff --git a/lib/banzai/reference_parser/commit_parser.rb b/lib/banzai/reference_parser/commit_parser.rb
deleted file mode 100644
index 0fee9d267d..0000000000
--- a/lib/banzai/reference_parser/commit_parser.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-module Banzai
- module ReferenceParser
- class CommitParser < BaseParser
- self.reference_type = :commit
-
- def referenced_by(nodes)
- commit_ids = commit_ids_per_project(nodes)
- projects = find_projects_for_hash_keys(commit_ids)
-
- projects.flat_map do |project|
- find_commits(project, commit_ids[project.id])
- end
- end
-
- def commit_ids_per_project(nodes)
- gather_attributes_per_project(nodes, self.class.data_attribute)
- end
-
- def find_commits(project, ids)
- commits = []
-
- return commits unless project.valid_repo?
-
- ids.each do |id|
- commit = project.commit(id)
-
- commits << commit if commit
- end
-
- commits
- end
- end
- end
-end
diff --git a/lib/banzai/reference_parser/commit_range_parser.rb b/lib/banzai/reference_parser/commit_range_parser.rb
deleted file mode 100644
index 69d01f8db1..0000000000
--- a/lib/banzai/reference_parser/commit_range_parser.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-module Banzai
- module ReferenceParser
- class CommitRangeParser < BaseParser
- self.reference_type = :commit_range
-
- def referenced_by(nodes)
- range_ids = commit_range_ids_per_project(nodes)
- projects = find_projects_for_hash_keys(range_ids)
-
- projects.flat_map do |project|
- find_ranges(project, range_ids[project.id])
- end
- end
-
- def commit_range_ids_per_project(nodes)
- gather_attributes_per_project(nodes, self.class.data_attribute)
- end
-
- def find_ranges(project, range_ids)
- ranges = []
-
- range_ids.each do |id|
- range = find_object(project, id)
-
- ranges << range if range
- end
-
- ranges
- end
-
- def find_object(project, id)
- range = CommitRange.new(id, project)
-
- range.valid_commits? ? range : nil
- end
- end
- end
-end
diff --git a/lib/banzai/reference_parser/external_issue_parser.rb b/lib/banzai/reference_parser/external_issue_parser.rb
deleted file mode 100644
index a1264db211..0000000000
--- a/lib/banzai/reference_parser/external_issue_parser.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module Banzai
- module ReferenceParser
- class ExternalIssueParser < BaseParser
- self.reference_type = :external_issue
-
- def referenced_by(nodes)
- issue_ids = issue_ids_per_project(nodes)
- projects = find_projects_for_hash_keys(issue_ids)
- issues = []
-
- projects.each do |project|
- issue_ids[project.id].each do |id|
- issues << ExternalIssue.new(id, project)
- end
- end
-
- issues
- end
-
- def issue_ids_per_project(nodes)
- gather_attributes_per_project(nodes, self.class.data_attribute)
- end
- end
- end
-end
diff --git a/lib/banzai/reference_parser/issue_parser.rb b/lib/banzai/reference_parser/issue_parser.rb
deleted file mode 100644
index 24076e3d9e..0000000000
--- a/lib/banzai/reference_parser/issue_parser.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-module Banzai
- module ReferenceParser
- class IssueParser < BaseParser
- self.reference_type = :issue
-
- def nodes_visible_to_user(user, nodes)
- # It is not possible to check access rights for external issue trackers
- return nodes if project && project.external_issue_tracker
-
- issues = issues_for_nodes(nodes)
-
- nodes.select do |node|
- issue = issue_for_node(issues, node)
-
- issue ? can?(user, :read_issue, issue) : false
- end
- end
-
- def referenced_by(nodes)
- issues = issues_for_nodes(nodes)
-
- nodes.map { |node| issue_for_node(issues, node) }.uniq
- end
-
- def issues_for_nodes(nodes)
- @issues_for_nodes ||= grouped_objects_for_nodes(
- nodes,
- Issue.all.includes(:author, :assignee, :project),
- self.class.data_attribute
- )
- end
-
- private
-
- def issue_for_node(issues, node)
- issues[node.attr(self.class.data_attribute).to_i]
- end
- end
- end
-end
diff --git a/lib/banzai/reference_parser/label_parser.rb b/lib/banzai/reference_parser/label_parser.rb
deleted file mode 100644
index e5d1eb11d7..0000000000
--- a/lib/banzai/reference_parser/label_parser.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module Banzai
- module ReferenceParser
- class LabelParser < BaseParser
- self.reference_type = :label
-
- def references_relation
- Label
- end
- end
- end
-end
diff --git a/lib/banzai/reference_parser/merge_request_parser.rb b/lib/banzai/reference_parser/merge_request_parser.rb
deleted file mode 100644
index c9a9ca79c0..0000000000
--- a/lib/banzai/reference_parser/merge_request_parser.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module Banzai
- module ReferenceParser
- class MergeRequestParser < BaseParser
- self.reference_type = :merge_request
-
- def references_relation
- MergeRequest.includes(:author, :assignee, :target_project)
- end
- end
- end
-end
diff --git a/lib/banzai/reference_parser/milestone_parser.rb b/lib/banzai/reference_parser/milestone_parser.rb
deleted file mode 100644
index a000ac61e5..0000000000
--- a/lib/banzai/reference_parser/milestone_parser.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module Banzai
- module ReferenceParser
- class MilestoneParser < BaseParser
- self.reference_type = :milestone
-
- def references_relation
- Milestone
- end
- end
- end
-end
diff --git a/lib/banzai/reference_parser/snippet_parser.rb b/lib/banzai/reference_parser/snippet_parser.rb
deleted file mode 100644
index fa71b3c952..0000000000
--- a/lib/banzai/reference_parser/snippet_parser.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module Banzai
- module ReferenceParser
- class SnippetParser < BaseParser
- self.reference_type = :snippet
-
- def references_relation
- Snippet
- end
- end
- end
-end
diff --git a/lib/banzai/reference_parser/user_parser.rb b/lib/banzai/reference_parser/user_parser.rb
deleted file mode 100644
index a12b0d1956..0000000000
--- a/lib/banzai/reference_parser/user_parser.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-module Banzai
- module ReferenceParser
- class UserParser < BaseParser
- self.reference_type = :user
-
- def referenced_by(nodes)
- group_ids = []
- user_ids = []
- project_ids = []
-
- nodes.each do |node|
- if node.has_attribute?('data-group')
- group_ids << node.attr('data-group').to_i
- elsif node.has_attribute?(self.class.data_attribute)
- user_ids << node.attr(self.class.data_attribute).to_i
- elsif node.has_attribute?('data-project')
- project_ids << node.attr('data-project').to_i
- end
- end
-
- find_users_for_groups(group_ids) | find_users(user_ids) |
- find_users_for_projects(project_ids)
- end
-
- def nodes_visible_to_user(user, nodes)
- group_attr = 'data-group'
- groups = lazy { grouped_objects_for_nodes(nodes, Group, group_attr) }
- visible = []
- remaining = []
-
- nodes.each do |node|
- if node.has_attribute?(group_attr)
- node_group = groups[node.attr(group_attr).to_i]
-
- if node_group &&
- can?(user, :read_group, node_group)
- visible << node
- end
- # Remaining nodes will be processed by the parent class'
- # implementation of this method.
- else
- remaining << node
- end
- end
-
- visible + super(current_user, remaining)
- end
-
- def nodes_user_can_reference(current_user, nodes)
- project_attr = 'data-project'
- author_attr = 'data-author'
-
- projects = lazy { projects_for_nodes(nodes) }
- users = lazy { grouped_objects_for_nodes(nodes, User, author_attr) }
-
- nodes.select do |node|
- project_id = node.attr(project_attr)
- user_id = node.attr(author_attr)
-
- if project && project_id && project.id == project_id.to_i
- true
- elsif project_id && user_id
- project = projects[project_id.to_i]
- user = users[user_id.to_i]
-
- project && user ? project.team.member?(user) : false
- else
- true
- end
- end
- end
-
- def find_users(ids)
- return [] if ids.empty?
-
- User.where(id: ids).to_a
- end
-
- def find_users_for_groups(ids)
- return [] if ids.empty?
-
- User.joins(:group_members).where(members: { source_id: ids }).to_a
- end
-
- def find_users_for_projects(ids)
- return [] if ids.empty?
-
- Project.where(id: ids).flat_map { |p| p.team.members.to_a }
- end
- end
- end
-end
diff --git a/lib/ci/ansi2html.rb b/lib/ci/ansi2html.rb
index 229050151d..ac6d667cf8 100644
--- a/lib/ci/ansi2html.rb
+++ b/lib/ci/ansi2html.rb
@@ -23,8 +23,8 @@ module Ci
cross: 0x10,
}
- def self.convert(ansi, state = nil)
- Converter.new.convert(ansi, state)
+ def self.convert(ansi)
+ Converter.new().convert(ansi)
end
class Converter
@@ -84,38 +84,22 @@ module Ci
def on_107(s) set_bg_color(7, 'l') end
def on_109(s) set_bg_color(9, 'l') end
- attr_accessor :offset, :n_open_tags, :fg_color, :bg_color, :style_mask
+ def convert(ansi)
+ @out = ""
+ @n_open_tags = 0
+ reset()
- STATE_PARAMS = [:offset, :n_open_tags, :fg_color, :bg_color, :style_mask]
-
- def convert(raw, new_state)
- reset_state
- restore_state(raw, new_state) if new_state.present?
-
- start = @offset
- ansi = raw[@offset..-1]
-
- open_new_tag
-
- s = StringScanner.new(ansi)
- until s.eos?
+ s = StringScanner.new(ansi.gsub("<", "<"))
+ while(!s.eos?)
if s.scan(/\e([@-_])(.*?)([@-~])/)
handle_sequence(s)
- elsif s.scan(/\e(([@-_])(.*?)?)?$/)
- break
- elsif s.scan(/)
- @out << '<'
- elsif s.scan(/\n/)
- @out << '
'
else
@out << s.scan(/./m)
end
- @offset += s.matched_size
end
close_open_tags()
-
- { state: state, html: @out, text: ansi[0, @offset - start], append: start > 0 }
+ @out
end
def handle_sequence(s)
@@ -137,20 +121,6 @@ module Ci
evaluate_command_stack(commands)
- open_new_tag
- end
-
- def evaluate_command_stack(stack)
- return unless command = stack.shift()
-
- if self.respond_to?("on_#{command}", true)
- self.send("on_#{command}", stack)
- end
-
- evaluate_command_stack(stack)
- end
-
- def open_new_tag
css_classes = []
unless @fg_color.nil?
@@ -168,8 +138,20 @@ module Ci
css_classes << "term-#{css_class}" if @style_mask & flag != 0
end
- return if css_classes.empty?
+ open_new_tag(css_classes) if css_classes.length > 0
+ end
+ def evaluate_command_stack(stack)
+ return unless command = stack.shift()
+
+ if self.respond_to?("on_#{command}", true)
+ self.send("on_#{command}", stack)
+ end
+
+ evaluate_command_stack(stack)
+ end
+
+ def open_new_tag(css_classes)
@out << %{}
@n_open_tags += 1
end
@@ -181,31 +163,6 @@ module Ci
end
end
- def reset_state
- @offset = 0
- @n_open_tags = 0
- @out = ''
- reset
- end
-
- def state
- state = STATE_PARAMS.inject({}) do |h, param|
- h[param] = send(param)
- h
- end
- Base64.urlsafe_encode64(state.to_json)
- end
-
- def restore_state(raw, new_state)
- state = Base64.urlsafe_decode64(new_state)
- state = JSON.parse(state, symbolize_names: true)
- return if state[:offset].to_i > raw.length
-
- STATE_PARAMS.each do |param|
- send("#{param}=".to_sym, state[param])
- end
- end
-
def reset
@fg_color = nil
@bg_color = nil
diff --git a/lib/ci/api/api.rb b/lib/ci/api/api.rb
index 17bb99a2ae..353c4ddebf 100644
--- a/lib/ci/api/api.rb
+++ b/lib/ci/api/api.rb
@@ -1,7 +1,9 @@
+Dir["#{Rails.root}/lib/ci/api/*.rb"].each {|file| require file}
+
module Ci
module API
class API < Grape::API
- include ::API::APIGuard
+ include APIGuard
version 'v1', using: :path
rescue_from ActiveRecord::RecordNotFound do
@@ -29,9 +31,9 @@ module Ci
helpers ::API::Helpers
helpers Gitlab::CurrentSettings
- mount ::Ci::API::Builds
- mount ::Ci::API::Runners
- mount ::Ci::API::Triggers
+ mount Builds
+ mount Runners
+ mount Triggers
end
end
end
diff --git a/lib/ci/api/runners.rb b/lib/ci/api/runners.rb
index 0c41f22c7c..192b1d18a5 100644
--- a/lib/ci/api/runners.rb
+++ b/lib/ci/api/runners.rb
@@ -28,20 +28,20 @@ module Ci
post "register" do
required_attributes! [:token]
- attributes = { description: params[:description],
- tag_list: params[:tag_list] }
-
- unless params[:run_untagged].nil?
- attributes[:run_untagged] = params[:run_untagged]
- end
-
runner =
if runner_registration_token_valid?
# Create shared runner. Requires admin access
- Ci::Runner.create(attributes.merge(is_shared: true))
+ Ci::Runner.create(
+ description: params[:description],
+ tag_list: params[:tag_list],
+ is_shared: true
+ )
elsif project = Project.find_by(runners_token: params[:token])
# Create a specific runner for project.
- project.runners.create(attributes)
+ project.runners.create(
+ description: params[:description],
+ tag_list: params[:tag_list]
+ )
end
return forbidden! unless runner
diff --git a/lib/ci/charts.rb b/lib/ci/charts.rb
index e163663693..d53bdcbd0f 100644
--- a/lib/ci/charts.rb
+++ b/lib/ci/charts.rb
@@ -64,8 +64,7 @@ module Ci
commits.each do |commit|
@labels << commit.short_sha
- duration = commit.duration || 0
- @build_times << (duration / 60)
+ @build_times << (commit.duration / 60)
end
end
end
diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb
index 026a5ac97c..504d3df9d3 100644
--- a/lib/ci/gitlab_ci_yaml_processor.rb
+++ b/lib/ci/gitlab_ci_yaml_processor.rb
@@ -1,6 +1,6 @@
module Ci
class GitlabCiYamlProcessor
- class ValidationError < StandardError; end
+ class ValidationError < StandardError;end
DEFAULT_STAGES = %w(build test deploy)
DEFAULT_STAGE = 'test'
@@ -265,7 +265,7 @@ module Ci
end
def validate_job_dependencies!(name, job)
- unless validate_array_of_strings(job[:dependencies])
+ if !validate_array_of_strings(job[:dependencies])
raise ValidationError, "#{name} job: dependencies parameter should be an array of strings"
end
diff --git a/lib/container_registry/blob.rb b/lib/container_registry/blob.rb
deleted file mode 100644
index 4e20dc4f87..0000000000
--- a/lib/container_registry/blob.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-module ContainerRegistry
- class Blob
- attr_reader :repository, :config
-
- delegate :registry, :client, to: :repository
-
- def initialize(repository, config)
- @repository = repository
- @config = config || {}
- end
-
- def valid?
- digest.present?
- end
-
- def path
- "#{repository.path}@#{digest}"
- end
-
- def digest
- config['digest']
- end
-
- def type
- config['mediaType']
- end
-
- def size
- config['size']
- end
-
- def revision
- digest.split(':')[1]
- end
-
- def short_revision
- revision[0..8]
- end
-
- def delete
- client.delete_blob(repository.name, digest)
- end
-
- def data
- @data ||= client.blob(repository.name, digest, type)
- end
- end
-end
diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb
deleted file mode 100644
index 4d726692f4..0000000000
--- a/lib/container_registry/client.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-require 'faraday'
-require 'faraday_middleware'
-
-module ContainerRegistry
- class Client
- attr_accessor :uri
-
- MANIFEST_VERSION = 'application/vnd.docker.distribution.manifest.v2+json'
-
- def initialize(base_uri, options = {})
- @base_uri = base_uri
- @faraday = Faraday.new(@base_uri) do |conn|
- initialize_connection(conn, options)
- end
- end
-
- def repository_tags(name)
- @faraday.get("/v2/#{name}/tags/list").body
- end
-
- def repository_manifest(name, reference)
- @faraday.get("/v2/#{name}/manifests/#{reference}").body
- end
-
- def repository_tag_digest(name, reference)
- response = @faraday.head("/v2/#{name}/manifests/#{reference}")
- response.headers['docker-content-digest'] if response.success?
- end
-
- def delete_repository_tag(name, reference)
- @faraday.delete("/v2/#{name}/manifests/#{reference}").success?
- end
-
- def blob(name, digest, type = nil)
- headers = {}
- headers['Accept'] = type if type
- @faraday.get("/v2/#{name}/blobs/#{digest}", nil, headers).body
- end
-
- def delete_blob(name, digest)
- @faraday.delete("/v2/#{name}/blobs/#{digest}").success?
- end
-
- private
-
- def initialize_connection(conn, options)
- conn.request :json
- conn.headers['Accept'] = MANIFEST_VERSION
-
- conn.response :json, content_type: /\bjson$/
-
- if options[:user] && options[:password]
- conn.request(:basic_auth, options[:user].to_s, options[:password].to_s)
- elsif options[:token]
- conn.request(:authorization, :bearer, options[:token].to_s)
- end
-
- conn.adapter :net_http
- end
- end
-end
diff --git a/lib/container_registry/config.rb b/lib/container_registry/config.rb
deleted file mode 100644
index 589f9f4380..0000000000
--- a/lib/container_registry/config.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-module ContainerRegistry
- class Config
- attr_reader :tag, :blob, :data
-
- def initialize(tag, blob)
- @tag, @blob = tag, blob
- @data = JSON.parse(blob.data)
- end
-
- def [](key)
- return unless data
-
- data[key]
- end
- end
-end
diff --git a/lib/container_registry/registry.rb b/lib/container_registry/registry.rb
deleted file mode 100644
index 0e634f6b6e..0000000000
--- a/lib/container_registry/registry.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-module ContainerRegistry
- class Registry
- attr_reader :uri, :client, :path
-
- def initialize(uri, options = {})
- @uri = uri
- @path = options[:path] || default_path
- @client = ContainerRegistry::Client.new(uri, options)
- end
-
- def repository(name)
- ContainerRegistry::Repository.new(self, name)
- end
-
- private
-
- def default_path
- @uri.sub(/^https?:\/\//, '')
- end
- end
-end
diff --git a/lib/container_registry/repository.rb b/lib/container_registry/repository.rb
deleted file mode 100644
index 0e4a7cb3cc..0000000000
--- a/lib/container_registry/repository.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-module ContainerRegistry
- class Repository
- attr_reader :registry, :name
-
- delegate :client, to: :registry
-
- def initialize(registry, name)
- @registry, @name = registry, name
- end
-
- def path
- [registry.path, name].compact.join('/')
- end
-
- def tag(tag)
- ContainerRegistry::Tag.new(self, tag)
- end
-
- def manifest
- return @manifest if defined?(@manifest)
-
- @manifest = client.repository_tags(name)
- end
-
- def valid?
- manifest.present?
- end
-
- def tags
- return @tags if defined?(@tags)
- return [] unless manifest && manifest['tags']
-
- @tags = manifest['tags'].map do |tag|
- ContainerRegistry::Tag.new(self, tag)
- end
- end
-
- def blob(config)
- ContainerRegistry::Blob.new(self, config)
- end
-
- def delete_tags
- return unless tags
-
- tags.all?(&:delete)
- end
- end
-end
diff --git a/lib/container_registry/tag.rb b/lib/container_registry/tag.rb
deleted file mode 100644
index 43f8d6dc8c..0000000000
--- a/lib/container_registry/tag.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-module ContainerRegistry
- class Tag
- attr_reader :repository, :name
-
- delegate :registry, :client, to: :repository
-
- def initialize(repository, name)
- @repository, @name = repository, name
- end
-
- def valid?
- manifest.present?
- end
-
- def manifest
- return @manifest if defined?(@manifest)
-
- @manifest = client.repository_manifest(repository.name, name)
- end
-
- def path
- "#{repository.path}:#{name}"
- end
-
- def [](key)
- return unless manifest
-
- manifest[key]
- end
-
- def digest
- return @digest if defined?(@digest)
-
- @digest = client.repository_tag_digest(repository.name, name)
- end
-
- def config_blob
- return @config_blob if defined?(@config_blob)
- return unless manifest && manifest['config']
-
- @config_blob = repository.blob(manifest['config'])
- end
-
- def config
- return unless config_blob
-
- @config ||= ContainerRegistry::Config.new(self, config_blob)
- end
-
- def created_at
- return unless config
-
- @created_at ||= DateTime.rfc3339(config['created'])
- end
-
- def layers
- return @layers if defined?(@layers)
- return unless manifest
-
- @layers = manifest['layers'].map do |layer|
- repository.blob(layer)
- end
- end
-
- def total_size
- return unless layers
-
- layers.map(&:size).sum
- end
-
- def delete
- return unless digest
-
- client.delete_repository_tag(repository.name, digest)
- end
- end
-end
diff --git a/lib/event_filter.rb b/lib/event_filter.rb
index 668d2fa41b..f15b2cfd23 100644
--- a/lib/event_filter.rb
+++ b/lib/event_filter.rb
@@ -27,7 +27,7 @@ class EventFilter
@params = if params
params.dup
else
- [] # EventFilter.default_filter
+ []#EventFilter.default_filter
end
end
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index 37f4c34054..7479e729db 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -1,4 +1,4 @@
-require_dependency 'gitlab/git'
+require 'gitlab/git'
module Gitlab
def self.com?
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb
index 3e3986d638..132f9cd196 100644
--- a/lib/gitlab/backend/shell.rb
+++ b/lib/gitlab/backend/shell.rb
@@ -180,7 +180,7 @@ module Gitlab
# exists?('gitlab/cookies.git')
#
def exists?(dir_name)
- File.exist?(full_path(dir_name))
+ File.exists?(full_path(dir_name))
end
protected
diff --git a/lib/gitlab/bitbucket_import/client.rb b/lib/gitlab/bitbucket_import/client.rb
index 8d1ad62fae..9b83292ef3 100644
--- a/lib/gitlab/bitbucket_import/client.rb
+++ b/lib/gitlab/bitbucket_import/client.rb
@@ -121,7 +121,7 @@ module Gitlab
def get(url)
response = api.get(url)
- raise Unauthorized if (400..499).cover?(response.code.to_i)
+ raise Unauthorized if (400..499).include?(response.code.to_i)
response
end
diff --git a/lib/gitlab/bitbucket_import/project_creator.rb b/lib/gitlab/bitbucket_import/project_creator.rb
index b90ef0b0fb..941f818b84 100644
--- a/lib/gitlab/bitbucket_import/project_creator.rb
+++ b/lib/gitlab/bitbucket_import/project_creator.rb
@@ -11,7 +11,7 @@ module Gitlab
end
def execute
- ::Projects::CreateService.new(
+ project = ::Projects::CreateService.new(
current_user,
name: repo["name"],
path: repo["slug"],
@@ -21,8 +21,11 @@ module Gitlab
import_type: "bitbucket",
import_source: "#{repo["owner"]}/#{repo["slug"]}",
import_url: "ssh://git@bitbucket.org/#{repo["owner"]}/#{repo["slug"]}.git",
- import_data: { credentials: { bb_session: session_data } }
).execute
+
+ project.create_or_update_import_data(credentials: { bb_session: session_data })
+
+ project
end
end
end
diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb
index cd2e83b4c2..f2020c82d4 100644
--- a/lib/gitlab/ci/build/artifacts/metadata.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata.rb
@@ -56,7 +56,7 @@ module Gitlab
child_pattern = '[^/]*/?$' unless @opts[:recursive]
match_pattern = /^#{Regexp.escape(@path)}#{child_pattern}/
- until gz.eof?
+ until gz.eof? do
begin
path = read_string(gz).force_encoding('UTF-8')
meta = read_string(gz).force_encoding('UTF-8')
diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb
index 9dc2602867..85583dce9e 100644
--- a/lib/gitlab/contributions_calendar.rb
+++ b/lib/gitlab/contributions_calendar.rb
@@ -19,7 +19,7 @@ module Gitlab
select('date(created_at) as date, count(id) as total_amount').
map(&:attributes)
- dates = (1.year.ago.to_date..Date.today).to_a
+ dates = (1.year.ago.to_date..(Date.today + 1.day)).to_a
dates.each do |date|
date_id = date.to_time.to_i.to_s
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 92c7e8b9d8..f44d1b3a44 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -1,24 +1,20 @@
module Gitlab
module CurrentSettings
def current_application_settings
- if RequestStore.active?
- RequestStore.fetch(:current_application_settings) { ensure_application_settings! }
- else
- ensure_application_settings!
+ key = :current_application_settings
+
+ RequestStore.store[key] ||= begin
+ settings = nil
+
+ if connect_to_db?
+ settings = ::ApplicationSetting.current
+ settings ||= ::ApplicationSetting.create_from_defaults unless ActiveRecord::Migrator.needs_migration?
+ end
+
+ settings || fake_application_settings
end
end
- def ensure_application_settings!
- settings = ::ApplicationSetting.cached
-
- if !settings && connect_to_db?
- settings = ::ApplicationSetting.current
- settings ||= ::ApplicationSetting.create_from_defaults unless ActiveRecord::Migrator.needs_migration?
- end
-
- settings || fake_application_settings
- end
-
def fake_application_settings
OpenStruct.new(
default_projects_limit: Settings.gitlab['default_projects_limit'],
@@ -40,7 +36,6 @@ module Gitlab
two_factor_grace_period: 48,
akismet_enabled: false,
repository_checks_enabled: true,
- container_registry_token_expire_delay: 5,
)
end
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index 42bec913a4..6f9da69983 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -5,11 +5,11 @@ module Gitlab
end
def self.mysql?
- adapter_name.casecmp('mysql2').zero?
+ adapter_name.downcase == 'mysql2'
end
def self.postgresql?
- adapter_name.casecmp('postgresql').zero?
+ adapter_name.downcase == 'postgresql'
end
def self.version
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
deleted file mode 100644
index fd14234c55..0000000000
--- a/lib/gitlab/database/migration_helpers.rb
+++ /dev/null
@@ -1,142 +0,0 @@
-module Gitlab
- module Database
- module MigrationHelpers
- # Creates a new index, concurrently when supported
- #
- # On PostgreSQL this method creates an index concurrently, on MySQL this
- # creates a regular index.
- #
- # Example:
- #
- # add_concurrent_index :users, :some_column
- #
- # See Rails' `add_index` for more info on the available arguments.
- def add_concurrent_index(*args)
- if transaction_open?
- raise 'add_concurrent_index can not be run inside a transaction, ' \
- 'you can disable transactions by calling disable_ddl_transaction! ' \
- 'in the body of your migration class'
- end
-
- if Database.postgresql?
- args << { algorithm: :concurrently }
- end
-
- add_index(*args)
- end
-
- # Updates the value of a column in batches.
- #
- # This method updates the table in batches of 5% of the total row count.
- # Any data inserted while running this method (or after it has finished
- # running) is _not_ updated automatically.
- #
- # This method _only_ updates rows where the column's value is set to NULL.
- #
- # table - The name of the table.
- # column - The name of the column to update.
- # value - The value for the column.
- def update_column_in_batches(table, column, value)
- quoted_table = quote_table_name(table)
- quoted_column = quote_column_name(column)
-
- ##
- # Workaround for #17711
- #
- # It looks like for MySQL `ActiveRecord::Base.conntection.quote(true)`
- # returns correct value (1), but `ActiveRecord::Migration.new.quote`
- # returns incorrect value ('true'), which causes migrations to fail.
- #
- quoted_value = connection.quote(value)
- processed = 0
-
- total = exec_query("SELECT COUNT(*) AS count FROM #{quoted_table}").
- to_hash.
- first['count'].
- to_i
-
- # Update in batches of 5%
- batch_size = ((total / 100.0) * 5.0).ceil
-
- while processed < total
- start_row = exec_query(%Q{
- SELECT id
- FROM #{quoted_table}
- ORDER BY id ASC
- LIMIT 1 OFFSET #{processed}
- }).to_hash.first
-
- stop_row = exec_query(%Q{
- SELECT id
- FROM #{quoted_table}
- ORDER BY id ASC
- LIMIT 1 OFFSET #{processed + batch_size}
- }).to_hash.first
-
- query = %Q{
- UPDATE #{quoted_table}
- SET #{quoted_column} = #{quoted_value}
- WHERE id >= #{start_row['id']}
- }
-
- if stop_row
- query += " AND id < #{stop_row['id']}"
- end
-
- execute(query)
-
- processed += batch_size
- end
- end
-
- # Adds a column with a default value without locking an entire table.
- #
- # This method runs the following steps:
- #
- # 1. Add the column with a default value of NULL.
- # 2. Update all existing rows in batches.
- # 3. Change the default value of the column to the specified value.
- # 4. Update any remaining rows.
- #
- # These steps ensure a column can be added to a large and commonly used
- # table without locking the entire table for the duration of the table
- # modification.
- #
- # table - The name of the table to update.
- # column - The name of the column to add.
- # type - The column type (e.g. `:integer`).
- # default - The default value for the column.
- # allow_null - When set to `true` the column will allow NULL values, the
- # default is to not allow NULL values.
- def add_column_with_default(table, column, type, default:, allow_null: false)
- if transaction_open?
- raise 'add_column_with_default can not be run inside a transaction, ' \
- 'you can disable transactions by calling disable_ddl_transaction! ' \
- 'in the body of your migration class'
- end
-
- transaction do
- add_column(table, column, type, default: nil)
-
- # Changing the default before the update ensures any newly inserted
- # rows already use the proper default value.
- change_column_default(table, column, default)
- end
-
- begin
- transaction do
- update_column_in_batches(table, column, default)
- end
- # We want to rescue _all_ exceptions here, even those that don't inherit
- # from StandardError.
- rescue Exception => error # rubocop: disable all
- remove_column(table, column)
-
- raise error
- end
-
- change_column_null(table, column, false) unless allow_null
- end
- end
- end
-end
diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb
index 87a9b1e23a..dccb717e95 100644
--- a/lib/gitlab/diff/inline_diff_marker.rb
+++ b/lib/gitlab/diff/inline_diff_marker.rb
@@ -1,11 +1,6 @@
module Gitlab
module Diff
class InlineDiffMarker
- MARKDOWN_SYMBOLS = {
- addition: "+",
- deletion: "-"
- }
-
attr_accessor :raw_line, :rich_line
def initialize(raw_line, rich_line = raw_line)
@@ -13,7 +8,7 @@ module Gitlab
@rich_line = ERB::Util.html_escape(rich_line)
end
- def mark(line_inline_diffs, mode: nil, markdown: false)
+ def mark(line_inline_diffs)
return rich_line unless line_inline_diffs
marker_ranges = []
@@ -25,22 +20,13 @@ module Gitlab
end
offset = 0
-
# Mark each range
- marker_ranges.each_with_index do |range, index|
- before_content =
- if markdown
- "{#{MARKDOWN_SYMBOLS[mode]}"
- else
- ""
- end
- after_content =
- if markdown
- "#{MARKDOWN_SYMBOLS[mode]}}"
- else
- ""
- end
- offset = insert_around_range(rich_line, range, before_content, after_content, offset)
+ marker_ranges.each_with_index do |range, i|
+ class_names = ["idiff"]
+ class_names << "left" if i == 0
+ class_names << "right" if i == marker_ranges.length - 1
+
+ offset = insert_around_range(rich_line, range, "", "", offset)
end
rich_line.html_safe
@@ -48,14 +34,6 @@ module Gitlab
private
- def html_class_names(marker_ranges, mode, index)
- class_names = ["idiff"]
- class_names << "left" if index == 0
- class_names << "right" if index == marker_ranges.length - 1
- class_names << mode if mode
- class_names.join(" ")
- end
-
# Mapping of character positions in the raw line, to the rich (highlighted) line
def position_mapping
@position_mapping ||= begin
diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb
index 522dd2b942..d0815fc7ee 100644
--- a/lib/gitlab/diff/parser.rb
+++ b/lib/gitlab/diff/parser.rb
@@ -17,16 +17,16 @@ module Gitlab
Enumerator.new do |yielder|
@lines.each do |line|
next if filename?(line)
-
- full_line = line.delete("\n")
-
+
+ full_line = line.gsub(/\n/, '')
+
if line.match(/^@@ -/)
type = "match"
-
+
line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0
line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
-
- next if line_old <= 1 && line_new <= 1 # top of file
+
+ next if line_old <= 1 && line_new <= 1 #top of file
yielder << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
line_obj_index += 1
next
@@ -39,8 +39,8 @@ module Gitlab
yielder << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
line_obj_index += 1
end
-
-
+
+
case line[0]
when "+"
line_new += 1
diff --git a/lib/gitlab/email/message/repository_push.rb b/lib/gitlab/email/message/repository_push.rb
index e2fee6b9f3..8f9be6cd9a 100644
--- a/lib/gitlab/email/message/repository_push.rb
+++ b/lib/gitlab/email/message/repository_push.rb
@@ -2,21 +2,22 @@ module Gitlab
module Email
module Message
class RepositoryPush
+ attr_accessor :recipient
attr_reader :author_id, :ref, :action
include Gitlab::Routing.url_helpers
- include DiffHelper
delegate :namespace, :name_with_namespace, to: :project, prefix: :project
delegate :name, to: :author, prefix: :author
delegate :username, to: :author, prefix: :author
- def initialize(notify, project_id, opts = {})
+ def initialize(notify, project_id, recipient, opts = {})
raise ArgumentError, 'Missing options: author_id, ref, action' unless
opts[:author_id] && opts[:ref] && opts[:action]
@notify = notify
@project_id = project_id
+ @recipient = recipient
@opts = opts.dup
@author_id = @opts.delete(:author_id)
@@ -37,7 +38,7 @@ module Gitlab
end
def diffs
- @diffs ||= (safe_diff_files(compare.diffs, diff_refs) if compare)
+ @diffs ||= (compare.diffs if compare)
end
def diffs_count
@@ -48,10 +49,6 @@ module Gitlab
@opts[:compare]
end
- def diff_refs
- @opts[:diff_refs]
- end
-
def compare_timeout
diffs.overflow? if diffs
end
diff --git a/lib/gitlab/email/reply_parser.rb b/lib/gitlab/email/reply_parser.rb
index 3411eb1d9c..6ed36b51f1 100644
--- a/lib/gitlab/email/reply_parser.rb
+++ b/lib/gitlab/email/reply_parser.rb
@@ -65,7 +65,7 @@ module Gitlab
(l =~ /On \w+ \d+,? \d+,?.*wrote:/)
# Headers on subsequent lines
- break if (0..2).all? { |off| lines[idx + off] =~ REPLYING_HEADER_REGEX }
+ break if (0..2).all? { |off| lines[idx+off] =~ REPLYING_HEADER_REGEX }
# Headers on the same line
break if REPLYING_HEADER_LABELS.count { |label| l.include?(label) } >= 3
diff --git a/lib/gitlab/fogbugz_import/project_creator.rb b/lib/gitlab/fogbugz_import/project_creator.rb
index 1918d5b208..3840765db8 100644
--- a/lib/gitlab/fogbugz_import/project_creator.rb
+++ b/lib/gitlab/fogbugz_import/project_creator.rb
@@ -12,7 +12,7 @@ module Gitlab
end
def execute
- ::Projects::CreateService.new(
+ project = ::Projects::CreateService.new(
current_user,
name: repo.safe_name,
path: repo.path,
@@ -21,9 +21,12 @@ module Gitlab
visibility_level: Gitlab::VisibilityLevel::INTERNAL,
import_type: 'fogbugz',
import_source: repo.name,
- import_url: Project::UNKNOWN_IMPORT_URL,
- import_data: { data: { 'repo' => repo.raw_data, 'user_map' => user_map }, credentials: { fb_session: fb_session } }
+ import_url: Project::UNKNOWN_IMPORT_URL
).execute
+
+ project.create_or_update_import_data(data: { 'repo' => repo.raw_data, 'user_map' => user_map }, credentials: { fb_session: fb_session })
+
+ project
end
end
end
diff --git a/lib/gitlab/github_import/branch_formatter.rb b/lib/gitlab/github_import/branch_formatter.rb
deleted file mode 100644
index a15fc84b41..0000000000
--- a/lib/gitlab/github_import/branch_formatter.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-module Gitlab
- module GithubImport
- class BranchFormatter < BaseFormatter
- delegate :repo, :sha, :ref, to: :raw_data
-
- def exists?
- project.repository.branch_exists?(ref)
- end
-
- def name
- @name ||= exists? ? ref : "#{ref}-#{short_id}"
- end
-
- def valid?
- repo.present?
- end
-
- def valid?
- repo.present?
- end
-
- private
-
- def short_id
- sha.to_s[0..7]
- end
- end
- end
-end
diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb
index 408d9b7963..0f9e3ee14e 100644
--- a/lib/gitlab/github_import/importer.rb
+++ b/lib/gitlab/github_import/importer.rb
@@ -3,15 +3,12 @@ module Gitlab
class Importer
include Gitlab::ShellAdapter
- attr_reader :client, :project, :repo, :repo_url
+ attr_reader :project, :client
def initialize(project)
- @project = project
- @repo = project.import_source
- @repo_url = project.import_url
-
- if credentials
- @client = Client.new(credentials[:user])
+ @project = project
+ if import_data_credentials
+ @client = Client.new(import_data_credentials[:user])
@formatter = Gitlab::ImportFormatter.new
else
raise Projects::ImportService::Error, "Unable to find project import data credentials for project ID: #{@project.id}"
@@ -25,12 +22,12 @@ module Gitlab
private
- def credentials
- @credentials ||= project.import_data.credentials if project.import_data
+ def import_data_credentials
+ @import_data_credentials ||= project.import_data.credentials if project.import_data
end
def import_labels
- client.labels(repo).each do |raw_data|
+ client.labels(project.import_source).each do |raw_data|
Label.create!(LabelFormatter.new(project, raw_data).attributes)
end
@@ -40,7 +37,7 @@ module Gitlab
end
def import_milestones
- client.list_milestones(repo, state: :all).each do |raw_data|
+ client.list_milestones(project.import_source, state: :all).each do |raw_data|
Milestone.create!(MilestoneFormatter.new(project, raw_data).attributes)
end
@@ -50,7 +47,9 @@ module Gitlab
end
def import_issues
- client.list_issues(repo, state: :all, sort: :created, direction: :asc).each do |raw_data|
+ client.list_issues(project.import_source, state: :all,
+ sort: :created,
+ direction: :asc).each do |raw_data|
gh_issue = IssueFormatter.new(project, raw_data)
if gh_issue.valid?
@@ -69,50 +68,29 @@ module Gitlab
end
def import_pull_requests
- pull_requests = client.pull_requests(repo, state: :all, sort: :created, direction: :asc)
- .map { |raw| PullRequestFormatter.new(project, raw) }
- .select(&:valid?)
+ client.pull_requests(project.import_source, state: :all,
+ sort: :created,
+ direction: :asc).each do |raw_data|
+ pull_request = PullRequestFormatter.new(project, raw_data)
- source_branches_removed = pull_requests.reject(&:source_branch_exists?).map { |pr| [pr.source_branch_name, pr.source_branch_sha] }
- target_branches_removed = pull_requests.reject(&:target_branch_exists?).map { |pr| [pr.target_branch_name, pr.target_branch_sha] }
- branches_removed = source_branches_removed | target_branches_removed
+ if pull_request.valid?
+ merge_request = MergeRequest.new(pull_request.attributes)
- create_refs(branches_removed)
-
- pull_requests.each do |pull_request|
- merge_request = MergeRequest.new(pull_request.attributes)
-
- if merge_request.save
- apply_labels(pull_request.number, merge_request)
- import_comments(pull_request.number, merge_request)
- import_comments_on_diff(pull_request.number, merge_request)
+ if merge_request.save
+ apply_labels(pull_request.number, merge_request)
+ import_comments(pull_request.number, merge_request)
+ import_comments_on_diff(pull_request.number, merge_request)
+ end
end
end
- delete_refs(branches_removed)
-
true
rescue ActiveRecord::RecordInvalid => e
raise Projects::ImportService::Error, e.message
end
- def create_refs(branches)
- branches.each do |name, sha|
- client.create_ref(repo, "refs/heads/#{name}", sha)
- end
-
- project.repository.fetch_ref(repo_url, '+refs/heads/*', 'refs/heads/*')
- end
-
- def delete_refs(branches)
- branches.each do |name, _|
- client.delete_ref(repo, "heads/#{name}")
- project.repository.rm_branch(project.creator, name)
- end
- end
-
def apply_labels(number, issuable)
- issue = client.issue(repo, number)
+ issue = client.issue(project.import_source, number)
if issue.labels.count > 0
label_ids = issue.labels.map do |raw|
@@ -124,12 +102,12 @@ module Gitlab
end
def import_comments(issue_number, noteable)
- comments = client.issue_comments(repo, issue_number)
+ comments = client.issue_comments(project.import_source, issue_number)
create_comments(comments, noteable)
end
def import_comments_on_diff(pull_request_number, merge_request)
- comments = client.pull_request_comments(repo, pull_request_number)
+ comments = client.pull_request_comments(project.import_source, pull_request_number)
create_comments(comments, merge_request)
end
diff --git a/lib/gitlab/github_import/pull_request_formatter.rb b/lib/gitlab/github_import/pull_request_formatter.rb
index a2947b56ad..d21b942ad4 100644
--- a/lib/gitlab/github_import/pull_request_formatter.rb
+++ b/lib/gitlab/github_import/pull_request_formatter.rb
@@ -1,20 +1,15 @@
module Gitlab
module GithubImport
class PullRequestFormatter < BaseFormatter
- delegate :exists?, :name, :project, :repo, :sha, to: :source_branch, prefix: true
- delegate :exists?, :name, :project, :repo, :sha, to: :target_branch, prefix: true
-
def attributes
{
iid: number,
title: raw_data.title,
description: description,
- source_project: source_branch_project,
- source_branch: source_branch_name,
- head_source_sha: source_branch_sha,
- target_project: target_branch_project,
- target_branch: target_branch_name,
- base_target_sha: target_branch_sha,
+ source_project: source_project,
+ source_branch: source_branch.name,
+ target_project: target_project,
+ target_branch: target_branch.name,
state: state,
milestone: milestone,
author_id: author_id,
@@ -29,15 +24,7 @@ module Gitlab
end
def valid?
- source_branch.valid? && target_branch.valid? && !cross_project?
- end
-
- def source_branch
- @source_branch ||= BranchFormatter.new(project, raw_data.head)
- end
-
- def target_branch
- @target_branch ||= BranchFormatter.new(project, raw_data.base)
+ !cross_project? && source_branch.present? && target_branch.present?
end
private
@@ -65,7 +52,7 @@ module Gitlab
end
def cross_project?
- source_branch_repo.id != target_branch_repo.id
+ source_repo.present? && target_repo.present? && source_repo.id != target_repo.id
end
def description
@@ -78,10 +65,35 @@ module Gitlab
end
end
+ def source_project
+ project
+ end
+
+ def source_repo
+ raw_data.head.repo
+ end
+
+ def source_branch
+ source_project.repository.find_branch(raw_data.head.ref)
+ end
+
+ def target_project
+ project
+ end
+
+ def target_repo
+ raw_data.base.repo
+ end
+
+ def target_branch
+ target_project.repository.find_branch(raw_data.base.ref)
+ end
+
def state
- @state ||= if raw_data.state == 'closed' && raw_data.merged_at.present?
+ @state ||= case true
+ when raw_data.state == 'closed' && raw_data.merged_at.present?
'merged'
- elsif raw_data.state == 'closed'
+ when raw_data.state == 'closed'
'closed'
else
'opened'
diff --git a/lib/gitlab/gitignore.rb b/lib/gitlab/gitignore.rb
deleted file mode 100644
index f46b43b61a..0000000000
--- a/lib/gitlab/gitignore.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-module Gitlab
- class Gitignore
- FILTER_REGEX = /\.gitignore\z/.freeze
-
- def initialize(path)
- @path = path
- end
-
- def name
- File.basename(@path, '.gitignore')
- end
-
- def content
- File.read(@path)
- end
-
- class << self
- def all
- languages_frameworks + global
- end
-
- def find(key)
- file_name = "#{key}.gitignore"
-
- directory = select_directory(file_name)
- directory ? new(File.join(directory, file_name)) : nil
- end
-
- def global
- files_for_folder(global_dir).map { |file| new(File.join(global_dir, file)) }
- end
-
- def languages_frameworks
- files_for_folder(gitignore_dir).map { |file| new(File.join(gitignore_dir, file)) }
- end
-
- private
-
- def select_directory(file_name)
- [gitignore_dir, global_dir].find { |dir| File.exist?(File.join(dir, file_name)) }
- end
-
- def global_dir
- File.join(gitignore_dir, 'Global')
- end
-
- def gitignore_dir
- Rails.root.join('vendor/gitignore')
- end
-
- def files_for_folder(dir)
- Dir.glob("#{dir.to_s}/*.gitignore").map { |file| file.gsub(FILTER_REGEX, '') }
- end
- end
- end
-end
diff --git a/lib/gitlab/gitlab_import/importer.rb b/lib/gitlab/gitlab_import/importer.rb
index 3f76ec9797..96717b42ba 100644
--- a/lib/gitlab/gitlab_import/importer.rb
+++ b/lib/gitlab/gitlab_import/importer.rb
@@ -5,9 +5,9 @@ module Gitlab
def initialize(project)
@project = project
- import_data = project.import_data
- if import_data && import_data.credentials && import_data.credentials[:password]
- @client = Client.new(import_data.credentials[:password])
+ credentials = import_data
+ if credentials && credentials[:password]
+ @client = Client.new(credentials[:password])
@formatter = Gitlab::ImportFormatter.new
else
raise Projects::ImportService::Error, "Unable to find project import data credentials for project ID: #{@project.id}"
@@ -17,7 +17,7 @@ module Gitlab
def execute
project_identifier = CGI.escape(project.import_source)
- # Issues && Comments
+ #Issues && Comments
issues = client.issues(project_identifier)
issues.each do |issue|
diff --git a/lib/gitlab/google_code_import/project_creator.rb b/lib/gitlab/google_code_import/project_creator.rb
index 326cfcaa8a..0abb7a64c1 100644
--- a/lib/gitlab/google_code_import/project_creator.rb
+++ b/lib/gitlab/google_code_import/project_creator.rb
@@ -11,7 +11,7 @@ module Gitlab
end
def execute
- ::Projects::CreateService.new(
+ project = ::Projects::CreateService.new(
current_user,
name: repo.name,
path: repo.name,
@@ -21,9 +21,12 @@ module Gitlab
visibility_level: Gitlab::VisibilityLevel::PUBLIC,
import_type: "google_code",
import_source: repo.name,
- import_url: repo.import_url,
- import_data: { data: { 'repo' => repo.raw_data, 'user_map' => user_map } }
+ import_url: repo.import_url
).execute
+
+ project.create_or_update_import_data(data: { 'repo' => repo.raw_data, 'user_map' => user_map })
+
+ project
end
end
end
diff --git a/lib/gitlab/url_sanitizer.rb b/lib/gitlab/import_url.rb
similarity index 66%
rename from lib/gitlab/url_sanitizer.rb
rename to lib/gitlab/import_url.rb
index 7d02fe3c97..d23b013c1f 100644
--- a/lib/gitlab/url_sanitizer.rb
+++ b/lib/gitlab/import_url.rb
@@ -1,13 +1,7 @@
module Gitlab
- class UrlSanitizer
- def self.sanitize(content)
- regexp = URI::Parser.new.make_regexp(['http', 'https', 'ssh', 'git'])
-
- content.gsub(regexp) { |url| new(url).masked_url }
- end
-
+ class ImportUrl
def initialize(url, credentials: nil)
- @url = Addressable::URI.parse(url)
+ @url = URI.parse(URI.encode(url))
@credentials = credentials
end
@@ -15,13 +9,6 @@ module Gitlab
@sanitized_url ||= safe_url.to_s
end
- def masked_url
- url = @url.dup
- url.password = "*****" unless url.password.nil?
- url.user = "*****" unless url.user.nil?
- url.to_s
- end
-
def credentials
@credentials ||= { user: @url.user, password: @url.password }
end
diff --git a/lib/gitlab/lazy.rb b/lib/gitlab/lazy.rb
deleted file mode 100644
index 2a659ae4c7..0000000000
--- a/lib/gitlab/lazy.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-module Gitlab
- # A class that can be wrapped around an expensive method call so it's only
- # executed when actually needed.
- #
- # Usage:
- #
- # object = Gitlab::Lazy.new { some_expensive_work_here }
- #
- # object['foo']
- # object.bar
- class Lazy < BasicObject
- def initialize(&block)
- @block = block
- end
-
- def method_missing(name, *args, &block)
- __evaluate__
-
- @result.__send__(name, *args, &block)
- end
-
- def respond_to_missing?(name, include_private = false)
- __evaluate__
-
- @result.respond_to?(name, include_private) || super
- end
-
- private
-
- def __evaluate__
- @result = @block.call unless defined?(@result)
- end
- end
-end
diff --git a/lib/gitlab/markup_helper.rb b/lib/gitlab/markup_helper.rb
index dda371e655..a5f767b134 100644
--- a/lib/gitlab/markup_helper.rb
+++ b/lib/gitlab/markup_helper.rb
@@ -40,7 +40,7 @@ module Gitlab
# Returns boolean
def plain?(filename)
filename.downcase.end_with?('.txt') ||
- filename.casecmp('readme').zero?
+ filename.downcase == 'readme'
end
def previewable?(filename)
diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb
index 0f115893a1..708ef79f30 100644
--- a/lib/gitlab/metrics/instrumentation.rb
+++ b/lib/gitlab/metrics/instrumentation.rb
@@ -154,6 +154,8 @@ module Gitlab
duration = (Time.now - start) * 1000.0
if duration >= Gitlab::Metrics.method_call_threshold
+ trans.increment(:method_duration, duration)
+
trans.add_metric(Gitlab::Metrics::Instrumentation::SERIES,
{ duration: duration },
method: #{label.inspect})
diff --git a/lib/gitlab/metrics/subscribers/rails_cache.rb b/lib/gitlab/metrics/subscribers/rails_cache.rb
index 8e345e8ae4..49e5f86e6e 100644
--- a/lib/gitlab/metrics/subscribers/rails_cache.rb
+++ b/lib/gitlab/metrics/subscribers/rails_cache.rb
@@ -6,28 +6,26 @@ module Gitlab
attach_to :active_support
def cache_read(event)
- increment(:cache_read, event.duration)
+ increment(:cache_read_duration, event.duration)
end
def cache_write(event)
- increment(:cache_write, event.duration)
+ increment(:cache_write_duration, event.duration)
end
def cache_delete(event)
- increment(:cache_delete, event.duration)
+ increment(:cache_delete_duration, event.duration)
end
def cache_exist?(event)
- increment(:cache_exists, event.duration)
+ increment(:cache_exists_duration, event.duration)
end
def increment(key, duration)
return unless current_transaction
current_transaction.increment(:cache_duration, duration)
- current_transaction.increment(:cache_count, 1)
- current_transaction.increment("#{key}_duration".to_sym, duration)
- current_transaction.increment("#{key}_count".to_sym, 1)
+ current_transaction.increment(key, duration)
end
private
diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb
index 5764ab1565..50b0dd3238 100644
--- a/lib/gitlab/middleware/go.rb
+++ b/lib/gitlab/middleware/go.rb
@@ -39,7 +39,7 @@ module Gitlab
request_url = URI.join(base_url, project_path)
domain_path = strip_url(request_url.to_s)
- "\n"
+ "\n";
end
def strip_url(url)
diff --git a/lib/gitlab/middleware/rails_queue_duration.rb b/lib/gitlab/middleware/rails_queue_duration.rb
deleted file mode 100644
index 56608b1b27..0000000000
--- a/lib/gitlab/middleware/rails_queue_duration.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# This Rack middleware is intended to measure the latency between
-# gitlab-workhorse forwarding a request to the Rails application and the
-# time this middleware is reached.
-
-module Gitlab
- module Middleware
- class RailsQueueDuration
- def initialize(app)
- @app = app
- end
-
- def call(env)
- trans = Gitlab::Metrics.current_transaction
- proxy_start = env['HTTP_GITLAB_WORHORSE_PROXY_START'].presence
- if trans && proxy_start
- # Time in milliseconds since gitlab-workhorse started the request
- trans.set(:rails_queue_duration, Time.now.to_f * 1_000 - proxy_start.to_f / 1_000_000)
- end
-
- @app.call(env)
- end
- end
- end
-end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index 183bd10d6a..71c5b6801f 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -74,7 +74,7 @@ module Gitlab
end
def notes
- project.notes.user.search(query, as_user: @current_user).order('updated_at DESC')
+ project.notes.user.search(query).order('updated_at DESC')
end
def commits
diff --git a/lib/gitlab/redis.rb b/lib/gitlab/redis.rb
index 40766f35f7..5c352c96de 100644
--- a/lib/gitlab/redis.rb
+++ b/lib/gitlab/redis.rb
@@ -25,7 +25,7 @@ module Gitlab
end
@pool.with { |redis| yield redis }
end
-
+
def self.redis_store_options
url = new.url
redis_config_hash = ::Redis::Store::Factory.extract_host_options_from_uri(url)
@@ -40,10 +40,10 @@ module Gitlab
def initialize(rails_env=nil)
rails_env ||= Rails.env
config_file = File.expand_path('../../../config/resque.yml', __FILE__)
-
+
@url = "redis://localhost:6379"
- if File.exist?(config_file)
- @url = YAML.load_file(config_file)[rails_env]
+ if File.exists?(config_file)
+ @url =YAML.load_file(config_file)[rails_env]
end
end
end
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index 11c0b01f0d..13c4d64c99 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -4,9 +4,10 @@ module Gitlab
REFERABLES = %i(user issue label milestone merge_request snippet commit commit_range)
attr_accessor :project, :current_user, :author
- def initialize(project, current_user = nil)
+ def initialize(project, current_user = nil, author = nil)
@project = project
@current_user = current_user
+ @author = author
@references = {}
@@ -17,21 +18,17 @@ module Gitlab
super(text, context.merge(project: project))
end
- def references(type)
- super(type, project, current_user)
- end
-
REFERABLES.each do |type|
define_method("#{type}s") do
- @references[type] ||= references(type)
+ @references[type] ||= references(type, reference_context)
end
end
def issues
if project && project.jira_tracker?
- @references[:external_issue] ||= references(:external_issue)
+ @references[:external_issue] ||= references(:external_issue, reference_context)
else
- @references[:issue] ||= references(:issue)
+ @references[:issue] ||= references(:issue, reference_context)
end
end
@@ -49,5 +46,11 @@ module Gitlab
@pattern = Regexp.union(patterns.compact)
end
+
+ private
+
+ def reference_context
+ { project: project, current_user: current_user, author: author }
+ end
end
end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 1cbd6d945a..ace906a6f5 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -96,9 +96,5 @@ module Gitlab
(? %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage target text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
- 'altGlyph' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format glyph-orientation-horizontal glyph-orientation-vertical glyphRef id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
- 'altGlyphDef' => %w[id xml:base xml:lang xml:space],
- 'altGlyphItem' => %w[id xml:base xml:lang xml:space],
- 'animate' => %w[accumulate additive alignment-baseline attributeName attributeType baseline-shift begin by calcMode clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dur enable-background end externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight from glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning keySplines keyTimes letter-spacing lighting-color marker-end marker-mid marker-start mask max min onbegin onend onload onrepeat opacity overflow pointer-events repeatCount repeatDur requiredExtensions requiredFeatures restart shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width systemLanguage text-anchor text-decoration text-rendering to unicode-bidi values visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
- 'animateColor' => %w[accumulate additive alignment-baseline attributeName attributeType baseline-shift begin by calcMode clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dur enable-background end externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight from glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning keySplines keyTimes letter-spacing lighting-color marker-end marker-mid marker-start mask max min onbegin onend onload onrepeat opacity overflow pointer-events repeatCount repeatDur requiredExtensions requiredFeatures restart shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width systemLanguage text-anchor text-decoration text-rendering to unicode-bidi values visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
- 'animateMotion' => %w[accumulate additive begin by calcMode dur end externalResourcesRequired fill from id keyPoints keySplines keyTimes max min onbegin onend onload onrepeat origin path repeatCount repeatDur requiredExtensions requiredFeatures restart rotate systemLanguage to values xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
- 'animateTransform' => %w[accumulate additive attributeName attributeType begin by calcMode dur end externalResourcesRequired fill from id keySplines keyTimes max min onbegin onend onload onrepeat repeatCount repeatDur requiredExtensions requiredFeatures restart systemLanguage to type values xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
- 'circle' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events r requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'clipPath' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule clipPathUnits color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'color-profile' => %w[id local name rendering-intent xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
- 'cursor' => %w[externalResourcesRequired id requiredExtensions requiredFeatures systemLanguage x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
- 'defs' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'desc' => %w[class id style xml:base xml:lang xml:space],
- 'ellipse' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rx ry shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'feBlend' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask mode opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feColorMatrix' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering type unicode-bidi values visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feComponentTransfer' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feComposite' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 k1 k2 k3 k4 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity operator overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feConvolveMatrix' => %w[alignment-baseline baseline-shift bias class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display divisor dominant-baseline edgeMode enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelMatrix kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity order overflow pointer-events preserveAlpha result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style targetX targetY text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feDiffuseLighting' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor diffuseConstant direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feDisplacementMap' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result scale shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xChannelSelector xml:base xml:lang xml:space y yChannelSelector],
- 'feDistantLight' => %w[azimuth elevation id xml:base xml:lang xml:space],
- 'feFlood' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feFuncA' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
- 'feFuncB' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
- 'feFuncG' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
- 'feFuncR' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
- 'feGaussianBlur' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stdDeviation stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feImage' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events preserveAspectRatio result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
- 'feMerge' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feMergeNode' => %w[id xml:base xml:lang xml:space],
- 'feMorphology' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity operator overflow pointer-events radius result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feOffset' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'fePointLight' => %w[id x xml:base xml:lang xml:space y z],
- 'feSpecularLighting' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering specularConstant specularExponent stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feSpotLight' => %w[id limitingConeAngle pointsAtX pointsAtY pointsAtZ specularExponent x xml:base xml:lang xml:space y z],
- 'feTile' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'feTurbulence' => %w[alignment-baseline baseFrequency baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask numOctaves opacity overflow pointer-events result seed shape-rendering stitchTiles stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering type unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'filter' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events primitiveUnits shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
- 'font' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x horiz-origin-y id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'font-face' => %w[accent-height alphabetic ascent bbox cap-height descent font-family font-size font-stretch font-style font-variant font-weight hanging id ideographic mathematical overline-position overline-thickness panose-1 slope stemh stemv strikethrough-position strikethrough-thickness underline-position underline-thickness unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical widths x-height xml:base xml:lang xml:space],
- 'font-face-format' => %w[id string xml:base xml:lang xml:space],
- 'font-face-name' => %w[id name xml:base xml:lang xml:space],
- 'font-face-src' => %w[id xml:base xml:lang xml:space],
- 'font-face-uri' => %w[id xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
- 'foreignObject' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'g' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'glyph' => %w[alignment-baseline arabic-form baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x id image-rendering kerning lang letter-spacing lighting-color marker-end marker-mid marker-start mask opacity orientation overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'glyphRef' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format glyph-orientation-horizontal glyph-orientation-vertical glyphRef id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
- 'hkern' => %w[g1 g2 id k u1 u2 xml:base xml:lang xml:space],
- 'image' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
- 'line' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode x1 x2 xml:base xml:lang xml:space y1 y2],
- 'linearGradient' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical gradientTransform gradientUnits id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering spreadMethod stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x1 x2 xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space y1 y2],
- 'marker' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask opacity orient overflow pointer-events preserveAspectRatio refX refY shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi viewBox visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'mask' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask maskContentUnits maskUnits opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'metadata' => %w[id xml:base xml:lang xml:space],
- 'missing-glyph' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'mpath' => %w[externalResourcesRequired id xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
- 'path' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pathLength pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'pattern' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow patternContentUnits patternTransform patternUnits pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi viewBox visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
- 'polygon' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events points requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'polyline' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events points requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'radialGradient' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight fx fy glyph-orientation-horizontal glyph-orientation-vertical gradientTransform gradientUnits id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events r shape-rendering spreadMethod stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space],
- 'rect' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rx ry shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'script' => %w[externalResourcesRequired id type xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
- 'set' => %w[attributeName attributeType begin dur end externalResourcesRequired fill id max min onbegin onend onload onrepeat repeatCount repeatDur requiredExtensions requiredFeatures restart systemLanguage to xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
- 'stop' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask offset opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'style' => %w[id media title type xml:base xml:lang xml:space],
- 'svg' => %w[alignment-baseline baseProfile baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onabort onactivate onclick onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onresize onscroll onunload onzoom opacity overflow pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi version viewBox visibility width word-spacing writing-mode x xml:base xml:lang xml:space xmlns y zoomAndPan],
- 'switch' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'symbol' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events preserveAspectRatio shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi viewBox visibility word-spacing writing-mode xml:base xml:lang xml:space],
- 'text' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength transform unicode-bidi visibility word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'textPath' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask method onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering spacing startOffset stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space],
- 'title' => %w[class id style xml:base xml:lang xml:space],
- 'tref' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode x xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space y],
- 'tspan' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode x xml:base xml:lang xml:space y],
- 'use' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
- 'view' => %w[externalResourcesRequired id preserveAspectRatio viewBox viewTarget xml:base xml:lang xml:space zoomAndPan],
- 'vkern' => %w[g1 g2 id k u1 u2 xml:base xml:lang xml:space]
- }.freeze
- end
+ ALLOWED_ATTRIBUTES = {
+ 'a' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage target text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'altGlyph' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format glyph-orientation-horizontal glyph-orientation-vertical glyphRef id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'altGlyphDef' => %w[id xml:base xml:lang xml:space],
+ 'altGlyphItem' => %w[id xml:base xml:lang xml:space],
+ 'animate' => %w[accumulate additive alignment-baseline attributeName attributeType baseline-shift begin by calcMode clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dur enable-background end externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight from glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning keySplines keyTimes letter-spacing lighting-color marker-end marker-mid marker-start mask max min onbegin onend onload onrepeat opacity overflow pointer-events repeatCount repeatDur requiredExtensions requiredFeatures restart shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width systemLanguage text-anchor text-decoration text-rendering to unicode-bidi values visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'animateColor' => %w[accumulate additive alignment-baseline attributeName attributeType baseline-shift begin by calcMode clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dur enable-background end externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight from glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning keySplines keyTimes letter-spacing lighting-color marker-end marker-mid marker-start mask max min onbegin onend onload onrepeat opacity overflow pointer-events repeatCount repeatDur requiredExtensions requiredFeatures restart shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width systemLanguage text-anchor text-decoration text-rendering to unicode-bidi values visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'animateMotion' => %w[accumulate additive begin by calcMode dur end externalResourcesRequired fill from id keyPoints keySplines keyTimes max min onbegin onend onload onrepeat origin path repeatCount repeatDur requiredExtensions requiredFeatures restart rotate systemLanguage to values xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'animateTransform' => %w[accumulate additive attributeName attributeType begin by calcMode dur end externalResourcesRequired fill from id keySplines keyTimes max min onbegin onend onload onrepeat repeatCount repeatDur requiredExtensions requiredFeatures restart systemLanguage to type values xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'circle' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events r requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'clipPath' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule clipPathUnits color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'color-profile' => %w[id local name rendering-intent xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'cursor' => %w[externalResourcesRequired id requiredExtensions requiredFeatures systemLanguage x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'defs' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'desc' => %w[class id style xml:base xml:lang xml:space],
+ 'ellipse' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rx ry shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'feBlend' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask mode opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feColorMatrix' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering type unicode-bidi values visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feComponentTransfer' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feComposite' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 k1 k2 k3 k4 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity operator overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feConvolveMatrix' => %w[alignment-baseline baseline-shift bias class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display divisor dominant-baseline edgeMode enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelMatrix kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity order overflow pointer-events preserveAlpha result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style targetX targetY text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feDiffuseLighting' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor diffuseConstant direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feDisplacementMap' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result scale shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xChannelSelector xml:base xml:lang xml:space y yChannelSelector],
+ 'feDistantLight' => %w[azimuth elevation id xml:base xml:lang xml:space],
+ 'feFlood' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feFuncA' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
+ 'feFuncB' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
+ 'feFuncG' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
+ 'feFuncR' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
+ 'feGaussianBlur' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stdDeviation stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feImage' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events preserveAspectRatio result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'feMerge' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feMergeNode' => %w[id xml:base xml:lang xml:space],
+ 'feMorphology' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity operator overflow pointer-events radius result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feOffset' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'fePointLight' => %w[id x xml:base xml:lang xml:space y z],
+ 'feSpecularLighting' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering specularConstant specularExponent stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feSpotLight' => %w[id limitingConeAngle pointsAtX pointsAtY pointsAtZ specularExponent x xml:base xml:lang xml:space y z],
+ 'feTile' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feTurbulence' => %w[alignment-baseline baseFrequency baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask numOctaves opacity overflow pointer-events result seed shape-rendering stitchTiles stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering type unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'filter' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events primitiveUnits shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'font' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x horiz-origin-y id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'font-face' => %w[accent-height alphabetic ascent bbox cap-height descent font-family font-size font-stretch font-style font-variant font-weight hanging id ideographic mathematical overline-position overline-thickness panose-1 slope stemh stemv strikethrough-position strikethrough-thickness underline-position underline-thickness unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical widths x-height xml:base xml:lang xml:space],
+ 'font-face-format' => %w[id string xml:base xml:lang xml:space],
+ 'font-face-name' => %w[id name xml:base xml:lang xml:space],
+ 'font-face-src' => %w[id xml:base xml:lang xml:space],
+ 'font-face-uri' => %w[id xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'foreignObject' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'g' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'glyph' => %w[alignment-baseline arabic-form baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x id image-rendering kerning lang letter-spacing lighting-color marker-end marker-mid marker-start mask opacity orientation overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'glyphRef' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format glyph-orientation-horizontal glyph-orientation-vertical glyphRef id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'hkern' => %w[g1 g2 id k u1 u2 xml:base xml:lang xml:space],
+ 'image' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'line' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode x1 x2 xml:base xml:lang xml:space y1 y2],
+ 'linearGradient' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical gradientTransform gradientUnits id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering spreadMethod stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x1 x2 xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space y1 y2],
+ 'marker' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask opacity orient overflow pointer-events preserveAspectRatio refX refY shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi viewBox visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'mask' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask maskContentUnits maskUnits opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'metadata' => %w[id xml:base xml:lang xml:space],
+ 'missing-glyph' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'mpath' => %w[externalResourcesRequired id xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'path' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pathLength pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'pattern' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow patternContentUnits patternTransform patternUnits pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi viewBox visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'polygon' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events points requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'polyline' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events points requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'radialGradient' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight fx fy glyph-orientation-horizontal glyph-orientation-vertical gradientTransform gradientUnits id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events r shape-rendering spreadMethod stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space],
+ 'rect' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rx ry shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'script' => %w[externalResourcesRequired id type xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'set' => %w[attributeName attributeType begin dur end externalResourcesRequired fill id max min onbegin onend onload onrepeat repeatCount repeatDur requiredExtensions requiredFeatures restart systemLanguage to xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'stop' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask offset opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'style' => %w[id media title type xml:base xml:lang xml:space],
+ 'svg' => %w[alignment-baseline baseProfile baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onabort onactivate onclick onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onresize onscroll onunload onzoom opacity overflow pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi version viewBox visibility width word-spacing writing-mode x xml:base xml:lang xml:space xmlns y zoomAndPan],
+ 'switch' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'symbol' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events preserveAspectRatio shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi viewBox visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'text' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength transform unicode-bidi visibility word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'textPath' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask method onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering spacing startOffset stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space],
+ 'title' => %w[class id style xml:base xml:lang xml:space],
+ 'tref' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode x xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'tspan' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'use' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'view' => %w[externalResourcesRequired id preserveAspectRatio viewBox viewTarget xml:base xml:lang xml:space zoomAndPan],
+ 'vkern' => %w[g1 g2 id k u1 u2 xml:base xml:lang xml:space]
+ }.freeze
end
end
end
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
index fe65c24610..2bbbd3074e 100644
--- a/lib/gitlab/url_builder.rb
+++ b/lib/gitlab/url_builder.rb
@@ -62,7 +62,7 @@ module Gitlab
end
def wiki_page_url
- namespace_project_wiki_url(object.wiki.project.namespace, object.wiki.project, object.slug)
+ "#{Gitlab.config.gitlab.url}#{object.wiki.wiki_base_path}/#{object.slug}"
end
end
end
diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb
index 9462f3368e..a1ee1cba21 100644
--- a/lib/gitlab/visibility_level.rb
+++ b/lib/gitlab/visibility_level.rb
@@ -32,13 +32,6 @@ module Gitlab
}
end
- def highest_allowed_level
- restricted_levels = current_application_settings.restricted_visibility_levels
-
- allowed_levels = self.values - restricted_levels
- allowed_levels.max || PRIVATE
- end
-
def allowed_for?(user, level)
user.is_admin? || allowed_level?(level.to_i)
end
diff --git a/lib/json_web_token/rsa_token.rb b/lib/json_web_token/rsa_token.rb
deleted file mode 100644
index d6d6af7089..0000000000
--- a/lib/json_web_token/rsa_token.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-module JSONWebToken
- class RSAToken < Token
- attr_reader :key_file
-
- def initialize(key_file)
- super()
- @key_file = key_file
- end
-
- def encoded
- headers = {
- kid: kid
- }
- JWT.encode(payload, key, 'RS256', headers)
- end
-
- private
-
- def key_data
- @key_data ||= File.read(key_file)
- end
-
- def key
- @key ||= OpenSSL::PKey::RSA.new(key_data)
- end
-
- def public_key
- key.public_key
- end
-
- def kid
- # calculate sha256 from DER encoded ASN1
- kid = Digest::SHA256.digest(public_key.to_der)
-
- # we encode only 30 bytes with base32
- kid = Base32.encode(kid[0..29])
-
- # insert colon every 4 characters
- kid.scan(/.{4}/).join(':')
- end
- end
-end
diff --git a/lib/json_web_token/token.rb b/lib/json_web_token/token.rb
deleted file mode 100644
index 5b67715b0b..0000000000
--- a/lib/json_web_token/token.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-module JSONWebToken
- class Token
- attr_accessor :issuer, :subject, :audience, :id
- attr_accessor :issued_at, :not_before, :expire_time
-
- def initialize
- @id = SecureRandom.uuid
- @issued_at = Time.now
- # we give a few seconds for time shift
- @not_before = issued_at - 5.seconds
- # default 60 seconds should be more than enough for this authentication token
- @expire_time = issued_at + 1.minute
- @custom_payload = {}
- end
-
- def [](key)
- @custom_payload[key]
- end
-
- def []=(key, value)
- @custom_payload[key] = value
- end
-
- def encoded
- raise NotImplementedError
- end
-
- def payload
- @custom_payload.merge(default_payload)
- end
-
- private
-
- def default_payload
- {
- jti: id,
- aud: audience,
- sub: subject,
- iss: issuer,
- iat: issued_at.to_i,
- nbf: not_before.to_i,
- exp: expire_time.to_i
- }.compact
- end
- end
-end
diff --git a/lib/support/nginx/registry-ssl b/lib/support/nginx/registry-ssl
deleted file mode 100644
index 92511e2686..0000000000
--- a/lib/support/nginx/registry-ssl
+++ /dev/null
@@ -1,53 +0,0 @@
-## Lines starting with two hashes (##) are comments with information.
-## Lines starting with one hash (#) are configuration parameters that can be uncommented.
-##
-###################################
-## configuration ##
-###################################
-
-## Redirects all HTTP traffic to the HTTPS host
-server {
- listen *:80;
- server_name registry.gitlab.example.com;
- server_tokens off; ## Don't show the nginx version number, a security best practice
- return 301 https://$http_host:$request_uri;
- access_log /var/log/nginx/gitlab_registry_access.log gitlab_access;
- error_log /var/log/nginx/gitlab_registry_error.log;
-}
-
-server {
- # If a different port is specified in https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/config/gitlab.yml.example#L182,
- # it should be declared here as well
- listen *:443 ssl http2;
- server_name registry.gitlab.example.com;
- server_tokens off; ## Don't show the nginx version number, a security best practice
-
- client_max_body_size 0;
- chunked_transfer_encoding on;
-
- ## Strong SSL Security
- ## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/
- ssl on;
- ssl_certificate /etc/gitlab/ssl/registry.gitlab.example.com.crt
- ssl_certificate_key /etc/gitlab/ssl/registry.gitlab.example.com.key
-
- ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4';
- ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
- ssl_prefer_server_ciphers on;
- ssl_session_cache builtin:1000 shared:SSL:10m;
- ssl_session_timeout 5m;
-
- access_log /var/log/gitlab/nginx/gitlab_registry_access.log gitlab_access;
- error_log /var/log/gitlab/nginx/gitlab_registry_error.log;
-
- location / {
- proxy_set_header Host $http_host; # required for docker client's sake
- proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_read_timeout 900;
-
- proxy_pass http://localhost:5000;
- }
-
-}
diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake
new file mode 100644
index 0000000000..16bad4bd2b
--- /dev/null
+++ b/lib/tasks/auto_annotate_models.rake
@@ -0,0 +1,44 @@
+if Rails.env.development?
+ task :set_annotation_options do
+ # You can override any of these by setting an environment variable of the
+ # same name.
+ Annotate.set_defaults(
+ 'routes' => 'false',
+ 'position_in_routes' => 'before',
+ 'position_in_class' => 'before',
+ 'position_in_test' => 'before',
+ 'position_in_fixture' => 'before',
+ 'position_in_factory' => 'before',
+ 'position_in_serializer' => 'before',
+ 'show_foreign_keys' => 'true',
+ 'show_indexes' => 'false',
+ 'simple_indexes' => 'false',
+ 'model_dir' => 'app/models',
+ 'root_dir' => '',
+ 'include_version' => 'false',
+ 'require' => '',
+ 'exclude_tests' => 'true',
+ 'exclude_fixtures' => 'true',
+ 'exclude_factories' => 'true',
+ 'exclude_serializers' => 'true',
+ 'exclude_scaffolds' => 'true',
+ 'exclude_controllers' => 'true',
+ 'exclude_helpers' => 'true',
+ 'ignore_model_sub_dir' => 'false',
+ 'ignore_columns' => nil,
+ 'ignore_unknown_models' => 'false',
+ 'hide_limit_column_types' => 'integer,boolean',
+ 'skip_on_db_migrate' => 'false',
+ 'format_bare' => 'true',
+ 'format_rdoc' => 'false',
+ 'format_markdown' => 'false',
+ 'sort' => 'false',
+ 'force' => 'false',
+ 'trace' => 'false',
+ 'wrapper_open' => nil,
+ 'wrapper_close' => nil,
+ )
+ end
+
+ Annotate.load_tasks
+end
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index 596eaca6d0..402bb338f2 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -14,7 +14,6 @@ namespace :gitlab do
Rake::Task["gitlab:backup:builds:create"].invoke
Rake::Task["gitlab:backup:artifacts:create"].invoke
Rake::Task["gitlab:backup:lfs:create"].invoke
- Rake::Task["gitlab:backup:registry:create"].invoke
backup = Backup::Manager.new
backup.pack
@@ -55,7 +54,6 @@ namespace :gitlab do
Rake::Task['gitlab:backup:builds:restore'].invoke unless backup.skipped?('builds')
Rake::Task['gitlab:backup:artifacts:restore'].invoke unless backup.skipped?('artifacts')
Rake::Task['gitlab:backup:lfs:restore'].invoke unless backup.skipped?('lfs')
- Rake::Task['gitlab:backup:registry:restore'].invoke unless backup.skipped?('registry')
Rake::Task['gitlab:shell:setup'].invoke
backup.cleanup
@@ -175,33 +173,6 @@ namespace :gitlab do
end
end
- namespace :registry do
- task create: :environment do
- $progress.puts "Dumping container registry images ... ".blue
-
- if Gitlab.config.registry.enabled
- if ENV["SKIP"] && ENV["SKIP"].include?("registry")
- $progress.puts "[SKIPPED]".cyan
- else
- Backup::Registry.new.dump
- $progress.puts "done".green
- end
- else
- $progress.puts "[DISABLED]".cyan
- end
- end
-
- task restore: :environment do
- $progress.puts "Restoring container registry images ... ".blue
- if Gitlab.config.registry.enabled
- Backup::Registry.new.restore
- $progress.puts "done".green
- else
- $progress.puts "[DISABLED]".cyan
- end
- end
- end
-
def configure_cron_mode
if ENV['CRON']
# We need an object we can say 'puts' and 'print' to; let's use a
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index fad89c7376..effb8eb600 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -303,7 +303,7 @@ namespace :gitlab do
else
puts "no".red
try_fixing_it(
- "sudo chmod 700 #{upload_path}"
+ "sudo find #{upload_path} -type d -not -path #{upload_path} -exec chmod 0700 {} \\;"
)
for_more_information(
see_installation_guide_section "GitLab"
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index 86f5d65f12..1c706dc11b 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -29,22 +29,10 @@ namespace :gitlab do
tables.delete 'schema_migrations'
# Truncate schema_migrations to ensure migrations re-run
connection.execute('TRUNCATE schema_migrations')
-
# Drop tables with cascade to avoid dependent table errors
# PG: http://www.postgresql.org/docs/current/static/ddl-depend.html
# MySQL: http://dev.mysql.com/doc/refman/5.7/en/drop-table.html
- # Add `IF EXISTS` because cascade could have already deleted a table.
- tables.each { |t| connection.execute("DROP TABLE IF EXISTS #{t} CASCADE") }
- end
-
- desc 'Configures the database by running migrate, or by loading the schema and seeding if needed'
- task configure: :environment do
- if ActiveRecord::Base.connection.tables.any?
- Rake::Task['db:migrate'].invoke
- else
- Rake::Task['db:schema:load'].invoke
- Rake::Task['db:seed_fu'].invoke
- end
+ tables.each { |t| connection.execute("DROP TABLE #{t} CASCADE") }
end
end
end
diff --git a/lib/tasks/gitlab/update_gitignore.rake b/lib/tasks/gitlab/update_gitignore.rake
deleted file mode 100644
index 84aa312002..0000000000
--- a/lib/tasks/gitlab/update_gitignore.rake
+++ /dev/null
@@ -1,46 +0,0 @@
-namespace :gitlab do
- desc "GitLab | Update gitignore"
- task :update_gitignore do
- unless clone_gitignores
- puts "Cloning the gitignores failed".red
- return
- end
-
- remove_unneeded_files(gitignore_directory)
- remove_unneeded_files(global_directory)
-
- puts "Done".green
- end
-
- def clone_gitignores
- FileUtils.rm_rf(gitignore_directory) if Dir.exist?(gitignore_directory)
- FileUtils.cd vendor_directory
-
- system('git clone --depth=1 --branch=master https://github.com/github/gitignore.git')
- end
-
- # Retain only certain files:
- # - The LICENSE, because we have to
- # - The sub dir global
- # - The gitignores themself
- # - Dir.entires returns also the entries '.' and '..'
- def remove_unneeded_files(path)
- Dir.foreach(path) do |file|
- FileUtils.rm_rf(File.join(path, file)) unless file =~ /(\.{1,2}|LICENSE|Global|\.gitignore)\z/
- end
- end
-
- private
-
- def vendor_directory
- Rails.root.join('vendor')
- end
-
- def gitignore_directory
- File.join(vendor_directory, 'gitignore')
- end
-
- def global_directory
- File.join(gitignore_directory, 'Global')
- end
-end
diff --git a/lib/tasks/rubocop.rake b/lib/tasks/rubocop.rake
index 78ffccc9d0..ddfaf5d51f 100644
--- a/lib/tasks/rubocop.rake
+++ b/lib/tasks/rubocop.rake
@@ -1,5 +1,4 @@
unless Rails.env.production?
require 'rubocop/rake_task'
-
RuboCop::RakeTask.new
end
diff --git a/public/robots.txt b/public/robots.txt
index 334f4c0353..4f616c7f4c 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -65,4 +65,3 @@ Disallow: /*/*/deploy_keys
Disallow: /*/*/hooks
Disallow: /*/*/services
Disallow: /*/*/protected_branches
-Disallow: /*/*/uploads/
diff --git a/shared/registry/.gitkeep b/shared/registry/.gitkeep
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/spec/config/mail_room_spec.rb b/spec/config/mail_room_spec.rb
index 6fad7e2b9e..462afb24f0 100644
--- a/spec/config/mail_room_spec.rb
+++ b/spec/config/mail_room_spec.rb
@@ -43,7 +43,7 @@ describe "mail_room.yml" do
redis_config_file = Rails.root.join('config', 'resque.yml')
redis_url =
- if File.exist?(redis_config_file)
+ if File.exists?(redis_config_file)
YAML.load_file(redis_config_file)[Rails.env]
else
"redis://localhost:6379"
diff --git a/spec/controllers/admin/projects_controller_spec.rb b/spec/controllers/admin/projects_controller_spec.rb
index 4cb8b8da15..2ba0d48919 100644
--- a/spec/controllers/admin/projects_controller_spec.rb
+++ b/spec/controllers/admin/projects_controller_spec.rb
@@ -17,7 +17,7 @@ describe Admin::ProjectsController do
it 'does not retrieve the project' do
get :index, visibility_levels: [Gitlab::VisibilityLevel::INTERNAL]
- expect(response.body).not_to match(project.name)
+ expect(response.body).to_not match(project.name)
end
end
end
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index 6caf37ddc2..ce2a62ae1f 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -114,82 +114,6 @@ describe Admin::UsersController do
end
end
- describe 'POST update' do
- context 'when the password has changed' do
- def update_password(user, password, password_confirmation = nil)
- params = {
- id: user.to_param,
- user: {
- password: password,
- password_confirmation: password_confirmation || password
- }
- }
-
- post :update, params
- end
-
- context 'when the new password is valid' do
- it 'redirects to the user' do
- update_password(user, 'AValidPassword1')
-
- expect(response).to redirect_to(admin_user_path(user))
- end
-
- it 'updates the password' do
- update_password(user, 'AValidPassword1')
-
- expect { user.reload }.to change { user.encrypted_password }
- end
-
- it 'sets the new password to expire immediately' do
- update_password(user, 'AValidPassword1')
-
- expect { user.reload }.to change { user.password_expires_at }.to(a_value <= Time.now)
- end
- end
-
- context 'when the new password is invalid' do
- it 'shows the edit page again' do
- update_password(user, 'invalid')
-
- expect(response).to render_template(:edit)
- end
-
- it 'returns the error message' do
- update_password(user, 'invalid')
-
- expect(assigns[:user].errors).to contain_exactly(a_string_matching(/too short/))
- end
-
- it 'does not update the password' do
- update_password(user, 'invalid')
-
- expect { user.reload }.not_to change { user.encrypted_password }
- end
- end
-
- context 'when the new password does not match the password confirmation' do
- it 'shows the edit page again' do
- update_password(user, 'AValidPassword1', 'AValidPassword2')
-
- expect(response).to render_template(:edit)
- end
-
- it 'returns the error message' do
- update_password(user, 'AValidPassword1', 'AValidPassword2')
-
- expect(assigns[:user].errors).to contain_exactly(a_string_matching(/doesn't match/))
- end
-
- it 'does not update the password' do
- update_password(user, 'AValidPassword1', 'AValidPassword2')
-
- expect { user.reload }.not_to change { user.encrypted_password }
- end
- end
- end
- end
-
describe "POST impersonate" do
context "when the user is blocked" do
before do
diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb
deleted file mode 100644
index 0d8a68bb51..0000000000
--- a/spec/controllers/health_check_controller_spec.rb
+++ /dev/null
@@ -1,105 +0,0 @@
-require 'spec_helper'
-
-describe HealthCheckController do
- let(:token) { current_application_settings.health_check_access_token }
- let(:json_response) { JSON.parse(response.body) }
- let(:xml_response) { Hash.from_xml(response.body)['hash'] }
-
- describe 'GET #index' do
- context 'when services are up but NO access token' do
- it 'returns a not found page' do
- get :index
- expect(response).to be_not_found
- end
- end
-
- context 'when services are up and an access token is provided' do
- it 'supports passing the token in the header' do
- request.headers['TOKEN'] = token
- get :index
- expect(response).to be_success
- expect(response.content_type).to eq 'text/plain'
- end
-
- it 'supports successful plaintest response' do
- get :index, token: token
- expect(response).to be_success
- expect(response.content_type).to eq 'text/plain'
- end
-
- it 'supports successful json response' do
- get :index, token: token, format: :json
- expect(response).to be_success
- expect(response.content_type).to eq 'application/json'
- expect(json_response['healthy']).to be true
- end
-
- it 'supports successful xml response' do
- get :index, token: token, format: :xml
- expect(response).to be_success
- expect(response.content_type).to eq 'application/xml'
- expect(xml_response['healthy']).to be true
- end
-
- it 'supports successful responses for specific checks' do
- get :index, token: token, checks: 'email', format: :json
- expect(response).to be_success
- expect(response.content_type).to eq 'application/json'
- expect(json_response['healthy']).to be true
- end
- end
-
- context 'when a service is down but NO access token' do
- it 'returns a not found page' do
- get :index
- expect(response).to be_not_found
- end
- end
-
- context 'when a service is down and an access token is provided' do
- before do
- allow(HealthCheck::Utils).to receive(:process_checks).with('standard').and_return('The server is on fire')
- allow(HealthCheck::Utils).to receive(:process_checks).with('email').and_return('Email is on fire')
- end
-
- it 'supports passing the token in the header' do
- request.headers['TOKEN'] = token
- get :index
- expect(response.status).to eq(500)
- expect(response.content_type).to eq 'text/plain'
- expect(response.body).to include('The server is on fire')
- end
-
- it 'supports failure plaintest response' do
- get :index, token: token
- expect(response.status).to eq(500)
- expect(response.content_type).to eq 'text/plain'
- expect(response.body).to include('The server is on fire')
- end
-
- it 'supports failure json response' do
- get :index, token: token, format: :json
- expect(response.status).to eq(500)
- expect(response.content_type).to eq 'application/json'
- expect(json_response['healthy']).to be false
- expect(json_response['message']).to include('The server is on fire')
- end
-
- it 'supports failure xml response' do
- get :index, token: token, format: :xml
- expect(response.status).to eq(500)
- expect(response.content_type).to eq 'application/xml'
- expect(xml_response['healthy']).to be false
- expect(xml_response['message']).to include('The server is on fire')
- end
-
- it 'supports failure responses for specific checks' do
- get :index, token: token, checks: 'email', format: :json
- expect(response.status).to eq(500)
- expect(response.content_type).to eq 'application/json'
- expect(json_response['healthy']).to be false
- expect(json_response['message']).to include('Email is on fire')
- end
- end
- end
-end
diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb
index c4b4a888b4..8ad7347211 100644
--- a/spec/controllers/projects/branches_controller_spec.rb
+++ b/spec/controllers/projects/branches_controller_spec.rb
@@ -122,23 +122,27 @@ describe Projects::BranchesController do
let(:branch) { "feature" }
it { expect(response.status).to eq(200) }
+ it { expect(subject).to render_template('destroy') }
end
context "valid branch name with unencoded slashes" do
let(:branch) { "improve/awesome" }
it { expect(response.status).to eq(200) }
+ it { expect(subject).to render_template('destroy') }
end
context "valid branch name with encoded slashes" do
let(:branch) { "improve%2Fawesome" }
it { expect(response.status).to eq(200) }
+ it { expect(subject).to render_template('destroy') }
end
context "invalid branch name, valid ref" do
let(:branch) { "no-branch" }
it { expect(response.status).to eq(404) }
+ it { expect(subject).to render_template('destroy') }
end
end
end
diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb
index 4018dac95a..788a609ee4 100644
--- a/spec/controllers/projects/compare_controller_spec.rb
+++ b/spec/controllers/projects/compare_controller_spec.rb
@@ -19,7 +19,7 @@ describe Projects::CompareController do
to: ref_to)
expect(response).to be_success
- expect(assigns(:diffs).first).not_to be_nil
+ expect(assigns(:diffs).first).to_not be_nil
expect(assigns(:commits).length).to be >= 1
end
@@ -32,7 +32,7 @@ describe Projects::CompareController do
w: 1)
expect(response).to be_success
- expect(assigns(:diffs).first).not_to be_nil
+ expect(assigns(:diffs).first).to_not be_nil
expect(assigns(:commits).length).to be >= 1
# without whitespace option, there are more than 2 diff_splits
diff_splits = assigns(:diffs).first.diff.split("\n")
diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb
index fbe8758dda..40bd83af86 100644
--- a/spec/controllers/projects/group_links_controller_spec.rb
+++ b/spec/controllers/projects/group_links_controller_spec.rb
@@ -28,7 +28,7 @@ describe Projects::GroupLinksController do
expect(group.shared_projects).to include project
end
- it 'redirects to project group links page' do
+ it 'redirects to project group links page'do
expect(response).to redirect_to(
namespace_project_group_links_path(project.namespace, project)
)
@@ -43,7 +43,7 @@ describe Projects::GroupLinksController do
end
it 'does not share project with that group' do
- expect(group.shared_projects).not_to include project
+ expect(group.shared_projects).to_not include project
end
end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index c469480b08..2b2ad3b941 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -56,7 +56,7 @@ describe Projects::IssuesController do
move_issue
expect(response).to have_http_status :found
- expect(another_project.issues).not_to be_empty
+ expect(another_project.issues).to_not be_empty
end
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 4f621a43d7..c0a1f45195 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -63,7 +63,7 @@ describe Projects::MergeRequestsController do
id: merge_request.iid,
format: format)
- expect(response.body).to eq(merge_request.send(:"to_#{format}").to_s)
+ expect(response.body).to eq((merge_request.send(:"to_#{format}")).to_s)
end
it "should not escape Html" do
diff --git a/spec/controllers/projects/notification_settings_controller_spec.rb b/spec/controllers/projects/notification_settings_controller_spec.rb
index c5d17d97ec..4908b54564 100644
--- a/spec/controllers/projects/notification_settings_controller_spec.rb
+++ b/spec/controllers/projects/notification_settings_controller_spec.rb
@@ -34,19 +34,5 @@ describe Projects::NotificationSettingsController do
expect(response.status).to eq 200
end
end
-
- context 'not authorized' do
- let(:private_project) { create(:project, :private) }
- before { sign_in(user) }
-
- it 'returns 404' do
- put :update,
- namespace_id: private_project.namespace.to_param,
- project_id: private_project.to_param,
- notification_setting: { level: :participating }
-
- expect(response.status).to eq(404)
- end
- end
end
end
diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb
index 750fbecdd0..ed64e7cf9a 100644
--- a/spec/controllers/projects/project_members_controller_spec.rb
+++ b/spec/controllers/projects/project_members_controller_spec.rb
@@ -38,7 +38,7 @@ describe Projects::ProjectMembersController do
include_context 'import applied'
it 'does not import team members' do
- expect(project.team_members).not_to include member
+ expect(project.team_members).to_not include member
end
it 'responds with not found' do
diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb
index fb29274c68..1caa476d37 100644
--- a/spec/controllers/projects/raw_controller_spec.rb
+++ b/spec/controllers/projects/raw_controller_spec.rb
@@ -42,7 +42,7 @@ describe Projects::RawController do
before do
public_project.lfs_objects << lfs_object
allow_any_instance_of(LfsObjectUploader).to receive(:exists?).and_return(true)
- allow(controller).to receive(:send_file) { controller.head :ok }
+ allow(controller).to receive(:send_file) { controller.render nothing: true }
end
it 'serves the file' do
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index fba545560c..069cd917e5 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -8,40 +8,6 @@ describe ProjectsController do
let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') }
describe "GET show" do
- context "user not project member" do
- before { sign_in(user) }
-
- context "user does not have access to project" do
- let(:private_project) { create(:project, :private) }
-
- it "does not initialize notification setting" do
- get :show, namespace_id: private_project.namespace.path, id: private_project.path
- expect(assigns(:notification_setting)).to be_nil
- end
- end
-
- context "user has access to project" do
- context "and does not have notification setting" do
- it "initializes notification as disabled" do
- get :show, namespace_id: public_project.namespace.path, id: public_project.path
- expect(assigns(:notification_setting).level).to eq("global")
- end
- end
-
- context "and has notification setting" do
- before do
- setting = user.notification_settings_for(public_project)
- setting.level = :watch
- setting.save
- end
-
- it "shows current notification setting" do
- get :show, namespace_id: public_project.namespace.path, id: public_project.path
- expect(assigns(:notification_setting).level).to eq("watch")
- end
- end
- end
- end
context "rendering default project view" do
render_views
@@ -115,17 +81,6 @@ describe ProjectsController do
expect(public_project_with_dot_atom).not_to be_valid
end
end
-
- context 'when the project is pending deletions' do
- it 'renders a 404 error' do
- project = create(:project, pending_delete: true)
- sign_in(user)
-
- get :show, namespace_id: project.namespace.path, id: project.path
-
- expect(response.status).to eq 404
- end
- end
end
describe "#update" do
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
deleted file mode 100644
index 209fa37d97..0000000000
--- a/spec/controllers/registrations_controller_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require 'spec_helper'
-
-describe RegistrationsController do
- describe '#create' do
- around(:each) do |example|
- perform_enqueued_jobs do
- example.run
- end
- end
-
- let(:user_params) { { user: { name: "new_user", username: "new_username", email: "new@user.com", password: "Any_password" } } }
-
- context 'when sending email confirmation' do
- before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(false) }
-
- it 'logs user in directly' do
- post(:create, user_params)
- expect(ActionMailer::Base.deliveries.last).to be_nil
- expect(subject.current_user).not_to be_nil
- end
- end
-
- context 'when not sending email confirmation' do
- before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) }
-
- it 'does not authenticate user and sends confirmation email' do
- post(:create, user_params)
- expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
- expect(subject.current_user).to be_nil
- end
- end
- end
-end
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index 5dc8724fb5..83cc8ec6d2 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -12,7 +12,7 @@ describe SessionsController do
post(:create, user: { login: 'invalid', password: 'invalid' })
expect(response)
- .to set_flash.now[:alert].to /Invalid Login or password/
+ .to set_flash.now[:alert].to /Invalid login or password/
end
end
@@ -35,27 +35,6 @@ describe SessionsController do
post(:create, { user: user_params }, { otp_user_id: user.id })
end
- context 'remember_me field' do
- it 'sets a remember_user_token cookie when enabled' do
- allow(controller).to receive(:find_user).and_return(user)
- expect(controller).
- to receive(:remember_me).with(user).and_call_original
-
- authenticate_2fa(remember_me: '1', otp_attempt: user.current_otp)
-
- expect(response.cookies['remember_user_token']).to be_present
- end
-
- it 'does nothing when disabled' do
- allow(controller).to receive(:find_user).and_return(user)
- expect(controller).not_to receive(:remember_me)
-
- authenticate_2fa(remember_me: '0', otp_attempt: user.current_otp)
-
- expect(response.cookies['remember_user_token']).to be_nil
- end
- end
-
##
# See #14900 issue
#
@@ -68,7 +47,7 @@ describe SessionsController do
authenticate_2fa(login: another_user.username,
otp_attempt: another_user.current_otp)
- expect(subject.current_user).not_to eq another_user
+ expect(subject.current_user).to_not eq another_user
end
end
@@ -77,7 +56,7 @@ describe SessionsController do
authenticate_2fa(login: another_user.username,
otp_attempt: 'invalid')
- expect(subject.current_user).not_to eq another_user
+ expect(subject.current_user).to_not eq another_user
end
end
@@ -94,7 +73,7 @@ describe SessionsController do
before { authenticate_2fa(otp_attempt: 'invalid') }
it 'does not authenticate' do
- expect(subject.current_user).not_to eq user
+ expect(subject.current_user).to_not eq user
end
it 'warns about invalid OTP code' do
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index c61ec17466..8045c8b940 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -112,26 +112,4 @@ describe UsersController do
expect(response).to render_template('calendar_activities')
end
end
-
- describe 'GET #snippets' do
- before do
- sign_in(user)
- end
-
- context 'format html' do
- it 'renders snippets page' do
- get :snippets, username: user.username
- expect(response.status).to eq(200)
- expect(response).to render_template('show')
- end
- end
-
- context 'format json' do
- it 'response with snippets json data' do
- get :snippets, username: user.username, format: :json
- expect(response.status).to eq(200)
- expect(JSON.parse(response.body)).to have_key('html')
- end
- end
- end
end
diff --git a/spec/factories/abuse_reports.rb b/spec/factories/abuse_reports.rb
index 8f6422a782..d0e8c77851 100644
--- a/spec/factories/abuse_reports.rb
+++ b/spec/factories/abuse_reports.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: abuse_reports
+#
+# id :integer not null, primary key
+# reporter_id :integer
+# user_id :integer
+# message :text
+# created_at :datetime
+# updated_at :datetime
+#
+
FactoryGirl.define do
factory :abuse_report do
reporter factory: :user
diff --git a/spec/factories/broadcast_messages.rb b/spec/factories/broadcast_messages.rb
index efe9803b1a..c80e736655 100644
--- a/spec/factories/broadcast_messages.rb
+++ b/spec/factories/broadcast_messages.rb
@@ -1,3 +1,17 @@
+# == Schema Information
+#
+# Table name: broadcast_messages
+#
+# id :integer not null, primary key
+# message :text not null
+# starts_at :datetime
+# ends_at :datetime
+# created_at :datetime
+# updated_at :datetime
+# color :string(255)
+# font :string(255)
+#
+
FactoryGirl.define do
factory :broadcast_message do
message "MyText"
diff --git a/spec/factories/forked_project_links.rb b/spec/factories/forked_project_links.rb
index b16c1272e6..19a54946fe 100644
--- a/spec/factories/forked_project_links.rb
+++ b/spec/factories/forked_project_links.rb
@@ -1,3 +1,14 @@
+# == Schema Information
+#
+# Table name: forked_project_links
+#
+# id :integer not null, primary key
+# forked_to_project_id :integer not null
+# forked_from_project_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+#
+
FactoryGirl.define do
factory :forked_project_link do
association :forked_to_project, factory: :project
diff --git a/spec/factories/label_links.rb b/spec/factories/label_links.rb
index 3580174e87..2939d4307c 100644
--- a/spec/factories/label_links.rb
+++ b/spec/factories/label_links.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: label_links
+#
+# id :integer not null, primary key
+# label_id :integer
+# target_id :integer
+# target_type :string(255)
+# created_at :datetime
+# updated_at :datetime
+#
+
FactoryGirl.define do
factory :label_link do
label
diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb
index eb48909985..ea2be8928d 100644
--- a/spec/factories/labels.rb
+++ b/spec/factories/labels.rb
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: labels
+#
+# id :integer not null, primary key
+# title :string(255)
+# color :string(255)
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# template :boolean default(FALSE)
+#
+
FactoryGirl.define do
factory :label do
sequence(:title) { |n| "label#{n}" }
diff --git a/spec/factories/lfs_objects.rb b/spec/factories/lfs_objects.rb
index a81645acd2..327858ce43 100644
--- a/spec/factories/lfs_objects.rb
+++ b/spec/factories/lfs_objects.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: lfs_objects
+#
+# id :integer not null, primary key
+# oid :string(255) not null
+# size :integer not null
+# created_at :datetime
+# updated_at :datetime
+# file :string(255)
+#
+
include ActionDispatch::TestProcess
FactoryGirl.define do
diff --git a/spec/factories/lfs_objects_projects.rb b/spec/factories/lfs_objects_projects.rb
index 1ed0355c8e..50b45843c9 100644
--- a/spec/factories/lfs_objects_projects.rb
+++ b/spec/factories/lfs_objects_projects.rb
@@ -1,3 +1,14 @@
+# == Schema Information
+#
+# Table name: lfs_objects_projects
+#
+# id :integer not null, primary key
+# lfs_object_id :integer not null
+# project_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+#
+
FactoryGirl.define do
factory :lfs_objects_project do
lfs_object
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index c6a08d78b7..e281e2f227 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -1,3 +1,32 @@
+# == Schema Information
+#
+# Table name: merge_requests
+#
+# id :integer not null, primary key
+# target_branch :string(255) not null
+# source_branch :string(255) not null
+# source_project_id :integer not null
+# author_id :integer
+# assignee_id :integer
+# title :string(255)
+# created_at :datetime
+# updated_at :datetime
+# milestone_id :integer
+# state :string(255)
+# merge_status :string(255)
+# target_project_id :integer not null
+# iid :integer
+# description :text
+# position :integer default(0)
+# locked_at :datetime
+# updated_by_id :integer
+# merge_error :string(255)
+# merge_params :text
+# merge_when_build_succeeds :boolean default(FALSE), not null
+# merge_user_id :integer
+# merge_commit_sha :string
+#
+
FactoryGirl.define do
factory :merge_request do
title
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index c32e205ee6..e5dcb15901 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -1,3 +1,24 @@
+# == Schema Information
+#
+# Table name: notes
+#
+# id :integer not null, primary key
+# note :text
+# noteable_type :string(255)
+# author_id :integer
+# created_at :datetime
+# updated_at :datetime
+# project_id :integer
+# attachment :string(255)
+# line_code :string(255)
+# commit_id :string(255)
+# noteable_id :integer
+# system :boolean default(FALSE), not null
+# st_diff :text
+# updated_by_id :integer
+# is_award :boolean default(FALSE), not null
+#
+
require_relative '../support/repo_helpers'
include ActionDispatch::TestProcess
@@ -7,39 +28,41 @@ FactoryGirl.define do
project
note "Note"
author
- on_issue
factory :note_on_commit, traits: [:on_commit]
- factory :note_on_commit_diff, traits: [:on_commit, :on_diff], class: LegacyDiffNote
+ factory :note_on_commit_diff, traits: [:on_commit, :on_diff]
factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note]
factory :note_on_merge_request, traits: [:on_merge_request]
- factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff], class: LegacyDiffNote
+ factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff]
factory :note_on_project_snippet, traits: [:on_project_snippet]
factory :system_note, traits: [:system]
factory :downvote_note, traits: [:award, :downvote]
factory :upvote_note, traits: [:award, :upvote]
trait :on_commit do
- noteable nil
- noteable_id nil
- noteable_type 'Commit'
+ project
commit_id RepoHelpers.sample_commit.id
+ noteable_type "Commit"
end
trait :on_diff do
line_code "0_184_184"
end
- trait :on_issue do
- noteable { create(:issue, project: project) }
+ trait :on_merge_request do
+ project
+ noteable_id 1
+ noteable_type "MergeRequest"
end
- trait :on_merge_request do
- noteable { create(:merge_request, source_project: project) }
+ trait :on_issue do
+ noteable_id 1
+ noteable_type "Issue"
end
trait :on_project_snippet do
- noteable { create(:snippet, project: project) }
+ noteable_id 1
+ noteable_type "Snippet"
end
trait :system do
diff --git a/spec/factories/oauth_access_tokens.rb b/spec/factories/oauth_access_tokens.rb
index ccf02d0719..7700b15d53 100644
--- a/spec/factories/oauth_access_tokens.rb
+++ b/spec/factories/oauth_access_tokens.rb
@@ -1,3 +1,18 @@
+# == Schema Information
+#
+# Table name: oauth_access_tokens
+#
+# id :integer not null, primary key
+# resource_owner_id :integer
+# application_id :integer
+# token :string not null
+# refresh_token :string
+# expires_in :integer
+# revoked_at :datetime
+# created_at :datetime not null
+# scopes :string
+#
+
FactoryGirl.define do
factory :oauth_access_token do
resource_owner
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index da8d97c9f8..ecd0e44dd6 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -1,3 +1,42 @@
+# == Schema Information
+#
+# Table name: projects
+#
+# id :integer not null, primary key
+# name :string(255)
+# path :string(255)
+# description :text
+# created_at :datetime
+# updated_at :datetime
+# creator_id :integer
+# issues_enabled :boolean default(TRUE), not null
+# merge_requests_enabled :boolean default(TRUE), not null
+# wiki_enabled :boolean default(TRUE), not null
+# namespace_id :integer
+# issues_tracker :string(255) default("gitlab"), not null
+# issues_tracker_id :string(255)
+# snippets_enabled :boolean default(TRUE), not null
+# last_activity_at :datetime
+# import_url :string(255)
+# visibility_level :integer default(0), not null
+# archived :boolean default(FALSE), not null
+# avatar :string(255)
+# import_status :string(255)
+# repository_size :float default(0.0)
+# star_count :integer default(0), not null
+# import_type :string(255)
+# import_source :string(255)
+# commit_count :integer default(0)
+# import_error :text
+# ci_id :integer
+# builds_enabled :boolean default(TRUE), not null
+# shared_runners_enabled :boolean default(TRUE), not null
+# runners_token :string
+# build_coverage_regex :string
+# build_allow_git_fetch :boolean default(TRUE), not null
+# build_timeout :integer default(3600), not null
+#
+
FactoryGirl.define do
# Project without repository
#
@@ -21,12 +60,6 @@ FactoryGirl.define do
trait :private do
visibility_level Gitlab::VisibilityLevel::PRIVATE
end
-
- trait :empty_repo do
- after(:create) do |project|
- project.create_repository
- end
- end
end
# Project with empty repository
@@ -34,7 +67,9 @@ FactoryGirl.define do
# This is a case when you just created a project
# but not pushed any code there yet
factory :project_empty_repo, parent: :empty_project do
- empty_repo
+ after :create do |project|
+ project.create_repository
+ end
end
# Project with test repository
diff --git a/spec/factories/releases.rb b/spec/factories/releases.rb
index 74497dc82c..7f331c3725 100644
--- a/spec/factories/releases.rb
+++ b/spec/factories/releases.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: releases
+#
+# id :integer not null, primary key
+# tag :string(255)
+# description :text
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+#
+
FactoryGirl.define do
factory :release do
tag "v1.1.0"
diff --git a/spec/factories/todos.rb b/spec/factories/todos.rb
index f426e27afe..7ae06c2784 100644
--- a/spec/factories/todos.rb
+++ b/spec/factories/todos.rb
@@ -1,3 +1,21 @@
+# == Schema Information
+#
+# Table name: todos
+#
+# id :integer not null, primary key
+# user_id :integer not null
+# project_id :integer not null
+# target_id :integer
+# target_type :string not null
+# author_id :integer
+# action :integer not null
+# state :string not null
+# created_at :datetime
+# updated_at :datetime
+# note_id :integer
+# commit_id :string
+#
+
FactoryGirl.define do
factory :todo do
project
@@ -18,9 +36,5 @@ FactoryGirl.define do
commit_id RepoHelpers.sample_commit.id
target_type "Commit"
end
-
- trait :build_failed do
- action { Todo::BUILD_FAILED }
- end
end
end
diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb
index 675d9bd18b..62de081661 100644
--- a/spec/factories_spec.rb
+++ b/spec/factories_spec.rb
@@ -5,8 +5,8 @@ describe 'factories' do
describe "#{factory.name} factory" do
let(:entity) { build(factory.name) }
- it 'does not raise error when created' do
- expect { entity }.not_to raise_error
+ it 'does not raise error when created 'do
+ expect { entity }.to_not raise_error
end
it 'should be valid', if: factory.build_class < ActiveRecord::Base do
diff --git a/spec/features/admin/admin_builds_spec.rb b/spec/features/admin/admin_builds_spec.rb
index 7bbe20fec4..2e9851fb44 100644
--- a/spec/features/admin/admin_builds_spec.rb
+++ b/spec/features/admin/admin_builds_spec.rb
@@ -19,7 +19,6 @@ describe 'Admin Builds' do
visit admin_builds_path
expect(page).to have_selector('.nav-links li.active', text: 'All')
- expect(page).to have_selector('.row-content-block', text: 'All builds')
expect(page.all('.build-link').size).to eq(4)
expect(page).to have_link 'Cancel all'
end
diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb
deleted file mode 100644
index dec2dedf2b..0000000000
--- a/spec/features/admin/admin_health_check_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-require 'spec_helper'
-
-feature "Admin Health Check", feature: true do
- include WaitForAjax
-
- before do
- login_as :admin
- end
-
- describe '#show' do
- before do
- visit admin_health_check_path
- end
-
- it { page.has_text? 'Health Check' }
- it { page.has_text? 'Health information can be retrieved' }
-
- it 'has a health check access token' do
- token = current_application_settings.health_check_access_token
- expect(page).to have_content("Access token is #{token}")
- expect(page).to have_selector('#health-check-token', text: token)
- end
-
- describe 'reload access token', js: true do
- it 'changes the access token' do
- orig_token = current_application_settings.health_check_access_token
- click_button 'Reset health check access token'
- wait_for_ajax
- expect(find('#health-check-token').text).not_to eq orig_token
- end
- end
- end
-
- context 'when services are up' do
- before do
- visit admin_health_check_path
- end
-
- it 'shows healthy status' do
- expect(page).to have_content('Current Status: Healthy')
- end
- end
-
- context 'when a service is down' do
- before do
- allow(HealthCheck::Utils).to receive(:process_checks).and_return('The server is on fire')
- visit admin_health_check_path
- end
-
- it 'shows unhealthy status' do
- expect(page).to have_content('Current Status: Unhealthy')
- expect(page).to have_content('The server is on fire')
- end
- end
-end
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 8ebd4a6808..26d03944b8 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -79,7 +79,7 @@ describe "Admin Runners" do
end
it 'changes registration token' do
- expect(page_token).not_to eq token
+ expect(page_token).to_not eq token
end
end
end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 96621843b3..4570e40912 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -152,7 +152,7 @@ describe "Admin::Users", feature: true do
it 'sees impersonation log out icon' do
icon = first('.fa.fa-user-secret')
- expect(icon).not_to eql nil
+ expect(icon).to_not eql nil
end
it 'can log out of impersonated user back to original user' do
@@ -210,8 +210,6 @@ describe "Admin::Users", feature: true do
before do
fill_in "user_name", with: "Big Bang"
fill_in "user_email", with: "bigbang@mail.com"
- fill_in "user_password", with: "AValidPassword1"
- fill_in "user_password_confirmation", with: "AValidPassword1"
check "user_admin"
click_button "Save changes"
end
@@ -225,7 +223,6 @@ describe "Admin::Users", feature: true do
@simple_user.reload
expect(@simple_user.name).to eq('Big Bang')
expect(@simple_user.is_admin?).to be_truthy
- expect(@simple_user.password_expires_at).to be <= Time.now
end
end
end
diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb
index 7a05d30e8b..090a941958 100644
--- a/spec/features/builds_spec.rb
+++ b/spec/features/builds_spec.rb
@@ -46,7 +46,7 @@ describe "Builds" do
it { expect(page).to have_content @build.short_sha }
it { expect(page).to have_content @build.ref }
it { expect(page).to have_content @build.name }
- it { expect(page).not_to have_link 'Cancel running' }
+ it { expect(page).to_not have_link 'Cancel running' }
end
end
@@ -62,7 +62,7 @@ describe "Builds" do
it { expect(page).to have_content @build.short_sha }
it { expect(page).to have_content @build.ref }
it { expect(page).to have_content @build.name }
- it { expect(page).not_to have_link 'Cancel running' }
+ it { expect(page).to_not have_link 'Cancel running' }
end
describe "GET /:project/builds/:id" do
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index 20f0b27bcc..dacaa96d76 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -137,8 +137,8 @@ describe 'Commits' do
expect(page).to have_content commit.git_commit_message
expect(page).to have_content commit.git_author_name
expect(page).to have_link('Download artifacts')
- expect(page).not_to have_link('Cancel running')
- expect(page).not_to have_link('Retry failed')
+ expect(page).to_not have_link('Cancel running')
+ expect(page).to_not have_link('Retry failed')
end
end
@@ -155,9 +155,9 @@ describe 'Commits' do
expect(page).to have_content commit.sha[0..7]
expect(page).to have_content commit.git_commit_message
expect(page).to have_content commit.git_author_name
- expect(page).not_to have_link('Download artifacts')
- expect(page).not_to have_link('Cancel running')
- expect(page).not_to have_link('Retry failed')
+ expect(page).to_not have_link('Download artifacts')
+ expect(page).to_not have_link('Cancel running')
+ expect(page).to_not have_link('Retry failed')
end
end
end
diff --git a/spec/features/container_registry_spec.rb b/spec/features/container_registry_spec.rb
deleted file mode 100644
index 53b4f02711..0000000000
--- a/spec/features/container_registry_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-require 'spec_helper'
-
-describe "Container Registry" do
- let(:project) { create(:empty_project) }
- let(:repository) { project.container_registry_repository }
- let(:tag_name) { 'latest' }
- let(:tags) { [tag_name] }
-
- before do
- login_as(:user)
- project.team << [@user, :developer]
- stub_container_registry_tags(*tags)
- stub_container_registry_config(enabled: true)
- allow(Auth::ContainerRegistryAuthenticationService).to receive(:full_access_token).and_return('token')
- end
-
- describe 'GET /:project/container_registry' do
- before do
- visit namespace_project_container_registry_index_path(project.namespace, project)
- end
-
- context 'when no tags' do
- let(:tags) { [] }
-
- it { expect(page).to have_content('No images in Container Registry for this project') }
- end
-
- context 'when there are tags' do
- it { expect(page).to have_content(tag_name)}
- end
- end
-
- describe 'DELETE /:project/container_registry/tag' do
- before do
- visit namespace_project_container_registry_index_path(project.namespace, project)
- end
-
- it do
- expect_any_instance_of(::ContainerRegistry::Tag).to receive(:delete).and_return(true)
-
- click_on 'Remove'
- end
- end
-end
diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb
index 7efbaaa048..192e361937 100644
--- a/spec/features/issues/filter_issues_spec.rb
+++ b/spec/features/issues/filter_issues_spec.rb
@@ -154,180 +154,4 @@ describe 'Filter issues', feature: true do
end
end
end
-
- describe 'filter issues by text' do
- before do
- create(:issue, title: "Bug", project: project)
-
- bug_label = create(:label, project: project, title: 'bug')
- milestone = create(:milestone, title: "8", project: project)
-
- issue = create(:issue,
- title: "Bug 2",
- project: project,
- milestone: milestone,
- author: user,
- assignee: user)
- issue.labels << bug_label
-
- visit namespace_project_issues_path(project.namespace, project)
- end
-
- context 'only text', js: true do
- it 'should filter issues by searched text' do
- fill_in 'issue_search', with: 'Bug'
-
- page.within '.issues-list' do
- expect(page).to have_selector('.issue', count: 2)
- end
- end
-
- it 'should not show any issues' do
- fill_in 'issue_search', with: 'testing'
-
- page.within '.issues-list' do
- expect(page).not_to have_selector('.issue')
- end
- end
- end
-
- context 'text and dropdown options', js: true do
- it 'should filter by text and label' do
- fill_in 'issue_search', with: 'Bug'
-
- page.within '.issues-list' do
- expect(page).to have_selector('.issue', count: 2)
- end
-
- click_button 'Label'
- page.within '.labels-filter' do
- click_link 'bug'
- end
-
- page.within '.issues-list' do
- expect(page).to have_selector('.issue', count: 1)
- end
- end
-
- it 'should filter by text and milestone' do
- fill_in 'issue_search', with: 'Bug'
-
- page.within '.issues-list' do
- expect(page).to have_selector('.issue', count: 2)
- end
-
- click_button 'Milestone'
- page.within '.milestone-filter' do
- click_link '8'
- end
-
- page.within '.issues-list' do
- expect(page).to have_selector('.issue', count: 1)
- end
- end
-
- it 'should filter by text and assignee' do
- fill_in 'issue_search', with: 'Bug'
-
- page.within '.issues-list' do
- expect(page).to have_selector('.issue', count: 2)
- end
-
- click_button 'Assignee'
- page.within '.dropdown-menu-assignee' do
- click_link user.name
- end
-
- page.within '.issues-list' do
- expect(page).to have_selector('.issue', count: 1)
- end
- end
-
- it 'should filter by text and author' do
- fill_in 'issue_search', with: 'Bug'
-
- page.within '.issues-list' do
- expect(page).to have_selector('.issue', count: 2)
- end
-
- click_button 'Author'
- page.within '.dropdown-menu-author' do
- click_link user.name
- end
-
- page.within '.issues-list' do
- expect(page).to have_selector('.issue', count: 1)
- end
- end
- end
- end
-
- describe 'filter issues and sort', js: true do
- before do
- bug_label = create(:label, project: project, title: 'bug')
- bug_one = create(:issue, title: "Frontend", project: project)
- bug_two = create(:issue, title: "Bug 2", project: project)
-
- bug_one.labels << bug_label
- bug_two.labels << bug_label
-
- visit namespace_project_issues_path(project.namespace, project)
- end
-
- it 'should be able to filter and sort issues' do
- click_button 'Label'
- page.within '.labels-filter' do
- click_link 'bug'
- end
-
- page.within '.issues-list' do
- expect(page).to have_selector('.issue', count: 2)
- end
-
- click_button 'Last created'
- page.within '.dropdown-menu-sort' do
- click_link 'Oldest created'
- end
-
- page.within '.issues-list' do
- expect(first('.issue')).to have_content('Frontend')
- end
- end
- end
-
- describe 'filter by any author', js: true do
- before do
- user2 = create(:user, name: "tester")
- create(:issue, project: project, author: user)
- create(:issue, project: project, author: user2)
-
- visit namespace_project_issues_path(project.namespace, project)
- end
-
- it 'should show filter by any author link' do
- click_button "Author"
- fill_in "Search authors", with: "tester"
-
- page.within ".dropdown-menu-author" do
- expect(page).to have_content "tester"
- end
- end
-
- it 'should show filter issues by any author' do
- page.within '.issues-list' do
- expect(page).to have_selector ".issue", count: 2
- end
-
- click_button "Author"
- fill_in "Search authors", with: "tester"
-
- page.within ".dropdown-menu-author" do
- click_link "tester"
- end
-
- page.within '.issues-list' do
- expect(page).to have_selector ".issue", count: 1
- end
- end
- end
end
diff --git a/spec/features/issues/move_spec.rb b/spec/features/issues/move_spec.rb
index c7019c5aea..84c8e20eba 100644
--- a/spec/features/issues/move_spec.rb
+++ b/spec/features/issues/move_spec.rb
@@ -19,7 +19,7 @@ feature 'issue move to another project' do
end
scenario 'moving issue to another project not allowed' do
- expect(page).to have_no_selector('#move_to_project_id')
+ expect(page).to have_no_select('move_to_project_id')
end
end
@@ -37,7 +37,7 @@ feature 'issue move to another project' do
end
scenario 'moving issue to another project' do
- first('#move_to_project_id', visible: false).set(new_project.id)
+ select(new_project.name_with_namespace, from: 'move_to_project_id')
click_button('Save changes')
expect(current_url).to include project_path(new_project)
@@ -47,18 +47,14 @@ feature 'issue move to another project' do
expect(page).to have_content(issue.title)
end
- context 'user does not have permission to move the issue to a project', js: true do
+ context 'projects user does not have permission to move issue to exist' do
let!(:private_project) { create(:project, :private) }
let(:another_project) { create(:project) }
background { another_project.team << [user, :guest] }
scenario 'browsing projects in projects select' do
- click_link 'Select project'
-
- page.within '.select2-results' do
- expect(page).to have_content 'No project'
- expect(page).to have_content new_project.name_with_namespace
- end
+ options = [ '', 'No project', new_project.name_with_namespace ]
+ expect(page).to have_select('move_to_project_id', options: options)
end
end
@@ -69,7 +65,7 @@ feature 'issue move to another project' do
end
scenario 'user wants to move issue that has already been moved' do
- expect(page).to have_no_selector('#move_to_project_id')
+ expect(page).to have_no_select('move_to_project_id')
end
end
end
diff --git a/spec/features/issues/note_polling_spec.rb b/spec/features/issues/note_polling_spec.rb
index f5cfe2d666..e4efdbe242 100644
--- a/spec/features/issues/note_polling_spec.rb
+++ b/spec/features/issues/note_polling_spec.rb
@@ -9,11 +9,8 @@ feature 'Issue notes polling' do
end
scenario 'Another user adds a comment to an issue', js: true do
- note = create(:note, noteable: issue, project: project,
- note: 'Looks good!')
-
+ note = create(:note_on_issue, noteable: issue, note: 'Looks good!')
page.execute_script('notes.refresh();')
-
expect(page).to have_selector("#note_#{note.id}", text: 'Looks good!')
end
end
diff --git a/spec/features/issues/update_issues_spec.rb b/spec/features/issues/update_issues_spec.rb
index 466a6f7dfa..b03dd0f666 100644
--- a/spec/features/issues/update_issues_spec.rb
+++ b/spec/features/issues/update_issues_spec.rb
@@ -95,7 +95,7 @@ feature 'Multiple issue updating from issues#index', feature: true do
find('.dropdown-menu-milestone a', text: "No Milestone").click
click_update_issues_button
- expect(first('.issue')).not_to have_content milestone.title
+ expect(first('.issue')).to_not have_content milestone.title
end
end
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 9271964166..d5755c293c 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -64,68 +64,10 @@ describe 'Issues', feature: true do
end
end
- describe 'due date', js: true do
- context 'on new form' do
- before do
- visit new_namespace_project_issue_path(project.namespace, project)
- end
-
- it 'should save with due date' do
- date = Date.today.at_beginning_of_month
-
- fill_in 'issue_title', with: 'bug 345'
- fill_in 'issue_description', with: 'bug description'
-
- page.within '.datepicker' do
- click_link date.day
- end
-
- expect(find('#issuable-due-date', visible: false).value).to eq date.to_s
-
- click_button 'Submit issue'
-
- page.within '.issuable-sidebar' do
- expect(page).to have_content date.to_s(:medium)
- end
- end
- end
-
- context 'on edit form' do
- let(:issue) { create(:issue, author: @user,project: project, due_date: Date.today.at_beginning_of_month.to_s) }
-
- before do
- visit edit_namespace_project_issue_path(project.namespace, project, issue)
- end
-
- it 'should save with due date' do
- date = Date.today.at_beginning_of_month
-
- expect(find('#issuable-due-date', visible: false).value).to eq date.to_s
-
- date = date.tomorrow
-
- fill_in 'issue_title', with: 'bug 345'
- fill_in 'issue_description', with: 'bug description'
-
- page.within '.datepicker' do
- click_link date.day
- end
-
- expect(find('#issuable-due-date', visible: false).value).to eq date.to_s
-
- click_button 'Save changes'
-
- page.within '.issuable-sidebar' do
- expect(page).to have_content date.to_s(:medium)
- end
- end
- end
- end
-
describe 'Issue info' do
it 'excludes award_emoji from comment count' do
issue = create(:issue, author: @user, assignee: @user, project: project, title: 'foobar')
- create(:upvote_note, noteable: issue, project: project)
+ create(:upvote_note, noteable: issue)
visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id)
@@ -389,7 +331,7 @@ describe 'Issues', feature: true do
page.within '.assignee' do
click_link 'Edit'
end
-
+
page.within '.dropdown-menu-user' do
click_link @user.name
end
@@ -489,43 +431,6 @@ describe 'Issues', feature: true do
end
end
- describe 'due date' do
- context 'update due on issue#show', js: true do
- let(:issue) { create(:issue, project: project, author: @user, assignee: @user) }
-
- before do
- visit namespace_project_issue_path(project.namespace, project, issue)
- end
-
- it 'should add due date to issue' do
- page.within '.due_date' do
- click_link 'Edit'
-
- page.within '.ui-datepicker-calendar' do
- first('.ui-state-default').click
- end
-
- expect(page).to have_no_content 'None'
- end
- end
-
- it 'should remove due date from issue' do
- page.within '.due_date' do
- click_link 'Edit'
-
- page.within '.ui-datepicker-calendar' do
- first('.ui-state-default').click
- end
-
- expect(page).to have_no_content 'None'
-
- click_link 'remove due date'
- expect(page).to have_content 'None'
- end
- end
- end
- end
-
def first_issue
page.all('ul.issues-list > li').first.text
end
diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb
index c1b178c3b6..8c38dd5b12 100644
--- a/spec/features/login_spec.rb
+++ b/spec/features/login_spec.rb
@@ -32,7 +32,7 @@ feature 'Login', feature: true do
let(:user) { create(:user, :two_factor) }
before do
- login_with(user, remember: true)
+ login_with(user)
expect(page).to have_content('Two-factor Authentication')
end
@@ -52,12 +52,6 @@ feature 'Login', feature: true do
expect(current_path).to eq root_path
end
- it 'persists remember_me value via hidden field' do
- field = first('input#user_remember_me', visible: false)
-
- expect(field.value).to eq '1'
- end
-
it 'blocks login with invalid code' do
enter_code('foo')
expect(page).to have_content('Invalid two-factor code')
@@ -127,7 +121,7 @@ feature 'Login', feature: true do
user = create(:user, password: 'not-the-default')
login_with(user)
- expect(page).to have_content('Invalid Login or password.')
+ expect(page).to have_content('Invalid login or password.')
end
end
diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb
index 1d892fe1a5..0148c87084 100644
--- a/spec/features/markdown_spec.rb
+++ b/spec/features/markdown_spec.rb
@@ -278,10 +278,6 @@ describe 'GitLab Markdown', feature: true do
it 'includes GollumTagsFilter' do
expect(doc).to parse_gollum_tags
end
-
- it 'includes InlineDiffFilter' do
- expect(doc).to parse_inline_diffs
- end
end
# Fake a `current_user` helper
diff --git a/spec/features/merge_requests/created_from_fork_spec.rb b/spec/features/merge_requests/created_from_fork_spec.rb
deleted file mode 100644
index edc0bdec3d..0000000000
--- a/spec/features/merge_requests/created_from_fork_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-require 'spec_helper'
-
-feature 'Merge request created from fork' do
- given(:user) { create(:user) }
- given(:project) { create(:project, :public) }
- given(:fork_project) { create(:project, :public) }
-
- given!(:merge_request) do
- create(:forked_project_link, forked_to_project: fork_project,
- forked_from_project: project)
-
- create(:merge_request_with_diffs, source_project: fork_project,
- target_project: project,
- description: 'Test merge request')
- end
-
- background do
- fork_project.team << [user, :master]
- login_as user
- end
-
- scenario 'user can access merge request' do
- visit_merge_request(merge_request)
-
- expect(page).to have_content 'Test merge request'
- end
-
- context 'pipeline present in source project' do
- include WaitForAjax
-
- given(:pipeline) do
- create(:ci_commit_with_two_jobs, project: fork_project,
- sha: merge_request.last_commit.id,
- ref: merge_request.source_branch)
- end
-
- background { pipeline.create_builds(user) }
-
- scenario 'user visits a pipelines page', js: true do
- visit_merge_request(merge_request)
- page.within('.merge-request-tabs') { click_link 'Builds' }
- wait_for_ajax
-
- page.within('table.builds') do
- expect(page).to have_content 'rspec'
- expect(page).to have_content 'spinach'
- end
-
- expect(find_link('Cancel running')[:href])
- .to include fork_project.path_with_namespace
- end
- end
-
- def visit_merge_request(mr)
- visit namespace_project_merge_request_path(project.namespace,
- project, mr)
- end
-end
diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
deleted file mode 100644
index 1c130057c5..0000000000
--- a/spec/features/merge_requests/user_lists_merge_requests_spec.rb
+++ /dev/null
@@ -1,161 +0,0 @@
-require 'spec_helper'
-
-describe 'Projects > Merge requests > User lists merge requests', feature: true do
- include SortingHelper
-
- let(:project) { create(:project, :public) }
- let(:user) { create(:user) }
-
- before do
- @fix = create(:merge_request,
- title: 'fix',
- source_project: project,
- source_branch: 'fix',
- assignee: user,
- milestone: create(:milestone, due_date: '2013-12-11'),
- created_at: 1.minute.ago,
- updated_at: 1.minute.ago)
- create(:merge_request,
- title: 'markdown',
- source_project: project,
- source_branch: 'markdown',
- assignee: user,
- milestone: create(:milestone, due_date: '2013-12-12'),
- created_at: 2.minutes.ago,
- updated_at: 2.minutes.ago)
- create(:merge_request,
- title: 'lfs',
- source_project: project,
- source_branch: 'lfs',
- created_at: 3.minutes.ago,
- updated_at: 10.seconds.ago)
- end
-
- it 'filters on no assignee' do
- visit_merge_requests(project, assignee_id: IssuableFinder::NONE)
-
- expect(current_path).to eq(namespace_project_merge_requests_path(project.namespace, project))
- expect(page).to have_content 'lfs'
- expect(page).not_to have_content 'fix'
- expect(page).not_to have_content 'markdown'
- expect(count_merge_requests).to eq(1)
- end
-
- it 'filters on a specific assignee' do
- visit_merge_requests(project, assignee_id: user.id)
-
- expect(page).not_to have_content 'lfs'
- expect(page).to have_content 'fix'
- expect(page).to have_content 'markdown'
- expect(count_merge_requests).to eq(2)
- end
-
- it 'sorts by newest' do
- visit_merge_requests(project, sort: sort_value_recently_created)
-
- expect(first_merge_request).to include('lfs')
- expect(last_merge_request).to include('fix')
- expect(count_merge_requests).to eq(3)
- end
-
- it 'sorts by oldest' do
- visit_merge_requests(project, sort: sort_value_oldest_created)
-
- expect(first_merge_request).to include('fix')
- expect(last_merge_request).to include('lfs')
- expect(count_merge_requests).to eq(3)
- end
-
- it 'sorts by last updated' do
- visit_merge_requests(project, sort: sort_value_recently_updated)
-
- expect(first_merge_request).to include('lfs')
- expect(count_merge_requests).to eq(3)
- end
-
- it 'sorts by oldest updated' do
- visit_merge_requests(project, sort: sort_value_oldest_updated)
-
- expect(first_merge_request).to include('markdown')
- expect(count_merge_requests).to eq(3)
- end
-
- it 'sorts by milestone due soon' do
- visit_merge_requests(project, sort: sort_value_milestone_soon)
-
- expect(first_merge_request).to include('fix')
- expect(count_merge_requests).to eq(3)
- end
-
- it 'sorts by milestone due later' do
- visit_merge_requests(project, sort: sort_value_milestone_later)
-
- expect(first_merge_request).to include('markdown')
- expect(count_merge_requests).to eq(3)
- end
-
- it 'filters on one label and sorts by due soon' do
- label = create(:label, project: project)
- create(:label_link, label: label, target: @fix)
-
- visit_merge_requests(project, label_name: [label.name],
- sort: sort_value_due_date_soon)
-
- expect(first_merge_request).to include('fix')
- expect(count_merge_requests).to eq(1)
- end
-
- context 'while filtering on two labels' do
- let(:label) { create(:label, project: project) }
- let(:label2) { create(:label, project: project) }
-
- before do
- create(:label_link, label: label, target: @fix)
- create(:label_link, label: label2, target: @fix)
- end
-
- it 'sorts by due soon' do
- visit_merge_requests(project, label_name: [label.name, label2.name],
- sort: sort_value_due_date_soon)
-
- expect(first_merge_request).to include('fix')
- expect(count_merge_requests).to eq(1)
- end
-
- context 'filter on assignee and' do
- it 'sorts by due soon' do
- visit_merge_requests(project, label_name: [label.name, label2.name],
- assignee_id: user.id,
- sort: sort_value_due_date_soon)
-
- expect(first_merge_request).to include('fix')
- expect(count_merge_requests).to eq(1)
- end
-
- it 'sorts by recently due milestone' do
- visit namespace_project_merge_requests_path(project.namespace, project,
- label_name: [label.name, label2.name],
- assignee_id: user.id,
- sort: sort_value_milestone_soon)
-
- expect(first_merge_request).to include('fix')
- end
- end
- end
-
- def visit_merge_requests(project, opts = {})
- visit namespace_project_merge_requests_path(project.namespace, project, opts)
- end
-
- def first_merge_request
- page.all('ul.mr-list > li').first.text
- end
-
- def last_merge_request
- page.all('ul.mr-list > li').last.text
- end
-
- def count_merge_requests
- page.all('ul.mr-list > li').count
- end
-end
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index 2835cf4449..389812ff7e 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -19,14 +19,10 @@ describe 'Comments', feature: true do
end
describe 'On a merge request', js: true, feature: true do
- let!(:project) { create(:project) }
- let!(:merge_request) do
- create(:merge_request, source_project: project, target_project: project)
- end
-
+ let!(:merge_request) { create(:merge_request) }
+ let!(:project) { merge_request.source_project }
let!(:note) do
- create(:note_on_merge_request, :with_attachment, noteable: merge_request,
- project: project)
+ create(:note_on_merge_request, :with_attachment, project: project)
end
before do
@@ -196,7 +192,7 @@ describe 'Comments', feature: true do
end
it 'should be removed when canceled' do
- page.within(".diff-file form[id$='#{line_code}-true']") do
+ page.within(".diff-file form[id$='#{line_code}']") do
find('.js-close-discussion-note-form').trigger('click')
end
diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb
index c7c00a3266..1adab7e9c6 100644
--- a/spec/features/participants_autocomplete_spec.rb
+++ b/spec/features/participants_autocomplete_spec.rb
@@ -32,8 +32,7 @@ feature 'Member autocomplete', feature: true do
context 'adding a new note on a Issue', js: true do
before do
issue = create(:issue, author: author, project: project)
- create(:note, note: 'Ultralight Beam', noteable: issue,
- project: project, author: participant)
+ create(:note, note: 'Ultralight Beam', noteable: issue, author: participant)
visit_issue(project, issue)
end
@@ -48,8 +47,7 @@ feature 'Member autocomplete', feature: true do
context 'adding a new note on a Merge Request ', js: true do
before do
merge = create(:merge_request, source_project: project, target_project: project, author: author)
- create(:note, note: 'Ultralight Beam', noteable: merge,
- project: project, author: participant)
+ create(:note, note: 'Ultralight Beam', noteable: merge, author: participant)
visit_merge_request(project, merge)
end
diff --git a/spec/features/pipelines_spec.rb b/spec/features/pipelines_spec.rb
deleted file mode 100644
index acd6fb3538..0000000000
--- a/spec/features/pipelines_spec.rb
+++ /dev/null
@@ -1,189 +0,0 @@
-require 'spec_helper'
-
-describe "Pipelines" do
- include GitlabRoutingHelper
-
- let(:project) { create(:empty_project) }
- let(:user) { create(:user) }
-
- before do
- login_as(user)
- project.team << [user, :developer]
- end
-
- describe 'GET /:project/pipelines' do
- let!(:pipeline) { create(:ci_commit, project: project, ref: 'master', status: 'running') }
-
- [:all, :running, :branches].each do |scope|
- context "displaying #{scope}" do
- let(:project) { create(:project) }
-
- before { visit namespace_project_pipelines_path(project.namespace, project, scope: scope) }
-
- it { expect(page).to have_content(pipeline.short_sha) }
- end
- end
-
- context 'anonymous access' do
- before { visit namespace_project_pipelines_path(project.namespace, project) }
-
- it { expect(page).to have_http_status(:success) }
- end
-
- context 'cancelable pipeline' do
- let!(:running) { create(:ci_build, :running, commit: pipeline, stage: 'test', commands: 'test') }
-
- before { visit namespace_project_pipelines_path(project.namespace, project) }
-
- it { expect(page).to have_link('Cancel') }
- it { expect(page).to have_selector('.ci-running') }
-
- context 'when canceling' do
- before { click_link('Cancel') }
-
- it { expect(page).not_to have_link('Cancel') }
- it { expect(page).to have_selector('.ci-canceled') }
- end
- end
-
- context 'retryable pipelines' do
- let!(:failed) { create(:ci_build, :failed, commit: pipeline, stage: 'test', commands: 'test') }
-
- before { visit namespace_project_pipelines_path(project.namespace, project) }
-
- it { expect(page).to have_link('Retry') }
- it { expect(page).to have_selector('.ci-failed') }
-
- context 'when retrying' do
- before { click_link('Retry') }
-
- it { expect(page).not_to have_link('Retry') }
- it { expect(page).to have_selector('.ci-pending') }
- end
- end
-
- context 'for generic statuses' do
- context 'when running' do
- let!(:running) { create(:generic_commit_status, status: 'running', commit: pipeline, stage: 'test') }
-
- before { visit namespace_project_pipelines_path(project.namespace, project) }
-
- it 'not be cancelable' do
- expect(page).not_to have_link('Cancel')
- end
-
- it 'pipeline is running' do
- expect(page).to have_selector('.ci-running')
- end
- end
-
- context 'when failed' do
- let!(:running) { create(:generic_commit_status, status: 'failed', commit: pipeline, stage: 'test') }
-
- before { visit namespace_project_pipelines_path(project.namespace, project) }
-
- it 'not be retryable' do
- expect(page).not_to have_link('Retry')
- end
-
- it 'pipeline is failed' do
- expect(page).to have_selector('.ci-failed')
- end
- end
- end
-
- context 'downloadable pipelines' do
- context 'with artifacts' do
- let!(:with_artifacts) { create(:ci_build, :artifacts, :success, commit: pipeline, name: 'rspec tests', stage: 'test') }
-
- before { visit namespace_project_pipelines_path(project.namespace, project) }
-
- it { expect(page).to have_selector('.build-artifacts') }
- it { expect(page).to have_link(with_artifacts.name) }
- end
-
- context 'without artifacts' do
- let!(:without_artifacts) { create(:ci_build, :success, commit: pipeline, name: 'rspec', stage: 'test') }
-
- it { expect(page).not_to have_selector('.build-artifacts') }
- end
- end
- end
-
- describe 'GET /:project/pipelines/:id' do
- let(:pipeline) { create(:ci_commit, project: project, ref: 'master') }
-
- before do
- @success = create(:ci_build, :success, commit: pipeline, stage: 'build', name: 'build')
- @failed = create(:ci_build, :failed, commit: pipeline, stage: 'test', name: 'test', commands: 'test')
- @running = create(:ci_build, :running, commit: pipeline, stage: 'deploy', name: 'deploy')
- @external = create(:generic_commit_status, status: 'success', commit: pipeline, name: 'jenkins', stage: 'external')
- end
-
- before { visit namespace_project_pipeline_path(project.namespace, project, pipeline) }
-
- it 'showing a list of builds' do
- expect(page).to have_content('Tests')
- expect(page).to have_content(@success.id)
- expect(page).to have_content('Deploy')
- expect(page).to have_content(@failed.id)
- expect(page).to have_content(@running.id)
- expect(page).to have_content(@external.id)
- expect(page).to have_content('Retry failed')
- expect(page).to have_content('Cancel running')
- end
-
- context 'retrying builds' do
- it { expect(page).not_to have_content('retried') }
-
- context 'when retrying' do
- before { click_on 'Retry failed' }
-
- it { expect(page).not_to have_content('Retry failed') }
- it { expect(page).to have_content('retried') }
- end
- end
-
- context 'canceling builds' do
- it { expect(page).not_to have_selector('.ci-canceled') }
-
- context 'when canceling' do
- before { click_on 'Cancel running' }
-
- it { expect(page).not_to have_content('Cancel running') }
- it { expect(page).to have_selector('.ci-canceled') }
- end
- end
- end
-
- describe 'POST /:project/pipelines' do
- let(:project) { create(:project) }
-
- before { visit new_namespace_project_pipeline_path(project.namespace, project) }
-
- context 'for valid commit' do
- before { fill_in('Create for', with: 'master') }
-
- context 'with gitlab-ci.yml' do
- before { stub_ci_commit_to_return_yaml_file }
-
- it { expect{ click_on 'Create pipeline' }.to change{ Ci::Commit.count }.by(1) }
- end
-
- context 'without gitlab-ci.yml' do
- before { click_on 'Create pipeline' }
-
- it { expect(page).to have_content('Missing .gitlab-ci.yml file') }
- end
- end
-
- context 'for invalid commit' do
- before do
- fill_in('Create for', with: 'invalid reference')
- click_on 'Create pipeline'
- end
-
- it { expect(page).to have_content('Reference not found') }
- end
- end
-end
diff --git a/spec/features/projects/shortcuts_spec.rb b/spec/features/project/shortcuts_spec.rb
similarity index 79%
rename from spec/features/projects/shortcuts_spec.rb
rename to spec/features/project/shortcuts_spec.rb
index 54aa9c66a0..2595c4181e 100644
--- a/spec/features/projects/shortcuts_spec.rb
+++ b/spec/features/project/shortcuts_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
feature 'Project shortcuts', feature: true do
- let(:project) { create(:project, name: 'Victorialand') }
+ let(:project) { create(:project) }
let(:user) { create(:user) }
describe 'On a project', js: true do
@@ -14,7 +14,7 @@ feature 'Project shortcuts', feature: true do
describe 'pressing "i"' do
it 'redirects to new issue page' do
find('body').native.send_key('i')
- expect(page).to have_content('Victorialand')
+ expect(page).to have_content('New Issue')
end
end
end
diff --git a/spec/features/projects/badges/list_spec.rb b/spec/features/projects/badges/list_spec.rb
index 51be81d634..13c9b95b31 100644
--- a/spec/features/projects/badges/list_spec.rb
+++ b/spec/features/projects/badges/list_spec.rb
@@ -8,10 +8,12 @@ feature 'list of badges' do
project = create(:project)
project.team << [user, :master]
login_as(user)
- visit namespace_project_badges_path(project.namespace, project)
+ visit edit_namespace_project_path(project.namespace, project)
end
scenario 'user displays list of badges' do
+ click_link 'Badges'
+
expect(page).to have_content 'build status'
expect(page).to have_content 'Markdown'
expect(page).to have_content 'HTML'
@@ -24,6 +26,7 @@ feature 'list of badges' do
end
scenario 'user changes current ref on badges list page', js: true do
+ click_link 'Badges'
select2('improve/awesome', from: '#ref')
expect(page).to have_content 'badges/improve/awesome/build.svg'
diff --git a/spec/features/projects/developer_views_empty_project_instructions_spec.rb b/spec/features/projects/developer_views_empty_project_instructions_spec.rb
deleted file mode 100644
index 0c51fe72ca..0000000000
--- a/spec/features/projects/developer_views_empty_project_instructions_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-require 'rails_helper'
-
-feature 'Developer views empty project instructions', feature: true do
- let(:project) { create(:empty_project, :empty_repo) }
- let(:developer) { create(:user) }
-
- background do
- project.team << [developer, :developer]
-
- login_as(developer)
- end
-
- context 'without an SSH key' do
- scenario 'defaults to HTTP' do
- visit_project
-
- expect_instructions_for('http')
- end
-
- scenario 'switches to SSH', js: true do
- visit_project
-
- select_protocol('SSH')
-
- expect_instructions_for('ssh')
- end
- end
-
- context 'with an SSH key' do
- background do
- create(:personal_key, user: developer)
- end
-
- scenario 'defaults to SSH' do
- visit_project
-
- expect_instructions_for('ssh')
- end
-
- scenario 'switches to HTTP', js: true do
- visit_project
-
- select_protocol('HTTP')
-
- expect_instructions_for('http')
- end
- end
-
- def visit_project
- visit namespace_project_path(project.namespace, project)
- end
-
- def select_protocol(protocol)
- find('#clone-dropdown').click
- find(".#{protocol.downcase}-selector").click
- end
-
- def expect_instructions_for(protocol)
- msg = :"#{protocol.downcase}_url_to_repo"
-
- expect(page).to have_content("git clone #{project.send(msg)}")
- end
-end
diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb
deleted file mode 100644
index 073a83b689..0000000000
--- a/spec/features/projects/files/gitignore_dropdown_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'spec_helper'
-
-feature 'User wants to add a .gitignore file', feature: true do
- include WaitForAjax
-
- before do
- user = create(:user)
- project = create(:project)
- project.team << [user, :master]
- login_as user
- visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: '.gitignore')
- end
-
- scenario 'user can see .gitignore dropdown' do
- expect(page).to have_css('.gitignore-selector')
- end
-
- scenario 'user can pick a .gitignore file from the dropdown', js: true do
- find('.js-gitignore-selector').click
- wait_for_ajax
- within '.gitignore-selector' do
- find('.dropdown-input-field').set('rails')
- find('.dropdown-content li', text: 'Rails').click
- end
- wait_for_ajax
-
- expect(page).to have_content('/.bundle')
- expect(page).to have_content('# Gemfile.lock, .ruby-version, .ruby-gemset')
- end
-end
diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
index ecc818eb1e..3d6ffbc4c6 100644
--- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb
+++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
@@ -25,7 +25,7 @@ feature 'project owner creates a license file', feature: true, js: true do
file_content = find('.file-content')
expect(file_content).to have_content('The MIT License (MIT)')
- expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
+ expect(file_content).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
fill_in :commit_message, with: 'Add a LICENSE file', visible: true
click_button 'Commit Changes'
@@ -33,7 +33,7 @@ feature 'project owner creates a license file', feature: true, js: true do
expect(current_path).to eq(
namespace_project_blob_path(project.namespace, project, 'master/LICENSE'))
expect(page).to have_content('The MIT License (MIT)')
- expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
+ expect(page).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
end
scenario 'project master creates a license file from the "Add license" link' do
@@ -48,7 +48,7 @@ feature 'project owner creates a license file', feature: true, js: true do
file_content = find('.file-content')
expect(file_content).to have_content('The MIT License (MIT)')
- expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
+ expect(file_content).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
fill_in :commit_message, with: 'Add a LICENSE file', visible: true
click_button 'Commit Changes'
@@ -56,6 +56,6 @@ feature 'project owner creates a license file', feature: true, js: true do
expect(current_path).to eq(
namespace_project_blob_path(project.namespace, project, 'master/LICENSE'))
expect(page).to have_content('The MIT License (MIT)')
- expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
+ expect(page).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
end
end
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index 34eda29c28..3268e24020 100644
--- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -24,7 +24,7 @@ feature 'project owner sees a link to create a license file in empty project', f
file_content = find('.file-content')
expect(file_content).to have_content('The MIT License (MIT)')
- expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
+ expect(file_content).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
fill_in :commit_message, with: 'Add a LICENSE file', visible: true
# Remove pre-receive hook so we can push without auth
@@ -34,6 +34,6 @@ feature 'project owner sees a link to create a license file in empty project', f
expect(current_path).to eq(
namespace_project_blob_path(project.namespace, project, 'master/LICENSE'))
expect(page).to have_content('The MIT License (MIT)')
- expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
+ expect(page).to have_content("Copyright (c) 2016 #{project.namespace.human_name}")
end
end
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index a5ed3595b0..8edeb8d18a 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -29,8 +29,8 @@ describe "Runners" do
end
before do
- expect(page).not_to have_content(@specific_runner3.display_name)
- expect(page).not_to have_content(@specific_runner3.display_name)
+ expect(page).to_not have_content(@specific_runner3.display_name)
+ expect(page).to_not have_content(@specific_runner3.display_name)
end
it "places runners in right places" do
@@ -110,37 +110,4 @@ describe "Runners" do
expect(page).to have_content(@specific_runner.platform)
end
end
-
- feature 'configuring runners ability to picking untagged jobs' do
- given(:project) { create(:empty_project) }
- given(:runner) { create(:ci_runner) }
-
- background do
- project.team << [user, :master]
- project.runners << runner
- end
-
- scenario 'user checks default configuration' do
- visit namespace_project_runner_path(project.namespace, project, runner)
-
- expect(page).to have_content 'Can run untagged jobs Yes'
- end
-
- context 'when runner has tags' do
- before { runner.update_attribute(:tag_list, ['tag']) }
-
- scenario 'user wants to prevent runner from running untagged job' do
- visit runners_path(project)
- page.within('.activated-specific-runners') do
- first('small > a').click
- end
-
- uncheck 'runner_run_untagged'
- click_button 'Save changes'
-
- expect(page).to have_content 'Can run untagged jobs No'
- expect(runner.reload.run_untagged?).to eq false
- end
- end
- end
end
diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb
index 4229e82b44..58aabd913e 100644
--- a/spec/features/signup_spec.rb
+++ b/spec/features/signup_spec.rb
@@ -2,45 +2,20 @@ require 'spec_helper'
feature 'Signup', feature: true do
describe 'signup with no errors' do
+ it 'creates the user account and sends a confirmation email' do
+ user = build(:user)
- context "when sending confirmation email" do
- before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) }
+ visit root_path
- it 'creates the user account and sends a confirmation email' do
- user = build(:user)
+ fill_in 'new_user_name', with: user.name
+ fill_in 'new_user_username', with: user.username
+ fill_in 'new_user_email', with: user.email
+ fill_in 'new_user_password', with: user.password
+ click_button "Sign up"
- visit root_path
-
- fill_in 'new_user_name', with: user.name
- fill_in 'new_user_username', with: user.username
- fill_in 'new_user_email', with: user.email
- fill_in 'new_user_password', with: user.password
- click_button "Sign up"
-
- expect(current_path).to eq users_almost_there_path
- expect(page).to have_content("Please check your email to confirm your account")
- end
+ expect(current_path).to eq users_almost_there_path
+ expect(page).to have_content("Please check your email to confirm your account")
end
-
- context "when not sending confirmation email" do
- before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(false) }
-
- it 'creates the user account and goes to dashboard' do
- user = build(:user)
-
- visit root_path
-
- fill_in 'new_user_name', with: user.name
- fill_in 'new_user_username', with: user.username
- fill_in 'new_user_email', with: user.email
- fill_in 'new_user_password', with: user.password
- click_button "Sign up"
-
- expect(current_path).to eq dashboard_projects_path
- expect(page).to have_content("Welcome! You have signed up successfully.")
- end
- end
-
end
describe 'signup with errors' do
diff --git a/spec/features/tags/master_creates_tag_spec.rb b/spec/features/tags/master_creates_tag_spec.rb
deleted file mode 100644
index 08a97085a9..0000000000
--- a/spec/features/tags/master_creates_tag_spec.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-require 'spec_helper'
-
-feature 'Master creates tag', feature: true do
- let(:user) { create(:user) }
- let(:project) { create(:project, namespace: user.namespace) }
-
- before do
- project.team << [user, :master]
- login_with(user)
- visit namespace_project_tags_path(project.namespace, project)
- end
-
- scenario 'with an invalid name displays an error' do
- create_tag_in_form(tag: 'v 1.0', ref: 'master')
-
- expect(page).to have_content 'Tag name invalid'
- end
-
- scenario 'with an invalid reference displays an error' do
- create_tag_in_form(tag: 'v2.0', ref: 'foo')
-
- expect(page).to have_content 'Target foo is invalid'
- end
-
- scenario 'that already exists displays an error' do
- create_tag_in_form(tag: 'v1.1.0', ref: 'master')
-
- expect(page).to have_content 'Tag v1.1.0 already exists'
- end
-
- scenario 'with multiline message displays the message in a block' do
- create_tag_in_form(tag: 'v3.0', ref: 'master', message: "Awesome tag message\n\n- hello\n- world")
-
- expect(current_path).to eq(
- namespace_project_tag_path(project.namespace, project, 'v3.0'))
- expect(page).to have_content 'v3.0'
- page.within 'pre.body' do
- expect(page).to have_content "Awesome tag message\n\n- hello\n- world"
- end
- end
-
- scenario 'with multiline release notes parses the release note as Markdown' do
- create_tag_in_form(tag: 'v4.0', ref: 'master', desc: "Awesome release notes\n\n- hello\n- world")
-
- expect(current_path).to eq(
- namespace_project_tag_path(project.namespace, project, 'v4.0'))
- expect(page).to have_content 'v4.0'
- page.within '.description' do
- expect(page).to have_content 'Awesome release notes'
- expect(page).to have_selector('ul li', count: 2)
- end
- end
-
- def create_tag_in_form(tag:, ref:, message: nil, desc: nil)
- click_link 'New tag'
- fill_in 'tag_name', with: tag
- fill_in 'ref', with: ref
- fill_in 'message', with: message unless message.nil?
- fill_in 'release_description', with: desc unless desc.nil?
- click_button 'Create tag'
- end
-end
diff --git a/spec/features/tags/master_deletes_tag_spec.rb b/spec/features/tags/master_deletes_tag_spec.rb
deleted file mode 100644
index f0990118e3..0000000000
--- a/spec/features/tags/master_deletes_tag_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require 'spec_helper'
-
-feature 'Master deletes tag', feature: true do
- let(:user) { create(:user) }
- let(:project) { create(:project, namespace: user.namespace) }
-
- before do
- project.team << [user, :master]
- login_with(user)
- visit namespace_project_tags_path(project.namespace, project)
- end
-
- context 'from the tags list page' do
- scenario 'deletes the tag' do
- expect(page).to have_content 'v1.1.0'
-
- page.within('.content') do
- first('.btn-remove').click
- end
-
- expect(current_path).to eq(
- namespace_project_tags_path(project.namespace, project))
- expect(page).not_to have_content 'v1.1.0'
- end
-
- end
-
- context 'from a specific tag page' do
- scenario 'deletes the tag' do
- click_on 'v1.0.0'
- expect(current_path).to eq(
- namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
-
- click_on 'Delete tag'
-
- expect(current_path).to eq(
- namespace_project_tags_path(project.namespace, project))
- expect(page).not_to have_content 'v1.0.0'
- end
- end
-end
diff --git a/spec/features/tags/master_updates_tag_spec.rb b/spec/features/tags/master_updates_tag_spec.rb
deleted file mode 100644
index 6b5b3122f7..0000000000
--- a/spec/features/tags/master_updates_tag_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require 'spec_helper'
-
-feature 'Master updates tag', feature: true do
- let(:user) { create(:user) }
- let(:project) { create(:project, namespace: user.namespace) }
-
- before do
- project.team << [user, :master]
- login_with(user)
- visit namespace_project_tags_path(project.namespace, project)
- end
-
- context 'from the tags list page' do
- scenario 'updates the release notes' do
- page.within(first('.content-list .controls')) do
- click_link 'Edit release notes'
- end
-
- fill_in 'release_description', with: 'Awesome release notes'
- click_button 'Save changes'
-
- expect(current_path).to eq(
- namespace_project_tag_path(project.namespace, project, 'v1.1.0'))
- expect(page).to have_content 'v1.1.0'
- expect(page).to have_content 'Awesome release notes'
- end
- end
-
- context 'from a specific tag page' do
- scenario 'updates the release notes' do
- click_on 'v1.1.0'
- click_link 'Edit release notes'
- fill_in 'release_description', with: 'Awesome release notes'
- click_button 'Save changes'
-
- expect(current_path).to eq(
- namespace_project_tag_path(project.namespace, project, 'v1.1.0'))
- expect(page).to have_content 'v1.1.0'
- expect(page).to have_content 'Awesome release notes'
- end
- end
-end
diff --git a/spec/features/tags/master_views_tags_spec.rb b/spec/features/tags/master_views_tags_spec.rb
deleted file mode 100644
index 29d2c24472..0000000000
--- a/spec/features/tags/master_views_tags_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-require 'spec_helper'
-
-feature 'Master views tags', feature: true do
- let(:user) { create(:user) }
-
- before do
- project.team << [user, :master]
- login_with(user)
- end
-
- context 'when project has no tags' do
- let(:project) { create(:project_empty_repo) }
- before do
- visit namespace_project_path(project.namespace, project)
- click_on 'README'
- fill_in :commit_message, with: 'Add a README file', visible: true
- # Remove pre-receive hook so we can push without auth
- FileUtils.rm_f(File.join(project.repository.path, 'hooks', 'pre-receive'))
- click_button 'Commit Changes'
- visit namespace_project_tags_path(project.namespace, project)
- end
-
- scenario 'displays a specific message' do
- expect(page).to have_content 'Repository has no tags yet.'
- end
- end
-
- context 'when project has tags' do
- let(:project) { create(:project, namespace: user.namespace) }
- before do
- visit namespace_project_tags_path(project.namespace, project)
- end
-
- scenario 'views the tags list page' do
- expect(page).to have_content 'v1.0.0'
- end
-
- scenario 'views a specific tag page' do
- click_on 'v1.0.0'
-
- expect(current_path).to eq(
- namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
- expect(page).to have_content 'v1.0.0'
- expect(page).to have_content 'This tag has no release notes.'
- end
-
- describe 'links on the tag page' do
- scenario 'has a button to browse files' do
- click_on 'v1.0.0'
-
- expect(current_path).to eq(
- namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
-
- click_on 'Browse files'
-
- expect(current_path).to eq(
- namespace_project_tree_path(project.namespace, project, 'v1.0.0'))
- end
-
- scenario 'has a button to browse commits' do
- click_on 'v1.0.0'
-
- expect(current_path).to eq(
- namespace_project_tag_path(project.namespace, project, 'v1.0.0'))
-
- click_on 'Browse commits'
-
- expect(current_path).to eq(
- namespace_project_commits_path(project.namespace, project, 'v1.0.0'))
- end
- end
- end
-end
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index 6ed279ef9b..b7368cca29 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -75,10 +75,7 @@ feature 'Task Lists', feature: true do
describe 'for Notes' do
let!(:issue) { create(:issue, author: user, project: project) }
- let!(:note) do
- create(:note, note: markdown, noteable: issue,
- project: project, author: user)
- end
+ let!(:note) { create(:note, note: markdown, noteable: issue, author: user) }
it 'renders for note body' do
visit_issue(project, issue)
diff --git a/spec/features/todos/target_state_spec.rb b/spec/features/todos/target_state_spec.rb
deleted file mode 100644
index 72491ac7e6..0000000000
--- a/spec/features/todos/target_state_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-require 'rails_helper'
-
-feature 'Todo target states', feature: true do
- let(:user) { create(:user) }
- let(:author) { create(:user) }
- let(:project) { create(:project) }
-
- before do
- login_as user
- end
-
- scenario 'on a closed issue todo has closed label' do
- issue_closed = create(:issue, state: 'closed')
- create_todo issue_closed
- visit dashboard_todos_path
-
- page.within '.todos-list' do
- expect(page).to have_content('Closed')
- end
- end
-
- scenario 'on an open issue todo does not have an open label' do
- issue_open = create(:issue)
- create_todo issue_open
- visit dashboard_todos_path
-
- page.within '.todos-list' do
- expect(page).not_to have_content('Open')
- end
- end
-
- scenario 'on a merged merge request todo has merged label' do
- mr_merged = create(:merge_request, :simple, author: user, state: 'merged')
- create_todo mr_merged
- visit dashboard_todos_path
-
- page.within '.todos-list' do
- expect(page).to have_content('Merged')
- end
- end
-
- scenario 'on a closed merge request todo has closed label' do
- mr_closed = create(:merge_request, :simple, author: user, state: 'closed')
- create_todo mr_closed
- visit dashboard_todos_path
-
- page.within '.todos-list' do
- expect(page).to have_content('Closed')
- end
- end
-
- scenario 'on an open merge request todo does not have an open label' do
- mr_open = create(:merge_request, :simple, author: user)
- create_todo mr_open
- visit dashboard_todos_path
-
- page.within '.todos-list' do
- expect(page).not_to have_content('Open')
- end
- end
-
- def create_todo(target)
- create(:todo, :mentioned, user: user, project: project, target: target, author: author)
- end
-end
diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb
index 4e627753cc..3354f52929 100644
--- a/spec/features/todos/todos_spec.rb
+++ b/spec/features/todos/todos_spec.rb
@@ -43,27 +43,6 @@ describe 'Dashboard Todos', feature: true do
end
end
- context 'User has Todos with labels spanning multiple projects' do
- before do
- label1 = create(:label, project: project)
- note1 = create(:note_on_issue, note: "Hello #{label1.to_reference(format: :name)}", noteable_id: issue.id, noteable_type: 'Issue', project: issue.project)
- create(:todo, :mentioned, project: project, target: issue, user: user, note_id: note1.id)
-
- project2 = create(:project)
- label2 = create(:label, project: project2)
- issue2 = create(:issue, project: project2)
- note2 = create(:note_on_issue, note: "Test #{label2.to_reference(format: :name)}", noteable_id: issue2.id, noteable_type: 'Issue', project: project2)
- create(:todo, :mentioned, project: project2, target: issue2, user: user, note_id: note2.id)
-
- login_as(user)
- visit dashboard_todos_path
- end
-
- it 'shows page with two Todos' do
- expect(page).to have_selector('.todos-list .todo', count: 2)
- end
- end
-
context 'User has multiple pages of Todos' do
before do
allow(Todo).to receive(:default_per_page).and_return(1)
diff --git a/spec/features/variables_spec.rb b/spec/features/variables_spec.rb
index a2b8f7b693..afea1840cd 100644
--- a/spec/features/variables_spec.rb
+++ b/spec/features/variables_spec.rb
@@ -1,53 +1,24 @@
require 'spec_helper'
-describe 'Project variables', js: true do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
- let(:variable) { create(:ci_variable, key: 'test') }
+describe "Variables" do
+ let(:user) { create(:user) }
+ before { login_as(user) }
- before do
- login_as(user)
- project.team << [user, :master]
- project.variables << variable
-
- visit namespace_project_variables_path(project.namespace, project)
- end
-
- it 'should show list of variables' do
- page.within('.variables-table') do
- expect(page).to have_content(variable.key)
- end
- end
-
- it 'should add new variable' do
- fill_in('variable_key', with: 'key')
- fill_in('variable_value', with: 'key value')
- click_button('Add new variable')
-
- page.within('.variables-table') do
- expect(page).to have_content('key')
- end
- end
-
- it 'should delete variable' do
- page.within('.variables-table') do
- find('.btn-variable-delete').click
+ describe "specific runners" do
+ before do
+ @project = FactoryGirl.create :empty_project
+ @project.team << [user, :master]
end
- expect(page).not_to have_selector('variables-table')
- end
+ it "creates variable", js: true do
+ visit namespace_project_variables_path(@project.namespace, @project)
+ click_on "Add a variable"
+ fill_in "Key", with: "SECRET_KEY"
+ fill_in "Value", with: "SECRET_VALUE"
+ click_on "Save changes"
- it 'should edit variable' do
- page.within('.variables-table') do
- find('.btn-variable-edit').click
- end
-
- fill_in('variable_key', with: 'key')
- fill_in('variable_value', with: 'key value')
- click_button('Save variable')
-
- page.within('.variables-table') do
- expect(page).to have_content('key')
+ expect(page).to have_content("Variables were successfully updated.")
+ expect(@project.variables.count).to eq(1)
end
end
end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index ec8809e692..bc607a2975 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -1,10 +1,10 @@
require 'spec_helper'
describe IssuesFinder do
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
- let(:project1) { create(:empty_project) }
- let(:project2) { create(:empty_project) }
+ let(:user) { create :user }
+ let(:user2) { create :user }
+ let(:project1) { create(:project) }
+ let(:project2) { create(:project) }
let(:milestone) { create(:milestone, project: project1) }
let(:label) { create(:label, project: project2) }
let(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone) }
@@ -16,147 +16,101 @@ describe IssuesFinder do
project1.team << [user, :master]
project2.team << [user, :developer]
project2.team << [user2, :developer]
-
- issue1
- issue2
- issue3
end
- describe '#execute' do
- let(:search_user) { user }
- let(:params) { {} }
- let(:issues) { IssuesFinder.new(search_user, params.merge(scope: scope, state: 'opened')).execute }
+ describe :execute do
+ before :each do
+ issue1
+ issue2
+ issue3
+ end
context 'scope: all' do
- let(:scope) { 'all' }
-
- it 'returns all issues' do
- expect(issues).to contain_exactly(issue1, issue2, issue3)
+ it 'should filter by all' do
+ params = { scope: "all", state: 'opened' }
+ issues = IssuesFinder.new(user, params).execute
+ expect(issues.size).to eq(3)
end
- context 'filtering by assignee ID' do
- let(:params) { { assignee_id: user.id } }
-
- it 'returns issues assigned to that user' do
- expect(issues).to contain_exactly(issue1, issue2)
- end
+ it 'should filter by assignee id' do
+ params = { scope: "all", assignee_id: user.id, state: 'opened' }
+ issues = IssuesFinder.new(user, params).execute
+ expect(issues.size).to eq(2)
end
- context 'filtering by author ID' do
- let(:params) { { author_id: user2.id } }
-
- it 'returns issues created by that user' do
- expect(issues).to contain_exactly(issue3)
- end
+ it 'should filter by author id' do
+ params = { scope: "all", author_id: user2.id, state: 'opened' }
+ issues = IssuesFinder.new(user, params).execute
+ expect(issues).to eq([issue3])
end
- context 'filtering by milestone' do
- let(:params) { { milestone_title: milestone.title } }
-
- it 'returns issues assigned to that milestone' do
- expect(issues).to contain_exactly(issue1)
- end
+ it 'should filter by milestone id' do
+ params = { scope: "all", milestone_title: milestone.title, state: 'opened' }
+ issues = IssuesFinder.new(user, params).execute
+ expect(issues).to eq([issue1])
end
- context 'filtering by no milestone' do
- let(:params) { { milestone_title: Milestone::None.title } }
-
- it 'returns issues with no milestone' do
- expect(issues).to contain_exactly(issue2, issue3)
- end
+ it 'should filter by no milestone id' do
+ params = { scope: "all", milestone_title: Milestone::None.title, state: 'opened' }
+ issues = IssuesFinder.new(user, params).execute
+ expect(issues).to match_array([issue2, issue3])
end
- context 'filtering by upcoming milestone' do
- let(:params) { { milestone_title: Milestone::Upcoming.name } }
-
- let(:project_no_upcoming_milestones) { create(:empty_project, :public) }
- let(:project_next_1_1) { create(:empty_project, :public) }
- let(:project_next_8_8) { create(:empty_project, :public) }
-
- let(:yesterday) { Date.today - 1.day }
- let(:tomorrow) { Date.today + 1.day }
- let(:two_days_from_now) { Date.today + 2.days }
- let(:ten_days_from_now) { Date.today + 10.days }
-
- let(:milestones) do
- [
- create(:milestone, :closed, project: project_no_upcoming_milestones),
- create(:milestone, project: project_next_1_1, title: '1.1', due_date: two_days_from_now),
- create(:milestone, project: project_next_1_1, title: '8.8', due_date: ten_days_from_now),
- create(:milestone, project: project_next_8_8, title: '1.1', due_date: yesterday),
- create(:milestone, project: project_next_8_8, title: '8.8', due_date: tomorrow)
- ]
- end
-
- before do
- milestones.each do |milestone|
- create(:issue, project: milestone.project, milestone: milestone, author: user, assignee: user)
- end
- end
-
- it 'returns issues in the upcoming milestone for each project' do
- expect(issues.map { |issue| issue.milestone.title }).to contain_exactly('1.1', '8.8')
- expect(issues.map { |issue| issue.milestone.due_date }).to contain_exactly(tomorrow, two_days_from_now)
- end
+ it 'should filter by label name' do
+ params = { scope: "all", label_name: label.title, state: 'opened' }
+ issues = IssuesFinder.new(user, params).execute
+ expect(issues).to eq([issue2])
end
- context 'filtering by label' do
- let(:params) { { label_name: label.title } }
+ it 'returns unique issues when filtering by multiple labels' do
+ label2 = create(:label, project: project2)
- it 'returns issues with that label' do
- expect(issues).to contain_exactly(issue2)
- end
+ create(:label_link, label: label2, target: issue2)
+
+ params = {
+ scope: 'all',
+ label_name: [label.title, label2.title].join(','),
+ state: 'opened'
+ }
+
+ issues = IssuesFinder.new(user, params).execute
+
+ expect(issues).to eq([issue2])
end
- context 'filtering by multiple labels' do
- let(:params) { { label_name: [label.title, label2.title].join(',') } }
- let(:label2) { create(:label, project: project2) }
-
- before { create(:label_link, label: label2, target: issue2) }
-
- it 'returns the unique issues with any of those labels' do
- expect(issues).to contain_exactly(issue2)
- end
+ it 'should filter by no label name' do
+ params = { scope: "all", label_name: Label::None.title, state: 'opened' }
+ issues = IssuesFinder.new(user, params).execute
+ expect(issues).to match_array([issue1, issue3])
end
- context 'filtering by no label' do
- let(:params) { { label_name: Label::None.title } }
-
- it 'returns issues with no labels' do
- expect(issues).to contain_exactly(issue1, issue3)
- end
+ it 'should be empty for unauthorized user' do
+ params = { scope: "all", state: 'opened' }
+ issues = IssuesFinder.new(nil, params).execute
+ expect(issues.size).to be_zero
end
- context 'when the user is unauthorized' do
- let(:search_user) { nil }
-
- it 'returns no results' do
- expect(issues).to be_empty
- end
- end
-
- context 'when the user can see some, but not all, issues' do
- let(:search_user) { user2 }
-
- it 'returns only issues they can see' do
- expect(issues).to contain_exactly(issue2, issue3)
- end
+ it 'should not include unauthorized issues' do
+ params = { scope: "all", state: 'opened' }
+ issues = IssuesFinder.new(user2, params).execute
+ expect(issues.size).to eq(2)
+ expect(issues).not_to include(issue1)
+ expect(issues).to include(issue2)
+ expect(issues).to include(issue3)
end
end
context 'personal scope' do
- let(:scope) { 'assigned-to-me' }
-
- it 'returns issue assigned to the user' do
- expect(issues).to contain_exactly(issue1, issue2)
+ it 'should filter by assignee' do
+ params = { scope: "assigned-to-me", state: 'opened' }
+ issues = IssuesFinder.new(user, params).execute
+ expect(issues.size).to eq(2)
end
- context 'filtering by project' do
- let(:params) { { project_id: project1.id } }
-
- it 'returns issues assigned to the user in that project' do
- expect(issues).to contain_exactly(issue1)
- end
+ it 'should filter by project' do
+ params = { scope: "assigned-to-me", state: 'opened', project_id: project1.id }
+ issues = IssuesFinder.new(user, params).execute
+ expect(issues.size).to eq(1)
end
end
end
diff --git a/spec/fixtures/container_registry/config_blob.json b/spec/fixtures/container_registry/config_blob.json
deleted file mode 100644
index 1028c994a2..0000000000
--- a/spec/fixtures/container_registry/config_blob.json
+++ /dev/null
@@ -1 +0,0 @@
-{"architecture":"amd64","config":{"Hostname":"b14cd8298755","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":null,"Image":"","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"b14cd82987550b01af9a666a2f4c996280a6152e66873134fae5a0f223dc5976","container_config":{"Hostname":"b14cd8298755","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":["/bin/sh","-c","#(nop) ADD file:033ab063740d9ff4dcfb1c69eccf25f91d88729f57cd5a73050e014e3e094aa0 in /"],"Image":"","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"created":"2016-04-01T20:53:00.160300546Z","docker_version":"1.9.1","history":[{"created":"2016-04-01T20:53:00.160300546Z","created_by":"/bin/sh -c #(nop) ADD file:033ab063740d9ff4dcfb1c69eccf25f91d88729f57cd5a73050e014e3e094aa0 in /"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:c56b7dabbc7aa730eeab07668bdcbd7e3d40855047ca9a0cc1bfed23a2486111"]}}
diff --git a/spec/fixtures/container_registry/tag_manifest.json b/spec/fixtures/container_registry/tag_manifest.json
deleted file mode 100644
index 1b6008e287..0000000000
--- a/spec/fixtures/container_registry/tag_manifest.json
+++ /dev/null
@@ -1 +0,0 @@
-{"schemaVersion":2,"mediaType":"application/vnd.docker.distribution.manifest.v2+json","config":{"mediaType":"application/octet-stream","size":1145,"digest":"sha256:d7a513a663c1a6dcdba9ed832ca53c02ac2af0c333322cd6ca92936d1d9917ac"},"layers":[{"mediaType":"application/vnd.docker.image.rootfs.diff.tar.gzip","size":2319870,"digest":"sha256:420890c9e918b6668faaedd9000e220190f2493b0693ee563ebd7b4cc754a57d"}]}
diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb
index 34ce7c4f03..1772cc3f6a 100644
--- a/spec/fixtures/markdown.md.erb
+++ b/spec/fixtures/markdown.md.erb
@@ -216,14 +216,10 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
#### MilestoneReferenceFilter
-- Milestone by ID: <%= simple_milestone.to_reference %>
-- Milestone by name: <%= Milestone.reference_prefix %><%= simple_milestone.name %>
-- Milestone by name in quotes: <%= milestone.to_reference(format: :name) %>
+- Milestone: <%= milestone.to_reference %>
- Milestone in another project: <%= xmilestone.to_reference(project) %>
-- Ignored in code: `<%= simple_milestone.to_reference %>`
-- Ignored in links: [Link to <%= simple_milestone.to_reference %>](#milestone-link)
-- Milestone by URL: <%= urls.namespace_project_milestone_url(milestone.project.namespace, milestone.project, milestone) %>
-- Link to milestone by URL: [Milestone](<%= milestone.to_reference %>)
+- Ignored in code: `<%= milestone.to_reference %>`
+- Link to milestone by URL: [Milestone](<%= urls.namespace_project_milestone_url(milestone.project.namespace, milestone.project, milestone) %>)
### Task Lists
@@ -243,16 +239,3 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
- [[link-text|http://example.com/pdfs/gollum.pdf]]
- [[images/example.jpg]]
- [[http://example.com/images/example.jpg]]
-
-### Inline Diffs
-
-With inline diffs tags you can display {+ additions +} or [- deletions -].
-
-The wrapping tags can be either curly braces or square brackets [+ additions +] or {- deletions -}.
-
-However the wrapping tags can not be mixed as such -
-
-- {+ additions +]
-- [+ additions +}
-- {- delletions -]
-- [- delletions -}
diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
index 49ea4fa6d3..e47a54fdac 100644
--- a/spec/helpers/auth_helper_spec.rb
+++ b/spec/helpers/auth_helper_spec.rb
@@ -2,7 +2,7 @@ require "spec_helper"
describe AuthHelper do
describe "button_based_providers" do
- it 'returns all enabled providers from devise' do
+ it 'returns all enabled providers' do
allow(helper).to receive(:auth_providers) { [:twitter, :github] }
expect(helper.button_based_providers).to include(*[:twitter, :github])
end
@@ -17,49 +17,4 @@ describe AuthHelper do
expect(helper.button_based_providers).to eq([])
end
end
-
- describe 'enabled_button_based_providers' do
- before do
- allow(helper).to receive(:auth_providers) { [:twitter, :github] }
- end
-
- context 'all providers are enabled to sign in' do
- it 'returns all the enabled providers from settings' do
- expect(helper.enabled_button_based_providers).to include('twitter', 'github')
- end
- end
-
- context 'GitHub OAuth sign in is disabled from application setting' do
- it "doesn't return github as provider" do
- stub_application_setting(
- disabled_oauth_sign_in_sources: ['github']
- )
-
- expect(helper.enabled_button_based_providers).to include('twitter')
- expect(helper.enabled_button_based_providers).not_to include('github')
- end
- end
- end
-
- describe 'button_based_providers_enabled?' do
- before do
- allow(helper).to receive(:auth_providers) { [:twitter, :github] }
- end
-
- context 'button based providers enabled' do
- it 'returns true' do
- expect(helper.button_based_providers_enabled?).to be true
- end
- end
-
- context 'all the button based providers are disabled via application_setting' do
- it 'returns false' do
- stub_application_setting(
- disabled_oauth_sign_in_sources: ['github', 'twitter']
- )
-
- expect(helper.button_based_providers_enabled?).to be false
- end
- end
- end
end
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index 52764f41e0..b7810185d1 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -93,9 +93,9 @@ describe DiffHelper do
it "returns strings with marked inline diffs" do
marked_old_line, marked_new_line = mark_inline_diffs(old_line, new_line)
- expect(marked_old_line).to eq("abc 'def'")
+ expect(marked_old_line).to eq("abc 'def'")
expect(marked_old_line).to be_html_safe
- expect(marked_new_line).to eq("abc "def"")
+ expect(marked_new_line).to eq("abc "def"")
expect(marked_new_line).to be_html_safe
end
end
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index c0d2be98e8..e68a5ec29a 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -1,65 +1,64 @@
require 'spec_helper'
describe EventsHelper do
- describe '#event_note' do
- before do
- allow(helper).to receive(:current_user).and_return(double)
- end
+ include ApplicationHelper
+ include GitlabMarkdownHelper
- it 'should display one line of plain text without alteration' do
- input = 'A short, plain note'
- expect(helper.event_note(input)).to match(input)
- expect(helper.event_note(input)).not_to match(/\.\.\.\z/)
- end
+ let(:current_user) { create(:user, email: "current@email.com") }
- it 'should display inline code' do
- input = 'A note with `inline code`'
- expected = 'A note with inline code'
+ it 'should display one line of plain text without alteration' do
+ input = 'A short, plain note'
+ expect(event_note(input)).to match(input)
+ expect(event_note(input)).not_to match(/\.\.\.\z/)
+ end
- expect(helper.event_note(input)).to match(expected)
- end
+ it 'should display inline code' do
+ input = 'A note with `inline code`'
+ expected = 'A note with inline code'
- it 'should truncate a note with multiple paragraphs' do
- input = "Paragraph 1\n\nParagraph 2"
- expected = 'Paragraph 1...'
+ expect(event_note(input)).to match(expected)
+ end
- expect(helper.event_note(input)).to match(expected)
- end
+ it 'should truncate a note with multiple paragraphs' do
+ input = "Paragraph 1\n\nParagraph 2"
+ expected = 'Paragraph 1...'
- it 'should display the first line of a code block' do
- input = "```\nCode block\nwith two lines\n```"
- expected = %r{Code block\.\.\.}
+ expect(event_note(input)).to match(expected)
+ end
- expect(helper.event_note(input)).to match(expected)
- end
+ it 'should display the first line of a code block' do
+ input = "```\nCode block\nwith two lines\n```"
+ expected = %r{Code block\.\.\.}
- it 'should truncate a single long line of text' do
- text = 'The quick brown fox jumped over the lazy dog twice' # 50 chars
- input = text * 4
- expected = (text * 2).sub(/.{3}/, '...')
+ expect(event_note(input)).to match(expected)
+ end
- expect(helper.event_note(input)).to match(expected)
- end
+ it 'should truncate a single long line of text' do
+ text = 'The quick brown fox jumped over the lazy dog twice' # 50 chars
+ input = "#{text}#{text}#{text}#{text}" # 200 chars
+ expected = "#{text}#{text}".sub(/.{3}/, '...')
- it 'should preserve a link href when link text is truncated' do
- text = 'The quick brown fox jumped over the lazy dog' # 44 chars
- input = "#{text}#{text}#{text} " # 133 chars
- link_url = 'http://example.com/foo/bar/baz' # 30 chars
- input << link_url
- expected_link_text = 'http://example...'
+ expect(event_note(input)).to match(expected)
+ end
- expect(helper.event_note(input)).to match(link_url)
- expect(helper.event_note(input)).to match(expected_link_text)
- end
+ it 'should preserve a link href when link text is truncated' do
+ text = 'The quick brown fox jumped over the lazy dog' # 44 chars
+ input = "#{text}#{text}#{text} " # 133 chars
+ link_url = 'http://example.com/foo/bar/baz' # 30 chars
+ input << link_url
+ expected_link_text = 'http://example...'
- it 'should preserve code color scheme' do
- input = "```ruby\ndef test\n 'hello world'\nend\n```"
- expected = '' \
- "def test\n" \
- " \'hello world\'\n" \
- "end" \
- '
'
- expect(helper.event_note(input)).to eq(expected)
- end
+ expect(event_note(input)).to match(link_url)
+ expect(event_note(input)).to match(expected_link_text)
+ end
+
+ it 'should preserve code color scheme' do
+ input = "```ruby\ndef test\n 'hello world'\nend\n```"
+ expected = '' \
+ "def test\n" \
+ " \'hello world\'\n" \
+ "end" \
+ '
'
+ expect(event_note(input)).to eq(expected)
end
end
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index 8e7ed42e88..600e1c4e9e 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -17,7 +17,7 @@ describe MergeRequestsHelper do
it 'does not include api credentials in a link' do
allow(ci_service).
to receive(:build_page).and_return("http://secretuser:secretpass@jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c")
- expect(helper.ci_build_details_path(merge_request)).not_to match("secret")
+ expect(helper.ci_build_details_path(merge_request)).to_not match("secret")
end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index ac5af8740d..29bcb8c589 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -88,18 +88,18 @@ describe ProjectsHelper do
end
describe 'default_clone_protocol' do
- context 'when user is not logged in and gitlab protocol is HTTP' do
+ describe 'using HTTP' do
it 'returns HTTP' do
- allow(helper).to receive(:current_user).and_return(nil)
+ expect(helper).to receive(:current_user).and_return(nil)
expect(helper.send(:default_clone_protocol)).to eq('http')
end
end
- context 'when user is not logged in and gitlab protocol is HTTPS' do
+ describe 'using HTTPS' do
it 'returns HTTPS' do
- stub_config_setting(protocol: 'https')
- allow(helper).to receive(:current_user).and_return(nil)
+ allow(Gitlab.config.gitlab).to receive(:protocol).and_return('https')
+ expect(helper).to receive(:current_user).and_return(nil)
expect(helper.send(:default_clone_protocol)).to eq('https')
end
diff --git a/spec/javascripts/fixtures/right_sidebar.html.haml b/spec/javascripts/fixtures/right_sidebar.html.haml
deleted file mode 100644
index 95efaff4b6..0000000000
--- a/spec/javascripts/fixtures/right_sidebar.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-%div
- %div.page-gutter.page-with-sidebar
-
- %aside.right-sidebar
- %div.block.issuable-sidebar-header
- %a.gutter-toggle.pull-right.js-sidebar-toggle
- %i.fa.fa-angle-double-left
-
- %form.issuable-context-form
- %div.block.labels
- %div.sidebar-collapsed-icon
- %i.fa.fa-tags
- %span 1
diff --git a/spec/javascripts/project_title_spec.js.coffee b/spec/javascripts/project_title_spec.js.coffee
index 1cf34d4d2d..3d8de2ff98 100644
--- a/spec/javascripts/project_title_spec.js.coffee
+++ b/spec/javascripts/project_title_spec.js.coffee
@@ -1,6 +1,5 @@
#= require bootstrap
#= require select2
-#= require lib/type_utility
#= require gl_dropdown
#= require api
#= require project_select
diff --git a/spec/javascripts/right_sidebar_spec.js.coffee b/spec/javascripts/right_sidebar_spec.js.coffee
deleted file mode 100644
index 2075cacdb6..0000000000
--- a/spec/javascripts/right_sidebar_spec.js.coffee
+++ /dev/null
@@ -1,69 +0,0 @@
-#= require right_sidebar
-#= require jquery
-#= require jquery.cookie
-
-@sidebar = null
-$aside = null
-$toggle = null
-$icon = null
-$page = null
-$labelsIcon = null
-
-
-assertSidebarState = (state) ->
-
- shouldBeExpanded = state is 'expanded'
- shouldBeCollapsed = state is 'collapsed'
-
- expect($aside.hasClass('right-sidebar-expanded')).toBe shouldBeExpanded
- expect($page.hasClass('right-sidebar-expanded')).toBe shouldBeExpanded
- expect($icon.hasClass('fa-angle-double-right')).toBe shouldBeExpanded
-
- expect($aside.hasClass('right-sidebar-collapsed')).toBe shouldBeCollapsed
- expect($page.hasClass('right-sidebar-collapsed')).toBe shouldBeCollapsed
- expect($icon.hasClass('fa-angle-double-left')).toBe shouldBeCollapsed
-
-
-describe 'RightSidebar', ->
-
- fixture.preload 'right_sidebar.html'
-
- beforeEach ->
- fixture.load 'right_sidebar.html'
-
- @sidebar = new Sidebar
- $aside = $ '.right-sidebar'
- $page = $ '.page-with-sidebar'
- $icon = $aside.find 'i'
- $toggle = $aside.find '.js-sidebar-toggle'
- $labelsIcon = $aside.find '.sidebar-collapsed-icon'
-
-
- it 'should expand the sidebar when arrow is clicked', ->
-
- $toggle.click()
- assertSidebarState 'expanded'
-
-
- it 'should collapse the sidebar when arrow is clicked', ->
-
- $toggle.click()
- assertSidebarState 'expanded'
-
- $toggle.click()
- assertSidebarState 'collapsed'
-
-
- it 'should float over the page and when sidebar icons clicked', ->
-
- $labelsIcon.click()
- assertSidebarState 'expanded'
-
-
- it 'should collapse when the icon arrow clicked while it is floating on page', ->
-
- $labelsIcon.click()
- assertSidebarState 'expanded'
-
- $toggle.click()
- assertSidebarState 'collapsed'
diff --git a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js b/spec/javascripts/stat_graph_contributors_graph_spec.js
similarity index 98%
rename from spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
rename to spec/javascripts/stat_graph_contributors_graph_spec.js
index 82ee1954a5..78d39f1b42 100644
--- a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
+++ b/spec/javascripts/stat_graph_contributors_graph_spec.js
@@ -1,4 +1,4 @@
-//= require graphs/stat_graph_contributors_graph
+//= require stat_graph_contributors_graph
describe("ContributorsGraph", function () {
describe("#set_x_domain", function () {
diff --git a/spec/javascripts/graphs/stat_graph_contributors_util_spec.js b/spec/javascripts/stat_graph_contributors_util_spec.js
similarity index 99%
rename from spec/javascripts/graphs/stat_graph_contributors_util_spec.js
rename to spec/javascripts/stat_graph_contributors_util_spec.js
index 5b99244747..dbafe782b7 100644
--- a/spec/javascripts/graphs/stat_graph_contributors_util_spec.js
+++ b/spec/javascripts/stat_graph_contributors_util_spec.js
@@ -1,4 +1,4 @@
-//= require graphs/stat_graph_contributors_util
+//= require stat_graph_contributors_util
describe("ContributorsStatGraphUtil", function () {
diff --git a/spec/javascripts/graphs/stat_graph_spec.js b/spec/javascripts/stat_graph_spec.js
similarity index 92%
rename from spec/javascripts/graphs/stat_graph_spec.js
rename to spec/javascripts/stat_graph_spec.js
index 4b05d401a4..4c652910cd 100644
--- a/spec/javascripts/graphs/stat_graph_spec.js
+++ b/spec/javascripts/stat_graph_spec.js
@@ -1,4 +1,4 @@
-//= require graphs/stat_graph
+//= require stat_graph
describe("StatGraph", function () {
diff --git a/spec/lib/award_emoji_spec.rb b/spec/lib/award_emoji_spec.rb
index c309857429..88c2291295 100644
--- a/spec/lib/award_emoji_spec.rb
+++ b/spec/lib/award_emoji_spec.rb
@@ -5,7 +5,7 @@ describe AwardEmoji do
subject { AwardEmoji.urls }
it { is_expected.to be_an_instance_of(Array) }
- it { is_expected.not_to be_empty }
+ it { is_expected.to_not be_empty }
context 'every Hash in the Array' do
it 'has the correct keys and values' do
diff --git a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
index 593bd6d5ca..c2a8ad36c3 100644
--- a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
@@ -98,6 +98,11 @@ describe Banzai::Filter::CommitRangeReferenceFilter, lib: true do
expect(link).not_to match %r(https?://)
expect(link).to eq urls.namespace_project_compare_url(project.namespace, project, from: commit1.id, to: commit2.id, only_path: true)
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("See #{reference}")
+ expect(result[:references][:commit_range]).not_to be_empty
+ end
end
context 'cross-project reference' do
@@ -130,6 +135,11 @@ describe Banzai::Filter::CommitRangeReferenceFilter, lib: true do
exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}"
expect(reference_filter(act).to_html).to eq exp
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("See #{reference}")
+ expect(result[:references][:commit_range]).not_to be_empty
+ end
end
context 'cross-project URL reference' do
@@ -163,5 +173,10 @@ describe Banzai::Filter::CommitRangeReferenceFilter, lib: true do
exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}"
expect(reference_filter(act).to_html).to eq exp
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("See #{reference}")
+ expect(result[:references][:commit_range]).not_to be_empty
+ end
end
end
diff --git a/spec/lib/banzai/filter/commit_reference_filter_spec.rb b/spec/lib/banzai/filter/commit_reference_filter_spec.rb
index d46d3f1489..63a32d9d45 100644
--- a/spec/lib/banzai/filter/commit_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/commit_reference_filter_spec.rb
@@ -93,6 +93,11 @@ describe Banzai::Filter::CommitReferenceFilter, lib: true do
expect(link).not_to match %r(https?://)
expect(link).to eq urls.namespace_project_commit_url(project.namespace, project, reference, only_path: true)
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("See #{reference}")
+ expect(result[:references][:commit]).not_to be_empty
+ end
end
context 'cross-project reference' do
@@ -119,6 +124,11 @@ describe Banzai::Filter::CommitReferenceFilter, lib: true do
exp = act = "Committed #{invalidate_reference(reference)}"
expect(reference_filter(act).to_html).to eq exp
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("See #{reference}")
+ expect(result[:references][:commit]).not_to be_empty
+ end
end
context 'cross-project URL reference' do
@@ -144,5 +154,10 @@ describe Banzai::Filter::CommitReferenceFilter, lib: true do
act = "Committed #{invalidate_reference(reference)}"
expect(reference_filter(act).to_html).to match(/#{Regexp.escape(invalidate_reference(reference))}<\/a>/)
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("See #{reference}")
+ expect(result[:references][:commit]).not_to be_empty
+ end
end
end
diff --git a/spec/lib/banzai/filter/inline_diff_filter_spec.rb b/spec/lib/banzai/filter/inline_diff_filter_spec.rb
deleted file mode 100644
index 9e52637129..0000000000
--- a/spec/lib/banzai/filter/inline_diff_filter_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::Filter::InlineDiffFilter, lib: true do
- include FilterSpecHelper
-
- it 'adds inline diff span tags for deletions when using square brackets' do
- doc = "START [-something deleted-] END"
- expect(filter(doc).to_html).to eq('START something deleted END')
- end
-
- it 'adds inline diff span tags for deletions when using curley braces' do
- doc = "START {-something deleted-} END"
- expect(filter(doc).to_html).to eq('START something deleted END')
- end
-
- it 'does not add inline diff span tags when a closing tag is not provided' do
- doc = "START [- END"
- expect(filter(doc).to_html).to eq(doc)
- end
-
- it 'adds inline span tags for additions when using square brackets' do
- doc = "START [+something added+] END"
- expect(filter(doc).to_html).to eq('START something added END')
- end
-
- it 'adds inline span tags for additions when using curley braces' do
- doc = "START {+something added+} END"
- expect(filter(doc).to_html).to eq('START something added END')
- end
-
- it 'does not add inline diff span tags when a closing addition tag is not provided' do
- doc = "START {+ END"
- expect(filter(doc).to_html).to eq(doc)
- end
-
- it 'does not add inline diff span tags when the tags do not match' do
- examples = [
- "{+ additions +]",
- "[+ additions +}",
- "{- delletions -]",
- "[- delletions -}"
- ]
-
- examples.each do |doc|
- expect(filter(doc).to_html).to eq(doc)
- end
- end
-
- it 'prevents user-land html being injected' do
- doc = "START {+<script>alert('I steal cookies')</script>+} END"
- expect(filter(doc).to_html).to eq("START <script>alert('I steal cookies')</script> END")
- end
-
- it 'preserves content inside pre tags' do
- doc = "START {+something added+} END"
- expect(filter(doc).to_html).to eq(doc)
- end
-
- it 'preserves content inside code tags' do
- doc = "START {+something added+} END"
- expect(filter(doc).to_html).to eq(doc)
- end
-
- it 'preserves content inside tt tags' do
- doc = "START {+something added+} END"
- expect(filter(doc).to_html).to eq(doc)
- end
-end
diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
index 8e6a264970..266ebef33d 100644
--- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
@@ -91,6 +91,11 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do
expect(link).to eq helper.url_for_issue(issue.iid, project, only_path: true)
end
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Fixed #{reference}")
+ expect(result[:references][:issue]).to eq [issue]
+ end
+
it 'does not process links containing issue numbers followed by text' do
href = "#{reference}st"
doc = reference_filter("")
@@ -131,6 +136,11 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do
expect(reference_filter(act).to_html).to eq exp
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Fixed #{reference}")
+ expect(result[:references][:issue]).to eq [issue]
+ end
end
context 'cross-project URL reference' do
@@ -150,6 +160,11 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do
doc = reference_filter("Fixed (#{reference}.)")
expect(doc.to_html).to match(/\(#{Regexp.escape(issue.to_reference(project))} \(comment 123\)<\/a>\.\)/)
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Fixed #{reference}")
+ expect(result[:references][:issue]).to eq [issue]
+ end
end
context 'cross-project reference in link href' do
@@ -169,6 +184,11 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do
doc = reference_filter("Fixed (#{reference}.)")
expect(doc.to_html).to match(/\(Reference<\/a>\.\)/)
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Fixed #{reference}")
+ expect(result[:references][:issue]).to eq [issue]
+ end
end
context 'cross-project URL in link href' do
@@ -188,5 +208,10 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do
doc = reference_filter("Fixed (#{reference}.)")
expect(doc.to_html).to match(/\(Reference<\/a>\.\)/)
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Fixed #{reference}")
+ expect(result[:references][:issue]).to eq [issue]
+ end
end
end
diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb
index f1064a701d..b0a38e7c25 100644
--- a/spec/lib/banzai/filter/label_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/label_reference_filter_spec.rb
@@ -48,6 +48,11 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do
expect(link).to eq urls.namespace_project_issues_path(project.namespace, project, label_name: label.name)
end
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Label #{reference}")
+ expect(result[:references][:label]).to eq [label]
+ end
+
describe 'label span element' do
it 'includes default classes' do
doc = reference_filter("Label #{reference}")
@@ -165,6 +170,11 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do
expect(link).to have_attribute('data-label')
expect(link.attr('data-label')).to eq label.id.to_s
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Label #{reference}")
+ expect(result[:references][:label]).to eq [label]
+ end
end
describe 'cross project label references' do
diff --git a/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb b/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb
index 3185e41fe5..352710df30 100644
--- a/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb
@@ -78,6 +78,11 @@ describe Banzai::Filter::MergeRequestReferenceFilter, lib: true do
expect(link).not_to match %r(https?://)
expect(link).to eq urls.namespace_project_merge_request_url(project.namespace, project, merge, only_path: true)
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Merge #{reference}")
+ expect(result[:references][:merge_request]).to eq [merge]
+ end
end
context 'cross-project reference' do
@@ -104,6 +109,11 @@ describe Banzai::Filter::MergeRequestReferenceFilter, lib: true do
expect(reference_filter(act).to_html).to eq exp
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Merge #{reference}")
+ expect(result[:references][:merge_request]).to eq [merge]
+ end
end
context 'cross-project URL reference' do
@@ -123,5 +133,10 @@ describe Banzai::Filter::MergeRequestReferenceFilter, lib: true do
doc = reference_filter("Merge (#{reference}.)")
expect(doc.to_html).to match(/\(#{Regexp.escape(merge.to_reference(project))} \(diffs, comment 123\)<\/a>\.\)/)
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Merge #{reference}")
+ expect(result[:references][:merge_request]).to eq [merge]
+ end
end
end
diff --git a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
index 9424f2363e..ebf3d7489b 100644
--- a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
@@ -3,9 +3,8 @@ require 'spec_helper'
describe Banzai::Filter::MilestoneReferenceFilter, lib: true do
include FilterSpecHelper
- let(:project) { create(:project, :public) }
- let(:milestone) { create(:milestone, project: project) }
- let(:reference) { milestone.to_reference }
+ let(:project) { create(:project, :public) }
+ let(:milestone) { create(:milestone, project: project) }
it 'requires project context' do
expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
@@ -18,106 +17,10 @@ describe Banzai::Filter::MilestoneReferenceFilter, lib: true do
end
end
- it 'includes default classes' do
- doc = reference_filter("Milestone #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-milestone'
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Milestone #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-milestone attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-milestone')
- expect(link.attr('data-milestone')).to eq milestone.id.to_s
- end
-
- it 'supports an :only_path context' do
- doc = reference_filter("Milestone #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).not_to match %r(https?://)
- expect(link).to eq urls.
- namespace_project_milestone_path(project.namespace, project, milestone)
- end
-
- context 'Integer-based references' do
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.
- namespace_project_milestone_url(project.namespace, project, milestone)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Milestone (#{reference}.)")
- expect(doc.to_html).to match(%r(\(#{milestone.name}\.\)))
- end
-
- it 'ignores invalid milestone IIDs' do
- exp = act = "Milestone #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'String-based single-word references' do
- let(:milestone) { create(:milestone, name: 'gfm', project: project) }
- let(:reference) { "#{Milestone.reference_prefix}#{milestone.name}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.
- namespace_project_milestone_url(project.namespace, project, milestone)
- expect(doc.text).to eq 'See gfm'
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Milestone (#{reference}.)")
- expect(doc.to_html).to match(%r(\(#{milestone.name}\.\)))
- end
-
- it 'ignores invalid milestone names' do
- exp = act = "Milestone #{Milestone.reference_prefix}#{milestone.name.reverse}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'String-based multi-word references in quotes' do
- let(:milestone) { create(:milestone, name: 'gfm references', project: project) }
- let(:reference) { milestone.to_reference(format: :name) }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.
- namespace_project_milestone_url(project.namespace, project, milestone)
- expect(doc.text).to eq 'See gfm references'
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Milestone (#{reference}.)")
- expect(doc.to_html).to match(%r(\(#{milestone.name}\.\)))
- end
-
- it 'ignores invalid milestone names' do
- exp = act = %(Milestone #{Milestone.reference_prefix}"#{milestone.name.reverse}")
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- describe 'referencing a milestone in a link href' do
- let(:reference) { %Q{Milestone} }
+ context 'internal reference' do
+ # Convert the Markdown link to only the URL, since these tests aren't run through the regular Markdown pipeline.
+ # Milestone reference behavior in the full Markdown pipeline is tested elsewhere.
+ let(:reference) { milestone.to_reference.gsub(/\[([^\]]+)\]\(([^)]+)\)/, '\2') }
it 'links to a valid reference' do
doc = reference_filter("See #{reference}")
@@ -127,12 +30,29 @@ describe Banzai::Filter::MilestoneReferenceFilter, lib: true do
end
it 'links with adjacent text' do
- doc = reference_filter("Milestone (#{reference}.)")
- expect(doc.to_html).to match(%r(\(Milestone\.\)))
+ doc = reference_filter("milestone (#{reference}.)")
+ expect(doc.to_html).to match(/\(#{Regexp.escape(milestone.title)}<\/a>\.\)/)
+ end
+
+ it 'includes a title attribute' do
+ doc = reference_filter("milestone #{reference}")
+ expect(doc.css('a').first.attr('title')).to eq "Milestone: #{milestone.title}"
+ end
+
+ it 'escapes the title attribute' do
+ milestone.update_attribute(:title, %{">whateverwhateverText)
- exp = 'Text'
- expect(filter(act).to_html).to eq exp
- end
-
it 'allows whitelisted HTML tags from the user' do
exp = act = "\n- Term
\n- Definition
\n
"
expect(filter(act).to_html).to eq exp
diff --git a/spec/lib/banzai/filter/snippet_reference_filter_spec.rb b/spec/lib/banzai/filter/snippet_reference_filter_spec.rb
index 5068ddd7fa..26466fbb18 100644
--- a/spec/lib/banzai/filter/snippet_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/snippet_reference_filter_spec.rb
@@ -77,6 +77,11 @@ describe Banzai::Filter::SnippetReferenceFilter, lib: true do
expect(link).not_to match %r(https?://)
expect(link).to eq urls.namespace_project_snippet_url(project.namespace, project, snippet, only_path: true)
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Snippet #{reference}")
+ expect(result[:references][:snippet]).to eq [snippet]
+ end
end
context 'cross-project reference' do
@@ -102,6 +107,11 @@ describe Banzai::Filter::SnippetReferenceFilter, lib: true do
expect(reference_filter(act).to_html).to eq exp
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Snippet #{reference}")
+ expect(result[:references][:snippet]).to eq [snippet]
+ end
end
context 'cross-project URL reference' do
@@ -127,5 +137,10 @@ describe Banzai::Filter::SnippetReferenceFilter, lib: true do
expect(reference_filter(act).to_html).to match(/#{Regexp.escape(invalidate_reference(reference))}<\/a>/)
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Snippet #{reference}")
+ expect(result[:references][:snippet]).to eq [snippet]
+ end
end
end
diff --git a/spec/lib/banzai/filter/upload_link_filter_spec.rb b/spec/lib/banzai/filter/upload_link_filter_spec.rb
index b83be54746..3b073a90a9 100644
--- a/spec/lib/banzai/filter/upload_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/upload_link_filter_spec.rb
@@ -8,10 +8,6 @@ describe Banzai::Filter::UploadLinkFilter, lib: true do
project: project
})
- raw_filter(doc, contexts)
- end
-
- def raw_filter(doc, contexts = {})
described_class.call(doc, contexts)
end
@@ -74,18 +70,4 @@ describe Banzai::Filter::UploadLinkFilter, lib: true do
expect(doc.at_css('img')['src']).to match "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/%ED%95%9C%EA%B8%80.png"
end
end
-
- context 'when project context does not exist' do
- let(:upload_link) { link('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg') }
-
- it 'does not raise error' do
- expect { raw_filter(upload_link, project: nil) }.not_to raise_error
- end
-
- it 'does not rewrite link' do
- doc = raw_filter(upload_link, project: nil)
-
- expect(doc.to_html).to eq upload_link
- end
- end
end
diff --git a/spec/lib/banzai/filter/user_reference_filter_spec.rb b/spec/lib/banzai/filter/user_reference_filter_spec.rb
index d7dfd6699e..8bdebae184 100644
--- a/spec/lib/banzai/filter/user_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/user_reference_filter_spec.rb
@@ -31,22 +31,28 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do
end
it 'supports a special @all mention' do
- doc = reference_filter("Hey #{reference}", author: user)
+ doc = reference_filter("Hey #{reference}")
expect(doc.css('a').length).to eq 1
expect(doc.css('a').first.attr('href'))
.to eq urls.namespace_project_url(project.namespace, project)
end
- it 'includes a data-author attribute when there is an author' do
- doc = reference_filter(reference, author: user)
+ context "when the author is a member of the project" do
- expect(doc.css('a').first.attr('data-author')).to eq(user.id.to_s)
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Hey #{reference}", author: project.creator)
+ expect(result[:references][:user]).to eq [project.creator]
+ end
end
- it 'does not include a data-author attribute when there is no author' do
- doc = reference_filter(reference)
+ context "when the author is not a member of the project" do
- expect(doc.css('a').first.has_attribute?('data-author')).to eq(false)
+ let(:other_user) { create(:user) }
+
+ it "doesn't add to the results hash" do
+ result = reference_pipeline_result("Hey #{reference}", author: other_user)
+ expect(result[:references][:user]).to eq []
+ end
end
end
@@ -77,6 +83,11 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do
expect(link).to have_attribute('data-user')
expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Hey #{reference}")
+ expect(result[:references][:user]).to eq [user]
+ end
end
context 'mentioning a group' do
@@ -95,6 +106,11 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do
expect(link).to have_attribute('data-group')
expect(link.attr('data-group')).to eq group.id.to_s
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Hey #{reference}")
+ expect(result[:references][:user]).to eq group.users
+ end
end
it 'links with adjacent text' do
@@ -135,5 +151,10 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do
expect(link).to have_attribute('data-user')
expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s
end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Hey #{reference}")
+ expect(result[:references][:user]).to eq [user]
+ end
end
end
diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
deleted file mode 100644
index 185abbb210..0000000000
--- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::Filter::WikiLinkFilter, lib: true do
- include FilterSpecHelper
-
- let(:namespace) { build_stubbed(:namespace, name: "wiki_link_ns") }
- let(:project) { build_stubbed(:empty_project, :public, name: "wiki_link_project", namespace: namespace) }
- let(:user) { double }
- let(:project_wiki) { ProjectWiki.new(project, user) }
-
- describe "links within the wiki (relative)" do
- describe "hierarchical links to the current directory" do
- it "doesn't rewrite non-file links" do
- link = "Link to Page"
- filtered_link = filter(link, project_wiki: project_wiki).children[0]
-
- expect(filtered_link.attribute('href').value).to eq('./page')
- end
-
- it "doesn't rewrite file links" do
- link = "Link to Page"
- filtered_link = filter(link, project_wiki: project_wiki).children[0]
-
- expect(filtered_link.attribute('href').value).to eq('./page.md')
- end
- end
-
- describe "hierarchical links to the parent directory" do
- it "doesn't rewrite non-file links" do
- link = "Link to Page"
- filtered_link = filter(link, project_wiki: project_wiki).children[0]
-
- expect(filtered_link.attribute('href').value).to eq('../page')
- end
-
- it "doesn't rewrite file links" do
- link = "Link to Page"
- filtered_link = filter(link, project_wiki: project_wiki).children[0]
-
- expect(filtered_link.attribute('href').value).to eq('../page.md')
- end
- end
-
- describe "hierarchical links to a sub-directory" do
- it "doesn't rewrite non-file links" do
- link = "Link to Page"
- filtered_link = filter(link, project_wiki: project_wiki).children[0]
-
- expect(filtered_link.attribute('href').value).to eq('./subdirectory/page')
- end
-
- it "doesn't rewrite file links" do
- link = "Link to Page"
- filtered_link = filter(link, project_wiki: project_wiki).children[0]
-
- expect(filtered_link.attribute('href').value).to eq('./subdirectory/page.md')
- end
- end
-
- describe "non-hierarchical links" do
- it 'rewrites non-file links to be at the scope of the wiki root' do
- link = "Link to Page"
- filtered_link = filter(link, project_wiki: project_wiki).children[0]
-
- expect(filtered_link.attribute('href').value).to match('/wiki_link_ns/wiki_link_project/wikis/page')
- end
-
- it "doesn't rewrite file links" do
- link = "Link to Page"
- filtered_link = filter(link, project_wiki: project_wiki).children[0]
-
- expect(filtered_link.attribute('href').value).to eq('page.md')
- end
- end
- end
-
- describe "links outside the wiki (absolute)" do
- it "doesn't rewrite links" do
- link = "Link to Page"
- filtered_link = filter(link, project_wiki: project_wiki).children[0]
-
- expect(filtered_link.attribute('href').value).to eq('http://example.com/page')
- end
- end
-end
diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb
deleted file mode 100644
index 543b4786d8..0000000000
--- a/spec/lib/banzai/reference_parser/base_parser_spec.rb
+++ /dev/null
@@ -1,237 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::ReferenceParser::BaseParser, lib: true do
- include ReferenceParserHelpers
-
- let(:user) { create(:user) }
- let(:project) { create(:empty_project, :public) }
-
- subject do
- klass = Class.new(described_class) do
- self.reference_type = :foo
- end
-
- klass.new(project, user)
- end
-
- describe '.reference_type=' do
- it 'sets the reference type' do
- dummy = Class.new(described_class)
- dummy.reference_type = :foo
-
- expect(dummy.reference_type).to eq(:foo)
- end
- end
-
- describe '#nodes_visible_to_user' do
- let(:link) { empty_html_link }
-
- context 'when the link has a data-project attribute' do
- it 'returns the nodes if the attribute value equals the current project ID' do
- link['data-project'] = project.id.to_s
-
- expect(Ability.abilities).not_to receive(:allowed?)
- expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
- end
-
- it 'returns the nodes if the user can read the project' do
- other_project = create(:empty_project, :public)
-
- link['data-project'] = other_project.id.to_s
-
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_project, other_project).
- and_return(true)
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
- end
-
- it 'returns an empty Array when the attribute value is empty' do
- link['data-project'] = ''
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([])
- end
-
- it 'returns an empty Array when the user can not read the project' do
- other_project = create(:empty_project, :public)
-
- link['data-project'] = other_project.id.to_s
-
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_project, other_project).
- and_return(false)
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([])
- end
- end
-
- context 'when the link does not have a data-project attribute' do
- it 'returns the nodes' do
- expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
- end
- end
- end
-
- describe '#nodes_user_can_reference' do
- it 'returns the nodes' do
- link = double(:link)
-
- expect(subject.nodes_user_can_reference(user, [link])).to eq([link])
- end
- end
-
- describe '#referenced_by' do
- context 'when references_relation is implemented' do
- it 'returns a collection of objects' do
- links = Nokogiri::HTML.fragment("").
- children
-
- expect(subject).to receive(:references_relation).and_return(User)
- expect(subject.referenced_by(links)).to eq([user])
- end
- end
-
- context 'when references_relation is not implemented' do
- it 'raises NotImplementedError' do
- links = Nokogiri::HTML.fragment('').children
-
- expect { subject.referenced_by(links) }.
- to raise_error(NotImplementedError)
- end
- end
- end
-
- describe '#references_relation' do
- it 'raises NotImplementedError' do
- expect { subject.references_relation }.to raise_error(NotImplementedError)
- end
- end
-
- describe '#gather_attributes_per_project' do
- it 'returns a Hash containing attribute values per project' do
- link = Nokogiri::HTML.fragment('').
- children[0]
-
- hash = subject.gather_attributes_per_project([link], 'data-foo')
-
- expect(hash).to be_an_instance_of(Hash)
-
- expect(hash[1].to_a).to eq(['2'])
- end
- end
-
- describe '#grouped_objects_for_nodes' do
- it 'returns a Hash grouping objects per ID' do
- nodes = [double(:node)]
-
- expect(subject).to receive(:unique_attribute_values).
- with(nodes, 'data-user').
- and_return([user.id])
-
- hash = subject.grouped_objects_for_nodes(nodes, User, 'data-user')
-
- expect(hash).to eq({ user.id => user })
- end
-
- it 'returns an empty Hash when the list of nodes is empty' do
- expect(subject.grouped_objects_for_nodes([], User, 'data-user')).to eq({})
- end
- end
-
- describe '#unique_attribute_values' do
- it 'returns an Array of unique values' do
- link = double(:link)
-
- expect(link).to receive(:has_attribute?).
- with('data-foo').
- twice.
- and_return(true)
-
- expect(link).to receive(:attr).
- with('data-foo').
- twice.
- and_return('1')
-
- nodes = [link, link]
-
- expect(subject.unique_attribute_values(nodes, 'data-foo')).to eq(['1'])
- end
- end
-
- describe '#process' do
- it 'gathers the references for every node matching the reference type' do
- dummy = Class.new(described_class) do
- self.reference_type = :test
- end
-
- instance = dummy.new(project, user)
- document = Nokogiri::HTML.fragment('')
-
- expect(instance).to receive(:gather_references).
- with([document.children[1]]).
- and_return([user])
-
- expect(instance.process([document])).to eq([user])
- end
- end
-
- describe '#gather_references' do
- let(:link) { double(:link) }
-
- it 'does not process links a user can not reference' do
- expect(subject).to receive(:nodes_user_can_reference).
- with(user, [link]).
- and_return([])
-
- expect(subject).to receive(:referenced_by).with([])
-
- subject.gather_references([link])
- end
-
- it 'does not process links a user can not see' do
- expect(subject).to receive(:nodes_user_can_reference).
- with(user, [link]).
- and_return([link])
-
- expect(subject).to receive(:nodes_visible_to_user).
- with(user, [link]).
- and_return([])
-
- expect(subject).to receive(:referenced_by).with([])
-
- subject.gather_references([link])
- end
-
- it 'returns the references if a user can reference and see a link' do
- expect(subject).to receive(:nodes_user_can_reference).
- with(user, [link]).
- and_return([link])
-
- expect(subject).to receive(:nodes_visible_to_user).
- with(user, [link]).
- and_return([link])
-
- expect(subject).to receive(:referenced_by).with([link])
-
- subject.gather_references([link])
- end
- end
-
- describe '#can?' do
- it 'delegates the permissions check to the Ability class' do
- user = double(:user)
-
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_project, project)
-
- subject.can?(user, :read_project, project)
- end
- end
-
- describe '#find_projects_for_hash_keys' do
- it 'returns a list of Projects' do
- expect(subject.find_projects_for_hash_keys(project.id => project)).
- to eq([project])
- end
- end
-end
diff --git a/spec/lib/banzai/reference_parser/commit_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_parser_spec.rb
deleted file mode 100644
index 0b76d29fce..0000000000
--- a/spec/lib/banzai/reference_parser/commit_parser_spec.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::ReferenceParser::CommitParser, lib: true do
- include ReferenceParserHelpers
-
- let(:project) { create(:empty_project, :public) }
- let(:user) { create(:user) }
- subject { described_class.new(project, user) }
- let(:link) { empty_html_link }
-
- describe '#referenced_by' do
- context 'when the link has a data-project attribute' do
- before do
- link['data-project'] = project.id.to_s
- end
-
- context 'when the link has a data-commit attribute' do
- before do
- link['data-commit'] = '123'
- end
-
- it 'returns an Array of commits' do
- commit = double(:commit)
-
- allow_any_instance_of(Project).to receive(:valid_repo?).
- and_return(true)
-
- expect(subject).to receive(:find_commits).
- with(project, ['123']).
- and_return([commit])
-
- expect(subject.referenced_by([link])).to eq([commit])
- end
-
- it 'returns an empty Array when the commit could not be found' do
- allow_any_instance_of(Project).to receive(:valid_repo?).
- and_return(true)
-
- expect(subject).to receive(:find_commits).
- with(project, ['123']).
- and_return([])
-
- expect(subject.referenced_by([link])).to eq([])
- end
-
- it 'skips projects without valid repositories' do
- allow_any_instance_of(Project).to receive(:valid_repo?).
- and_return(false)
-
- expect(subject.referenced_by([link])).to eq([])
- end
- end
-
- context 'when the link does not have a data-commit attribute' do
- it 'returns an empty Array' do
- allow_any_instance_of(Project).to receive(:valid_repo?).
- and_return(true)
-
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
-
- context 'when the link does not have a data-project attribute' do
- it 'returns an empty Array' do
- allow_any_instance_of(Project).to receive(:valid_repo?).
- and_return(true)
-
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
-
- describe '#commit_ids_per_project' do
- before do
- link['data-project'] = project.id.to_s
- end
-
- it 'returns a Hash containing commit IDs per project' do
- link['data-commit'] = '123'
-
- hash = subject.commit_ids_per_project([link])
-
- expect(hash).to be_an_instance_of(Hash)
-
- expect(hash[project.id].to_a).to eq(['123'])
- end
-
- it 'does not add a project when the data-commit attribute is empty' do
- hash = subject.commit_ids_per_project([link])
-
- expect(hash).to be_empty
- end
- end
-
- describe '#find_commits' do
- it 'returns an Array of commit objects' do
- commit = double(:commit)
-
- expect(project).to receive(:commit).with('123').and_return(commit)
- expect(project).to receive(:valid_repo?).and_return(true)
-
- expect(subject.find_commits(project, %w{123})).to eq([commit])
- end
-
- it 'skips commit IDs for which no commit could be found' do
- expect(project).to receive(:commit).with('123').and_return(nil)
- expect(project).to receive(:valid_repo?).and_return(true)
-
- expect(subject.find_commits(project, %w{123})).to eq([])
- end
- end
-end
diff --git a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb
deleted file mode 100644
index ba982f3854..0000000000
--- a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::ReferenceParser::CommitRangeParser, lib: true do
- include ReferenceParserHelpers
-
- let(:project) { create(:empty_project, :public) }
- let(:user) { create(:user) }
- subject { described_class.new(project, user) }
- let(:link) { empty_html_link }
-
- describe '#referenced_by' do
- context 'when the link has a data-project attribute' do
- before do
- link['data-project'] = project.id.to_s
- end
-
- context 'when the link as a data-commit-range attribute' do
- before do
- link['data-commit-range'] = '123..456'
- end
-
- it 'returns an Array of commit ranges' do
- range = double(:range)
-
- expect(subject).to receive(:find_object).
- with(project, '123..456').
- and_return(range)
-
- expect(subject.referenced_by([link])).to eq([range])
- end
-
- it 'returns an empty Array when the commit range could not be found' do
- expect(subject).to receive(:find_object).
- with(project, '123..456').
- and_return(nil)
-
- expect(subject.referenced_by([link])).to eq([])
- end
- end
-
- context 'when the link does not have a data-commit-range attribute' do
- it 'returns an empty Array' do
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
-
- context 'when the link does not have a data-project attribute' do
- it 'returns an empty Array' do
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
-
- describe '#commit_range_ids_per_project' do
- before do
- link['data-project'] = project.id.to_s
- end
-
- it 'returns a Hash containing range IDs per project' do
- link['data-commit-range'] = '123..456'
-
- hash = subject.commit_range_ids_per_project([link])
-
- expect(hash).to be_an_instance_of(Hash)
-
- expect(hash[project.id].to_a).to eq(['123..456'])
- end
-
- it 'does not add a project when the data-commit-range attribute is empty' do
- hash = subject.commit_range_ids_per_project([link])
-
- expect(hash).to be_empty
- end
- end
-
- describe '#find_ranges' do
- it 'returns an Array of range objects' do
- range = double(:commit)
-
- expect(subject).to receive(:find_object).
- with(project, '123..456').
- and_return(range)
-
- expect(subject.find_ranges(project, ['123..456'])).to eq([range])
- end
-
- it 'skips ranges that could not be found' do
- expect(subject).to receive(:find_object).
- with(project, '123..456').
- and_return(nil)
-
- expect(subject.find_ranges(project, ['123..456'])).to eq([])
- end
- end
-
- describe '#find_object' do
- let(:range) { double(:range) }
-
- before do
- expect(CommitRange).to receive(:new).and_return(range)
- end
-
- context 'when the range has valid commits' do
- it 'returns the commit range' do
- expect(range).to receive(:valid_commits?).and_return(true)
-
- expect(subject.find_object(project, '123..456')).to eq(range)
- end
- end
-
- context 'when the range does not have any valid commits' do
- it 'returns nil' do
- expect(range).to receive(:valid_commits?).and_return(false)
-
- expect(subject.find_object(project, '123..456')).to be_nil
- end
- end
- end
-end
diff --git a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb
deleted file mode 100644
index a6ef8394fe..0000000000
--- a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::ReferenceParser::ExternalIssueParser, lib: true do
- include ReferenceParserHelpers
-
- let(:project) { create(:empty_project, :public) }
- let(:user) { create(:user) }
- subject { described_class.new(project, user) }
- let(:link) { empty_html_link }
-
- describe '#referenced_by' do
- context 'when the link has a data-project attribute' do
- before do
- link['data-project'] = project.id.to_s
- end
-
- context 'when the link has a data-external-issue attribute' do
- it 'returns an Array of ExternalIssue instances' do
- link['data-external-issue'] = '123'
-
- refs = subject.referenced_by([link])
-
- expect(refs).to eq([ExternalIssue.new('123', project)])
- end
- end
-
- context 'when the link does not have a data-external-issue attribute' do
- it 'returns an empty Array' do
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
-
- context 'when the link does not have a data-project attribute' do
- it 'returns an empty Array' do
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
-
- describe '#issue_ids_per_project' do
- before do
- link['data-project'] = project.id.to_s
- end
-
- it 'returns a Hash containing range IDs per project' do
- link['data-external-issue'] = '123'
-
- hash = subject.issue_ids_per_project([link])
-
- expect(hash).to be_an_instance_of(Hash)
-
- expect(hash[project.id].to_a).to eq(['123'])
- end
-
- it 'does not add a project when the data-external-issue attribute is empty' do
- hash = subject.issue_ids_per_project([link])
-
- expect(hash).to be_empty
- end
- end
-end
diff --git a/spec/lib/banzai/reference_parser/issue_parser_spec.rb b/spec/lib/banzai/reference_parser/issue_parser_spec.rb
deleted file mode 100644
index 514c752546..0000000000
--- a/spec/lib/banzai/reference_parser/issue_parser_spec.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::ReferenceParser::IssueParser, lib: true do
- include ReferenceParserHelpers
-
- let(:project) { create(:empty_project, :public) }
- let(:user) { create(:user) }
- let(:issue) { create(:issue, project: project) }
- subject { described_class.new(project, user) }
- let(:link) { empty_html_link }
-
- describe '#nodes_visible_to_user' do
- context 'when the link has a data-issue attribute' do
- before do
- link['data-issue'] = issue.id.to_s
- end
-
- it 'returns the nodes when the user can read the issue' do
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_issue, issue).
- and_return(true)
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
- end
-
- it 'returns an empty Array when the user can not read the issue' do
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_issue, issue).
- and_return(false)
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([])
- end
- end
-
- context 'when the link does not have a data-issue attribute' do
- it 'returns an empty Array' do
- expect(subject.nodes_visible_to_user(user, [link])).to eq([])
- end
- end
-
- context 'when the project uses an external issue tracker' do
- it 'returns all nodes' do
- link = double(:link)
-
- expect(project).to receive(:external_issue_tracker).and_return(true)
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
- end
- end
- end
-
- describe '#referenced_by' do
- context 'when the link has a data-issue attribute' do
- context 'using an existing issue ID' do
- before do
- link['data-issue'] = issue.id.to_s
- end
-
- it 'returns an Array of issues' do
- expect(subject.referenced_by([link])).to eq([issue])
- end
-
- it 'returns an empty Array when the list of nodes is empty' do
- expect(subject.referenced_by([link])).to eq([issue])
- expect(subject.referenced_by([])).to eq([])
- end
- end
- end
- end
-
- describe '#issues_for_nodes' do
- it 'returns a Hash containing the issues for a list of nodes' do
- link['data-issue'] = issue.id.to_s
- nodes = [link]
-
- expect(subject.issues_for_nodes(nodes)).to eq({ issue.id => issue })
- end
- end
-end
diff --git a/spec/lib/banzai/reference_parser/label_parser_spec.rb b/spec/lib/banzai/reference_parser/label_parser_spec.rb
deleted file mode 100644
index 77fda47f0e..0000000000
--- a/spec/lib/banzai/reference_parser/label_parser_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::ReferenceParser::LabelParser, lib: true do
- include ReferenceParserHelpers
-
- let(:project) { create(:empty_project, :public) }
- let(:user) { create(:user) }
- let(:label) { create(:label, project: project) }
- subject { described_class.new(project, user) }
- let(:link) { empty_html_link }
-
- describe '#referenced_by' do
- describe 'when the link has a data-label attribute' do
- context 'using an existing label ID' do
- it 'returns an Array of labels' do
- link['data-label'] = label.id.to_s
-
- expect(subject.referenced_by([link])).to eq([label])
- end
- end
-
- context 'using a non-existing label ID' do
- it 'returns an empty Array' do
- link['data-label'] = ''
-
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
- end
-end
diff --git a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb
deleted file mode 100644
index cf89ad598e..0000000000
--- a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::ReferenceParser::MergeRequestParser, lib: true do
- include ReferenceParserHelpers
-
- let(:user) { create(:user) }
- let(:merge_request) { create(:merge_request) }
- subject { described_class.new(merge_request.target_project, user) }
- let(:link) { empty_html_link }
-
- describe '#referenced_by' do
- describe 'when the link has a data-merge-request attribute' do
- context 'using an existing merge request ID' do
- it 'returns an Array of merge requests' do
- link['data-merge-request'] = merge_request.id.to_s
-
- expect(subject.referenced_by([link])).to eq([merge_request])
- end
- end
-
- context 'using a non-existing merge request ID' do
- it 'returns an empty Array' do
- link['data-merge-request'] = ''
-
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
- end
-end
diff --git a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb
deleted file mode 100644
index 6aa45a22cc..0000000000
--- a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::ReferenceParser::MilestoneParser, lib: true do
- include ReferenceParserHelpers
-
- let(:project) { create(:empty_project, :public) }
- let(:user) { create(:user) }
- let(:milestone) { create(:milestone, project: project) }
- subject { described_class.new(project, user) }
- let(:link) { empty_html_link }
-
- describe '#referenced_by' do
- describe 'when the link has a data-milestone attribute' do
- context 'using an existing milestone ID' do
- it 'returns an Array of milestones' do
- link['data-milestone'] = milestone.id.to_s
-
- expect(subject.referenced_by([link])).to eq([milestone])
- end
- end
-
- context 'using a non-existing milestone ID' do
- it 'returns an empty Array' do
- link['data-milestone'] = ''
-
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
- end
-end
diff --git a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb
deleted file mode 100644
index 59127b7c5d..0000000000
--- a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::ReferenceParser::SnippetParser, lib: true do
- include ReferenceParserHelpers
-
- let(:project) { create(:empty_project, :public) }
- let(:user) { create(:user) }
- let(:snippet) { create(:snippet, project: project) }
- subject { described_class.new(project, user) }
- let(:link) { empty_html_link }
-
- describe '#referenced_by' do
- describe 'when the link has a data-snippet attribute' do
- context 'using an existing snippet ID' do
- it 'returns an Array of snippets' do
- link['data-snippet'] = snippet.id.to_s
-
- expect(subject.referenced_by([link])).to eq([snippet])
- end
- end
-
- context 'using a non-existing snippet ID' do
- it 'returns an empty Array' do
- link['data-snippet'] = ''
-
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
- end
-end
diff --git a/spec/lib/banzai/reference_parser/user_parser_spec.rb b/spec/lib/banzai/reference_parser/user_parser_spec.rb
deleted file mode 100644
index 9a82891297..0000000000
--- a/spec/lib/banzai/reference_parser/user_parser_spec.rb
+++ /dev/null
@@ -1,189 +0,0 @@
-require 'spec_helper'
-
-describe Banzai::ReferenceParser::UserParser, lib: true do
- include ReferenceParserHelpers
-
- let(:group) { create(:group) }
- let(:user) { create(:user) }
- let(:project) { create(:empty_project, :public, group: group, creator: user) }
- subject { described_class.new(project, user) }
- let(:link) { empty_html_link }
-
- describe '#referenced_by' do
- context 'when the link has a data-group attribute' do
- context 'using an existing group ID' do
- before do
- link['data-group'] = project.group.id.to_s
- end
-
- it 'returns the users of the group' do
- create(:group_member, group: group, user: user)
-
- expect(subject.referenced_by([link])).to eq([user])
- end
-
- it 'returns an empty Array when the group has no users' do
- expect(subject.referenced_by([link])).to eq([])
- end
- end
-
- context 'using a non-existing group ID' do
- it 'returns an empty Array' do
- link['data-group'] = ''
-
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
-
- context 'when the link has a data-user attribute' do
- it 'returns an Array of users' do
- link['data-user'] = user.id.to_s
-
- expect(subject.referenced_by([link])).to eq([user])
- end
- end
-
- context 'when the link has a data-project attribute' do
- context 'using an existing project ID' do
- let(:contributor) { create(:user) }
-
- before do
- project.team << [user, :developer]
- project.team << [contributor, :developer]
- end
-
- it 'returns the members of a project' do
- link['data-project'] = project.id.to_s
-
- # This uses an explicit sort to make sure this spec doesn't randomly
- # fail when objects are returned in a different order.
- refs = subject.referenced_by([link]).sort_by(&:id)
-
- expect(refs).to eq([user, contributor])
- end
- end
-
- context 'using a non-existing project ID' do
- it 'returns an empty Array' do
- link['data-project'] = ''
-
- expect(subject.referenced_by([link])).to eq([])
- end
- end
- end
- end
-
- describe '#nodes_visible_to_use?' do
- context 'when the link has a data-group attribute' do
- context 'using an existing group ID' do
- before do
- link['data-group'] = group.id.to_s
- end
-
- it 'returns the nodes if the user can read the group' do
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_group, group).
- and_return(true)
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
- end
-
- it 'returns an empty Array if the user can not read the group' do
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_group, group).
- and_return(false)
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([])
- end
- end
-
- context 'when the link does not have a data-group attribute' do
- context 'with a data-project attribute' do
- it 'returns the nodes if the attribute value equals the current project ID' do
- link['data-project'] = project.id.to_s
-
- expect(Ability.abilities).not_to receive(:allowed?)
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
- end
-
- it 'returns the nodes if the user can read the project' do
- other_project = create(:empty_project, :public)
-
- link['data-project'] = other_project.id.to_s
-
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_project, other_project).
- and_return(true)
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
- end
-
- it 'returns an empty Array if the user can not read the project' do
- other_project = create(:empty_project, :public)
-
- link['data-project'] = other_project.id.to_s
-
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_project, other_project).
- and_return(false)
-
- expect(subject.nodes_visible_to_user(user, [link])).to eq([])
- end
- end
-
- context 'without a data-project attribute' do
- it 'returns the nodes' do
- expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
- end
- end
- end
- end
- end
-
- describe '#nodes_user_can_reference' do
- context 'when the link has a data-author attribute' do
- it 'returns the nodes when the user is a member of the project' do
- other_project = create(:project)
- other_project.team << [user, :developer]
-
- link['data-project'] = other_project.id.to_s
- link['data-author'] = user.id.to_s
-
- expect(subject.nodes_user_can_reference(user, [link])).to eq([link])
- end
-
- it 'returns an empty Array when the project could not be found' do
- link['data-project'] = ''
- link['data-author'] = user.id.to_s
-
- expect(subject.nodes_user_can_reference(user, [link])).to eq([])
- end
-
- it 'returns an empty Array when the user could not be found' do
- other_project = create(:project)
-
- link['data-project'] = other_project.id.to_s
- link['data-author'] = ''
-
- expect(subject.nodes_user_can_reference(user, [link])).to eq([])
- end
-
- it 'returns an empty Array when the user is not a team member' do
- other_project = create(:project)
-
- link['data-project'] = other_project.id.to_s
- link['data-author'] = user.id.to_s
-
- expect(subject.nodes_user_can_reference(user, [link])).to eq([])
- end
- end
-
- context 'when the link does not have a data-author attribute' do
- it 'returns the nodes' do
- expect(subject.nodes_user_can_reference(user, [link])).to eq([link])
- end
- end
- end
-end
diff --git a/spec/lib/ci/ansi2html_spec.rb b/spec/lib/ci/ansi2html_spec.rb
index 898f1e84ab..3a2b568f4c 100644
--- a/spec/lib/ci/ansi2html_spec.rb
+++ b/spec/lib/ci/ansi2html_spec.rb
@@ -4,185 +4,131 @@ describe Ci::Ansi2html, lib: true do
subject { Ci::Ansi2html }
it "prints non-ansi as-is" do
- expect(subject.convert("Hello")[:html]).to eq('Hello')
+ expect(subject.convert("Hello")).to eq('Hello')
end
it "strips non-color-changing controll sequences" do
- expect(subject.convert("Hello \e[2Kworld")[:html]).to eq('Hello world')
+ expect(subject.convert("Hello \e[2Kworld")).to eq('Hello world')
end
it "prints simply red" do
- expect(subject.convert("\e[31mHello\e[0m")[:html]).to eq('Hello')
+ expect(subject.convert("\e[31mHello\e[0m")).to eq('Hello')
end
it "prints simply red without trailing reset" do
- expect(subject.convert("\e[31mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[31mHello")).to eq('Hello')
end
it "prints simply yellow" do
- expect(subject.convert("\e[33mHello\e[0m")[:html]).to eq('Hello')
+ expect(subject.convert("\e[33mHello\e[0m")).to eq('Hello')
end
it "prints default on blue" do
- expect(subject.convert("\e[39;44mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[39;44mHello")).to eq('Hello')
end
it "prints red on blue" do
- expect(subject.convert("\e[31;44mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[31;44mHello")).to eq('Hello')
end
it "resets colors after red on blue" do
- expect(subject.convert("\e[31;44mHello\e[0m world")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[31;44mHello\e[0m world")).to eq('Hello world')
end
it "performs color change from red/blue to yellow/blue" do
- expect(subject.convert("\e[31;44mHello \e[33mworld")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[31;44mHello \e[33mworld")).to eq('Hello world')
end
it "performs color change from red/blue to yellow/green" do
- expect(subject.convert("\e[31;44mHello \e[33;42mworld")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[31;44mHello \e[33;42mworld")).to eq('Hello world')
end
it "performs color change from red/blue to reset to yellow/green" do
- expect(subject.convert("\e[31;44mHello\e[0m \e[33;42mworld")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[31;44mHello\e[0m \e[33;42mworld")).to eq('Hello world')
end
it "ignores unsupported codes" do
- expect(subject.convert("\e[51mHello\e[0m")[:html]).to eq('Hello')
+ expect(subject.convert("\e[51mHello\e[0m")).to eq('Hello')
end
it "prints light red" do
- expect(subject.convert("\e[91mHello\e[0m")[:html]).to eq('Hello')
+ expect(subject.convert("\e[91mHello\e[0m")).to eq('Hello')
end
it "prints default on light red" do
- expect(subject.convert("\e[101mHello\e[0m")[:html]).to eq('Hello')
+ expect(subject.convert("\e[101mHello\e[0m")).to eq('Hello')
end
it "performs color change from red/blue to default/blue" do
- expect(subject.convert("\e[31;44mHello \e[39mworld")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[31;44mHello \e[39mworld")).to eq('Hello world')
end
it "performs color change from light red/blue to default/blue" do
- expect(subject.convert("\e[91;44mHello \e[39mworld")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[91;44mHello \e[39mworld")).to eq('Hello world')
end
it "prints bold text" do
- expect(subject.convert("\e[1mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[1mHello")).to eq('Hello')
end
it "resets bold text" do
- expect(subject.convert("\e[1mHello\e[21m world")[:html]).to eq('Hello world')
- expect(subject.convert("\e[1mHello\e[22m world")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[1mHello\e[21m world")).to eq('Hello world')
+ expect(subject.convert("\e[1mHello\e[22m world")).to eq('Hello world')
end
it "prints italic text" do
- expect(subject.convert("\e[3mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[3mHello")).to eq('Hello')
end
it "resets italic text" do
- expect(subject.convert("\e[3mHello\e[23m world")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[3mHello\e[23m world")).to eq('Hello world')
end
it "prints underlined text" do
- expect(subject.convert("\e[4mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[4mHello")).to eq('Hello')
end
it "resets underlined text" do
- expect(subject.convert("\e[4mHello\e[24m world")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[4mHello\e[24m world")).to eq('Hello world')
end
it "prints concealed text" do
- expect(subject.convert("\e[8mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[8mHello")).to eq('Hello')
end
it "resets concealed text" do
- expect(subject.convert("\e[8mHello\e[28m world")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[8mHello\e[28m world")).to eq('Hello world')
end
it "prints crossed-out text" do
- expect(subject.convert("\e[9mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[9mHello")).to eq('Hello')
end
it "resets crossed-out text" do
- expect(subject.convert("\e[9mHello\e[29m world")[:html]).to eq('Hello world')
+ expect(subject.convert("\e[9mHello\e[29m world")).to eq('Hello world')
end
it "can print 256 xterm fg colors" do
- expect(subject.convert("\e[38;5;16mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[38;5;16mHello")).to eq('Hello')
end
it "can print 256 xterm fg colors on normal magenta background" do
- expect(subject.convert("\e[38;5;16;45mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[38;5;16;45mHello")).to eq('Hello')
end
it "can print 256 xterm bg colors" do
- expect(subject.convert("\e[48;5;240mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[48;5;240mHello")).to eq('Hello')
end
it "can print 256 xterm bg colors on normal magenta foreground" do
- expect(subject.convert("\e[48;5;16;35mHello")[:html]).to eq('Hello')
+ expect(subject.convert("\e[48;5;16;35mHello")).to eq('Hello')
end
it "prints bold colored text vividly" do
- expect(subject.convert("\e[1;31mHello\e[0m")[:html]).to eq('Hello')
+ expect(subject.convert("\e[1;31mHello\e[0m")).to eq('Hello')
end
it "prints bold light colored text correctly" do
- expect(subject.convert("\e[1;91mHello\e[0m")[:html]).to eq('Hello')
- end
-
- it "prints <" do
- expect(subject.convert("<")[:html]).to eq('<')
- end
-
- describe "incremental update" do
- shared_examples 'stateable converter' do
- let(:pass1) { subject.convert(pre_text) }
- let(:pass2) { subject.convert(pre_text + text, pass1[:state]) }
-
- it "to returns html to append" do
- expect(pass2[:append]).to be_truthy
- expect(pass2[:html]).to eq(html)
- expect(pass1[:text] + pass2[:text]).to eq(pre_text + text)
- expect(pass1[:html] + pass2[:html]).to eq(pre_html + html)
- end
- end
-
- context "with split word" do
- let(:pre_text) { "\e[1mHello" }
- let(:pre_html) { "Hello" }
- let(:text) { "\e[1mWorld" }
- let(:html) { "World" }
-
- it_behaves_like 'stateable converter'
- end
-
- context "with split sequence" do
- let(:pre_text) { "\e[1m" }
- let(:pre_html) { "" }
- let(:text) { "Hello" }
- let(:html) { "Hello" }
-
- it_behaves_like 'stateable converter'
- end
-
- context "with partial sequence" do
- let(:pre_text) { "Hello\e" }
- let(:pre_html) { "Hello" }
- let(:text) { "[1m World" }
- let(:html) { " World" }
-
- it_behaves_like 'stateable converter'
- end
-
- context 'with new line' do
- let(:pre_text) { "Hello\r" }
- let(:pre_html) { "Hello\r" }
- let(:text) { "\nWorld" }
- let(:html) { "
World" }
-
- it_behaves_like 'stateable converter'
- end
+ expect(subject.convert("\e[1;91mHello\e[0m")).to eq('Hello')
end
end
diff --git a/spec/lib/ci/charts_spec.rb b/spec/lib/ci/charts_spec.rb
index 9d1215a576..50a77308cd 100644
--- a/spec/lib/ci/charts_spec.rb
+++ b/spec/lib/ci/charts_spec.rb
@@ -12,12 +12,5 @@ describe Ci::Charts, lib: true do
chart = Ci::Charts::BuildTime.new(@commit.project)
expect(chart.build_times).to eq([2])
end
-
- it 'should handle nil build times' do
- create(:ci_commit, duration: nil, project: @commit.project)
-
- chart = Ci::Charts::BuildTime.new(@commit.project)
- expect(chart.build_times).to eq([2, 0])
- end
end
end
diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
index 7375539cf1..c7ab318537 100644
--- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
+++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
@@ -443,12 +443,12 @@ module Ci
context 'when job variables are defined' do
context 'when syntax is correct' do
it 'returns job variables' do
- variables = {
+ variables = {
KEY1: 'value1',
SOME_KEY_2: 'value2'
}
- config = YAML.dump(
+ config = YAML.dump(
{ before_script: ['pwd'],
rspec: {
variables: variables,
@@ -619,19 +619,19 @@ module Ci
context 'no dependencies' do
let(:dependencies) { }
- it { expect { subject }.not_to raise_error }
+ it { expect { subject }.to_not raise_error }
end
context 'dependencies to builds' do
let(:dependencies) { ['build1', 'build2'] }
- it { expect { subject }.not_to raise_error }
+ it { expect { subject }.to_not raise_error }
end
context 'dependencies to builds defined as symbols' do
let(:dependencies) { [:build1, :build2] }
- it { expect { subject }.not_to raise_error }
+ it { expect { subject }.to_not raise_error }
end
context 'undefined dependency' do
diff --git a/spec/lib/container_registry/blob_spec.rb b/spec/lib/container_registry/blob_spec.rb
deleted file mode 100644
index 4d8cb787dd..0000000000
--- a/spec/lib/container_registry/blob_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-require 'spec_helper'
-
-describe ContainerRegistry::Blob do
- let(:digest) { 'sha256:0123456789012345' }
- let(:config) do
- {
- 'digest' => digest,
- 'mediaType' => 'binary',
- 'size' => 1000
- }
- end
-
- let(:registry) { ContainerRegistry::Registry.new('http://example.com') }
- let(:repository) { registry.repository('group/test') }
- let(:blob) { repository.blob(config) }
-
- it { expect(blob).to respond_to(:repository) }
- it { expect(blob).to delegate_method(:registry).to(:repository) }
- it { expect(blob).to delegate_method(:client).to(:repository) }
-
- context '#path' do
- subject { blob.path }
-
- it { is_expected.to eq('example.com/group/test@sha256:0123456789012345') }
- end
-
- context '#digest' do
- subject { blob.digest }
-
- it { is_expected.to eq(digest) }
- end
-
- context '#type' do
- subject { blob.type }
-
- it { is_expected.to eq('binary') }
- end
-
- context '#revision' do
- subject { blob.revision }
-
- it { is_expected.to eq('0123456789012345') }
- end
-
- context '#short_revision' do
- subject { blob.short_revision }
-
- it { is_expected.to eq('012345678') }
- end
-
- context '#delete' do
- before do
- stub_request(:delete, 'http://example.com/v2/group/test/blobs/sha256:0123456789012345').
- to_return(status: 200)
- end
-
- subject { blob.delete }
-
- it { is_expected.to be_truthy }
- end
-end
diff --git a/spec/lib/container_registry/registry_spec.rb b/spec/lib/container_registry/registry_spec.rb
deleted file mode 100644
index 4f3f8b24fc..0000000000
--- a/spec/lib/container_registry/registry_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require 'spec_helper'
-
-describe ContainerRegistry::Registry do
- let(:path) { nil }
- let(:registry) { described_class.new('http://example.com', path: path) }
-
- subject { registry }
-
- it { is_expected.to respond_to(:client) }
- it { is_expected.to respond_to(:uri) }
- it { is_expected.to respond_to(:path) }
-
- it { expect(subject.repository('test')).not_to be_nil }
-
- context '#path' do
- subject { registry.path }
-
- context 'path from URL' do
- it { is_expected.to eq('example.com') }
- end
-
- context 'custom path' do
- let(:path) { 'registry.example.com' }
-
- it { is_expected.to eq(path) }
- end
- end
-end
diff --git a/spec/lib/container_registry/repository_spec.rb b/spec/lib/container_registry/repository_spec.rb
deleted file mode 100644
index 279709521c..0000000000
--- a/spec/lib/container_registry/repository_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-require 'spec_helper'
-
-describe ContainerRegistry::Repository do
- let(:registry) { ContainerRegistry::Registry.new('http://example.com') }
- let(:repository) { registry.repository('group/test') }
-
- it { expect(repository).to respond_to(:registry) }
- it { expect(repository).to delegate_method(:client).to(:registry) }
- it { expect(repository.tag('test')).not_to be_nil }
-
- context '#path' do
- subject { repository.path }
-
- it { is_expected.to eq('example.com/group/test') }
- end
-
- context 'manifest processing' do
- before do
- stub_request(:get, 'http://example.com/v2/group/test/tags/list').
- with(headers: { 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json' }).
- to_return(
- status: 200,
- body: JSON.dump(tags: ['test']),
- headers: { 'Content-Type' => 'application/vnd.docker.distribution.manifest.v2+json' })
- end
-
- context '#manifest' do
- subject { repository.manifest }
-
- it { is_expected.not_to be_nil }
- end
-
- context '#valid?' do
- subject { repository.valid? }
-
- it { is_expected.to be_truthy }
- end
-
- context '#tags' do
- subject { repository.tags }
-
- it { is_expected.not_to be_empty }
- end
- end
-
- context '#delete_tags' do
- let(:tag) { ContainerRegistry::Tag.new(repository, 'tag') }
-
- before { expect(repository).to receive(:tags).twice.and_return([tag]) }
-
- subject { repository.delete_tags }
-
- context 'succeeds' do
- before { expect(tag).to receive(:delete).and_return(true) }
-
- it { is_expected.to be_truthy }
- end
-
- context 'any fails' do
- before { expect(tag).to receive(:delete).and_return(false) }
-
- it { is_expected.to be_falsey }
- end
- end
-end
diff --git a/spec/lib/container_registry/tag_spec.rb b/spec/lib/container_registry/tag_spec.rb
deleted file mode 100644
index 858cb0bb13..0000000000
--- a/spec/lib/container_registry/tag_spec.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-require 'spec_helper'
-
-describe ContainerRegistry::Tag do
- let(:registry) { ContainerRegistry::Registry.new('http://example.com') }
- let(:repository) { registry.repository('group/test') }
- let(:tag) { repository.tag('tag') }
- let(:headers) { { 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json' } }
-
- it { expect(tag).to respond_to(:repository) }
- it { expect(tag).to delegate_method(:registry).to(:repository) }
- it { expect(tag).to delegate_method(:client).to(:repository) }
-
- context '#path' do
- subject { tag.path }
-
- it { is_expected.to eq('example.com/group/test:tag') }
- end
-
- context 'manifest processing' do
- before do
- stub_request(:get, 'http://example.com/v2/group/test/manifests/tag').
- with(headers: headers).
- to_return(
- status: 200,
- body: File.read(Rails.root + 'spec/fixtures/container_registry/tag_manifest.json'),
- headers: { 'Content-Type' => 'application/vnd.docker.distribution.manifest.v2+json' })
- end
-
- context '#layers' do
- subject { tag.layers }
-
- it { expect(subject.length).to eq(1) }
- end
-
- context '#total_size' do
- subject { tag.total_size }
-
- it { is_expected.to eq(2319870) }
- end
-
- context 'config processing' do
- before do
- stub_request(:get, 'http://example.com/v2/group/test/blobs/sha256:d7a513a663c1a6dcdba9ed832ca53c02ac2af0c333322cd6ca92936d1d9917ac').
- with(headers: { 'Accept' => 'application/octet-stream' }).
- to_return(
- status: 200,
- body: File.read(Rails.root + 'spec/fixtures/container_registry/config_blob.json'))
- end
-
- context '#config' do
- subject { tag.config }
-
- it { is_expected.not_to be_nil }
- end
-
- context '#created_at' do
- subject { tag.created_at }
-
- it { is_expected.not_to be_nil }
- end
- end
- end
-
- context 'manifest digest' do
- before do
- stub_request(:head, 'http://example.com/v2/group/test/manifests/tag').
- with(headers: headers).
- to_return(status: 200, headers: { 'Docker-Content-Digest' => 'sha256:digest' })
- end
-
- context '#digest' do
- subject { tag.digest }
-
- it { is_expected.to eq('sha256:digest') }
- end
-
- context '#delete' do
- before do
- stub_request(:delete, 'http://example.com/v2/group/test/manifests/sha256:digest').
- with(headers: headers).
- to_return(status: 200)
- end
-
- subject { tag.delete }
-
- it { is_expected.to be_truthy }
- end
- end
-end
diff --git a/spec/lib/gitlab/akismet_helper_spec.rb b/spec/lib/gitlab/akismet_helper_spec.rb
index 88a7152886..53f5d6c5c8 100644
--- a/spec/lib/gitlab/akismet_helper_spec.rb
+++ b/spec/lib/gitlab/akismet_helper_spec.rb
@@ -6,8 +6,8 @@ describe Gitlab::AkismetHelper, type: :helper do
before do
allow(Gitlab.config.gitlab).to receive(:url).and_return(Settings.send(:build_gitlab_url))
- allow_any_instance_of(ApplicationSetting).to receive(:akismet_enabled).and_return(true)
- allow_any_instance_of(ApplicationSetting).to receive(:akismet_api_key).and_return('12345')
+ current_application_settings.akismet_enabled = true
+ current_application_settings.akismet_api_key = '12345'
end
describe '#check_for_spam?' do
diff --git a/spec/lib/gitlab/bitbucket_import/client_spec.rb b/spec/lib/gitlab/bitbucket_import/client_spec.rb
index 7718689e6d..af839f4242 100644
--- a/spec/lib/gitlab/bitbucket_import/client_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/client_spec.rb
@@ -59,7 +59,7 @@ describe Gitlab::BitbucketImport::Client, lib: true do
bitbucket_access_token_secret: "test" } })
project.import_url = "ssh://git@bitbucket.org/test/test.git"
- expect { described_class.from_project(project) }.not_to raise_error
+ expect { described_class.from_project(project) }.to_not raise_error
end
end
end
diff --git a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb
index 711a3e1c7d..acca0b08ba 100644
--- a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb
+++ b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb
@@ -10,8 +10,8 @@ describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do
'path/dir_1/subdir/subfile' => { size: 10 },
'path/second_dir' => {},
'path/second_dir/dir_3/file_2' => { size: 10 },
- 'path/second_dir/dir_3/file_3' => { size: 10 },
- 'another_directory/' => {},
+ 'path/second_dir/dir_3/file_3'=> { size: 10 },
+ 'another_directory/'=> {},
'another_file' => {},
'/file/with/absolute_path' => {} }
end
@@ -122,7 +122,7 @@ describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do
describe 'empty path', path: '' do
subject { |example| path(example) }
- it { is_expected.not_to have_parent }
+ it { is_expected.to_not have_parent }
describe '#children' do
subject { |example| path(example).children }
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
deleted file mode 100644
index 35ade7a2be..0000000000
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Database::MigrationHelpers, lib: true do
- let(:model) do
- ActiveRecord::Migration.new.extend(
- Gitlab::Database::MigrationHelpers
- )
- end
-
- before { allow(model).to receive(:puts) }
-
- describe '#add_concurrent_index' do
- context 'outside a transaction' do
- before do
- expect(model).to receive(:transaction_open?).and_return(false)
- end
-
- context 'using PostgreSQL' do
- it 'creates the index concurrently' do
- expect(Gitlab::Database).to receive(:postgresql?).and_return(true)
-
- expect(model).to receive(:add_index).
- with(:users, :foo, algorithm: :concurrently)
-
- model.add_concurrent_index(:users, :foo)
- end
- end
-
- context 'using MySQL' do
- it 'creates a regular index' do
- expect(Gitlab::Database).to receive(:postgresql?).and_return(false)
-
- expect(model).to receive(:add_index).
- with(:users, :foo)
-
- model.add_concurrent_index(:users, :foo)
- end
- end
- end
-
- context 'inside a transaction' do
- it 'raises RuntimeError' do
- expect(model).to receive(:transaction_open?).and_return(true)
-
- expect { model.add_concurrent_index(:users, :foo) }.
- to raise_error(RuntimeError)
- end
- end
- end
-
- describe '#update_column_in_batches' do
- before do
- create_list(:empty_project, 5)
- end
-
- it 'updates all the rows in a table' do
- model.update_column_in_batches(:projects, :import_error, 'foo')
-
- expect(Project.where(import_error: 'foo').count).to eq(5)
- end
-
- it 'updates boolean values correctly' do
- model.update_column_in_batches(:projects, :archived, true)
-
- expect(Project.where(archived: true).count).to eq(5)
- end
- end
-
- describe '#add_column_with_default' do
- context 'outside of a transaction' do
- before do
- expect(model).to receive(:transaction_open?).and_return(false)
-
- expect(model).to receive(:transaction).twice.and_yield
-
- expect(model).to receive(:add_column).
- with(:projects, :foo, :integer, default: nil)
-
- expect(model).to receive(:change_column_default).
- with(:projects, :foo, 10)
- end
-
- it 'adds the column while allowing NULL values' do
- expect(model).to receive(:update_column_in_batches).
- with(:projects, :foo, 10)
-
- expect(model).not_to receive(:change_column_null)
-
- model.add_column_with_default(:projects, :foo, :integer,
- default: 10,
- allow_null: true)
- end
-
- it 'adds the column while not allowing NULL values' do
- expect(model).to receive(:update_column_in_batches).
- with(:projects, :foo, 10)
-
- expect(model).to receive(:change_column_null).
- with(:projects, :foo, false)
-
- model.add_column_with_default(:projects, :foo, :integer, default: 10)
- end
-
- it 'removes the added column whenever updating the rows fails' do
- expect(model).to receive(:update_column_in_batches).
- with(:projects, :foo, 10).
- and_raise(RuntimeError)
-
- expect(model).to receive(:remove_column).
- with(:projects, :foo)
-
- expect do
- model.add_column_with_default(:projects, :foo, :integer, default: 10)
- end.to raise_error(RuntimeError)
- end
- end
-
- context 'inside a transaction' do
- it 'raises RuntimeError' do
- expect(model).to receive(:transaction_open?).and_return(true)
-
- expect do
- model.add_column_with_default(:projects, :foo, :integer, default: 10)
- end.to raise_error(RuntimeError)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/email/message/repository_push_spec.rb b/spec/lib/gitlab/email/message/repository_push_spec.rb
index c19f33e222..b2d7a79981 100644
--- a/spec/lib/gitlab/email/message/repository_push_spec.rb
+++ b/spec/lib/gitlab/email/message/repository_push_spec.rb
@@ -8,7 +8,7 @@ describe Gitlab::Email::Message::RepositoryPush do
let!(:author) { create(:author, name: 'Author') }
let(:message) do
- described_class.new(Notify, project.id, opts)
+ described_class.new(Notify, project.id, 'recipient@example.com', opts)
end
context 'new commits have been pushed to repository' do
@@ -57,7 +57,7 @@ describe Gitlab::Email::Message::RepositoryPush do
describe '#diffs' do
subject { message.diffs }
- it { is_expected.to all(be_an_instance_of Gitlab::Diff::File) }
+ it { is_expected.to all(be_an_instance_of Gitlab::Git::Diff) }
end
describe '#diffs_count' do
diff --git a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb
index 0af249d869..0a7ca3ec84 100644
--- a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb
+++ b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb
@@ -33,8 +33,8 @@ describe Gitlab::Gfm::ReferenceRewriter do
end
it { is_expected.to include issue_first.to_reference(new_project) }
- it { is_expected.not_to include issue_second.to_reference(new_project) }
- it { is_expected.not_to include merge_request.to_reference(new_project) }
+ it { is_expected.to_not include issue_second.to_reference(new_project) }
+ it { is_expected.to_not include merge_request.to_reference(new_project) }
end
context 'description ambigous elements' do
diff --git a/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb b/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb
index 6eca33f9fe..eda956e6f0 100644
--- a/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb
+++ b/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb
@@ -32,13 +32,13 @@ describe Gitlab::Gfm::UploadsRewriter do
let(:new_paths) { new_files.map(&:path) }
it 'rewrites content' do
- expect(new_text).not_to eq text
+ expect(new_text).to_not eq text
expect(new_text.length).to eq text.length
end
it 'copies files' do
expect(new_files).to all(exist)
- expect(old_paths).not_to match_array new_paths
+ expect(old_paths).to_not match_array new_paths
expect(old_paths).to all(include(old_project.path_with_namespace))
expect(new_paths).to all(include(new_project.path_with_namespace))
end
@@ -48,8 +48,8 @@ describe Gitlab::Gfm::UploadsRewriter do
end
it 'generates a new secret for each file' do
- expect(new_paths).not_to include image_uploader.secret
- expect(new_paths).not_to include zip_uploader.secret
+ expect(new_paths).to_not include image_uploader.secret
+ expect(new_paths).to_not include zip_uploader.secret
end
end
diff --git a/spec/lib/gitlab/github_import/branch_formatter_spec.rb b/spec/lib/gitlab/github_import/branch_formatter_spec.rb
deleted file mode 100644
index 3cb634ba01..0000000000
--- a/spec/lib/gitlab/github_import/branch_formatter_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::GithubImport::BranchFormatter, lib: true do
- let(:project) { create(:project) }
- let(:repo) { double }
- let(:raw) do
- {
- ref: 'feature',
- repo: repo,
- sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b'
- }
- end
-
- describe '#exists?' do
- it 'returns true when branch exists' do
- branch = described_class.new(project, double(raw))
-
- expect(branch.exists?).to eq true
- end
-
- it 'returns false when branch does not exist' do
- branch = described_class.new(project, double(raw.merge(ref: 'removed-branch')))
-
- expect(branch.exists?).to eq false
- end
- end
-
- describe '#name' do
- it 'returns raw ref when branch exists' do
- branch = described_class.new(project, double(raw))
-
- expect(branch.name).to eq 'feature'
- end
-
- it 'returns formatted ref when branch does not exist' do
- branch = described_class.new(project, double(raw.merge(ref: 'removed-branch')))
-
- expect(branch.name).to eq 'removed-branch-2e5d3239'
- end
- end
-
- describe '#repo' do
- it 'returns raw repo' do
- branch = described_class.new(project, double(raw))
-
- expect(branch.repo).to eq repo
- end
- end
-
- describe '#sha' do
- it 'returns raw sha' do
- branch = described_class.new(project, double(raw))
-
- expect(branch.sha).to eq '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b'
- end
- end
-
- describe '#valid?' do
- it 'returns true when repository exists' do
- branch = described_class.new(project, double(raw))
-
- expect(branch.valid?).to eq true
- end
-
- it 'returns false when repository does not exist' do
- branch = described_class.new(project, double(raw.merge(repo: nil)))
-
- expect(branch.valid?).to eq false
- end
- end
-end
diff --git a/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb b/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb
index 120f59e6e7..e59c0ca110 100644
--- a/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb
+++ b/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb
@@ -4,9 +4,9 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
let(:project) { create(:project) }
let(:repository) { double(id: 1, fork: false) }
let(:source_repo) { repository }
- let(:source_branch) { double(ref: 'feature', repo: source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b') }
+ let(:source_branch) { double(ref: 'feature', repo: source_repo) }
let(:target_repo) { repository }
- let(:target_branch) { double(ref: 'master', repo: target_repo, sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7') }
+ let(:target_branch) { double(ref: 'master', repo: target_repo) }
let(:octocat) { double(id: 123456, login: 'octocat') }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
@@ -41,10 +41,8 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
description: "*Created by: octocat*\n\nPlease pull these awesome changes",
source_project: project,
source_branch: 'feature',
- head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b',
target_project: project,
target_branch: 'master',
- base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7',
state: 'opened',
milestone: nil,
author_id: project.creator_id,
@@ -68,10 +66,8 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
description: "*Created by: octocat*\n\nPlease pull these awesome changes",
source_project: project,
source_branch: 'feature',
- head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b',
target_project: project,
target_branch: 'master',
- base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7',
state: 'closed',
milestone: nil,
author_id: project.creator_id,
@@ -95,10 +91,8 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
description: "*Created by: octocat*\n\nPlease pull these awesome changes",
source_project: project,
source_branch: 'feature',
- head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b',
target_project: project,
target_branch: 'master',
- base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7',
state: 'merged',
milestone: nil,
author_id: project.creator_id,
@@ -143,11 +137,11 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
let(:milestone) { double(number: 45) }
let(:raw_data) { double(base_data.merge(milestone: milestone)) }
- it 'returns nil when milestone does not exist' do
+ it 'returns nil when milestone does not exists' do
expect(pull_request.attributes.fetch(:milestone)).to be_nil
end
- it 'returns milestone when it exists' do
+ it 'returns milestone when is exists' do
milestone = create(:milestone, project: project, iid: 45)
expect(pull_request.attributes.fetch(:milestone)).to eq milestone
@@ -164,16 +158,36 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
end
describe '#valid?' do
- context 'when source, and target repos are not a fork' do
- let(:raw_data) { double(base_data) }
+ let(:invalid_branch) { double(ref: 'invalid-branch').as_null_object }
- it 'returns true' do
- expect(pull_request.valid?).to eq true
+ context 'when source, and target repositories are the same' do
+ context 'and source and target branches exists' do
+ let(:raw_data) { double(base_data.merge(head: source_branch, base: target_branch)) }
+
+ it 'returns true' do
+ expect(pull_request.valid?).to eq true
+ end
+ end
+
+ context 'and source branch doesn not exists' do
+ let(:raw_data) { double(base_data.merge(head: invalid_branch, base: target_branch)) }
+
+ it 'returns false' do
+ expect(pull_request.valid?).to eq false
+ end
+ end
+
+ context 'and target branch doesn not exists' do
+ let(:raw_data) { double(base_data.merge(head: source_branch, base: invalid_branch)) }
+
+ it 'returns false' do
+ expect(pull_request.valid?).to eq false
+ end
end
end
context 'when source repo is a fork' do
- let(:source_repo) { double(id: 2) }
+ let(:source_repo) { double(id: 2, fork: true) }
let(:raw_data) { double(base_data) }
it 'returns false' do
@@ -182,7 +196,7 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
end
context 'when target repo is a fork' do
- let(:target_repo) { double(id: 2) }
+ let(:target_repo) { double(id: 2, fork: true) }
let(:raw_data) { double(base_data) }
it 'returns false' do
diff --git a/spec/lib/gitlab/gitignore_spec.rb b/spec/lib/gitlab/gitignore_spec.rb
deleted file mode 100644
index 72baa516cc..0000000000
--- a/spec/lib/gitlab/gitignore_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Gitignore do
- subject { Gitlab::Gitignore }
-
- describe '.all' do
- it 'strips the gitignore suffix' do
- expect(subject.all.first.name).not_to end_with('.gitignore')
- end
-
- it 'combines the globals and rest' do
- all = subject.all.map(&:name)
-
- expect(all).to include('Vim')
- expect(all).to include('Ruby')
- end
- end
-
- describe '.find' do
- it 'returns nil if the file does not exist' do
- expect(subject.find('mepmep-yadida')).to be nil
- end
-
- it 'returns the Gitignore object of a valid file' do
- ruby = subject.find('Ruby')
-
- expect(ruby).to be_a Gitlab::Gitignore
- expect(ruby.name).to eq('Ruby')
- end
- end
-
- describe '#content' do
- it 'loads the full file' do
- gitignore = subject.new(Rails.root.join('vendor/gitignore/Ruby.gitignore'))
-
- expect(gitignore.name).to eq 'Ruby'
- expect(gitignore.content).to start_with('*.gem')
- end
- end
-end
diff --git a/spec/lib/gitlab/import_url_spec.rb b/spec/lib/gitlab/import_url_spec.rb
new file mode 100644
index 0000000000..f758cb8693
--- /dev/null
+++ b/spec/lib/gitlab/import_url_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe Gitlab::ImportUrl do
+
+ let(:credentials) { { user: 'blah', password: 'password' } }
+ let(:import_url) do
+ Gitlab::ImportUrl.new("https://github.com/me/project.git", credentials: credentials)
+ end
+
+ describe :full_url do
+ it { expect(import_url.full_url).to eq("https://blah:password@github.com/me/project.git") }
+ end
+
+ describe :sanitized_url do
+ it { expect(import_url.sanitized_url).to eq("https://github.com/me/project.git") }
+ end
+
+ describe :credentials do
+ it { expect(import_url.credentials).to eq(credentials) }
+ end
+end
diff --git a/spec/lib/gitlab/lazy_spec.rb b/spec/lib/gitlab/lazy_spec.rb
deleted file mode 100644
index b5ca89dd24..0000000000
--- a/spec/lib/gitlab/lazy_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Lazy, lib: true do
- let(:dummy) { double(:dummy) }
-
- context 'when not calling any methods' do
- it 'does not call the supplied block' do
- expect(dummy).not_to receive(:foo)
-
- described_class.new { dummy.foo }
- end
- end
-
- context 'when calling a method on the object' do
- it 'lazy loads the value returned by the block' do
- expect(dummy).to receive(:foo).and_return('foo')
-
- lazy = described_class.new { dummy.foo }
-
- expect(lazy.to_s).to eq('foo')
- end
- end
-
- describe '#respond_to?' do
- it 'returns true for a method defined on the wrapped object' do
- lazy = described_class.new { 'foo' }
-
- expect(lazy).to respond_to(:downcase)
- end
-
- it 'returns false for a method not defined on the wrapped object' do
- lazy = described_class.new { 'foo' }
-
- expect(lazy).not_to respond_to(:quack)
- end
- end
-end
diff --git a/spec/lib/gitlab/lfs/lfs_router_spec.rb b/spec/lib/gitlab/lfs/lfs_router_spec.rb
index 88814bc474..5852b31ab3 100644
--- a/spec/lib/gitlab/lfs/lfs_router_spec.rb
+++ b/spec/lib/gitlab/lfs/lfs_router_spec.rb
@@ -26,8 +26,8 @@ describe Gitlab::Lfs::Router, lib: true do
let(:sample_oid) { "b68143e6463773b1b6c6fd009a76c32aeec041faff32ba2ed42fd7f708a17f80" }
let(:sample_size) { 499013 }
- let(:respond_with_deprecated) {[ 501, { "Content-Type" => "application/json; charset=utf-8" }, ["{\"message\":\"Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]}
- let(:respond_with_disabled) {[ 501, { "Content-Type" => "application/json; charset=utf-8" }, ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]}
+ let(:respond_with_deprecated) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]}
+ let(:respond_with_disabled) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]}
describe 'when lfs is disabled' do
before do
@@ -368,7 +368,7 @@ describe Gitlab::Lfs::Router, lib: true do
expect(response['objects']).to be_kind_of(Array)
expect(response['objects'].first['oid']).to eq(sample_oid)
expect(response['objects'].first['size']).to eq(sample_size)
- expect(lfs_object.projects.pluck(:id)).not_to include(project.id)
+ expect(lfs_object.projects.pluck(:id)).to_not include(project.id)
expect(lfs_object.projects.pluck(:id)).to include(public_project.id)
expect(response['objects'].first['actions']['upload']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}/#{sample_size}")
expect(response['objects'].first['actions']['upload']['header']).to eq('Authorization' => @auth)
@@ -430,7 +430,7 @@ describe Gitlab::Lfs::Router, lib: true do
expect(response_body['objects'].last['oid']).to eq(sample_oid)
expect(response_body['objects'].last['size']).to eq(sample_size)
- expect(response_body['objects'].last).not_to have_key('actions')
+ expect(response_body['objects'].last).to_not have_key('actions')
end
end
end
diff --git a/spec/lib/gitlab/metrics/instrumentation_spec.rb b/spec/lib/gitlab/metrics/instrumentation_spec.rb
index 220e86924a..5c885a7a98 100644
--- a/spec/lib/gitlab/metrics/instrumentation_spec.rb
+++ b/spec/lib/gitlab/metrics/instrumentation_spec.rb
@@ -56,6 +56,9 @@ describe Gitlab::Metrics::Instrumentation do
allow(described_class).to receive(:transaction).
and_return(transaction)
+ expect(transaction).to receive(:increment).
+ with(:method_duration, a_kind_of(Numeric))
+
expect(transaction).to receive(:add_metric).
with(described_class::SERIES, an_instance_of(Hash),
method: 'Dummy.foo')
@@ -67,7 +70,7 @@ describe Gitlab::Metrics::Instrumentation do
allow(Gitlab::Metrics).to receive(:method_call_threshold).
and_return(100)
- expect(transaction).not_to receive(:add_metric)
+ expect(transaction).to_not receive(:add_metric)
@dummy.foo
end
@@ -136,6 +139,9 @@ describe Gitlab::Metrics::Instrumentation do
allow(described_class).to receive(:transaction).
and_return(transaction)
+ expect(transaction).to receive(:increment).
+ with(:method_duration, a_kind_of(Numeric))
+
expect(transaction).to receive(:add_metric).
with(described_class::SERIES, an_instance_of(Hash),
method: 'Dummy#bar')
@@ -147,7 +153,7 @@ describe Gitlab::Metrics::Instrumentation do
allow(Gitlab::Metrics).to receive(:method_call_threshold).
and_return(100)
- expect(transaction).not_to receive(:add_metric)
+ expect(transaction).to_not receive(:add_metric)
@dummy.new.bar
end
@@ -220,7 +226,7 @@ describe Gitlab::Metrics::Instrumentation do
described_class.instrument_methods(@dummy)
- expect(@dummy).not_to respond_to(:_original_kittens)
+ expect(@dummy).to_not respond_to(:_original_kittens)
end
it 'can take a block to determine if a method should be instrumented' do
@@ -228,7 +234,7 @@ describe Gitlab::Metrics::Instrumentation do
false
end
- expect(@dummy).not_to respond_to(:_original_foo)
+ expect(@dummy).to_not respond_to(:_original_foo)
end
end
diff --git a/spec/lib/gitlab/metrics/sampler_spec.rb b/spec/lib/gitlab/metrics/sampler_spec.rb
index 59db127674..38da77adc9 100644
--- a/spec/lib/gitlab/metrics/sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/sampler_spec.rb
@@ -130,7 +130,7 @@ describe Gitlab::Metrics::Sampler do
100.times do
interval = sampler.sleep_interval
- expect(interval).not_to eq(last)
+ expect(interval).to_not eq(last)
last = interval
end
diff --git a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
index 49699ffe28..e3293a0120 100644
--- a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
+++ b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
@@ -13,7 +13,7 @@ describe Gitlab::Metrics::Subscribers::ActiveRecord do
describe 'without a current transaction' do
it 'simply returns' do
expect_any_instance_of(Gitlab::Metrics::Transaction).
- not_to receive(:increment)
+ to_not receive(:increment)
subscriber.sql(event)
end
diff --git a/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb b/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb
index d824dc5443..e01b0b4bd2 100644
--- a/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb
+++ b/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb
@@ -9,7 +9,7 @@ describe Gitlab::Metrics::Subscribers::RailsCache do
describe '#cache_read' do
it 'increments the cache_read duration' do
expect(subscriber).to receive(:increment).
- with(:cache_read, event.duration)
+ with(:cache_read_duration, event.duration)
subscriber.cache_read(event)
end
@@ -18,7 +18,7 @@ describe Gitlab::Metrics::Subscribers::RailsCache do
describe '#cache_write' do
it 'increments the cache_write duration' do
expect(subscriber).to receive(:increment).
- with(:cache_write, event.duration)
+ with(:cache_write_duration, event.duration)
subscriber.cache_write(event)
end
@@ -27,7 +27,7 @@ describe Gitlab::Metrics::Subscribers::RailsCache do
describe '#cache_delete' do
it 'increments the cache_delete duration' do
expect(subscriber).to receive(:increment).
- with(:cache_delete, event.duration)
+ with(:cache_delete_duration, event.duration)
subscriber.cache_delete(event)
end
@@ -36,7 +36,7 @@ describe Gitlab::Metrics::Subscribers::RailsCache do
describe '#cache_exist?' do
it 'increments the cache_exists duration' do
expect(subscriber).to receive(:increment).
- with(:cache_exists, event.duration)
+ with(:cache_exists_duration, event.duration)
subscriber.cache_exist?(event)
end
@@ -61,16 +61,10 @@ describe Gitlab::Metrics::Subscribers::RailsCache do
expect(transaction).to receive(:increment).
with(:cache_duration, event.duration)
- expect(transaction).to receive(:increment).
- with(:cache_count, 1)
-
expect(transaction).to receive(:increment).
with(:cache_delete_duration, event.duration)
- expect(transaction).to receive(:increment).
- with(:cache_delete_count, 1)
-
- subscriber.increment(:cache_delete, event.duration)
+ subscriber.increment(:cache_delete_duration, event.duration)
end
end
end
diff --git a/spec/lib/gitlab/middleware/rails_queue_duration_spec.rb b/spec/lib/gitlab/middleware/rails_queue_duration_spec.rb
deleted file mode 100644
index fd6f684db0..0000000000
--- a/spec/lib/gitlab/middleware/rails_queue_duration_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Middleware::RailsQueueDuration do
- let(:app) { double(:app) }
- let(:middleware) { described_class.new(app) }
- let(:env) { {} }
- let(:transaction) { double(:transaction) }
-
- before { expect(app).to receive(:call).with(env).and_return('yay') }
-
- describe '#call' do
- it 'calls the app when metrics are disabled' do
- expect(Gitlab::Metrics).to receive(:current_transaction).and_return(nil)
- expect(middleware.call(env)).to eq('yay')
- end
-
- context 'when metrics are enabled' do
- before { allow(Gitlab::Metrics).to receive(:current_transaction).and_return(transaction) }
-
- it 'calls the app when metrics are enabled but no timing header is found' do
- expect(middleware.call(env)).to eq('yay')
- end
-
- it 'sets proxy_flight_time and calls the app when the header is present' do
- env['HTTP_GITLAB_WORHORSE_PROXY_START'] = '123'
- expect(transaction).to receive(:set).with(:rails_queue_duration, an_instance_of(Float))
- expect(middleware.call(env)).to eq('yay')
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/note_data_builder_spec.rb b/spec/lib/gitlab/note_data_builder_spec.rb
index e848d88182..f093d0a0d8 100644
--- a/spec/lib/gitlab/note_data_builder_spec.rb
+++ b/spec/lib/gitlab/note_data_builder_spec.rb
@@ -9,8 +9,7 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
before(:each) do
expect(data).to have_key(:object_attributes)
expect(data[:object_attributes]).to have_key(:url)
- expect(data[:object_attributes][:url])
- .to eq(Gitlab::UrlBuilder.build(note))
+ expect(data[:object_attributes][:url]).to eq(Gitlab::UrlBuilder.build(note))
expect(data[:object_kind]).to eq('note')
expect(data[:user]).to eq(user.hook_attrs)
end
@@ -38,21 +37,13 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
end
describe 'When asking for a note on issue' do
- let(:issue) do
- create(:issue, created_at: fixed_time, updated_at: fixed_time,
- project: project)
- end
-
- let(:note) do
- create(:note_on_issue, noteable: issue, project: project)
- end
+ let(:issue) { create(:issue, created_at: fixed_time, updated_at: fixed_time) }
+ let(:note) { create(:note_on_issue, noteable_id: issue.id, project: project) }
it 'returns the note and issue-specific data' do
expect(data).to have_key(:issue)
- expect(data[:issue].except('updated_at'))
- .to eq(issue.reload.hook_attrs.except('updated_at'))
- expect(data[:issue]['updated_at'])
- .to be > issue.hook_attrs['updated_at']
+ expect(data[:issue].except('updated_at')).to eq(issue.hook_attrs.except('updated_at'))
+ expect(data[:issue]['updated_at']).to be > issue.hook_attrs['updated_at']
end
include_examples 'project hook data'
@@ -60,23 +51,13 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
end
describe 'When asking for a note on merge request' do
- let(:merge_request) do
- create(:merge_request, created_at: fixed_time,
- updated_at: fixed_time,
- source_project: project)
- end
-
- let(:note) do
- create(:note_on_merge_request, noteable: merge_request,
- project: project)
- end
+ let(:merge_request) { create(:merge_request, created_at: fixed_time, updated_at: fixed_time) }
+ let(:note) { create(:note_on_merge_request, noteable_id: merge_request.id, project: project) }
it 'returns the note and merge request data' do
expect(data).to have_key(:merge_request)
- expect(data[:merge_request].except('updated_at'))
- .to eq(merge_request.reload.hook_attrs.except('updated_at'))
- expect(data[:merge_request]['updated_at'])
- .to be > merge_request.hook_attrs['updated_at']
+ expect(data[:merge_request].except('updated_at')).to eq(merge_request.hook_attrs.except('updated_at'))
+ expect(data[:merge_request]['updated_at']).to be > merge_request.hook_attrs['updated_at']
end
include_examples 'project hook data'
@@ -84,22 +65,13 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
end
describe 'When asking for a note on merge request diff' do
- let(:merge_request) do
- create(:merge_request, created_at: fixed_time, updated_at: fixed_time,
- source_project: project)
- end
-
- let(:note) do
- create(:note_on_merge_request_diff, noteable: merge_request,
- project: project)
- end
+ let(:merge_request) { create(:merge_request, created_at: fixed_time, updated_at: fixed_time) }
+ let(:note) { create(:note_on_merge_request_diff, noteable_id: merge_request.id, project: project) }
it 'returns the note and merge request diff data' do
expect(data).to have_key(:merge_request)
- expect(data[:merge_request].except('updated_at'))
- .to eq(merge_request.reload.hook_attrs.except('updated_at'))
- expect(data[:merge_request]['updated_at'])
- .to be > merge_request.hook_attrs['updated_at']
+ expect(data[:merge_request].except('updated_at')).to eq(merge_request.hook_attrs.except('updated_at'))
+ expect(data[:merge_request]['updated_at']).to be > merge_request.hook_attrs['updated_at']
end
include_examples 'project hook data'
@@ -107,22 +79,13 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
end
describe 'When asking for a note on project snippet' do
- let!(:snippet) do
- create(:project_snippet, created_at: fixed_time, updated_at: fixed_time,
- project: project)
- end
-
- let!(:note) do
- create(:note_on_project_snippet, noteable: snippet,
- project: project)
- end
+ let!(:snippet) { create(:project_snippet, created_at: fixed_time, updated_at: fixed_time) }
+ let!(:note) { create(:note_on_project_snippet, noteable_id: snippet.id, project: project) }
it 'returns the note and project snippet data' do
expect(data).to have_key(:snippet)
- expect(data[:snippet].except('updated_at'))
- .to eq(snippet.reload.hook_attrs.except('updated_at'))
- expect(data[:snippet]['updated_at'])
- .to be > snippet.hook_attrs['updated_at']
+ expect(data[:snippet].except('updated_at')).to eq(snippet.hook_attrs.except('updated_at'))
+ expect(data[:snippet]['updated_at']).to be > snippet.hook_attrs['updated_at']
end
include_examples 'project hook data'
diff --git a/spec/lib/gitlab/sherlock/collection_spec.rb b/spec/lib/gitlab/sherlock/collection_spec.rb
index 2ae79b50e7..de6bb86c5d 100644
--- a/spec/lib/gitlab/sherlock/collection_spec.rb
+++ b/spec/lib/gitlab/sherlock/collection_spec.rb
@@ -11,13 +11,13 @@ describe Gitlab::Sherlock::Collection, lib: true do
it 'adds a new transaction' do
collection.add(transaction)
- expect(collection).not_to be_empty
+ expect(collection).to_not be_empty
end
it 'is aliased as <<' do
collection << transaction
- expect(collection).not_to be_empty
+ expect(collection).to_not be_empty
end
end
@@ -47,7 +47,7 @@ describe Gitlab::Sherlock::Collection, lib: true do
it 'returns false for a collection with a transaction' do
collection.add(transaction)
- expect(collection).not_to be_empty
+ expect(collection).to_not be_empty
end
end
diff --git a/spec/lib/gitlab/sherlock/query_spec.rb b/spec/lib/gitlab/sherlock/query_spec.rb
index 0a62042813..05da915ccf 100644
--- a/spec/lib/gitlab/sherlock/query_spec.rb
+++ b/spec/lib/gitlab/sherlock/query_spec.rb
@@ -85,7 +85,7 @@ FROM users;
frames = query.application_backtrace
expect(frames).to be_an_instance_of(Array)
- expect(frames).not_to be_empty
+ expect(frames).to_not be_empty
frames.each do |frame|
expect(frame.path).to start_with(Rails.root.to_s)
diff --git a/spec/lib/gitlab/sherlock/transaction_spec.rb b/spec/lib/gitlab/sherlock/transaction_spec.rb
index 9fe18f253f..7553f2a045 100644
--- a/spec/lib/gitlab/sherlock/transaction_spec.rb
+++ b/spec/lib/gitlab/sherlock/transaction_spec.rb
@@ -203,7 +203,7 @@ describe Gitlab::Sherlock::Transaction, lib: true do
end
it 'only tracks queries triggered from the transaction thread' do
- expect(transaction).not_to receive(:track_query)
+ expect(transaction).to_not receive(:track_query)
Thread.new { subscription.publish('test', time, time, nil, query_data) }.
join
@@ -226,7 +226,7 @@ describe Gitlab::Sherlock::Transaction, lib: true do
end
it 'only tracks views rendered from the transaction thread' do
- expect(transaction).not_to receive(:track_view)
+ expect(transaction).to_not receive(:track_view)
Thread.new { subscription.publish('test', time, time, nil, view_data) }.
join
diff --git a/spec/lib/gitlab/url_sanitizer_spec.rb b/spec/lib/gitlab/url_sanitizer_spec.rb
deleted file mode 100644
index de55334118..0000000000
--- a/spec/lib/gitlab/url_sanitizer_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::UrlSanitizer, lib: true do
- let(:credentials) { { user: 'blah', password: 'password' } }
- let(:url_sanitizer) do
- described_class.new("https://github.com/me/project.git", credentials: credentials)
- end
-
- describe '.sanitize' do
- def sanitize_url(url)
- # We want to try with multi-line content because is how error messages are formatted
- described_class.sanitize(%Q{
- remote: Not Found
- fatal: repository '#{url}' not found
- })
- end
-
- it 'mask the credentials from HTTP URLs' do
- filtered_content = sanitize_url('http://user:pass@test.com/root/repoC.git/')
-
- expect(filtered_content).to include("http://*****:*****@test.com/root/repoC.git/")
- end
-
- it 'mask the credentials from HTTPS URLs' do
- filtered_content = sanitize_url('https://user:pass@test.com/root/repoA.git/')
-
- expect(filtered_content).to include("https://*****:*****@test.com/root/repoA.git/")
- end
-
- it 'mask credentials from SSH URLs' do
- filtered_content = sanitize_url('ssh://user@host.test/path/to/repo.git')
-
- expect(filtered_content).to include("ssh://*****@host.test/path/to/repo.git")
- end
-
- it 'does not modify Git URLs' do
- # git protocol does not support authentication
- filtered_content = sanitize_url('git://host.test/path/to/repo.git')
-
- expect(filtered_content).to include("git://host.test/path/to/repo.git")
- end
-
- it 'does not modify scp-like URLs' do
- filtered_content = sanitize_url('user@server:project.git')
-
- expect(filtered_content).to include("user@server:project.git")
- end
- end
-
- describe '#sanitized_url' do
- it { expect(url_sanitizer.sanitized_url).to eq("https://github.com/me/project.git") }
- end
-
- describe '#credentials' do
- it { expect(url_sanitizer.credentials).to eq(credentials) }
- end
-
- describe '#full_url' do
- it { expect(url_sanitizer.full_url).to eq("https://blah:password@github.com/me/project.git") }
-
- it 'supports scp-like URLs' do
- sanitizer = described_class.new('user@server:project.git')
-
- expect(sanitizer.full_url).to eq('user@server:project.git')
- end
- end
-
-end
diff --git a/spec/lib/json_web_token/rsa_token_spec.rb b/spec/lib/json_web_token/rsa_token_spec.rb
deleted file mode 100644
index 1872675451..0000000000
--- a/spec/lib/json_web_token/rsa_token_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-describe JSONWebToken::RSAToken do
- let(:rsa_key) do
- OpenSSL::PKey::RSA.new <<-eos.strip_heredoc
- -----BEGIN RSA PRIVATE KEY-----
- MIIBOgIBAAJBAMA5sXIBE0HwgIB40iNidN4PGWzOyLQK0bsdOBNgpEXkDlZBvnak
- OUgAPF+rME4PB0Yl415DabUI40T5UNmlwxcCAwEAAQJAZtY2pSwIFm3JAXIh0cZZ
- iXcAfiJ+YzuqinUOS+eW2sBCAEzjcARlU/o6sFQgtsOi4FOMczAd1Yx8UDMXMmrw
- 2QIhAPBgVhJiTF09pdmeFWutCvTJDlFFAQNbrbo2X2x/9WF9AiEAzLgqMKeStSRu
- H9N16TuDrUoO8R+DPqriCwkKrSHaWyMCIFzMhE4inuKcSywBaLmiG4m3GQzs++Al
- A6PRG/PSTpQtAiBxtBg6zdf+JC3GH3zt/dA0/10tL4OF2wORfYQghRzyYQIhAL2l
- 0ZQW+yLIZAGrdBFWYEAa52GZosncmzBNlsoTgwE4
- -----END RSA PRIVATE KEY-----
- eos
- end
- let(:rsa_token) { described_class.new(nil) }
- let(:rsa_encoded) { rsa_token.encoded }
-
- before { allow_any_instance_of(described_class).to receive(:key).and_return(rsa_key) }
-
- context 'token' do
- context 'for valid key to be validated' do
- before { rsa_token['key'] = 'value' }
-
- subject { JWT.decode(rsa_encoded, rsa_key) }
-
- it { expect{subject}.not_to raise_error }
- it { expect(subject.first).to include('key' => 'value') }
- it do
- expect(subject.second).to eq(
- "typ" => "JWT",
- "alg" => "RS256",
- "kid" => "OGXY:4TR7:FAVO:WEM2:XXEW:E4FP:TKL7:7ACK:TZAF:D54P:SUIA:P3B2")
- end
- end
-
- context 'for invalid key to raise an exception' do
- let(:new_key) { OpenSSL::PKey::RSA.generate(512) }
- subject { JWT.decode(rsa_encoded, new_key) }
-
- it { expect{subject}.to raise_error(JWT::DecodeError) }
- end
- end
-end
diff --git a/spec/lib/json_web_token/token_spec.rb b/spec/lib/json_web_token/token_spec.rb
deleted file mode 100644
index 3d955e4d77..0000000000
--- a/spec/lib/json_web_token/token_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-describe JSONWebToken::Token do
- let(:token) { described_class.new }
-
- context 'custom parameters' do
- let(:value) { 'value' }
- before { token[:key] = value }
-
- it { expect(token[:key]).to eq(value) }
- it { expect(token.payload).to include(key: value) }
- end
-
- context 'embeds default payload' do
- subject { token.payload }
- let(:default) { token.send(:default_payload) }
-
- it { is_expected.to include(default) }
- end
-end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 818825b147..495c5cbac0 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -51,7 +51,7 @@ describe Notify do
context 'when enabled email_author_in_body' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true)
+ allow(current_application_settings).to receive(:email_author_in_body).and_return(true)
end
it 'contains a link to note author' do
@@ -230,7 +230,7 @@ describe Notify do
context 'when enabled email_author_in_body' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true)
+ allow(current_application_settings).to receive(:email_author_in_body).and_return(true)
end
it 'contains a link to note author' do
@@ -454,7 +454,7 @@ describe Notify do
context 'when enabled email_author_in_body' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true)
+ allow(current_application_settings).to receive(:email_author_in_body).and_return(true)
end
it 'contains a link to note author' do
@@ -593,7 +593,7 @@ describe Notify do
let(:user) { create(:user) }
let(:tree_path) { namespace_project_tree_path(project.namespace, project, "master") }
- subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :create) }
+ subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :create) }
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
@@ -606,6 +606,10 @@ describe Notify do
expect(sender.address).to eq(gitlab_sender)
end
+ it 'is sent to recipient' do
+ is_expected.to deliver_to 'devs@company.name'
+ end
+
it 'has the correct subject' do
is_expected.to have_subject /Pushed new branch master/
end
@@ -620,7 +624,7 @@ describe Notify do
let(:user) { create(:user) }
let(:tree_path) { namespace_project_tree_path(project.namespace, project, "v1.0") }
- subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :create) }
+ subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :create) }
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
@@ -633,6 +637,10 @@ describe Notify do
expect(sender.address).to eq(gitlab_sender)
end
+ it 'is sent to recipient' do
+ is_expected.to deliver_to 'devs@company.name'
+ end
+
it 'has the correct subject' do
is_expected.to have_subject /Pushed new tag v1\.0/
end
@@ -646,7 +654,7 @@ describe Notify do
let(:example_site_path) { root_path }
let(:user) { create(:user) }
- subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :delete) }
+ subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :delete) }
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
@@ -659,6 +667,10 @@ describe Notify do
expect(sender.address).to eq(gitlab_sender)
end
+ it 'is sent to recipient' do
+ is_expected.to deliver_to 'devs@company.name'
+ end
+
it 'has the correct subject' do
is_expected.to have_subject /Deleted branch master/
end
@@ -668,7 +680,7 @@ describe Notify do
let(:example_site_path) { root_path }
let(:user) { create(:user) }
- subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) }
+ subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) }
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
@@ -681,6 +693,10 @@ describe Notify do
expect(sender.address).to eq(gitlab_sender)
end
+ it 'is sent to recipient' do
+ is_expected.to deliver_to 'devs@company.name'
+ end
+
it 'has the correct subject' do
is_expected.to have_subject /Deleted tag v1\.0/
end
@@ -693,9 +709,8 @@ describe Notify do
let(:commits) { Commit.decorate(compare.commits, nil) }
let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base, project), to: Commit.new(compare.head, project)) }
let(:send_from_committer_email) { false }
- let(:diff_refs) { [project.merge_base_commit(sample_image_commit.id, sample_commit.id), project.commit(sample_commit.id)] }
- subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, diff_refs: diff_refs, send_from_committer_email: send_from_committer_email) }
+ subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, send_from_committer_email: send_from_committer_email) }
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
@@ -708,6 +723,10 @@ describe Notify do
expect(sender.address).to eq(gitlab_sender)
end
+ it 'is sent to recipient' do
+ is_expected.to deliver_to 'devs@company.name'
+ end
+
it 'has the correct subject' do
is_expected.to have_subject /\[#{project.path_with_namespace}\]\[master\] #{commits.length} commits:/
end
@@ -716,15 +735,15 @@ describe Notify do
is_expected.to have_body_text /Change some files/
end
- it 'includes diffs with character-level highlighting' do
- is_expected.to have_body_text /def<\/span> archive_formats_regex/
+ it 'includes diffs' do
+ is_expected.to have_body_text /def archive_formats_regex/
end
it 'contains a link to the diff' do
is_expected.to have_body_text /#{diff_path}/
end
- it 'does not contain the misleading footer' do
+ it 'doesn not contain the misleading footer' do
is_expected.not_to have_body_text /you are a member of/
end
@@ -798,9 +817,8 @@ describe Notify do
let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_commit.parent_id, sample_commit.id) }
let(:commits) { Commit.decorate(compare.commits, nil) }
let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) }
- let(:diff_refs) { [project.merge_base_commit(sample_commit.parent_id, sample_commit.id), project.commit(sample_commit.id)] }
- subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, diff_refs: diff_refs) }
+ subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare) }
it_behaves_like 'it should show Gmail Actions View Commit link'
it_behaves_like "a user cannot unsubscribe through footer link"
@@ -813,6 +831,10 @@ describe Notify do
expect(sender.address).to eq(gitlab_sender)
end
+ it 'is sent to recipient' do
+ is_expected.to deliver_to 'devs@company.name'
+ end
+
it 'has the correct subject' do
is_expected.to have_subject /#{commits.first.title}/
end
@@ -821,8 +843,8 @@ describe Notify do
is_expected.to have_body_text /Change some files/
end
- it 'includes diffs with character-level highlighting' do
- is_expected.to have_body_text /def<\/span> archive_formats_regex/
+ it 'includes diffs' do
+ is_expected.to have_body_text /def archive_formats_regex/
end
it 'contains a link to the diff' do
diff --git a/spec/mailers/previews/devise_mailer_preview.rb b/spec/mailers/previews/devise_mailer_preview.rb
deleted file mode 100644
index dc3062a433..0000000000
--- a/spec/mailers/previews/devise_mailer_preview.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class DeviseMailerPreview < ActionMailer::Preview
- def confirmation_instructions_for_signup
- user = User.new(name: 'Jane Doe', email: 'signup@example.com')
- DeviseMailer.confirmation_instructions(user, 'faketoken', {})
- end
-
- def confirmation_instructions_for_new_email
- user = User.last
- DeviseMailer.confirmation_instructions(user, 'faketoken', {})
- end
-end
diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb
index 93de5850ba..5a85cb501d 100644
--- a/spec/mailers/shared/notify.rb
+++ b/spec/mailers/shared/notify.rb
@@ -146,8 +146,8 @@ shared_examples 'it should have Gmail Actions links' do
end
shared_examples 'it should not have Gmail Actions links' do
- it { is_expected.not_to have_body_text '