diff options
66 files changed, 884 insertions, 703 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index 3aac8401848..db0bcfadcf4 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -2,6 +2,8 @@ require: - rubocop-rspec - ./rubocop/rubocop +inherit_from: .rubocop_todo.yml + AllCops: TargetRubyVersion: 2.1 # Cop names are not displayed in offense messages by default. Change behavior @@ -52,14 +54,6 @@ Style/AlignArray: Style/AlignHash: Enabled: true -# Align the parameters of a method call if they span more than one line. -Style/AlignParameters: - Enabled: false - -# Use &&/|| instead of and/or. -Style/AndOr: - Enabled: false - # Use `Array#join` instead of `Array#*`. Style/ArrayJoin: Enabled: true @@ -80,10 +74,6 @@ Style/Attr: Style/BeginBlock: Enabled: true -# Checks if usage of %() or %Q() matches configuration. -Style/BarePercentLiterals: - Enabled: false - # Do not use block comments. Style/BlockComments: Enabled: true @@ -97,14 +87,6 @@ Style/BlockEndNewline: Style/BlockDelimiters: Enabled: true -# Enforce braces style around hash parameters. -Style/BracesAroundHashParameters: - Enabled: false - -# Avoid explicit use of the case equality operator(===). -Style/CaseEquality: - Enabled: false - # Indentation of when in a case/when/[else/]end. Style/CaseIndentation: Enabled: true @@ -133,24 +115,10 @@ Style/ClassMethods: Style/ClassVars: Enabled: true -# Do not use :: for method call. -Style/ColonMethodCall: - Enabled: false - -# Checks formatting of special comments (TODO, FIXME, OPTIMIZE, HACK, REVIEW). -Style/CommentAnnotation: - Enabled: false - # Indentation of comments. Style/CommentIndentation: Enabled: true -# Use the return value of `if` and `case` statements for assignment to a -# variable and variable comparison instead of assigning that variable -# inside of each branch. -Style/ConditionalAssignment: - Enabled: false - # Constants should use SCREAMING_SNAKE_CASE. Style/ConstantName: Enabled: true @@ -159,34 +127,14 @@ Style/ConstantName: Style/DefWithParentheses: Enabled: true -# Checks for use of deprecated Hash methods. -Style/DeprecatedHashMethods: - Enabled: false - # Document classes and non-namespace modules. Style/Documentation: Enabled: false -# Checks the position of the dot in multi-line method calls. -Style/DotPosition: - Enabled: false - -# Checks for uses of double negation (!!). -Style/DoubleNegation: - Enabled: false - -# Prefer `each_with_object` over `inject` or `reduce`. -Style/EachWithObject: - Enabled: false - # Align elses and elsifs correctly. Style/ElseAlignment: Enabled: true -# Avoid empty else-clauses. -Style/EmptyElse: - Enabled: false - # Use empty lines between defs. Style/EmptyLineBetweenDefs: Enabled: false @@ -215,10 +163,6 @@ Style/EmptyLinesAroundModuleBody: Style/EmptyLinesAroundMethodBody: Enabled: false -# Prefer literals to Array.new/Hash.new/String.new. -Style/EmptyLiteral: - Enabled: false - # Avoid the use of END blocks. Style/EndBlock: Enabled: true @@ -231,10 +175,6 @@ Style/EndOfLine: Style/EvenOdd: Enabled: true -# Do not use unnecessary spacing. -Style/ExtraSpacing: - Enabled: false - # Use snake_case for source file names. Style/FileName: Enabled: true @@ -252,31 +192,15 @@ Style/FlipFlop: Style/For: Enabled: true -# Enforce the use of Kernel#sprintf, Kernel#format or String#%. -Style/FormatString: - Enabled: false - # Do not introduce global variables. Style/GlobalVars: Enabled: true -# Check for conditionals that can be replaced with guard clauses. -Style/GuardClause: - Enabled: false - # Prefer Ruby 1.9 hash syntax `{ a: 1, b: 2 }` # over 1.8 syntax `{ :a => 1, :b => 2 }`. Style/HashSyntax: Enabled: true -# Finds if nodes inside else, which can be converted to elsif. -Style/IfInsideElse: - Enabled: false - -# Favor modifier if/unless usage when you have a single-line body. -Style/IfUnlessModifier: - Enabled: false - # Do not use if x; .... Use the ternary operator instead. Style/IfWithSemicolon: Enabled: true @@ -299,22 +223,10 @@ Style/IndentationConsistency: Style/IndentationWidth: Enabled: true -# Checks the indentation of the first element in an array literal. -Style/IndentArray: - Enabled: false - -# Checks the indentation of the first key in a hash literal. -Style/IndentHash: - Enabled: false - # Use Kernel#loop for infinite loops. Style/InfiniteLoop: Enabled: true -# Use the new lambda literal syntax for single-line blocks. -Style/Lambda: - Enabled: false - # Use lambda.call(...) instead of lambda.(...). Style/LambdaCall: Enabled: true @@ -323,14 +235,6 @@ Style/LambdaCall: Style/LeadingCommentSpace: Enabled: true -# Use \ instead of + or << to concatenate two string literals at line end. -Style/LineEndConcatenation: - Enabled: false - -# Do not use parentheses for method calls with no arguments. -Style/MethodCallParentheses: - Enabled: false - # Checks if the method definitions have or don't have parentheses. Style/MethodDefParentheses: Enabled: true @@ -387,39 +291,18 @@ Style/MultilineMethodDefinitionBraceLayout: Style/MultilineOperationIndentation: Enabled: false -# Avoid multi-line `? :` (the ternary operator), use if/unless instead. -Style/MultilineTernaryOperator: - Enabled: false - -# Do not assign mutable objects to constants. -Style/MutableConstant: - Enabled: false - # Favor unless over if for negative conditions (or control flow or). Style/NegatedIf: Enabled: true -# Favor until over while for negative conditions. -Style/NegatedWhile: - Enabled: false - # Avoid using nested modifiers. Style/NestedModifier: Enabled: true -# Parenthesize method calls which are nested inside the argument list of -# another parenthesized method call. -Style/NestedParenthesizedCalls: - Enabled: false - # Use one expression per branch in a ternary operator. Style/NestedTernaryOperator: Enabled: true -# Use `next` to skip iteration instead of a condition at the end. -Style/Next: - Enabled: false - # Prefer x.nil? to x == nil. Style/NilComparison: Enabled: true @@ -444,51 +327,10 @@ Style/OneLineConditional: Style/OpMethod: Enabled: true -# Check for simple usages of parallel assignment. It will only warn when -# the number of variables matches on both sides of the assignment. -Style/ParallelAssignment: - Enabled: false - # Don't use parentheses around the condition of an if/unless/while. Style/ParenthesesAroundCondition: Enabled: true -# Use `%`-literal delimiters consistently. -Style/PercentLiteralDelimiters: - Enabled: false - -# Checks if uses of %Q/%q match the configured preference. -Style/PercentQLiterals: - Enabled: false - -# Avoid Perl-style regex back references. -Style/PerlBackrefs: - Enabled: false - -# Check the names of predicate methods. -Style/PredicateName: - Enabled: false - -# Use proc instead of Proc.new. -Style/Proc: - Enabled: false - -# Checks the arguments passed to raise/fail. -Style/RaiseArgs: - Enabled: false - -# Don't use begin blocks when they are not needed. -Style/RedundantBegin: - Enabled: false - -# Checks for an obsolete RuntimeException argument in raise/fail. -Style/RedundantException: - Enabled: false - -# Checks usages of Object#freeze on immutable objects. -Style/RedundantFreeze: - Enabled: false - # Checks for parentheses that seem not to serve any purpose. Style/RedundantParentheses: Enabled: true @@ -497,24 +339,6 @@ Style/RedundantParentheses: Style/RedundantReturn: Enabled: true -# Don't use self where it's not needed. -Style/RedundantSelf: - Enabled: false - -# Use %r for regular expressions matching more than `MaxSlashes` '/' -# characters. Use %r only for regular expressions matching more -# than `MaxSlashes` '/' character. -Style/RegexpLiteral: - Enabled: false - -# Avoid using rescue in its modifier form. -Style/RescueModifier: - Enabled: false - -# Checks for places where self-assignment shorthand should have been used. -Style/SelfAssignment: - Enabled: false - # Don't use semicolons to terminate expressions. Style/Semicolon: Enabled: true @@ -524,14 +348,6 @@ Style/SignalException: EnforcedStyle: only_raise Enabled: true -# Enforces the names of some block params. -Style/SingleLineBlockParams: - Enabled: false - -# Avoid single-line methods. -Style/SingleLineMethods: - Enabled: false - # Use spaces after colons. Style/SpaceAfterColon: Enabled: true @@ -553,11 +369,6 @@ Style/SpaceAfterNot: Style/SpaceAfterSemicolon: Enabled: true -# Checks that the equals signs in parameter default assignments have or don't -# have surrounding space depending on configuration. -Style/SpaceAroundEqualsInParameterDefault: - Enabled: false - # Use a space around keywords if appropriate. Style/SpaceAroundKeyword: Enabled: true @@ -566,10 +377,6 @@ Style/SpaceAroundKeyword: Style/SpaceAroundOperators: Enabled: true -# Checks that the left block brace has or doesn't have space before it. -Style/SpaceBeforeBlockBraces: - Enabled: false - # No spaces before commas. Style/SpaceBeforeComma: Enabled: true @@ -578,33 +385,14 @@ Style/SpaceBeforeComma: Style/SpaceBeforeComment: Enabled: true -# Checks that exactly one space is used between a method name and the first -# argument for method calls without parentheses. -Style/SpaceBeforeFirstArg: - Enabled: false - # No spaces before semicolons. Style/SpaceBeforeSemicolon: Enabled: true -# Checks that block braces have or don't have surrounding space. -# For blocks taking parameters, checks that the left brace has or doesn't -# have trailing space. -Style/SpaceInsideBlockBraces: - Enabled: false - -# No spaces after [ or before ]. -Style/SpaceInsideBrackets: - Enabled: false - # Use spaces inside hash literal braces - or don't. Style/SpaceInsideHashLiteralBraces: Enabled: true -# No spaces after ( or before ). -Style/SpaceInsideParens: - Enabled: false - # No spaces inside range literals. Style/SpaceInsideRangeLiteral: Enabled: true @@ -614,10 +402,6 @@ Style/SpaceInsideStringInterpolation: EnforcedStyle: no_space Enabled: true -# Avoid Perl-style global variables. -Style/SpecialGlobalVars: - Enabled: false - # Check for the usage of parentheses around stabby lambda arguments. Style/StabbyLambdaParentheses: EnforcedStyle: require_parentheses @@ -627,25 +411,12 @@ Style/StabbyLambdaParentheses: Style/StringLiterals: Enabled: false -# Checks if uses of quotes inside expressions in interpolated strings match the -# configured preference. -Style/StringLiteralsInInterpolation: - Enabled: false - # Checks if configured preferred methods are used over non-preferred. Style/StringMethods: PreferredMethods: intern: to_sym Enabled: true -# Use %i or %I for arrays of symbols. -Style/SymbolArray: - Enabled: false - -# Use symbols as procs instead of blocks when possible. -Style/SymbolProc: - Enabled: false - # No hard tabs. Style/Tab: Enabled: true @@ -654,40 +425,10 @@ Style/Tab: Style/TrailingBlankLines: Enabled: true -# Checks for trailing comma in array and hash literals. -Style/TrailingCommaInLiteral: - Enabled: false - -# Checks for trailing comma in argument lists. -Style/TrailingCommaInArguments: - Enabled: false - -# Avoid trailing whitespace. -Style/TrailingWhitespace: - Enabled: false - -# Checks for the usage of unneeded trailing underscores at the end of -# parallel variable assignment. -Style/TrailingUnderscoreVariable: - Enabled: false - -# Prefer attr_* methods to trivial readers/writers. -Style/TrivialAccessors: - Enabled: false - -# Do not use unless with else. Rewrite these with the positive case first. -Style/UnlessElse: - Enabled: false - # Checks for %W when interpolation is not needed. Style/UnneededCapitalW: Enabled: true -# TODO: Enable UnneededInterpolation Cop. -# Checks for strings that are just an interpolated expression. -Style/UnneededInterpolation: - Enabled: false - # Checks for %q/%Q when single quotes or double quotes would do. Style/UnneededPercentQ: Enabled: false @@ -717,12 +458,6 @@ Style/WhileUntilModifier: Style/WordArray: Enabled: false -# TODO: Enable ZeroLengthPredicate Cop. -# Use #empty? when testing for objects of length 0. -Style/ZeroLengthPredicate: - Enabled: false - - #################### Metrics ################################ # A calculated magnitude based on number of assignments, @@ -776,15 +511,6 @@ Metrics/PerceivedComplexity: Lint/AmbiguousOperator: Enabled: true -# Checks for ambiguous regexp literals in the first argument of a method -# invocation without parentheses. -Lint/AmbiguousRegexpLiteral: - Enabled: false - -# Don't use assignment in conditions. -Lint/AssignmentInCondition: - Enabled: false - # Align block ends correctly. Lint/BlockAlignment: Enabled: true @@ -810,14 +536,6 @@ Lint/DefEndAlignment: Lint/DeprecatedClassMethods: Enabled: true -# Check for duplicate method definitions. -Lint/DuplicateMethods: - Enabled: false - -# Check for duplicate keys in hash literals. -Lint/DuplicatedKey: - Enabled: false - # Check for immutable argument given to each_with_object. Lint/EachWithObjectArgument: Enabled: true @@ -830,10 +548,6 @@ Lint/ElseLayout: Lint/EmptyEnsure: Enabled: true -# Checks for empty string interpolation. -Lint/EmptyInterpolation: - Enabled: false - # Align ends correctly. Lint/EndAlignment: Enabled: true @@ -858,21 +572,11 @@ Lint/FloatOutOfRange: Lint/FormatParameterMismatch: Enabled: true -# Don't suppress exception. -Lint/HandleExceptions: - Enabled: false - # Checks for adjacent string literals on the same line, which could better be # represented as a single string literal. Lint/ImplicitStringConcatenation: Enabled: true -# TODO: Enable IneffectiveAccessModifier Cop. -# Checks for attempts to use `private` or `protected` to set the visibility -# of a class method, which does not work. -Lint/IneffectiveAccessModifier: - Enabled: false - # Checks for invalid character literals with a non-escaped whitespace # character. Lint/InvalidCharacterLiteral: @@ -886,11 +590,6 @@ Lint/LiteralInCondition: Lint/LiteralInInterpolation: Enabled: true -# Use Kernel#loop with break rather than begin/end/until or begin/end/while -# for post-loop tests. -Lint/Loop: - Enabled: false - # Do not use nested method definitions. Lint/NestedMethodDefinition: Enabled: true @@ -916,13 +615,8 @@ Lint/RequireParentheses: Lint/RescueException: Enabled: true -# Do not use the same name as outer local variable for block arguments -# or block local variables. -Lint/ShadowingOuterLocalVariable: - Enabled: false - -# 'Checks for Object#to_s usage in string interpolation. -Lint/StringConversionInInterpolation: +# Checks for the order which exceptions are rescued to avoid rescueing a less specific exception before a more specific exception. +Lint/ShadowedException: Enabled: false # Do not use prefix `_` for a variable that is used. @@ -935,22 +629,10 @@ Lint/UnderscorePrefixedVariableName: Lint/UnneededDisable: Enabled: false -# Checks for unused block arguments. -Lint/UnusedBlockArgument: - Enabled: false - -# Checks for unused method arguments. -Lint/UnusedMethodArgument: - Enabled: false - # Unreachable code. Lint/UnreachableCode: Enabled: true -# Checks for useless access modifiers. -Lint/UselessAccessModifier: - Enabled: false - # Checks for useless assignment to a local variable. Lint/UselessAssignment: Enabled: true @@ -983,11 +665,6 @@ Performance/Casecmp: Performance/DoubleStartEndWith: Enabled: true -# TODO: Enable EndWith Cop. -# Use `end_with?` instead of a regex match anchored to the end of a string. -Performance/EndWith: - Enabled: false - # Use `strip` instead of `lstrip.rstrip`. Performance/LstripRstrip: Enabled: true @@ -996,24 +673,6 @@ Performance/LstripRstrip: Performance/RangeInclude: Enabled: true -# TODO: Enable RedundantBlockCall Cop. -# Use `yield` instead of `block.call`. -Performance/RedundantBlockCall: - Enabled: false - -# TODO: Enable RedundantMatch Cop. -# Use `=~` instead of `String#match` or `Regexp#match` in a context where the -# returned `MatchData` is not needed. -Performance/RedundantMatch: - Enabled: false - -# TODO: Enable RedundantMerge Cop. -# Use `Hash#[]=`, rather than `Hash#merge!` with a single key-value pair. -Performance/RedundantMerge: - # Max number of key-value pairs to consider an offense - MaxKeyValuePairs: 2 - Enabled: false - # Use `sort` instead of `sort_by { |x| x }`. Performance/RedundantSortBy: Enabled: true @@ -1082,18 +741,6 @@ Rails/ReadWriteAttribute: Rails/ScopeArgs: Enabled: true -# Checks the correct usage of time zone aware methods. -# http://danilenko.org/2012/7/6/rails_timezones -Rails/TimeZone: - Enabled: false - -# Use validates :attribute, hash of validations. -Rails/Validation: - Enabled: false - -Rails/UniqBeforePluck: - Enabled: false - ##################### RSpec ################################## # Check that instances are not being stubbed globally. diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000000..9310e711889 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,462 @@ +# This configuration was generated by +# `rubocop --auto-gen-config --exclude-limit 0` +# on 2016-07-13 12:36:08 -0600 using RuboCop version 0.41.2. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 154 +Lint/AmbiguousRegexpLiteral: + Enabled: false + +# Offense count: 43 +# Configuration parameters: AllowSafeAssignment. +Lint/AssignmentInCondition: + Enabled: false + +# Offense count: 14 +Lint/HandleExceptions: + Enabled: false + +# Offense count: 21 +Lint/IneffectiveAccessModifier: + Enabled: false + +# Offense count: 2 +Lint/Loop: + Enabled: false + +# Offense count: 15 +Lint/ShadowingOuterLocalVariable: + Enabled: false + +# Offense count: 3 +# Cop supports --auto-correct. +Lint/StringConversionInInterpolation: + Enabled: false + +# Offense count: 44 +# Cop supports --auto-correct. +# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. +Lint/UnusedBlockArgument: + Enabled: false + +# Offense count: 129 +# Cop supports --auto-correct. +# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods. +Lint/UnusedMethodArgument: + Enabled: false + +# Offense count: 11 +Lint/UselessAccessModifier: + Enabled: false + +# Offense count: 12 +# Cop supports --auto-correct. +Performance/PushSplat: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +Performance/RedundantBlockCall: + Enabled: false + +# Offense count: 4 +# Cop supports --auto-correct. +Performance/RedundantMatch: + Enabled: false + +# Offense count: 24 +# Cop supports --auto-correct. +# Configuration parameters: MaxKeyValuePairs. +Performance/RedundantMerge: + Enabled: false + +# Offense count: 60 +Rails/OutputSafety: + Enabled: false + +# Offense count: 128 +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: strict, flexible +Rails/TimeZone: + Enabled: false + +# Offense count: 12 +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/Validation: + Enabled: false + +# Offense count: 217 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. +# SupportedStyles: with_first_parameter, with_fixed_indentation +Style/AlignParameters: + Enabled: false + +# Offense count: 32 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: always, conditionals +Style/AndOr: + Enabled: false + +# Offense count: 47 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: percent_q, bare_percent +Style/BarePercentLiterals: + Enabled: false + +# Offense count: 258 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: braces, no_braces, context_dependent +Style/BracesAroundHashParameters: + Enabled: false + +# Offense count: 5 +Style/CaseEquality: + Enabled: false + +# Offense count: 19 +# Cop supports --auto-correct. +Style/ColonMethodCall: + Enabled: false + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: Keywords. +# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW +Style/CommentAnnotation: + Enabled: false + +# Offense count: 34 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, SingleLineConditionsOnly. +# SupportedStyles: assign_to_condition, assign_inside_condition +Style/ConditionalAssignment: + Enabled: false + +# Offense count: 789 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: leading, trailing +Style/DotPosition: + Enabled: false + +# Offense count: 13 +Style/DoubleNegation: + Enabled: false + +# Offense count: 3 +Style/EachWithObject: + Enabled: false + +# Offense count: 30 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: empty, nil, both +Style/EmptyElse: + Enabled: false + +# Offense count: 3 +# Cop supports --auto-correct. +Style/EmptyLiteral: + Enabled: false + +# Offense count: 123 +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment. +Style/ExtraSpacing: + Enabled: false + +# Offense count: 7 +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: format, sprintf, percent +Style/FormatString: + Enabled: false + +# Offense count: 48 +# Configuration parameters: MinBodyLength. +Style/GuardClause: + Enabled: false + +# Offense count: 11 +Style/IfInsideElse: + Enabled: false + +# Offense count: 177 +# Cop supports --auto-correct. +# Configuration parameters: MaxLineLength. +Style/IfUnlessModifier: + Enabled: false + +# Offense count: 52 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_brackets +Style/IndentArray: + Enabled: false + +# Offense count: 89 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_braces +Style/IndentHash: + Enabled: false + +# Offense count: 12 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: line_count_dependent, lambda, literal +Style/Lambda: + Enabled: false + +# Offense count: 6 +# Cop supports --auto-correct. +Style/LineEndConcatenation: + Enabled: false + +# Offense count: 13 +# Cop supports --auto-correct. +Style/MethodCallParentheses: + Enabled: false + +# Offense count: 3 +Style/MultilineTernaryOperator: + Enabled: false + +# Offense count: 62 +# Cop supports --auto-correct. +Style/MutableConstant: + Enabled: false + +# Offense count: 10 +# Cop supports --auto-correct. +Style/NestedParenthesizedCalls: + Enabled: false + +# Offense count: 12 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles. +# SupportedStyles: skip_modifier_ifs, always +Style/Next: + Enabled: false + +# Offense count: 8 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedOctalStyle, SupportedOctalStyles. +# SupportedOctalStyles: zero_with_o, zero_only +Style/NumericLiteralPrefix: + Enabled: false + +# Offense count: 29 +# Cop supports --auto-correct. +Style/ParallelAssignment: + Enabled: false + +# Offense count: 208 +# Cop supports --auto-correct. +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Enabled: false + +# Offense count: 11 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: lower_case_q, upper_case_q +Style/PercentQLiterals: + Enabled: false + +# Offense count: 13 +# Cop supports --auto-correct. +Style/PerlBackrefs: + Enabled: false + +# Offense count: 32 +# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist. +# NamePrefix: is_, has_, have_ +# NamePrefixBlacklist: is_, has_, have_ +# NameWhitelist: is_a? +Style/PredicateName: + Enabled: false + +# Offense count: 28 +# Cop supports --auto-correct. +Style/PreferredHashMethods: + Enabled: false + +# Offense count: 6 +# Cop supports --auto-correct. +Style/Proc: + Enabled: false + +# Offense count: 20 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: compact, exploded +Style/RaiseArgs: + Enabled: false + +# Offense count: 3 +# Cop supports --auto-correct. +Style/RedundantBegin: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +Style/RedundantException: + Enabled: false + +# Offense count: 23 +# Cop supports --auto-correct. +Style/RedundantFreeze: + Enabled: false + +# Offense count: 377 +# Cop supports --auto-correct. +Style/RedundantSelf: + Enabled: false + +# Offense count: 94 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes. +# SupportedStyles: slashes, percent_r, mixed +Style/RegexpLiteral: + Enabled: false + +# Offense count: 17 +# Cop supports --auto-correct. +Style/RescueModifier: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +Style/SelfAssignment: + Enabled: false + +# Offense count: 2 +# Configuration parameters: Methods. +# Methods: {"reduce"=>["a", "e"]}, {"inject"=>["a", "e"]} +Style/SingleLineBlockParams: + Enabled: false + +# Offense count: 50 +# Cop supports --auto-correct. +# Configuration parameters: AllowIfMethodIsEmpty. +Style/SingleLineMethods: + Enabled: false + +# Offense count: 14 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: space, no_space +Style/SpaceAroundEqualsInParameterDefault: + Enabled: false + +# Offense count: 119 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: space, no_space +Style/SpaceBeforeBlockBraces: + Enabled: false + +# Offense count: 11 +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment. +Style/SpaceBeforeFirstArg: + Enabled: false + +# Offense count: 130 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. +# SupportedStyles: space, no_space +Style/SpaceInsideBlockBraces: + Enabled: false + +# Offense count: 98 +# Cop supports --auto-correct. +Style/SpaceInsideBrackets: + Enabled: false + +# Offense count: 60 +# Cop supports --auto-correct. +Style/SpaceInsideParens: + Enabled: false + +# Offense count: 5 +# Cop supports --auto-correct. +Style/SpaceInsidePercentLiteralDelimiters: + Enabled: false + +# Offense count: 36 +# Cop supports --auto-correct. +# Configuration parameters: SupportedStyles. +# SupportedStyles: use_perl_names, use_english_names +Style/SpecialGlobalVars: + EnforcedStyle: use_perl_names + +# Offense count: 30 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiteralsInInterpolation: + Enabled: false + +# Offense count: 24 +# Cop supports --auto-correct. +# Configuration parameters: IgnoredMethods. +# IgnoredMethods: respond_to, define_method +Style/SymbolProc: + Enabled: false + +# Offense count: 23 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleForMultiline, SupportedStyles. +# SupportedStyles: comma, consistent_comma, no_comma +Style/TrailingCommaInArguments: + Enabled: false + +# Offense count: 113 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleForMultiline, SupportedStyles. +# SupportedStyles: comma, consistent_comma, no_comma +Style/TrailingCommaInLiteral: + Enabled: false + +# Offense count: 7 +# Cop supports --auto-correct. +# Configuration parameters: AllowNamedUnderscoreVariables. +Style/TrailingUnderscoreVariable: + Enabled: false + +# Offense count: 90 +# Cop supports --auto-correct. +Style/TrailingWhitespace: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist. +# Whitelist: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym +Style/TrivialAccessors: + Enabled: false + +# Offense count: 3 +# Cop supports --auto-correct. +Style/UnlessElse: + Enabled: false + +# Offense count: 13 +# Cop supports --auto-correct. +Style/UnneededInterpolation: + Enabled: false + +# Offense count: 8 +# Cop supports --auto-correct. +Style/ZeroLengthPredicate: + Enabled: false diff --git a/CHANGELOG b/CHANGELOG index 7e784bd641d..457943c6b4b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,10 +2,11 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.10.0 (unreleased) - Expose {should,force}_remove_source_branch (Ben Boeckel) + - Disable PostgreSQL statement timeout during migrations - Fix projects dropdown loading performance with a simplified api cal. !5113 (tiagonbotelho) - Fix commit builds API, return all builds for all pipelines for given commit. !4849 - Replace Haml with Hamlit to make view rendering faster. !3666 - - Expire the branch cache after `git gc` runs + - Refresh the branch cache after `git gc` runs - Refactor repository paths handling to allow multiple git mount points - Optimize system note visibility checking by memoizing the visible reference count !5070 - Add Application Setting to configure default Repository Path for new projects @@ -30,9 +31,12 @@ v 8.10.0 (unreleased) - Add Spring EmojiOne updates. - Add syntax for multiline blockquote using `>>>` fence !3954 - Fix viewing notification settings when a project is pending deletion + - Updated compare dropdown menus to use GL dropdown + - Eager load award emoji on notes - Fix pagination when sorting by columns with lots of ties (like priority) - The Markdown reference parsers now re-use query results to prevent running the same queries multiple times !5020 - Updated project header design + - Issuable collapsed assignee tooltip is now the users name - Exclude email check from the standard health check - Updated layout for Projects, Groups, Users on Admin area !4424 - Fix changing issue state columns in milestone view @@ -91,6 +95,8 @@ v 8.10.0 (unreleased) - Redesign Builds and Pipelines pages - Change status color and icon for running builds - Fix markdown rendering for: consecutive labels references, label references that begin with a digit or contains `.` + - Fix last update timestamp on issues not preserved on gitlab.com and project imports + - Fix issues importing projects from EE to CE - Fix creating group with space in group path v 8.9.6 @@ -299,7 +299,7 @@ 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', '~> 0.41.2', require: false gem 'rubocop-rspec', '~> 1.5.0', require: false gem 'scss_lint', '~> 0.47.0', require: false gem 'simplecov', '~> 0.11.0', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 67c0645c3d9..8430881e677 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -58,7 +58,7 @@ GEM faraday_middleware-multi_json (~> 0.0) oauth2 (~> 1.0) asciidoctor (1.5.3) - ast (2.2.0) + ast (2.3.0) attr_encrypted (3.0.1) encryptor (~> 3.0.0) attr_required (1.0.0) @@ -473,7 +473,7 @@ GEM orm_adapter (0.5.0) paranoia (2.1.4) activerecord (~> 4.0) - parser (2.3.1.0) + parser (2.3.1.2) ast (~> 2.2) pg (0.18.4) pkg-config (1.1.7) @@ -606,8 +606,8 @@ GEM rspec-retry (0.4.5) rspec-core rspec-support (3.5.0) - rubocop (0.40.0) - parser (>= 2.3.1.0, < 3.0) + rubocop (0.41.2) + parser (>= 2.3.1.1, < 3.0) powerpack (~> 0.1) rainbow (>= 1.99.1, < 3.0) ruby-progressbar (~> 1.7) @@ -758,7 +758,7 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.2) - unicode-display_width (1.0.5) + unicode-display_width (1.1.0) unicorn (4.9.0) kgio (~> 2.6) rack @@ -937,7 +937,7 @@ DEPENDENCIES rqrcode-rails3 (~> 0.1.7) rspec-rails (~> 3.5.0) rspec-retry (~> 0.4.5) - rubocop (~> 0.40.0) + rubocop (~> 0.41.2) rubocop-rspec (~> 1.5.0) ruby-fogbugz (~> 0.2.1) sanitize (~> 2.0) diff --git a/app/assets/javascripts/compare_autocomplete.js.coffee b/app/assets/javascripts/compare_autocomplete.js.coffee new file mode 100644 index 00000000000..7ad9fd97637 --- /dev/null +++ b/app/assets/javascripts/compare_autocomplete.js.coffee @@ -0,0 +1,41 @@ +class @CompareAutocomplete + constructor: -> + @initDropdown() + + initDropdown: -> + $('.js-compare-dropdown').each -> + $dropdown = $(@) + selected = $dropdown.data('selected') + + $dropdown.glDropdown( + data: (term, callback) -> + $.ajax( + url: $dropdown.data('refs-url') + data: + ref: $dropdown.data('ref') + ).done (refs) -> + callback(refs) + selectable: true + filterable: true + filterByText: true + fieldName: $dropdown.attr('name') + filterInput: 'input[type="text"]' + renderRow: (ref) -> + if ref.header? + $('<li />') + .addClass('dropdown-header') + .text(ref.header) + else + link = $('<a />') + .attr('href', '#') + .addClass(if ref is selected then 'is-active' else '') + .text(ref) + .attr('data-ref', escape(ref)) + + $('<li />') + .append(link) + id: (obj, $el) -> + $el.attr('data-ref') + toggleLabel: (obj, $el) -> + $el.text().trim() + ) diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 74fd77cf7ab..b5da15e9e49 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -39,6 +39,8 @@ class Dispatcher shortcut_handler = new ShortcutsNavigation() new GLForm($('.issue-form')) new IssuableForm($('.issue-form')) + new LabelsSelect() + new MilestoneSelect() when 'projects:merge_requests:new', 'projects:merge_requests:edit' new Diff() shortcut_handler = new ShortcutsNavigation() @@ -137,6 +139,8 @@ class Dispatcher new Project() new ProjectAvatar() switch path[1] + when 'compare' + new CompareAutocomplete() when 'edit' shortcut_handler = new ShortcutsNavigation() new ProjectNew() diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee index 1c65e833d47..1b0d0db8954 100644 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -456,6 +456,8 @@ class GitLabDropdown rowClicked: (el) -> fieldName = @options.fieldName + isInput = $(@el).is('input') + if @renderedData groupName = el.data('group') if groupName @@ -466,10 +468,19 @@ class GitLabDropdown selectedObject = @renderedData[selectedIndex] value = if @options.id then @options.id(selectedObject, el) else selectedObject.id - field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']") + + if isInput + field = $(@el) + else + field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']") + if el.hasClass(ACTIVE_CLASS) el.removeClass(ACTIVE_CLASS) - field.remove() + + if isInput + field.val('') + else + field.remove() # Toggle the dropdown label if @options.toggleLabel @@ -490,7 +501,9 @@ class GitLabDropdown else if not @options.multiSelect or el.hasClass('dropdown-clear-active') @dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS - @dropdown.parent().find("input[name='#{fieldName}']").remove() + + unless isInput + @dropdown.parent().find("input[name='#{fieldName}']").remove() if !value? field.remove() @@ -505,7 +518,9 @@ class GitLabDropdown if !field.length and fieldName @addInput(fieldName, value) else - field.val value + field + .val value + .trigger 'change' return selectedObject diff --git a/app/assets/javascripts/labels_select.js.coffee b/app/assets/javascripts/labels_select.js.coffee index 7688609b301..1a802b81452 100644 --- a/app/assets/javascripts/labels_select.js.coffee +++ b/app/assets/javascripts/labels_select.js.coffee @@ -184,20 +184,22 @@ class @LabelsSelect .value() if $dropdown.hasClass 'js-extra-options' - if showNo - data.unshift( - id: 0 - title: 'No Label' - ) - + extraData = [] if showAny - data.unshift( + extraData.push( isAny: true title: 'Any Label' ) - if data.length > 2 - data.splice 2, 0, 'divider' + if showNo + extraData.push( + id: 0 + title: 'No Label' + ) + + if extraData.length + extraData.push 'divider' + data = extraData.concat(data) callback data @@ -287,6 +289,12 @@ class @LabelsSelect defaultLabel fieldName: $dropdown.data('field-name') id: (label) -> + if $dropdown.hasClass('js-issuable-form-dropdown') + if label.id is 0 + return + else + return label.id + if $dropdown.hasClass("js-filter-submit") and not label.isAny? label.title else @@ -300,6 +308,9 @@ class @LabelsSelect $selectbox.hide() # display:block overrides the hide-collapse rule $value.removeAttr('style') + + return if $dropdown.hasClass('js-issuable-form-dropdown') + if $dropdown.hasClass 'js-multiselect' if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex) selectedLabels = $dropdown @@ -321,7 +332,7 @@ class @LabelsSelect clicked: (label) -> _this.enableBulkLabelDropdown() - if $dropdown.hasClass('js-filter-bulk-update') + if $dropdown.hasClass('js-filter-bulk-update') or $dropdown.hasClass('js-issuable-form-dropdown') return page = $('body').data 'page' diff --git a/app/assets/javascripts/milestone_select.js.coffee b/app/assets/javascripts/milestone_select.js.coffee index 8ab03ed93ee..3a036569317 100644 --- a/app/assets/javascripts/milestone_select.js.coffee +++ b/app/assets/javascripts/milestone_select.js.coffee @@ -62,7 +62,7 @@ class @MilestoneSelect title: 'Upcoming' ) - if extraOptions.length > 2 + if extraOptions.length > 0 extraOptions.push 'divider' callback(extraOptions.concat(data)) diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee index 4e032ab1ff1..e061f042ca9 100644 --- a/app/assets/javascripts/users_select.js.coffee +++ b/app/assets/javascripts/users_select.js.coffee @@ -56,6 +56,11 @@ class @UsersSelect username: '' avatar: '' $value.html(assigneeTemplate(user)) + + $collapsedSidebar + .attr('title', user.name) + .tooltip('fixTitle') + $collapsedSidebar.html(collapsedAssigneeTemplate(user)) @@ -63,7 +68,6 @@ class @UsersSelect '<% if( avatar ) { %> <a class="author_link" href="/u/<%- username %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> - <span class="author">Toni Boehm</span> </a> <% } else { %> <i class="fa fa-user"></i> @@ -151,11 +155,13 @@ class @UsersSelect # display:block overrides the hide-collapse rule $value.css('display', '') - clicked: (user) -> + clicked: (user, $el, e) -> page = $('body').data 'page' isIssueIndex = page is 'projects:issues:index' isMRIndex = page is page is 'projects:merge_requests:index' - if $dropdown.hasClass('js-filter-bulk-update') + if $dropdown.hasClass('js-filter-bulk-update') or $dropdown.hasClass('js-issuable-form-dropdown') + e.preventDefault() + selectedId = user.id return if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex) @@ -168,7 +174,8 @@ class @UsersSelect .closest('.selectbox') .find("input[name='#{$dropdown.data('field-name')}']").val() assignTo(selected) - + id: (user) -> + user.id renderRow: (user) -> username = if user.username then "@#{user.username}" else "" avatar = if user.avatar_url then user.avatar_url else false diff --git a/app/assets/stylesheets/framework/blank.scss b/app/assets/stylesheets/framework/blank.scss index d28cda6d62d..540718197e0 100644 --- a/app/assets/stylesheets/framework/blank.scss +++ b/app/assets/stylesheets/framework/blank.scss @@ -20,9 +20,12 @@ .blank-state-icon { padding-bottom: 20px; + color: $gray-darkest; + font-size: 56px; - path { - fill: $gray-darkest; + path, + polygon { + fill: currentColor; } } @@ -37,6 +40,10 @@ margin-top: 0; margin-bottom: $gl-padding; font-size: 15px; + + > strong { + font-weight: 600; + } } .blank-state-welcome-title { diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index 24b1ebab4b0..ad94e457cfd 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -16,8 +16,14 @@ font-weight: normal; font-size: 16px; line-height: 36px; + &.diff-collapsed { + padding: 5px; cursor: pointer; + + &:hover { + background-color: $row-hover; + } } } diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index f8aecd0558d..c1e5305644b 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -270,21 +270,6 @@ table { } } -.dashboard-intro-icon { - float: left; - text-align: center; - font-size: 32px; - color: #aaa; - width: 60px; -} - -.dashboard-intro-text { - display: inline-block; - margin-left: -60px; - padding-left: 60px; - width: 100%; -} - .btn-sign-in { text-shadow: none; diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index d4e900f80ef..3fd0e12568d 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -56,7 +56,7 @@ position: absolute; top: 50%; right: 6px; - margin-top: -4px; + margin-top: -6px; color: $dropdown-toggle-icon-color; font-size: 10px; } diff --git a/app/assets/stylesheets/pages/admin.scss b/app/assets/stylesheets/pages/admin.scss index 1d34a7f79ae..5607239d92d 100644 --- a/app/assets/stylesheets/pages/admin.scss +++ b/app/assets/stylesheets/pages/admin.scss @@ -88,13 +88,7 @@ .user-name { display: inline-block; - font-weight: bold; - } - - .controls { - > .btn, > .dropdown { - margin-left: 5px; - } + font-weight: 600; } .dropdown { diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index 701b9388454..2a3acc3eb4c 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -38,33 +38,6 @@ margin-right: 15px; } } - - &.group-admin { - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - - .group-avatar, .group-details, .group-controls { - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - } - - .group-details { - flex: 1 1 auto; - flex-direction: column; - min-width: 0; - } - - .group-controls { - align-items: center; - - a { - margin-left: 5px; - } - } - } - } .ldap-group-links { diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 15c6c9f231a..dba9a7ab3ee 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -324,6 +324,10 @@ .issuable-form-select-holder { display: inline-block; width: 250px; + + .dropdown-menu-toggle { + width: 100%; + } } .table-holder { diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index cbf8297f387..08da4e290dc 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -43,6 +43,13 @@ border-top-width: 1px; } + .commit-link { + + a:hover { + text-decoration: none; + } + } + .branch-commit { .branch-name { @@ -80,7 +87,12 @@ margin-left: 0; } + .label { + margin-right: 4px; + } + .label-container { + font-size: 0; .label { margin-top: 5px; @@ -116,6 +128,12 @@ color: $table-text-gray; } + .cancel-retry-btns { + .btn:not(:first-child) { + margin-left: 8px; + } + } + .dropdown-toggle, .dropdown-menu { color: $table-text-gray; diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 5be911dc562..ea9f7cf0540 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -482,6 +482,10 @@ pre.light-well { a:hover { text-decoration: none; } + + > span { + margin-left: 10px; + } } } @@ -639,3 +643,9 @@ pre.light-well { width: 300px; } } + +.compare-form-group { + .dropdown-menu { + width: 300px; + } +} diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 9e9b18fdbb8..c9d436d72ba 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -185,7 +185,7 @@ padding-right: $gl-padding + 15px; } - .btn-search { + .btn-search, .btn-new { width: 100%; margin-top: 5px; diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index f7ada5cfee4..b6e80762e3c 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -119,10 +119,6 @@ class Projects::IssuesController < Projects::ApplicationController render json: @issue.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }) end end - - rescue ActiveRecord::StaleObjectError - @conflict = true - render :edit end def referenced_merge_requests @@ -220,7 +216,7 @@ class Projects::IssuesController < Projects::ApplicationController def issue_params params.require(:issue).permit( :title, :assignee_id, :position, :description, :confidential, - :milestone_id, :due_date, :state_event, :task_num, :lock_version, label_ids: [] + :milestone_id, :due_date, :state_event, :task_num, label_ids: [] ) end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 2deb7959700..df659bb8c3b 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -196,9 +196,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController else render "edit" end - rescue ActiveRecord::StaleObjectError - @conflict = true - render :edit end def remove_wip @@ -427,7 +424,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :state_event, :description, :task_num, :force_remove_source_branch, - :lock_version, label_ids: [] + label_ids: [] ) end diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 47d174361db..a3a8c7d5ff9 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -9,7 +9,7 @@ module IssuablesHelper def multi_label_name(current_labels, default_label) # current_labels may be a string from before - if current_labels.is_a?(Array) + if current_labels.is_a?(Array) && current_labels.any? if current_labels.count > 1 "#{current_labels[0]} +#{current_labels.count - 1} more" else diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index b165b569372..fcb2703e837 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -45,7 +45,7 @@ module SearchHelper [ { category: "Help", label: "API Help", url: help_page_path("api/README") }, { category: "Help", label: "Markdown Help", url: help_page_path("markdown/markdown") }, - { category: "Help", label: "Permissions Help", url: help_page_path("permissions/permissions") }, + { category: "Help", label: "Permissions Help", url: help_page_path("user/permissions") }, { category: "Help", label: "Public Access Help", url: help_page_path("public_access/public_access") }, { category: "Help", label: "Rake Tasks Help", url: help_page_path("raketasks/README") }, { category: "Help", label: "SSH Keys Help", url: help_page_path("ssh/README") }, diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index fb49bd7dd64..acb6f5a2998 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -87,12 +87,6 @@ module Issuable User.find(assignee_id_was).update_cache_counts if assignee_id_was assignee.update_cache_counts if assignee end - - # We want to use optimistic lock for cases when only title or description are involved - # http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html - def locking_enabled? - title_changed? || description_changed? - end end module ClassMethods diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml index 59fd6c3fea0..77a11e49e20 100644 --- a/app/views/admin/groups/_group.html.haml +++ b/app/views/admin/groups/_group.html.haml @@ -1,20 +1,26 @@ -- css_class = '' unless local_assigns[:css_class] +- css_class = 'no-description' if group.description.blank? -%li.group-row.group-admin{ class: css_class } - .group-avatar - = image_tag group_icon(group), class: 'avatar hidden-xs' - .group-details - .title - = link_to [:admin, group], class: 'group-name' do - = group.name - .group-stats - %span>= pluralize(number_with_delimiter(group.projects.count), 'project') - , - %span= pluralize(number_with_delimiter(group.users.count), 'member') - - - if group.description.present? - .description - = markdown(group.description, pipeline: :description) - .group-controls.hidden-xs +%li.group-row{ class: css_class } + .controls = link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: 'btn' = link_to 'Delete', [:admin, group], data: { confirm: "Are you sure you want to remove #{group.name}?" }, method: :delete, class: 'btn btn-remove' + .stats + %span + = icon('bookmark') + = number_with_delimiter(group.projects.count) + + %span + = icon('users') + = number_with_delimiter(group.users.count) + + %span.visibility-icon.has-tooltip{data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group)} + = visibility_level_icon(group.visibility_level, fw: false) + + = image_tag group_icon(group), class: "avatar s40 hidden-xs" + .title + = link_to [:admin, group], class: 'group-name' do + = group.name + + - if group.description.present? + .description + = markdown(group.description, pipeline: :description) diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 40c8169ad9d..bb374694400 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -79,7 +79,7 @@ .panel-body.form-holder %p.light Read more about project permissions - %strong= link_to "here", help_page_path("permissions/permissions"), class: "vlink" + %strong= link_to "here", help_page_path("user/permissions"), class: "vlink" = form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do %div diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 7fbce25b2c4..1e755785d90 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -66,7 +66,7 @@ %ul.projects-list.content-list - @projects.each_with_index do |project| %li.project-row - .controls.pull-right + .controls - if project.archived %span.label.label-warning archived %span.label.label-gray diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml index d3519f616f6..4bf1c9cde3c 100644 --- a/app/views/admin/users/_user.html.haml +++ b/app/views/admin/users/_user.html.haml @@ -14,7 +14,7 @@ %span It's you! .user-email = mail_to user.email, user.email - .controls.pull-right + .controls = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn' - unless user == current_user .dropdown.inline diff --git a/app/views/dashboard/projects/_zero_authorized_projects.html.haml b/app/views/dashboard/projects/_zero_authorized_projects.html.haml index d54c7cad7be..fdea834ff45 100644 --- a/app/views/dashboard/projects/_zero_authorized_projects.html.haml +++ b/app/views/dashboard/projects/_zero_authorized_projects.html.haml @@ -1,53 +1,46 @@ - publicish_project_count = ProjectsFinder.new.execute(current_user).count -%h3.page-title Welcome to GitLab! -%p.light Self hosted Git management application. -%hr -%div - .dashboard-intro-icon - %i.fa.fa-bookmark-o - .dashboard-intro-text - %p.slead - You don't have access to any projects right now. - %br - - if current_user.can_create_project? - You can create up to - %strong= pluralize(number_with_delimiter(current_user.projects_limit), "project") + "." - - else - If you are added to a project, it will be displayed here. - +.blank-state.blank-state-welcome + %h2.blank-state-welcome-title + Welcome to GitLab + %p.blank-state-text + Code, test, and deploy together +.blank-state + .blank-state-icon + = custom_icon("project", size: 50) + %h3.blank-state-title + You don't have access to any projects right now + %p.blank-state-text - if current_user.can_create_project? - .link_holder - = link_to new_project_path, class: "btn btn-new" do - = icon('plus') - New Project + You can create up to + %strong= number_with_delimiter(current_user.projects_limit) + = succeed "." do + = "project".pluralize(current_user.projects_limit) + - else + If you are added to a project, it will be displayed here. + - if current_user.can_create_project? + = link_to new_project_path, class: "btn btn-new" do + New project - if current_user.can_create_group? - %hr - %div - .dashboard-intro-icon - %i.fa.fa-users - .dashboard-intro-text - %p.slead - You can create a group for several dependent projects. - %br - Groups are the best way to manage projects and members. - .link_holder - = link_to new_group_path, class: "btn btn-new" do - %i.fa.fa-plus - New Group + .blank-state + .blank-state-icon + = custom_icon("group", size: 50) + %h3.blank-state-title + You can create a group for several dependent projects. + %p.blank-state-text + Groups are the best way to manage projects and members. + = link_to new_group_path, class: "btn btn-new" do + New group -if publicish_project_count > 0 - %hr - %div - .dashboard-intro-icon - %i.fa.fa-globe - .dashboard-intro-text - %p.slead - There are - %strong= number_with_delimiter(publicish_project_count) - public projects on this server. - %br - Public projects are an easy way to allow everyone to have read-only access. - .link_holder - = link_to trending_explore_projects_path, class: "btn btn-new" do - Browse public projects + .blank-state + .blank-state-icon + = icon("globe") + %h3.blank-state-title + There are + = number_with_delimiter(publicish_project_count) + public projects on this server. + %p.blank-state-text + Public projects are an easy way to allow everyone to have read-only access. + = link_to trending_explore_projects_path, class: "btn btn-new" do + Browse projects diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml index 4565e752c1f..4f36a4a1c73 100644 --- a/app/views/dashboard/projects/index.html.haml +++ b/app/views/dashboard/projects/index.html.haml @@ -5,7 +5,8 @@ - page_title "Projects" - header_title "Projects", dashboard_projects_path -= render 'dashboard/projects_head' +- if @projects.any? || params[:filter_projects] + = render 'dashboard/projects_head' - if @last_push = render "events/event_last_push", event: @last_push diff --git a/app/views/errors/access_denied.html.haml b/app/views/errors/access_denied.html.haml index 2febeef99d3..c034bbe430e 100644 --- a/app/views/errors/access_denied.html.haml +++ b/app/views/errors/access_denied.html.haml @@ -3,4 +3,4 @@ %h3 Access Denied %hr %p You are not allowed to access this page. -%p Read more about project permissions #{link_to "here", help_page_path("permissions/permissions"), class: "vlink"} +%p Read more about project permissions #{link_to "here", help_page_path("user/permissions"), class: "vlink"} diff --git a/app/views/groups/group_members/_new_group_member.html.haml b/app/views/groups/group_members/_new_group_member.html.haml index 13ded2bc455..9bb9f962177 100644 --- a/app/views/groups/group_members/_new_group_member.html.haml +++ b/app/views/groups/group_members/_new_group_member.html.haml @@ -12,7 +12,7 @@ = select_tag :access_level, options_for_select(GroupMember.access_level_roles, @group_member.access_level), class: "project-access-select select2" .help-block Read more about role permissions - %strong= link_to "here", help_page_path("permissions/permissions"), class: "vlink" + %strong= link_to "here", help_page_path("user/permissions"), class: "vlink" .form-actions = f.submit 'Add users to group', class: "btn btn-create" diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 4ef72ff5d2a..b53a8633937 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -80,9 +80,10 @@ %span Download '#{build.name}' artifacts - if can?(current_user, :update_pipeline, @project) - - if pipeline.retryable? - = link_to retry_namespace_project_pipeline_path(@project.namespace, @project, pipeline.id), class: 'btn has-tooltip', title: "Retry", method: :post do - = icon("repeat") - - if pipeline.cancelable? - = link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, pipeline.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do - = icon("remove") + .cancel-retry-btns + - if pipeline.retryable? + = link_to retry_namespace_project_pipeline_path(@project.namespace, @project, pipeline.id), class: 'btn has-tooltip', title: "Retry", method: :post do + = icon("repeat") + - if pipeline.cancelable? + = link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, pipeline.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do + = icon("remove") diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml index dd590a4b8ec..af09b3418ea 100644 --- a/app/views/projects/compare/_form.html.haml +++ b/app/views/projects/compare/_form.html.haml @@ -2,15 +2,17 @@ .clearfix - if params[:to] && params[:from] = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has-tooltip', title: 'Switch base of comparison'} - .form-group + .form-group.dropdown.compare-form-group.js-compare-from-dropdown .input-group.inline-input-group %span.input-group-addon from - = text_field_tag :from, params[:from], class: "form-control", required: true + = text_field_tag :from, params[:from], class: "form-control js-compare-dropdown", required: true, data: { refs_url: refs_namespace_project_path(@project.namespace, @project), toggle: "dropdown", target: ".js-compare-from-dropdown", selected: params[:from].presence } + = render "ref_dropdown" = "..." - .form-group + .form-group.dropdown.compare-form-group.js-compare-to-dropdown .input-group.inline-input-group %span.input-group-addon to - = text_field_tag :to, params[:to], class: "form-control", required: true + = text_field_tag :to, params[:to], class: "form-control js-compare-dropdown", required: true, data: { refs_url: refs_namespace_project_path(@project.namespace, @project), toggle: "dropdown", target: ".js-compare-to-dropdown", selected: params[:to].presence } + = render "ref_dropdown" = button_tag "Compare", class: "btn btn-create commits-compare-btn" - if @merge_request.present? @@ -19,11 +21,3 @@ = link_to create_mr_path, class: 'prepend-left-10 btn' do = icon("plus") Create Merge Request - -:javascript - var availableTags = #{@project.repository.ref_names.to_json}; - - $("#from, #to").autocomplete({ - source: availableTags, - minLength: 1 - }); diff --git a/app/views/projects/compare/_ref_dropdown.html.haml b/app/views/projects/compare/_ref_dropdown.html.haml new file mode 100644 index 00000000000..c604c6d0135 --- /dev/null +++ b/app/views/projects/compare/_ref_dropdown.html.haml @@ -0,0 +1,4 @@ +.dropdown-menu.dropdown-menu-selectable + = dropdown_title "Select branch/tag" + = dropdown_content + = dropdown_loading diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml index ea3d82d858e..978c4dfc5ec 100644 --- a/app/views/projects/project_members/_new_project_member.html.haml +++ b/app/views/projects/project_members/_new_project_member.html.haml @@ -12,7 +12,7 @@ = select_tag :access_level, options_for_select(ProjectMember.access_level_roles, @project_member.access_level), class: "project-access-select select2" .help-block Read more about role permissions - %strong= link_to "here", help_page_path("permissions/permissions"), class: "vlink" + %strong= link_to "here", help_page_path("user/permissions"), class: "vlink" .form-actions = f.submit 'Add users to project', class: "btn btn-create" diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml index 3fab95751e0..883d3e3af1e 100644 --- a/app/views/projects/protected_branches/index.html.haml +++ b/app/views/projects/protected_branches/index.html.haml @@ -8,10 +8,10 @@ %p.prepend-top-20 Protected branches are designed to: %ul - %li prevent pushes from everybody except #{link_to "masters", help_page_path("permissions/permissions"), class: "vlink"} + %li prevent pushes from everybody except #{link_to "masters", help_page_path("user/permissions"), class: "vlink"} %li prevent anyone from force pushing to the branch %li prevent anyone from deleting the branch - %p.append-bottom-0 Read more about #{link_to "project permissions", help_page_path("permissions/permissions"), class: "underlined-link"} + %p.append-bottom-0 Read more about #{link_to "project permissions", help_page_path("user/permissions"), class: "underlined-link"} .col-lg-9 %h5.prepend-top-0 Protect a branch diff --git a/app/views/shared/icons/_group.svg b/app/views/shared/icons/_group.svg.erb index 75cae0d16c8..53635016900 100644 --- a/app/views/shared/icons/_group.svg +++ b/app/views/shared/icons/_group.svg.erb @@ -1,9 +1,4 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch --> - <title>Group</title> - <desc>Created with Sketch.</desc> - <defs></defs> +<svg width="<%= size %>" height="<%= size %>" viewBox="0 0 16 16"> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Group" fill="#303030"> <path d="M15.6667,10.0105 L10.3337,10.0105 C10.1497,10.0105 9.9997,10.1775 9.9997,10.3845 L9.9997,15.6145 C9.9997,15.8215 10.1497,15.9885 10.3337,15.9885 L15.6667,15.9885 C15.8507,15.9885 15.9997,15.8215 15.9997,15.6145 L15.9997,10.3845 C15.9997,10.1775 15.8507,10.0105 15.6667,10.0105 L15.6667,10.0105 L15.6667,10.0105 Z M11.9997,14.0105 L13.9997,14.0105 L13.9997,12.0105 L11.9997,12.0105 L11.9997,14.0105 L11.9997,14.0105 Z" id="Fill-11"></path> @@ -15,4 +10,4 @@ <path d="M11.6667,6.21724894e-15 L4.3337,6.21724894e-15 C4.1497,6.21724894e-15 3.9997,0.167 3.9997,0.374 L3.9997,6.604 C3.9997,6.811 4.1497,6.978 4.3337,6.978 L11.6667,6.978 C11.8507,6.978 11.9997,6.811 11.9997,6.604 L11.9997,0.374 C11.9997,0.167 11.8507,6.21724894e-15 11.6667,6.21724894e-15 L11.6667,6.21724894e-15 L11.6667,6.21724894e-15 Z M5.9997,5 L9.9997,5 L9.9997,2 L5.9997,2 L5.9997,5 L5.9997,5 Z" id="Fill-14"></path> </g> </g> -</svg>
\ No newline at end of file +</svg> diff --git a/app/views/shared/icons/_project.svg b/app/views/shared/icons/_project.svg deleted file mode 100644 index 1e8b43f8c6b..00000000000 --- a/app/views/shared/icons/_project.svg +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch --> - <title>Page 1</title> - <desc>Created with Sketch.</desc> - <defs></defs> - <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <path d="M6,6 L12,6 L12,5 L6,5 L6,6 Z M6,8 L12,8 L12,7 L6,7 L6,8 Z M6,10 L12,10 L12,9 L6,9 L6,10 Z M6,12 L12,12 L12,11 L6,11 L6,12 Z M4,6 L5,6 L5,5 L4,5 L4,6 Z M4,8 L5,8 L5,7 L4,7 L4,8 Z M4,10 L5,10 L5,9 L4,9 L4,10 Z M4,12 L5,12 L5,11 L4,11 L4,12 Z M13,3 L10,3 L10,4 L6,4 L6,3 L3,3 L3,13 L13,13 L13,3 Z M2,14 L14,14 L14,2 L2,2 L2,14 Z M1,0 C0.448,0 0,0.448 0,1 L0,15 C0,15.552 0.448,16 1,16 L15,16 C15.552,16 16,15.552 16,15 L16,1 C16,0.448 15.552,0 15,0 L1,0 Z" fill="#7F7E7E"></path> - </g> -</svg>
\ No newline at end of file diff --git a/app/views/shared/icons/_project.svg.erb b/app/views/shared/icons/_project.svg.erb new file mode 100644 index 00000000000..2f60bb7245e --- /dev/null +++ b/app/views/shared/icons/_project.svg.erb @@ -0,0 +1,3 @@ +<svg width="<%= size %>" height="<%= size %>" viewBox="0 0 16 16"> + <path d="M6,6 L12,6 L12,5 L6,5 L6,6 Z M6,8 L12,8 L12,7 L6,7 L6,8 Z M6,10 L12,10 L12,9 L6,9 L6,10 Z M6,12 L12,12 L12,11 L6,11 L6,12 Z M4,6 L5,6 L5,5 L4,5 L4,6 Z M4,8 L5,8 L5,7 L4,7 L4,8 Z M4,10 L5,10 L5,9 L4,9 L4,10 Z M4,12 L5,12 L5,11 L4,11 L4,12 Z M13,3 L10,3 L10,4 L6,4 L6,3 L3,3 L3,13 L13,13 L13,3 Z M2,14 L14,14 L14,2 L2,2 L2,14 Z M1,0 C0.448,0 0,0.448 0,1 L0,15 C0,15.552 0.448,16 1,16 L15,16 C15.552,16 16,15.552 16,15 L16,1 C16,0.448 15.552,0 15,0 L1,0 Z" fill="#7F7E7E" fill-rule="evenodd"></path> +</svg> diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index 094d6636c66..d5199bd86dd 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -21,10 +21,10 @@ placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: (@project.id if @project), selected: params[:assignee_id], field_name: "assignee_id", default_label: "Assignee" } }) .filter-item.inline.milestone-filter - = render "shared/issuable/milestone_dropdown" + = render "shared/issuable/milestone_dropdown", selected: params[:milestone_title], name: :milestone_title, show_any: true, show_upcoming: true .filter-item.inline.labels-filter - = render "shared/issuable/label_dropdown" + = render "shared/issuable/label_dropdown", selected: params[:label_name], data_options: { field_name: "label_name[]" } .pull-right = render 'shared/sort_dropdown' diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 98bbb12eaec..a8a8426df52 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -1,12 +1,5 @@ = form_errors(issuable) -- if @conflict - .alert.alert-danger - Someone edited the #{issuable.class.model_name.human.downcase} the same time you did. - Please check out - = link_to "the #{issuable.class.model_name.human.downcase}", polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), target: "_blank" - and make sure your changes will not unintentionally remove theirs - .form-group = f.label :title, class: 'control-label' .col-sm-10 @@ -59,38 +52,24 @@ = 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) } .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' + - project = @target_project || @project + - if issuable.assignee_id + = hidden_field_tag("#{issuable.class.model_name.param_key}[assignee_id]", issuable.assignee_id) + = dropdown_tag(user_dropdown_label(issuable.assignee_id, "Assignee"), options: { toggle_class: "js-user-search js-issuable-form-dropdown js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit", + placeholder: "Search assignee", data: { first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: (project.id if project), selected: issuable.assignee_id, field_name: "#{issuable.class.model_name.param_key}[assignee_id]", default_label: "Assignee" } }) .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" + .issuable-form-select-holder + = render "shared/issuable/milestone_dropdown", selected: issuable.milestone_id, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false .form-group - has_labels = issuable.project.labels.any? + - selected_labels = issuable.label_ids.any? ? issuable.label_ids : nil + - label_dropdown_toggle = issuable.labels.map { |label| label.title } = 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" + .issuable-form-select-holder + = render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: selected_labels, selected_toggle: label_dropdown_toggle, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: "false" } - if has_due_date .col-lg-6 .form-group @@ -156,5 +135,3 @@ = link_to 'Delete', polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), data: { confirm: "#{issuable.class.name.titleize} will be removed! Are you sure?" }, method: :delete, class: 'btn btn-danger btn-grouped' = link_to 'Cancel', polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), class: 'btn btn-grouped btn-cancel' - -= f.hidden_field :lock_version diff --git a/app/views/shared/issuable/_label_dropdown.html.haml b/app/views/shared/issuable/_label_dropdown.html.haml index d34d28f6736..bcbe133ce62 100644 --- a/app/views/shared/issuable/_label_dropdown.html.haml +++ b/app/views/shared/issuable/_label_dropdown.html.haml @@ -4,19 +4,21 @@ - show_footer = local_assigns.fetch(:show_footer, true) - data_options = local_assigns.fetch(:data_options, {}) - classes = local_assigns.fetch(:classes, []) -- dropdown_data = {toggle: 'dropdown', field_name: 'label_name[]', show_no: "true", show_any: "true", selected: params[:label_name], project_id: @project.try(:id), labels: labels_filter_path, default_label: "Label"} +- selected = local_assigns.fetch(:selected, nil) +- selected_toggle = local_assigns.fetch(:selected_toggle, nil) +- dropdown_data = {toggle: 'dropdown', field_name: "label_name[]", show_no: "true", show_any: "true", selected: selected, project_id: @project.try(:id), labels: labels_filter_path, default_label: "Label"} - dropdown_data.merge!(data_options) - classes << 'js-extra-options' if extra_options - classes << 'js-filter-submit' if filter_submit -- if params[:label_name].present? - - if params[:label_name].respond_to?('any?') - - params[:label_name].each do |label| - = hidden_field_tag "label_name[]", label, id: nil +- if selected.present? + - if selected.respond_to?('any?') + - selected.each do |label| + = hidden_field_tag data_options[:field_name], label, id: nil .dropdown %button.dropdown-menu-toggle.js-label-select.js-multiselect{class: classes.join(' '), type: "button", data: dropdown_data} %span.dropdown-toggle-text - = h(multi_label_name(params[:label_name], "Label")) + = h(multi_label_name(selected_toggle || selected, "Label")) = icon('chevron-down') .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable = render partial: "shared/issuable/label_page_default", locals: { title: "Filter by label", show_footer: show_footer, show_create: show_create } diff --git a/app/views/shared/issuable/_milestone_dropdown.html.haml b/app/views/shared/issuable/_milestone_dropdown.html.haml index 2fcf40ece99..9188ef72d52 100644 --- a/app/views/shared/issuable/_milestone_dropdown.html.haml +++ b/app/views/shared/issuable/_milestone_dropdown.html.haml @@ -1,7 +1,7 @@ -- if params[:milestone_title].present? - = hidden_field_tag(:milestone_title, params[:milestone_title]) -= dropdown_tag(milestone_dropdown_label(params[:milestone_title]), options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit', filter: true, dropdown_class: "dropdown-menu-selectable", - placeholder: "Search milestones", footer_content: @project.present?, data: { show_no: true, show_any: true, show_upcoming: true, field_name: "milestone_title", selected: params[:milestone_title], project_id: @project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do +- if selected.present? + = hidden_field_tag(name, selected) += dropdown_tag(milestone_dropdown_label(selected), options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit', filter: true, dropdown_class: "dropdown-menu-selectable", + placeholder: "Search milestones", footer_content: @project.present?, data: { show_no: true, show_any: show_any, show_upcoming: show_upcoming, field_name: name, selected: selected, project_id: @project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do - if @project %ul.dropdown-footer-list - if can? current_user, :admin_milestone, @project diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index adfab1af53e..e020a7d4d00 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -19,7 +19,7 @@ = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, format: :json, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| .block.assignee - .sidebar-collapsed-icon.sidebar-collapsed-user{data: {toggle: "tooltip", placement: "left", container: "body"}, title: (issuable.assignee.to_reference if issuable.assignee)} + .sidebar-collapsed-icon.sidebar-collapsed-user{data: {toggle: "tooltip", placement: "left", container: "body"}, title: (issuable.assignee.name if issuable.assignee)} - if issuable.assignee = link_to_member(@project, issuable.assignee, size: 24) - else diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb index 2fa3c838f55..a6cefd4d601 100644 --- a/app/workers/git_garbage_collect_worker.rb +++ b/app/workers/git_garbage_collect_worker.rb @@ -8,7 +8,9 @@ class GitGarbageCollectWorker project = Project.find(project_id) gitlab_shell.gc(project.repository_storage_path, project.path_with_namespace) - # Expire the branch cache in case garbage collection caused a ref lookup to fail + # Refresh the branch cache in case garbage collection caused a ref lookup to fail project.repository.after_create_branch + project.repository.branch_names + project.repository.has_visible_content? end end diff --git a/db/migrate/20160707104333_add_lock_to_issuables.rb b/db/migrate/20160707104333_add_lock_to_issuables.rb deleted file mode 100644 index cb516672800..00000000000 --- a/db/migrate/20160707104333_add_lock_to_issuables.rb +++ /dev/null @@ -1,17 +0,0 @@ -# See http://doc.gitlab.com/ce/development/migration_style_guide.html -# for more information on how to write migrations for GitLab. - -class AddLockToIssuables < ActiveRecord::Migration - include Gitlab::Database::MigrationHelpers - disable_ddl_transaction! - - def up - add_column_with_default :issues, :lock_version, :integer, default: 0 - add_column_with_default :merge_requests, :lock_version, :integer, default: 0 - end - - def down - remove_column :issues, :lock_version - remove_column :merge_requests, :lock_version - end -end diff --git a/db/schema.rb b/db/schema.rb index f24e47b85b2..8c12898eec9 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -70,11 +70,11 @@ ActiveRecord::Schema.define(version: 20160712171823) do t.string "recaptcha_site_key" t.string "recaptcha_private_key" 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.string "sentry_dsn" - t.boolean "akismet_enabled", default: false - t.string "akismet_api_key" t.boolean "email_author_in_body", default: false t.integer "default_group_visibility" t.boolean "repository_checks_enabled", default: false @@ -84,10 +84,10 @@ ActiveRecord::Schema.define(version: 20160712171823) do t.string "health_check_access_token" t.boolean "send_user_confirmation_email", default: false t.integer "container_registry_token_expire_delay", default: 5 + t.boolean "user_default_external", default: false, null: false t.text "after_sign_up_text" t.string "repository_storage", default: "default" t.string "enabled_git_access_protocol" - t.boolean "user_default_external", default: false, null: false end create_table "audit_events", force: :cascade do |t| @@ -165,8 +165,8 @@ ActiveRecord::Schema.define(version: 20160712171823) do t.text "artifacts_metadata" t.integer "erased_by_id" t.datetime "erased_at" - t.datetime "artifacts_expire_at" t.string "environment" + t.datetime "artifacts_expire_at" t.integer "artifacts_size" end @@ -481,11 +481,10 @@ ActiveRecord::Schema.define(version: 20160712171823) do t.string "state" t.integer "iid" t.integer "updated_by_id" - t.integer "moved_to_id" t.boolean "confidential", default: false t.datetime "deleted_at" t.date "due_date" - t.integer "lock_version", default: 0, null: false + t.integer "moved_to_id" end add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree @@ -625,7 +624,6 @@ ActiveRecord::Schema.define(version: 20160712171823) do t.integer "merge_user_id" t.string "merge_commit_sha" t.datetime "deleted_at" - t.integer "lock_version", default: 0, null: false end add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree @@ -775,10 +773,10 @@ ActiveRecord::Schema.define(version: 20160712171823) do t.integer "user_id", null: false t.string "token", null: false t.string "name", null: false - t.boolean "revoked", default: false - t.datetime "expires_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "revoked", default: false + t.datetime "expires_at" end add_index "personal_access_tokens", ["token"], name: "index_personal_access_tokens_on_token", unique: true, using: :btree @@ -898,9 +896,9 @@ ActiveRecord::Schema.define(version: 20160712171823) do t.string "type" t.string "title" t.integer "project_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.boolean "active", null: false + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "active", default: false, null: false t.text "properties" t.boolean "template", default: false t.boolean "push_events", default: true diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature index 358e622b736..80670063ea0 100644 --- a/features/project/issues/issues.feature +++ b/features/project/issues/issues.feature @@ -37,6 +37,7 @@ Feature: Project Issues And I submit new issue "500 error on profile" Then I should see issue "500 error on profile" + @javascript Scenario: I submit new unassigned issue with labels Given project "Shop" has labels: "bug", "feature", "enhancement" And I click link "New Issue" diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index 8176ec5ab45..21768c15c17 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -89,7 +89,7 @@ Feature: Project Merge Requests Then The list should be sorted by "Oldest updated" @javascript - Scenario: Visiting Merge Requests from a different Project after sorting + Scenario: Visiting Merge Requests from a differente Project after sorting Given I visit project "Shop" merge requests page And I sort the list by "Oldest updated" And I visit dashboard merge requests page diff --git a/features/steps/project/forked_merge_requests.rb b/features/steps/project/forked_merge_requests.rb index 6b56a77b832..8f71dfdd899 100644 --- a/features/steps/project/forked_merge_requests.rb +++ b/features/steps/project/forked_merge_requests.rb @@ -135,19 +135,17 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps end step 'I click "Assign to" dropdown"' do - first('.ajax-users-select').click + click_button 'Assignee' end step 'I should see the target project ID in the input selector' do - expect(page).to have_selector("input[data-project-id=\"#{@project.id}\"]") + expect(find('.js-assignee-search')["data-project-id"]).to eq "#{@project.id}" end step 'I should see the users from the target project ID' do - expect(page).to have_selector('.user-result', visible: true, count: 3) - users = page.all('.user-name') - expect(users[0].text).to eq 'Unassigned' - expect(users[1].text).to eq current_user.name - expect(users[2].text).to eq @project.users.first.name + expect(page).to have_content 'Unassigned' + expect(page).to have_content current_user.name + expect(page).to have_content @project.users.first.name end # Verify a link is generated against the correct project diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index 35f166c7c08..b785e15f70e 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -82,7 +82,8 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps step 'I submit new issue "500 error on profile" with label \'bug\'' do fill_in "issue_title", with: "500 error on profile" - select 'bug', from: "Labels" + click_button "Label" + click_link "bug" click_button "Submit issue" end diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index dec20d8659b..927f9dad20b 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -20,11 +20,19 @@ module Gitlab if Database.postgresql? options = options.merge({ algorithm: :concurrently }) + disable_statement_timeout end add_index(table_name, column_name, options) end + # Long-running migrations may take more than the timeout allowed by + # the database. Disable the session's statement timeout to ensure + # migrations don't get killed prematurely. (PostgreSQL only) + def disable_statement_timeout + ActiveRecord::Base.connection.execute('SET statement_timeout TO 0') if Database.postgresql? + end + # Updates the value of a column in batches. # # This method updates the table in batches of 5% of the total row count. @@ -133,6 +141,8 @@ module Gitlab 'in the body of your migration class' end + disable_statement_timeout + transaction do add_column(table, column, type, default: nil) diff --git a/lib/gitlab/gitlab_import/importer.rb b/lib/gitlab/gitlab_import/importer.rb index e6d31ea04c0..46d40f75be6 100644 --- a/lib/gitlab/gitlab_import/importer.rb +++ b/lib/gitlab/gitlab_import/importer.rb @@ -15,32 +15,35 @@ module Gitlab end def execute - project_identifier = CGI.escape(project.import_source) - - # Issues && Comments - issues = client.issues(project_identifier) - - issues.each do |issue| - body = @formatter.author_line(issue["author"]["name"]) - body += issue["description"] - - comments = client.issue_comments(project_identifier, issue["id"]) - - if comments.any? - body += @formatter.comments_header + ActiveRecord::Base.no_touching do + project_identifier = CGI.escape(project.import_source) + + # Issues && Comments + issues = client.issues(project_identifier) + + issues.each do |issue| + body = @formatter.author_line(issue["author"]["name"]) + body += issue["description"] + + comments = client.issue_comments(project_identifier, issue["id"]) + + if comments.any? + body += @formatter.comments_header + end + + comments.each do |comment| + body += @formatter.comment(comment["author"]["name"], comment["created_at"], comment["body"]) + end + + project.issues.create!( + iid: issue["iid"], + description: body, + title: issue["title"], + state: issue["state"], + updated_at: issue["updated_at"], + author_id: gl_user_id(project, issue["author"]["id"]) + ) end - - comments.each do |comment| - body += @formatter.comment(comment["author"]["name"], comment["created_at"], comment["body"]) - end - - project.issues.create!( - iid: issue["iid"], - description: body, - title: issue["title"], - state: issue["state"], - author_id: gl_user_id(project, issue["author"]["id"]) - ) end true diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 025ecc12f9f..051110c23cf 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -12,7 +12,10 @@ module Gitlab json = IO.read(@path) @tree_hash = ActiveSupport::JSON.decode(json) @project_members = @tree_hash.delete('project_members') - create_relations + + ActiveRecord::Base.no_touching do + create_relations + end rescue => e @shared.error(e) false diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 9824df3f274..6ba25a31641 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -87,7 +87,7 @@ module Gitlab project_id = @relation_hash.delete('project_id') # project_id may not be part of the export, but we always need to populate it if required. - @relation_hash['project_id'] = project_id if relation_class.column_names.include?('project_id') + @relation_hash['project_id'] = project_id @relation_hash['gl_project_id'] = project_id if @relation_hash['gl_project_id'] @relation_hash['target_project_id'] = project_id if @relation_hash['target_project_id'] @relation_hash['source_project_id'] = -1 if @relation_hash['source_project_id'] @@ -111,7 +111,7 @@ module Gitlab end def imported_object - imported_object = relation_class.new(@relation_hash) + imported_object = relation_class.new(parsed_relation_hash) yield(imported_object) if block_given? imported_object.importing = true if imported_object.respond_to?(:importing) imported_object @@ -125,6 +125,10 @@ module Gitlab def admin_user? @user.is_admin? end + + def parsed_relation_hash + @relation_hash.reject { |k, _v| !relation_class.attribute_method?(k) } + end end end end diff --git a/spec/features/compare_spec.rb b/spec/features/compare_spec.rb new file mode 100644 index 00000000000..c62556948e0 --- /dev/null +++ b/spec/features/compare_spec.rb @@ -0,0 +1,42 @@ +require "spec_helper" + +describe "Compare", js: true do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + project.team << [user, :master] + login_as user + visit namespace_project_compare_index_path(project.namespace, project, from: "master", to: "master") + end + + describe "branches" do + it "should pre-populate fields" do + expect(page.find_field("from").value).to eq("master") + end + + it "should compare branches" do + fill_in "from", with: "fea" + find("#from").click + + click_link "feature" + expect(page.find_field("from").value).to eq("feature") + + click_button "Compare" + expect(page).to have_content "Commits" + end + end + + describe "tags" do + it "should compare tags" do + fill_in "from", with: "v1.0" + find("#from").click + + click_link "v1.0.0" + expect(page.find_field("from").value).to eq("v1.0.0") + + click_button "Compare" + expect(page).to have_content "Commits" + end + end +end diff --git a/spec/features/issues/move_spec.rb b/spec/features/issues/move_spec.rb index 7773c486b4e..055210399a7 100644 --- a/spec/features/issues/move_spec.rb +++ b/spec/features/issues/move_spec.rb @@ -55,7 +55,7 @@ feature 'issue move to another project' do first('.select2-choice').click end - fill_in('s2id_autogen2_search', with: new_project_search.name) + fill_in('s2id_autogen1_search', with: new_project_search.name) page.within '.select2-drop' do expect(page).to have_content(new_project_search.name) diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index cfe6349a1a1..d00cffa4e2b 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -50,9 +50,8 @@ describe 'Issues', feature: true do expect(page).to have_content "Assignee #{@user.name}" - first('#s2id_issue_assignee_id').click - sleep 2 # wait for ajax stuff to complete - first('.user-result').click + first('.js-user-search').click + click_link 'Unassigned' click_button 'Save changes' @@ -121,17 +120,6 @@ describe 'Issues', feature: true do expect(page).to have_content date.to_s(:medium) end end - - it 'warns about version conflict' do - issue.update(title: "New title") - - fill_in 'issue_title', with: 'bug 345' - fill_in 'issue_description', with: 'bug description' - - click_button 'Save changes' - - expect(page).to have_content 'Someone edited the issue the same time you did' - end end end diff --git a/spec/features/merge_requests/edit_mr_spec.rb b/spec/features/merge_requests/edit_mr_spec.rb index 8ad884492d1..9e007ab7635 100644 --- a/spec/features/merge_requests/edit_mr_spec.rb +++ b/spec/features/merge_requests/edit_mr_spec.rb @@ -17,16 +17,5 @@ feature 'Edit Merge Request', feature: true do it 'form should have class js-quick-submit' do expect(page).to have_selector('.js-quick-submit') end - - it 'warns about version conflict' do - merge_request.update(title: "New title") - - fill_in 'merge_request_title', with: 'bug 345' - fill_in 'merge_request_description', with: 'bug description' - - click_button 'Save changes' - - expect(page).to have_content 'Someone edited the merge request the same time you did' - end end end diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb index 9096ad101b0..4ec3f19e03f 100644 --- a/spec/lib/gitlab/database/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -13,6 +13,10 @@ describe Gitlab::Database::MigrationHelpers, lib: true do context 'outside a transaction' do before do expect(model).to receive(:transaction_open?).and_return(false) + + unless Gitlab::Database.postgresql? + allow_any_instance_of(Gitlab::Database::MigrationHelpers).to receive(:disable_statement_timeout) + end end context 'using PostgreSQL' do diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 7286b0c39c0..4113d829c3c 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -26,6 +26,7 @@ "deleted_at": null, "due_date": null, "moved_to_id": null, + "test_ee_field": "test", "notes": [ { "id": 351, diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 05ffec8ea0a..877be300262 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -30,6 +30,14 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do expect(Event.where.not(data: nil).first.data[:ref]).not_to be_empty end + it 'preserves updated_at on issues' do + restored_project_json + + issue = Issue.where(description: 'Aliquam enim illo et possimus.').first + + expect(issue.reload.updated_at.to_s).to eq('2016-06-14 15:02:47 UTC') + end + context 'event at forth level of the tree' do let(:event) { Event.where(title: 'test levels').first } diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb index a9cce8b8b59..c9f5aae0815 100644 --- a/spec/workers/git_garbage_collect_worker_spec.rb +++ b/spec/workers/git_garbage_collect_worker_spec.rb @@ -16,7 +16,10 @@ describe GitGarbageCollectWorker do project.repository_storage_path, project.path_with_namespace). and_return(true) - expect_any_instance_of(Repository).to receive(:after_create_branch) + expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original + expect_any_instance_of(Repository).to receive(:branch_names).and_call_original + expect_any_instance_of(Repository).to receive(:branch_count).and_call_original + expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original subject.perform(project.id) end |