diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000000..a4b5100819 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,1006 @@ +Style/AccessModifierIndentation: + Description: Check indentation of private/protected visibility modifiers. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-public-private-protected' + Enabled: true + +Style/AccessorMethodName: + Description: Check the naming of accessor methods for get_/set_. + Enabled: false + +Style/Alias: + Description: 'Use alias_method instead of alias.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#alias-method' + Enabled: true + +Style/AlignArray: + Description: >- + Align the elements of an array literal if they span more than + one line. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#align-multiline-arrays' + Enabled: true + +Style/AlignHash: + Description: >- + Align the elements of a hash literal if they span more than + one line. + Enabled: true + +Style/AlignParameters: + Description: >- + Align the parameters of a method call if they span more + than one line. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-double-indent' + Enabled: false + +Style/AndOr: + Description: 'Use &&/|| instead of and/or.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-and-or-or' + Enabled: false + +Style/ArrayJoin: + Description: 'Use Array#join instead of Array#*.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#array-join' + Enabled: false + +Style/AsciiComments: + Description: 'Use only ascii symbols in comments.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-comments' + Enabled: true + +Style/AsciiIdentifiers: + Description: 'Use only ascii symbols in identifiers.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-identifiers' + Enabled: true + +Style/Attr: + Description: 'Checks for uses of Module#attr.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr' + Enabled: false + +Style/BeginBlock: + Description: 'Avoid the use of BEGIN blocks.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-BEGIN-blocks' + Enabled: true + +Style/BarePercentLiterals: + Description: 'Checks if usage of %() or %Q() matches configuration.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q-shorthand' + Enabled: false + +Style/BlockComments: + Description: 'Do not use block comments.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-block-comments' + Enabled: false + +Style/BlockEndNewline: + Description: 'Put end statement of multiline block on its own line.' + Enabled: true + +Style/Blocks: + Description: >- + Avoid using {...} for multi-line blocks (multiline chaining is + always ugly). + Prefer {...} over do...end for single-line blocks. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks' + Enabled: true + +Style/BracesAroundHashParameters: + Description: 'Enforce braces style around hash parameters.' + Enabled: false + +Style/CaseEquality: + Description: 'Avoid explicit use of the case equality operator(===).' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-case-equality' + Enabled: false + +Style/CaseIndentation: + Description: 'Indentation of when in a case/when/[else/]end.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-when-to-case' + Enabled: true + +Style/CharacterLiteral: + Description: 'Checks for uses of character literals.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-character-literals' + Enabled: true + +Style/ClassAndModuleCamelCase: + Description: 'Use CamelCase for classes and modules.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#camelcase-classes' + Enabled: true + +Style/ClassAndModuleChildren: + Description: 'Checks style of children classes and modules.' + Enabled: false + +Style/ClassCheck: + Description: 'Enforces consistent use of `Object#is_a?` or `Object#kind_of?`.' + Enabled: false + +Style/ClassMethods: + Description: 'Use self when defining module/class methods.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#def-self-singletons' + Enabled: false + +Style/ClassVars: + Description: 'Avoid the use of class variables.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-class-vars' + Enabled: true + +Style/ColonMethodCall: + Description: 'Do not use :: for method call.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#double-colons' + Enabled: false + +Style/CommentAnnotation: + Description: >- + Checks formatting of special comments + (TODO, FIXME, OPTIMIZE, HACK, REVIEW). + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#annotate-keywords' + Enabled: false + +Style/CommentIndentation: + Description: 'Indentation of comments.' + Enabled: true + +Style/ConstantName: + Description: 'Constants should use SCREAMING_SNAKE_CASE.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#screaming-snake-case' + Enabled: true + +Style/DefWithParentheses: + Description: 'Use def with parentheses when there are arguments.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens' + Enabled: false + +Style/DeprecatedHashMethods: + Description: 'Checks for use of deprecated Hash methods.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-key' + Enabled: false + +Style/Documentation: + Description: 'Document classes and non-namespace modules.' + Enabled: false + +Style/DotPosition: + Description: 'Checks the position of the dot in multi-line method calls.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains' + Enabled: false + +Style/DoubleNegation: + Description: 'Checks for uses of double negation (!!).' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-bang-bang' + Enabled: false + +Style/EachWithObject: + Description: 'Prefer `each_with_object` over `inject` or `reduce`.' + Enabled: false + +Style/ElseAlignment: + Description: 'Align elses and elsifs correctly.' + Enabled: true + +Style/EmptyElse: + Description: 'Avoid empty else-clauses.' + Enabled: false + +Style/EmptyLineBetweenDefs: + Description: 'Use empty lines between defs.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#empty-lines-between-methods' + Enabled: false + +Style/EmptyLines: + Description: "Don't use several empty lines in a row." + Enabled: false + +Style/EmptyLinesAroundAccessModifier: + Description: "Keep blank lines around access modifiers." + Enabled: false + +Style/EmptyLinesAroundBlockBody: + Description: "Keeps track of empty lines around block bodies." + Enabled: false + +Style/EmptyLinesAroundClassBody: + Description: "Keeps track of empty lines around class bodies." + Enabled: false + +Style/EmptyLinesAroundModuleBody: + Description: "Keeps track of empty lines around module bodies." + Enabled: false + +Style/EmptyLinesAroundMethodBody: + Description: "Keeps track of empty lines around method bodies." + Enabled: false + +Style/EmptyLiteral: + Description: 'Prefer literals to Array.new/Hash.new/String.new.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#literal-array-hash' + Enabled: false + +Style/EndBlock: + Description: 'Avoid the use of END blocks.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-END-blocks' + Enabled: false + +Style/EndOfLine: + Description: 'Use Unix-style line endings.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#crlf' + Enabled: false + +Style/EvenOdd: + Description: 'Favor the use of Fixnum#even? && Fixnum#odd?' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods' + Enabled: false + +Style/FileName: + Description: 'Use snake_case for source file names.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-files' + Enabled: false + +Style/FlipFlop: + Description: 'Checks for flip flops' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-flip-flops' + Enabled: false + +Style/For: + Description: 'Checks use of for or each in multiline loops.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-for-loops' + Enabled: false + +Style/FormatString: + Description: 'Enforce the use of Kernel#sprintf, Kernel#format or String#%.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#sprintf' + Enabled: false + +Style/GlobalVars: + Description: 'Do not introduce global variables.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#instance-vars' + Enabled: false + +Style/GuardClause: + Description: 'Check for conditionals that can be replaced with guard clauses' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals' + Enabled: false + +Style/HashSyntax: + Description: >- + Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax + { :a => 1, :b => 2 }. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-literals' + Enabled: true + +Style/IfUnlessModifier: + Description: >- + Favor modifier if/unless usage when you have a + single-line body. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier' + Enabled: false + +Style/IfWithSemicolon: + Description: 'Do not use if x; .... Use the ternary operator instead.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-semicolon-ifs' + Enabled: false + +Style/IndentationConsistency: + Description: 'Keep indentation straight.' + Enabled: true + +Style/IndentationWidth: + Description: 'Use 2 spaces for indentation.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-indentation' + Enabled: true + +Style/IndentArray: + Description: >- + Checks the indentation of the first element in an array + literal. + Enabled: false + +Style/IndentHash: + Description: 'Checks the indentation of the first key in a hash literal.' + Enabled: false + +Style/InfiniteLoop: + Description: 'Use Kernel#loop for infinite loops.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#infinite-loop' + Enabled: false + +Style/Lambda: + Description: 'Use the new lambda literal syntax for single-line blocks.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#lambda-multi-line' + Enabled: false + +Style/LambdaCall: + Description: 'Use lambda.call(...) instead of lambda.(...).' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#proc-call' + Enabled: false + +Style/LeadingCommentSpace: + Description: 'Comments should start with a space.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-space' + Enabled: false + +Style/LineEndConcatenation: + Description: >- + Use \ instead of + or << to concatenate two string literals at + line end. + Enabled: false + +Style/MethodCallParentheses: + Description: 'Do not use parentheses for method calls with no arguments.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-args-no-parens' + Enabled: false + +Style/MethodDefParentheses: + Description: >- + Checks if the method definitions have or don't have + parentheses. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens' + Enabled: false + +Style/MethodName: + Description: 'Use the configured style when naming methods.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars' + Enabled: false + +Style/ModuleFunction: + Description: 'Checks for usage of `extend self` in modules.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#module-function' + Enabled: false + +Style/MultilineBlockChain: + Description: 'Avoid multi-line chains of blocks.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks' + Enabled: false + +Style/MultilineBlockLayout: + Description: 'Ensures newlines after multiline block do statements.' + Enabled: false + +Style/MultilineIfThen: + Description: 'Do not use then for multi-line if/unless.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-then' + Enabled: false + +Style/MultilineOperationIndentation: + Description: >- + Checks indentation of binary operations that span more than + one line. + Enabled: false + +Style/MultilineTernaryOperator: + Description: >- + Avoid multi-line ?: (the ternary operator); + use if/unless instead. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-multiline-ternary' + Enabled: false + +Style/NegatedIf: + Description: >- + Favor unless over if for negative conditions + (or control flow or). + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#unless-for-negatives' + Enabled: false + +Style/NegatedWhile: + Description: 'Favor until over while for negative conditions.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#until-for-negatives' + Enabled: false + +Style/NestedTernaryOperator: + Description: 'Use one expression per branch in a ternary operator.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-ternary' + Enabled: false + +Style/Next: + Description: 'Use `next` to skip iteration instead of a condition at the end.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals' + Enabled: false + +Style/NilComparison: + Description: 'Prefer x.nil? to x == nil.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods' + Enabled: false + +Style/NonNilCheck: + Description: 'Checks for redundant nil checks.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-non-nil-checks' + Enabled: false + +Style/Not: + Description: 'Use ! instead of not.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bang-not-not' + Enabled: false + +Style/NumericLiterals: + Description: >- + Add underscores to large numeric literals to improve their + readability. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscores-in-numerics' + Enabled: false + +Style/OneLineConditional: + Description: >- + Favor the ternary operator(?:) over + if/then/else/end constructs. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#ternary-operator' + Enabled: false + +Style/OpMethod: + Description: 'When defining binary operators, name the argument other.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#other-arg' + Enabled: false + +Style/ParenthesesAroundCondition: + Description: >- + Don't use parentheses around the condition of an + if/unless/while. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-parens-if' + Enabled: false + +Style/PercentLiteralDelimiters: + Description: 'Use `%`-literal delimiters consistently' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-literal-braces' + Enabled: false + +Style/PercentQLiterals: + Description: 'Checks if uses of %Q/%q match the configured preference.' + Enabled: false + +Style/PerlBackrefs: + Description: 'Avoid Perl-style regex back references.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers' + Enabled: false + +Style/PredicateName: + Description: 'Check the names of predicate methods.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark' + Enabled: false + +Style/Proc: + Description: 'Use proc instead of Proc.new.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#proc' + Enabled: false + +Style/RaiseArgs: + Description: 'Checks the arguments passed to raise/fail.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#exception-class-messages' + Enabled: false + +Style/RedundantBegin: + Description: "Don't use begin blocks when they are not needed." + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#begin-implicit' + Enabled: false + +Style/RedundantException: + Description: "Checks for an obsolete RuntimeException argument in raise/fail." + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-explicit-runtimeerror' + Enabled: false + +Style/RedundantReturn: + Description: "Don't use return where it's not required." + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-explicit-return' + Enabled: false + +Style/RedundantSelf: + Description: "Don't use self where it's not needed." + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-self-unless-required' + Enabled: false + +Style/RegexpLiteral: + Description: >- + Use %r for regular expressions matching more than + `MaxSlashes` '/' characters. + Use %r only for regular expressions matching more than + `MaxSlashes` '/' character. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-r' + Enabled: false + +Style/RescueModifier: + Description: 'Avoid using rescue in its modifier form.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-rescue-modifiers' + Enabled: false + +Style/SelfAssignment: + Description: >- + Checks for places where self-assignment shorthand should have + been used. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#self-assignment' + Enabled: false + +Style/Semicolon: + Description: "Don't use semicolons to terminate expressions." + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-semicolon' + Enabled: false + +Style/SignalException: + Description: 'Checks for proper usage of fail and raise.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#fail-method' + Enabled: false + +Style/SingleLineBlockParams: + Description: 'Enforces the names of some block params.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#reduce-blocks' + Enabled: false + +Style/SingleLineMethods: + Description: 'Avoid single-line methods.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-single-line-methods' + Enabled: false + +Style/SingleSpaceBeforeFirstArg: + Description: >- + Checks that exactly one space is used between a method name + and the first argument for method calls without parentheses. + Enabled: false + +Style/SpaceAfterColon: + Description: 'Use spaces after colons.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' + Enabled: false + +Style/SpaceAfterComma: + Description: 'Use spaces after commas.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' + Enabled: false + +Style/SpaceAfterControlKeyword: + Description: 'Use spaces after if/elsif/unless/while/until/case/when.' + Enabled: false + +Style/SpaceAfterMethodName: + Description: >- + Do not put a space between a method name and the opening + parenthesis in a method definition. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-no-spaces' + Enabled: false + +Style/SpaceAfterNot: + Description: Tracks redundant space after the ! operator. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-space-bang' + Enabled: false + +Style/SpaceAfterSemicolon: + Description: 'Use spaces after semicolons.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' + Enabled: false + +Style/SpaceBeforeBlockBraces: + Description: >- + Checks that the left block brace has or doesn't have space + before it. + Enabled: false + +Style/SpaceBeforeComma: + Description: 'No spaces before commas.' + Enabled: false + +Style/SpaceBeforeComment: + Description: >- + Checks for missing space between code and a comment on the + same line. + Enabled: false + +Style/SpaceBeforeSemicolon: + Description: 'No spaces before semicolons.' + Enabled: false + +Style/SpaceInsideBlockBraces: + Description: >- + 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. + Enabled: false + +Style/SpaceAroundEqualsInParameterDefault: + Description: >- + Checks that the equals signs in parameter default assignments + have or don't have surrounding space depending on + configuration. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-around-equals' + Enabled: false + +Style/SpaceAroundOperators: + Description: 'Use spaces around operators.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' + Enabled: false + +Style/SpaceBeforeModifierKeyword: + Description: 'Put a space before the modifier keyword.' + Enabled: false + +Style/SpaceInsideBrackets: + Description: 'No spaces after [ or before ].' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces' + Enabled: false + +Style/SpaceInsideHashLiteralBraces: + Description: "Use spaces inside hash literal braces - or don't." + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' + Enabled: true + +Style/SpaceInsideParens: + Description: 'No spaces after ( or before ).' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces' + Enabled: false + +Style/SpaceInsideRangeLiteral: + Description: 'No spaces inside range literals.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-space-inside-range-literals' + Enabled: false + +Style/SpecialGlobalVars: + Description: 'Avoid Perl-style global variables.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms' + Enabled: false + +Style/StringLiterals: + Description: 'Checks if uses of quotes match the configured preference.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#consistent-string-literals' + Enabled: false + +Style/StringLiteralsInInterpolation: + Description: >- + Checks if uses of quotes inside expressions in interpolated + strings match the configured preference. + Enabled: false + +Style/SymbolProc: + Description: 'Use symbols as procs instead of blocks when possible.' + Enabled: false + +Style/Tab: + Description: 'No hard tabs.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-indentation' + Enabled: false + +Style/TrailingBlankLines: + Description: 'Checks trailing blank lines and final newline.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#newline-eof' + Enabled: true + +Style/TrailingComma: + Description: 'Checks for trailing comma in parameter lists and literals.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas' + Enabled: false + +Style/TrailingWhitespace: + Description: 'Avoid trailing whitespace.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace' + Enabled: false + +Style/TrivialAccessors: + Description: 'Prefer attr_* methods to trivial readers/writers.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr_family' + Enabled: false + +Style/UnlessElse: + Description: >- + Do not use unless with else. Rewrite these with the positive + case first. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-else-with-unless' + Enabled: false + +Style/UnneededCapitalW: + Description: 'Checks for %W when interpolation is not needed.' + Enabled: false + +Style/UnneededPercentQ: + Description: 'Checks for %q/%Q when single quotes or double quotes would do.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q' + Enabled: false + +Style/UnneededPercentX: + Description: 'Checks for %x when `` would do.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-x' + Enabled: false + +Style/VariableInterpolation: + Description: >- + Don't interpolate global, instance and class variables + directly in strings. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#curlies-interpolate' + Enabled: false + +Style/VariableName: + Description: 'Use the configured style when naming variables.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars' + Enabled: false + +Style/WhenThen: + Description: 'Use when x then ... for one-line cases.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#one-line-cases' + Enabled: false + +Style/WhileUntilDo: + Description: 'Checks for redundant do after while or until.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-multiline-while-do' + Enabled: false + +Style/WhileUntilModifier: + Description: >- + Favor modifier while/until usage when you have a + single-line body. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#while-as-a-modifier' + Enabled: false + +Style/WordArray: + Description: 'Use %w or %W for arrays of words.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-w' + Enabled: false + +#################### Metrics ################################ + +Metrics/AbcSize: + Description: >- + A calculated magnitude based on number of assignments, + branches, and conditions. + Enabled: false + +Metrics/BlockNesting: + Description: 'Avoid excessive block nesting' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#three-is-the-number-thou-shalt-count' + Enabled: false + +Metrics/ClassLength: + Description: 'Avoid classes longer than 100 lines of code.' + Enabled: false + +Metrics/CyclomaticComplexity: + Description: >- + A complexity metric that is strongly correlated to the number + of test cases needed to validate a method. + Enabled: false + +Metrics/LineLength: + Description: 'Limit lines to 80 characters.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#80-character-limits' + Enabled: false + +Metrics/MethodLength: + Description: 'Avoid methods longer than 10 lines of code.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods' + Enabled: false + +Metrics/ParameterLists: + Description: 'Avoid parameter lists longer than three or four parameters.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#too-many-params' + Enabled: false + +Metrics/PerceivedComplexity: + Description: >- + A complexity metric geared towards measuring complexity for a + human reader. + Enabled: false + +#################### Lint ################################ +### Warnings + +Lint/AmbiguousOperator: + Description: >- + Checks for ambiguous operators in the first argument of a + method invocation without parentheses. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-as-args' + Enabled: false + +Lint/AmbiguousRegexpLiteral: + Description: >- + Checks for ambiguous regexp literals in the first argument of + a method invocation without parenthesis. + Enabled: false + +Lint/AssignmentInCondition: + Description: "Don't use assignment in conditions." + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition' + Enabled: false + +Lint/BlockAlignment: + Description: 'Align block ends correctly.' + Enabled: false + +Lint/ConditionPosition: + Description: >- + Checks for condition placed in a confusing position relative to + the keyword. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#same-line-condition' + Enabled: false + +Lint/Debugger: + Description: 'Check for debugger calls.' + Enabled: false + +Lint/DefEndAlignment: + Description: 'Align ends corresponding to defs correctly.' + Enabled: false + +Lint/DeprecatedClassMethods: + Description: 'Check for deprecated class method calls.' + Enabled: false + +Lint/ElseLayout: + Description: 'Check for odd code arrangement in an else block.' + Enabled: false + +Lint/EmptyEnsure: + Description: 'Checks for empty ensure block.' + Enabled: false + +Lint/EmptyInterpolation: + Description: 'Checks for empty string interpolation.' + Enabled: false + +Lint/EndAlignment: + Description: 'Align ends correctly.' + Enabled: false + +Lint/EndInMethod: + Description: 'END blocks should not be placed inside method definitions.' + Enabled: false + +Lint/EnsureReturn: + Description: 'Do not use return in an ensure block.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-return-ensure' + Enabled: false + +Lint/Eval: + Description: 'The use of eval represents a serious security risk.' + Enabled: false + +Lint/HandleExceptions: + Description: "Don't suppress exception." + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions' + Enabled: false + +Lint/InvalidCharacterLiteral: + Description: >- + Checks for invalid character literals with a non-escaped + whitespace character. + Enabled: false + +Lint/LiteralInCondition: + Description: 'Checks of literals used in conditions.' + Enabled: false + +Lint/LiteralInInterpolation: + Description: 'Checks for literals used in interpolation.' + Enabled: false + +Lint/Loop: + Description: >- + Use Kernel#loop with break rather than begin/end/until or + begin/end/while for post-loop tests. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#loop-with-break' + Enabled: false + +Lint/ParenthesesAsGroupedExpression: + Description: >- + Checks for method calls with a space before the opening + parenthesis. + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-no-spaces' + Enabled: false + +Lint/RequireParentheses: + Description: >- + Use parentheses in the method call to avoid confusion + about precedence. + Enabled: false + +Lint/RescueException: + Description: 'Avoid rescuing the Exception class.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-blind-rescues' + Enabled: false + +Lint/ShadowingOuterLocalVariable: + Description: >- + Do not use the same name as outer local variable + for block arguments or block local variables. + Enabled: false + +Lint/SpaceBeforeFirstArg: + Description: >- + Put a space between a method name and the first argument + in a method call without parentheses. + Enabled: false + +Lint/StringConversionInInterpolation: + Description: 'Checks for Object#to_s usage in string interpolation.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-to-s' + Enabled: false + +Lint/UnderscorePrefixedVariableName: + Description: 'Do not use prefix `_` for a variable that is used.' + Enabled: true + +Lint/UnusedBlockArgument: + Description: 'Checks for unused block arguments.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars' + Enabled: false + +Lint/UnusedMethodArgument: + Description: 'Checks for unused method arguments.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars' + Enabled: false + +Lint/UnreachableCode: + Description: 'Unreachable code.' + Enabled: false + +Lint/UselessAccessModifier: + Description: 'Checks for useless access modifiers.' + Enabled: false + +Lint/UselessAssignment: + Description: 'Checks for useless assignment to a local variable.' + StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars' + Enabled: false + +Lint/UselessComparison: + Description: 'Checks for comparison of something with itself.' + Enabled: false + +Lint/UselessElseWithoutRescue: + Description: 'Checks for useless `else` in `begin..end` without `rescue`.' + Enabled: false + +Lint/UselessSetterCall: + Description: 'Checks for useless setter call to a local variable.' + Enabled: false + +Lint/Void: + Description: 'Possible use of operator/literal/variable in void context.' + Enabled: false + +##################### Rails ################################## + +Rails/ActionFilter: + Description: 'Enforces consistent use of action filter methods.' + Enabled: false + +Rails/DefaultScope: + Description: 'Checks if the argument passed to default_scope is a block.' + Enabled: false + +Rails/Delegate: + Description: 'Prefer delegate method for delegations.' + Enabled: false + +Rails/HasAndBelongsToMany: + Description: 'Prefer has_many :through to has_and_belongs_to_many.' + Enabled: true + +Rails/Output: + Description: 'Checks for calls to puts, print, etc.' + Enabled: true + +Rails/ReadWriteAttribute: + Description: >- + Checks for read_attribute(:attr) and + write_attribute(:attr, val). + Enabled: false + +Rails/ScopeArgs: + Description: 'Checks the arguments of ActiveRecord scopes.' + Enabled: false + +Rails/Validation: + Description: 'Use validates :attribute, hash of validations.' + Enabled: false + + +# Exclude some of GitLab files +# +# +AllCops: + RunRailsCops: true + Exclude: + - 'spec/**/*' + - 'features/**/*' + - 'vendor/**/*' + - 'db/**/*' + - 'tmp/**/*' + - 'bin/**/*' + - 'lib/backup/**/*' + - 'lib/tasks/**/*' + - 'lib/email_validator.rb' + - 'lib/gitlab/upgrader.rb' + - 'lib/gitlab/seeder.rb' diff --git a/CHANGELOG b/CHANGELOG index bd34cbe682..e2dbce8993 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,7 +8,7 @@ v 7.8.0 - Better UI for project services page - Cleaner UI for web editor - Add diff syntax highlighting in email-on-push service notifications (Hannes Rosenögger) - - + - Add API endpoint to fetch all changes on a MergeRequest (Jeroen van Baarsen) - - - Allow more variations for commit messages closing issues (Julien Bianchi and Hannes Rosenögger) @@ -25,11 +25,13 @@ v 7.8.0 - Upgrade Sidekiq gem to version 3.3.0 - Stop git zombie creation during force push check - Show success/error messages for test setting button in services - - + - Added Rubocop for code style checks - Fix commits pagination - - - - - + - Async load a branch information at the commit page + - Disable blacklist validation for project names + - Allow configuring protection of the default branch upon first push (Marco Wessel) + - - - Add a commit calendar to the user profile (Hannes Rosenögger) - @@ -42,7 +44,7 @@ v 7.8.0 - Password reset token validity increased from 2 hours to 2 days since it is also send on account creation. - - - - + - Enable raw image paste from clipboard, currently Chrome only (Marco Cyriacks) - - - Add action property to merge request hook (Julien Bianchi) @@ -53,15 +55,20 @@ v 7.8.0 - Add a new API function that retrieves all issues assigned to a single milestone (Justin Whear and Hannes Rosenögger) - - - - - - + - API: Access groups with their path (Julien Bianchi) + - Added link to milestone and keeping resource context on smaller viewports for issues and merge requests (Jason Blanchard) - - - API: Add support for editing an existing project (Mika Mäenpää and Hannes Rosenögger) - - - - + - When test web hook - show error message instead of 500 error page if connection to hook url was reset - Added support for firing system hooks on group create/destroy and adding/removing users to group (Boyan Tabakov) + - Added persistent collapse button for left side nav bar (Jason Blanchard) + +v 7.7.2 + - Update GitLab Shell to version 2.4.2 that fixes a bug when developers can push to protected branch + - Fix issue when LDAP user can't login with existing GitLab account v 7.7.1 - Improve mention autocomplete performance diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index 005119baaa..8e8299dcc0 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -2.4.1 +2.4.2 diff --git a/Gemfile b/Gemfile index 78b052e6e0..02f49289bb 100644 --- a/Gemfile +++ b/Gemfile @@ -208,8 +208,6 @@ group :development do gem 'better_errors' gem 'binding_of_caller' - gem 'rails_best_practices' - # Docs generator gem "sdoc" @@ -219,11 +217,12 @@ end group :development, :test do gem 'coveralls', require: false + gem 'rubocop', '0.28.0', require: false # gem 'rails-dev-tweaks' gem 'spinach-rails' gem "rspec-rails" gem "capybara", '~> 2.2.1' - gem "pry" + gem "pry-rails" gem "awesome_print" gem "database_cleaner" gem "launchy" @@ -256,7 +255,7 @@ end group :test do gem "simplecov", require: false - gem "shoulda-matchers", "~> 2.1.0" + gem "shoulda-matchers", "~> 2.7.0" gem 'email_spec' gem "webmock" gem 'test_after_commit' diff --git a/Gemfile.lock b/Gemfile.lock index cafcfda07c..72ce285e33 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -37,6 +37,9 @@ GEM rake (>= 0.8.7) arel (5.0.1.20140414130214) asciidoctor (0.1.4) + ast (2.0.0) + astrolabe (1.3.0) + parser (>= 2.2.0.pre.3, < 3.0) attr_required (1.0.0) awesome_print (1.2.0) axiom-types (0.0.5) @@ -67,8 +70,6 @@ GEM timers (~> 4.0.0) charlock_holmes (0.6.9.4) cliver (0.3.2) - code_analyzer (0.4.3) - sexp_processor coderay (1.1.0) coercible (1.0.0) descendants_tracker (~> 0.0.1) @@ -354,6 +355,8 @@ GEM org-ruby (0.9.12) rubypants (~> 0.2) orm_adapter (0.5.0) + parser (2.2.0.2) + ast (>= 1.1, < 3.0) pg (0.15.1) phantomjs (1.9.2.0) poltergeist (1.5.1) @@ -363,10 +366,13 @@ GEM websocket-driver (>= 0.2.0) polyglot (0.3.4) posix-spawn (0.3.9) + powerpack (0.0.9) pry (0.9.12.4) coderay (~> 1.0) method_source (~> 0.8) slop (~> 3.4) + pry-rails (0.3.2) + pry (>= 0.9.10) pyu-ruby-sasl (0.0.3.3) quiet_assets (1.0.2) railties (>= 3.1, < 5.0) @@ -403,20 +409,12 @@ GEM sprockets-rails (~> 2.0) rails_autolink (1.1.6) rails (> 3.1) - rails_best_practices (1.14.4) - activesupport - awesome_print - code_analyzer (>= 0.4.3) - colored - erubis - i18n - require_all - ruby-progressbar railties (4.1.1) actionpack (= 4.1.1) activesupport (= 4.1.1) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) + rainbow (2.0.0) raindrops (0.13.0) rake (10.3.2) raphael-rails (2.1.2) @@ -447,7 +445,6 @@ GEM redis (>= 2.2) ref (1.0.5) request_store (1.0.5) - require_all (1.3.2) rest-client (1.6.7) mime-types (>= 1.16) rinku (1.7.3) @@ -467,7 +464,13 @@ GEM rspec-core (~> 2.14.0) rspec-expectations (~> 2.14.0) rspec-mocks (~> 2.14.0) - ruby-progressbar (1.2.0) + rubocop (0.28.0) + astrolabe (~> 1.3) + parser (>= 2.2.0.pre.7, < 3.0) + powerpack (~> 0.0.6) + rainbow (>= 1.99.1, < 3.0) + ruby-progressbar (~> 1.4) + ruby-progressbar (1.7.1) rubyntlm (0.4.0) rubypants (0.2.0) rugged (0.21.2) @@ -495,8 +498,7 @@ GEM semantic-ui-sass (1.8.0.0) sass (~> 3.2) settingslogic (2.0.9) - sexp_processor (4.4.0) - shoulda-matchers (2.1.0) + shoulda-matchers (2.7.0) activesupport (>= 3.0.0) sidekiq (3.3.0) celluloid (>= 0.16.0) @@ -700,7 +702,7 @@ DEPENDENCIES org-ruby (= 0.9.12) pg poltergeist (~> 1.5.1) - pry + pry-rails quiet_assets (~> 1.0.1) rack-attack rack-cors @@ -708,7 +710,6 @@ DEPENDENCIES rack-oauth2 (~> 1.0.5) rails (~> 4.1.0) rails_autolink (~> 1.1) - rails_best_practices raphael-rails (~> 2.1.2) rb-fsevent rb-inotify @@ -717,6 +718,7 @@ DEPENDENCIES redis-rails request_store rspec-rails + rubocop (= 0.28.0) rugments sanitize (~> 2.0) sass-rails (~> 4.0.2) @@ -725,7 +727,7 @@ DEPENDENCIES select2-rails semantic-ui-sass (~> 1.8.0) settingslogic - shoulda-matchers (~> 2.1.0) + shoulda-matchers (~> 2.7.0) sidekiq (~> 3.3) sidetiq (= 0.6.3) simplecov diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee index 6a0d5e4356..70940e1385 100644 --- a/app/assets/javascripts/calendar.js.coffee +++ b/app/assets/javascripts/calendar.js.coffee @@ -9,8 +9,6 @@ class @calendar cal.init itemName: ["commit"] data: timestamps - domain: "year" - subDomain: "month" start: new Date(starting_year, starting_month) domainLabelFormat: "%b" id: "cal-heatmap" diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee index a0f0d98a8d..abb5bf519e 100644 --- a/app/assets/javascripts/dropzone_input.js.coffee +++ b/app/assets/javascripts/dropzone_input.js.coffee @@ -13,6 +13,8 @@ class @DropzoneInput form_textarea = $(form).find("textarea.markdown-area") form_textarea.wrap "
" + form_textarea.bind 'paste', (event) => + handlePaste(event) form_dropzone = $(form).find('.div-dropzone') form_dropzone.parent().addClass "div-dropzone-wrapper" @@ -133,24 +135,17 @@ class @DropzoneInput formatLink = (str) -> "![" + str.alt + "](" + str.url + ")" - handlePaste = (e) -> - e.preventDefault() - my_event = e.originalEvent + handlePaste = (event) -> + pasteEvent = event.originalEvent + if pasteEvent.clipboardData and pasteEvent.clipboardData.items + image = isImage(pasteEvent) + if image + event.preventDefault() - if my_event.clipboardData and my_event.clipboardData.items - processItem(my_event) - - processItem = (e) -> - image = isImage(e) - if image - filename = getFilename(e) or "image.png" - text = "{{" + filename + "}}" - pasteText(text) - uploadFile image.getAsFile(), filename - - else - text = e.clipboardData.getData("text/plain") - pasteText(text) + filename = getFilename(pasteEvent) or "image.png" + text = "{{" + filename + "}}" + pasteText(text) + uploadFile image.getAsFile(), filename isImage = (data) -> i = 0 diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee index c084d730d6..5013bcdacd 100644 --- a/app/assets/javascripts/sidebar.js.coffee +++ b/app/assets/javascripts/sidebar.js.coffee @@ -24,3 +24,18 @@ $ -> $(window).resize -> responsive_resize() return + +$(document).on("click", '.toggle-nav-collapse', (e) -> + e.preventDefault() + collapsed = 'page-sidebar-collapsed' + expanded = 'page-sidebar-expanded' + + if $('.page-with-sidebar').hasClass(collapsed) + $('.page-with-sidebar').removeClass(collapsed).addClass(expanded) + $('.toggle-nav-collapse i').removeClass('fa-angle-right').addClass('fa-angle-left') + $.cookie("collapsed_nav", "false", { path: '/' }) + else + $('.page-with-sidebar').removeClass(expanded).addClass(collapsed) + $('.toggle-nav-collapse i').removeClass('fa-angle-left').addClass('fa-angle-right') + $.cookie("collapsed_nav", "true", { path: '/' }) +) diff --git a/app/assets/stylesheets/generic/avatar.scss b/app/assets/stylesheets/generic/avatar.scss index b688620673..b88cdd8393 100644 --- a/app/assets/stylesheets/generic/avatar.scss +++ b/app/assets/stylesheets/generic/avatar.scss @@ -15,6 +15,10 @@ &.s24 { margin-right: 4px; } } + &.avatar-tile { + @include border-radius(0px); + } + &.s16 { width: 16px; height: 16px; margin-right: 6px; } &.s24 { width: 24px; height: 24px; margin-right: 8px; } &.s26 { width: 26px; height: 26px; margin-right: 8px; } diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss index 90010781af..17c0cd81b9 100644 --- a/app/assets/stylesheets/sections/dashboard.scss +++ b/app/assets/stylesheets/sections/dashboard.scss @@ -97,7 +97,17 @@ .dash-project-avatar { float: left; + + .avatar { + margin-top: -8px; + margin-left: -15px; + @include border-radius(0px); + } + .identicon { + line-height: 40px; + } } + .dash-project-access-icon { float: left; margin-right: 5px; diff --git a/app/assets/stylesheets/sections/diff.scss b/app/assets/stylesheets/sections/diff.scss index da50dbe471..f47ea32982 100644 --- a/app/assets/stylesheets/sections/diff.scss +++ b/app/assets/stylesheets/sections/diff.scss @@ -40,12 +40,12 @@ font-size: $code_font_size; .old { span.idiff { - background-color: #F99; + background-color: #f8cbcb; } } .new { span.idiff { - background-color: #8F8; + background-color: #a6f3a6; } } .unfold { @@ -84,7 +84,7 @@ padding: 0px; border: none; background: #F5F5F5; - color: #666; + color: rgba(0,0,0,0.3); padding: 0px 5px; border-right: 1px solid #ccc; text-align: right; @@ -96,7 +96,7 @@ float: left; width: 35px; font-weight: normal; - color: #666; + color: rgba(0,0,0,0.3); &:hover { text-decoration: underline; } @@ -114,13 +114,13 @@ .line_holder { &.old .old_line, &.old .new_line { - background: #FCC; - border-color: #E7BABA; + background: #ffdddd; + border-color: #f1c0c0; } &.new .old_line, &.new .new_line { - background: #CFC; - border-color: #B9ECB9; + background: #dbffdb; + border-color: #c1e9c1; } } .line_content { @@ -129,10 +129,10 @@ padding: 0px 0.5em; border: none; &.new { - background: #CFD; + background: #eaffea; } &.old { - background: #FDD; + background: #ffecec; } &.matched { color: #ccc; diff --git a/app/assets/stylesheets/sections/nav_sidebar.scss b/app/assets/stylesheets/sections/nav_sidebar.scss index a61c053b8a..b35043821d 100644 --- a/app/assets/stylesheets/sections/nav_sidebar.scss +++ b/app/assets/stylesheets/sections/nav_sidebar.scss @@ -1,5 +1,3 @@ - - .page-with-sidebar { background: #F5F5F5; @@ -101,9 +99,7 @@ } @mixin expanded-sidebar { - .page-with-sidebar { - padding-left: $sidebar_width; - } + padding-left: $sidebar_width; .sidebar-wrapper { width: $sidebar_width; @@ -122,9 +118,7 @@ } @mixin folded-sidebar { - .page-with-sidebar { - padding-left: 50px; - } + padding-left: 50px; .sidebar-wrapper { width: 52px; @@ -150,10 +144,33 @@ } } +.collapse-nav a { + position: fixed; + bottom: 15px; + padding: 10px; + background: #DDD; +} + @media (max-width: $screen-md-max) { - @include folded-sidebar; + .page-sidebar-collapsed { + @include folded-sidebar; + } + + .page-sidebar-expanded { + @include folded-sidebar; + } + + .collapse-nav { + display: none; + } } @media(min-width: $screen-md-max) { - @include expanded-sidebar; + .page-sidebar-collapsed { + @include folded-sidebar; + } + + .page-sidebar-expanded { + @include expanded-sidebar; + } } diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss index a124d23578..5494845eb8 100644 --- a/app/assets/stylesheets/sections/notes.scss +++ b/app/assets/stylesheets/sections/notes.scss @@ -81,7 +81,7 @@ ul.notes { .diff-file .notes_holder { font-size: 13px; line-height: 18px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: $regular_font; td { border: 1px solid #ddd; diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index a937f48487..7458542fc7 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -22,6 +22,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController def application_setting_params params.require(:application_setting).permit( :default_projects_limit, + :default_branch_protection, :signup_enabled, :signin_enabled, :gravatar_enabled, diff --git a/app/controllers/github_imports_controller.rb b/app/controllers/github_imports_controller.rb index 3c5448bc70..b73e3f7ffa 100644 --- a/app/controllers/github_imports_controller.rb +++ b/app/controllers/github_imports_controller.rb @@ -23,7 +23,7 @@ class GithubImportsController < ApplicationController end def jobs - jobs = current_user.created_projects.where(import_type: "github").to_json(:only => [:id, :import_status]) + jobs = current_user.created_projects.where(import_type: "github").to_json(only: [:id, :import_status]) render json: jobs end @@ -58,7 +58,7 @@ class GithubImportsController < ApplicationController def octo_client Octokit.auto_paginate = true - @octo_client ||= Octokit::Client.new(:access_token => current_user.github_access_token) + @octo_client ||= Octokit::Client.new(access_token: current_user.github_access_token) end def github_auth diff --git a/app/controllers/namespaces_controller.rb b/app/controllers/namespaces_controller.rb index c59a2401ce..b7a9d8c129 100644 --- a/app/controllers/namespaces_controller.rb +++ b/app/controllers/namespaces_controller.rb @@ -15,4 +15,3 @@ class NamespacesController < ApplicationController end end end - diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index b471d57f69..dccb96ba1d 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -59,8 +59,7 @@ class Projects::BlobController < Projects::ApplicationController def preview @content = params[:content] - diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', - include_diff_info: true) + diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true) @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/)) render layout: false diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 470efbd211..96a782bdf7 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -11,8 +11,6 @@ class Projects::CommitController < Projects::ApplicationController return git_not_found! unless @commit @line_notes = @project.notes.for_commit_id(commit.id).inline - @branches = @project.repository.branch_names_contains(commit.id) - @tags = @project.repository.tag_names_contains(commit.id) @diffs = @commit.diffs @note = @project.build_commit_note(commit) @notes_count = @project.notes.for_commit_id(commit.id).count @@ -31,6 +29,12 @@ class Projects::CommitController < Projects::ApplicationController end end + def branches + @branches = @project.repository.branch_names_contains(commit.id) + @tags = @project.repository.tag_names_contains(commit.id) + render layout: false + end + def commit @commit ||= @project.repository.commit(params[:id]) end diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index 84888265dc..c4ddc32e8c 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -35,4 +35,3 @@ class Projects::RawController < Projects::ApplicationController end end end - diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index cede0ebe0a..b80472f8eb 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -31,10 +31,10 @@ class Projects::RefsController < Projects::ApplicationController def logs_tree @offset = if params[:offset].present? - params[:offset].to_i - else - 0 - end + params[:offset].to_i + else + 0 + end @limit = 25 diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index 0e03956e73..0145207bf6 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -16,16 +16,16 @@ class Projects::WikisController < Projects::ApplicationController if @page render 'show' elsif file = @project_wiki.find_file(params[:id], params[:version_id]) - if file.on_disk? - send_file file.on_disk_path, disposition: 'inline' - else - send_data( - file.raw_data, - type: file.mime_type, - disposition: 'inline', - filename: file.name - ) - end + if file.on_disk? + send_file file.on_disk_path, disposition: 'inline' + else + send_data( + file.raw_data, + type: file.mime_type, + disposition: 'inline', + filename: file.name + ) + end else return render('empty') unless can?(current_user, :write_wiki, @project) @page = WikiPage.new(@project_wiki) diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 312e561b52..1ed3bc388f 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -27,7 +27,7 @@ class SnippetsController < ApplicationController @snippets = SnippetsFinder.new.execute(current_user, { filter: :by_user, user: @user, - scope: params[:scope]}). + scope: params[:scope] }). page(params[:page]).per(20) if @user == current_user diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9e5ea6cfa4..57d8ef09fa 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,14 +1,9 @@ class UsersController < ApplicationController - skip_before_filter :authenticate_user!, only: [:show, :activities] + skip_before_filter :authenticate_user! + before_filter :set_user layout :determine_layout def show - @user = User.find_by_username!(params[:username]) - - unless current_user || @user.public_profile? - return authenticate_user! - end - # Projects user can view visible_projects = ProjectsFinder.new.execute(current_user) authorized_projects_ids = visible_projects.pluck(:id) @@ -25,19 +20,22 @@ class UsersController < ApplicationController @title = @user.name - # Get user repositories and collect timestamps for commits - user_repositories = visible_projects.map(&:repository) - calendar = Gitlab::CommitsCalendar.new(user_repositories, @user) - @timestamps = calendar.timestamps - @starting_year = (Time.now - 1.year).strftime("%Y") - @starting_month = Date.today.strftime("%m").to_i - respond_to do |format| format.html format.atom { render layout: false } end end + def calendar + visible_projects = ProjectsFinder.new.execute(current_user) + calendar = Gitlab::CommitsCalendar.new(visible_projects, @user) + @timestamps = calendar.timestamps + @starting_year = calendar.starting_year + @starting_month = calendar.starting_month + + render 'calendar', layout: false + end + def determine_layout if current_user 'navless' @@ -45,4 +43,14 @@ class UsersController < ApplicationController 'public_users' end end + + private + + def set_user + @user = User.find_by_username!(params[:username]) + + unless current_user || @user.public_profile? + return authenticate_user! + end + end end diff --git a/app/finders/notes_finder.rb b/app/finders/notes_finder.rb index bef82d7f0f..6fe15b4106 100644 --- a/app/finders/notes_finder.rb +++ b/app/finders/notes_finder.rb @@ -7,18 +7,19 @@ class NotesFinder # Default to 0 to remain compatible with old clients last_fetched_at = Time.at(params.fetch(:last_fetched_at, 0).to_i) - notes = case target_type - when "commit" - project.notes.for_commit_id(target_id).not_inline.fresh - when "issue" - project.issues.find(target_id).notes.inc_author.fresh - when "merge_request" - project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh - when "snippet", "project_snippet" - project.snippets.find(target_id).notes.fresh - else - raise 'invalid target_type' - end + notes = + case target_type + when "commit" + project.notes.for_commit_id(target_id).not_inline.fresh + when "issue" + project.issues.find(target_id).notes.inc_author.fresh + when "merge_request" + project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh + when "snippet", "project_snippet" + project.snippets.find(target_id).notes.fresh + else + raise 'invalid target_type' + end # Use overlapping intervals to avoid worrying about race conditions notes.where('updated_at > ?', last_fetched_at - FETCH_OVERLAP) diff --git a/app/finders/snippets_finder.rb b/app/finders/snippets_finder.rb index 4b0c69f2d2..07b5759443 100644 --- a/app/finders/snippets_finder.rb +++ b/app/finders/snippets_finder.rb @@ -40,7 +40,7 @@ class SnippetsFinder when 'are_public' then snippets.are_public else - snippets + snippets end else snippets.public_and_internal diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 104ae517a0..e45f465030 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -75,10 +75,10 @@ module ApplicationHelper options[:class] ||= '' options[:class] << ' identicon' bg_key = project.id % 7 + style = "background-color: ##{ allowed_colors.values[bg_key] }; color: #555" - content_tag(:div, class: options[:class], - style: "background-color: ##{ allowed_colors.values[bg_key] }; color: #555") do - project.name[0, 1].upcase + content_tag(:div, class: options[:class], style: style) do + project.name[0, 1].upcase end end @@ -247,15 +247,6 @@ module ApplicationHelper Gitlab::MarkdownHelper.gitlab_markdown?(filename) end - def spinner(text = nil, visible = false) - css_class = 'loading' - css_class << ' hide' unless visible - - content_tag :div, class: css_class do - content_tag(:i, nil, class: 'fa fa-spinner fa-spin') + text - end - end - def link_to(name = nil, options = nil, html_options = nil, &block) begin uri = URI(options) @@ -324,4 +315,12 @@ module ApplicationHelper profile_key_path(key) end end + + def nav_sidebar_class + if nav_menu_collapsed? + "page-sidebar-collapsed" + else + "page-sidebar-expanded" + end + end end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 2a3e51ada5..b4ba14160e 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -65,8 +65,7 @@ module CommitsHelper branches.sort.map do |branch| link_to(project_tree_path(project, branch)) do content_tag :span, class: 'label label-gray' do - content_tag(:i, nil, class: 'fa fa-code-fork') + ' ' + - branch + icon('code-fork') + ' ' + branch end end end.join(" ").html_safe @@ -78,8 +77,7 @@ module CommitsHelper sorted.map do |tag| link_to(project_commits_path(project, project.repository.find_tag(tag).name)) do content_tag :span, class: 'label label-gray' do - content_tag(:i, nil, class: 'fa fa-tag') + ' ' + - tag + icon('tag') + ' ' + tag end end end.join(" ").html_safe @@ -114,12 +112,13 @@ module CommitsHelper person_name = user.nil? ? source_name : user.name person_email = user.nil? ? source_email : user.email - text = if options[:avatar] - avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") - %Q{#{avatar} #{person_name}} - else - person_name - end + text = + if options[:avatar] + avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "") + %Q{#{avatar} #{person_name}} + else + person_name + end options = { class: "commit-#{options[:source]}-link has_tooltip", diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb index 5ff19b8829..dd2e713a54 100644 --- a/app/helpers/compare_helper.rb +++ b/app/helpers/compare_helper.rb @@ -1,7 +1,7 @@ module CompareHelper def compare_to_mr_button? @project.merge_requests_enabled && - params[:from].present? && + params[:from].present? && params[:to].present? && @repository.branch_names.include?(params[:from]) && @repository.branch_names.include?(params[:to]) && @@ -10,6 +10,6 @@ module CompareHelper end def compare_mr_path - new_project_merge_request_path(@project, merge_request: {source_branch: params[:to], target_branch: params[:from]}) + new_project_merge_request_path(@project, merge_request: { source_branch: params[:to], target_branch: params[:from] }) end end diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb index b336263049..92cc9c426b 100644 --- a/app/helpers/emails_helper.rb +++ b/app/helpers/emails_helper.rb @@ -31,7 +31,7 @@ module EmailsHelper end def add_email_highlight_css - Rugments::Themes::Github.render(:scope => '.highlight') + Rugments::Themes::Github.render(scope: '.highlight') end def color_email_diff(diffcontent) diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 903a500961..d05f6df5f9 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -27,18 +27,17 @@ module EventsHelper content_tag :li, class: "filter_icon #{active}" do link_to request.path, class: 'has_tooltip event_filter_link', id: "#{key}_event_filter", 'data-original-title' => tooltip do - content_tag(:i, nil, class: icon_for_event[key]) + - content_tag(:span, ' ' + tooltip) + icon(icon_for_event[key]) + content_tag(:span, ' ' + tooltip) end end end def icon_for_event { - EventFilter.push => 'fa fa-upload', - EventFilter.merged => 'fa fa-check-square-o', - EventFilter.comments => 'fa fa-comments', - EventFilter.team => 'fa fa-user', + EventFilter.push => 'upload', + EventFilter.merged => 'check-square-o', + EventFilter.comments => 'comments', + EventFilter.team => 'user', } end diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb index aaa8f8d007..18260f0ed4 100644 --- a/app/helpers/icons_helper.rb +++ b/app/helpers/icons_helper.rb @@ -1,21 +1,39 @@ module IconsHelper + # Creates an icon tag given icon name(s) and possible icon modifiers. + # + # Right now this method simply delegates directly to `fa_icon` from the + # font-awesome-rails gem, but should we ever use a different icon pack in the + # future we won't have to change hundreds of method calls. + def icon(names, options = {}) + fa_icon(names, options) + end + + def spinner(text = nil, visible = false) + css_class = 'loading' + css_class << ' hide' unless visible + + content_tag :div, class: css_class do + icon('spinner spin') + text + end + end + def boolean_to_icon(value) if value.to_s == "true" - content_tag :i, nil, class: 'fa fa-circle cgreen' + icon('circle', class: 'cgreen') else - content_tag :i, nil, class: 'fa fa-power-off clgray' + icon('power-off', class: 'clgray') end end def public_icon - content_tag :i, nil, class: 'fa fa-globe' + icon('globe') end def internal_icon - content_tag :i, nil, class: 'fa fa-shield' + icon('shield') end def private_icon - content_tag :i, nil, class: 'fa fa-lock' + icon('lock') end end diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 9fe183e6e2..e1c1078344 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -49,7 +49,7 @@ module IssuesHelper ts << capture_haml do haml_tag :span do haml_concat '·' - haml_concat ' ' + haml_concat icon('edit', title: 'edited') haml_concat time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_edited_ago') end end diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index 9ef06e71ce..c584c736b3 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -15,11 +15,13 @@ module MergeRequestsHelper end def new_mr_from_push_event(event, target_project) - return :merge_request => { - source_project_id: event.project.id, - target_project_id: target_project.id, - source_branch: event.branch_name, - target_branch: target_project.repository.root_ref + return { + merge_request: { + source_project_id: event.project.id, + target_project_id: target_project.id, + source_branch: event.branch_name, + target_branch: target_project.repository.root_ref + } } end diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb new file mode 100644 index 0000000000..2b03269800 --- /dev/null +++ b/app/helpers/nav_helper.rb @@ -0,0 +1,5 @@ +module NavHelper + def nav_menu_collapsed? + cookies[:collapsed_nav] == 'true' + end +end diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 8f493f5d33..8edcb8e6a8 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -1,5 +1,5 @@ module NotesHelper - # Helps to distinguish e.g. commit notes in mr notes list + # Helps to distinguish e.g. commit notes in mr notes list def note_for_main_target?(note) (@noteable.class.name == note.noteable_type && !note.for_diff_line?) end @@ -22,7 +22,7 @@ module NotesHelper ts << capture_haml do haml_tag :span do haml_concat '·' - haml_concat ' ' + haml_concat icon('edit', title: 'edited') haml_concat time_ago_with_tooltip(note.updated_at, 'bottom', 'note_edited_ago') end end @@ -57,7 +57,7 @@ module NotesHelper button_tag(class: 'btn add-diff-note js-add-diff-note-button', data: data, title: 'Add a comment to this line') do - content_tag :i, nil, class: 'fa fa-comment-o' + icon('comment-o') end end @@ -74,7 +74,7 @@ module NotesHelper button_tag class: 'btn reply-btn js-discussion-reply-button', data: data, title: 'Add a reply' do - link_text = content_tag(:i, nil, class: 'fa fa-comment') + link_text = icon('comment') link_text << ' Reply' end end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index bad380e98a..f771fe761e 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -1,13 +1,13 @@ module NotificationsHelper def notification_icon(notification) if notification.disabled? - content_tag :i, nil, class: 'fa fa-volume-off ns-mute' + icon('volume-off', class: 'ns-mute') elsif notification.participating? - content_tag :i, nil, class: 'fa fa-volume-down ns-part' + icon('volume-down', class: 'ns-part') elsif notification.watch? - content_tag :i, nil, class: 'fa fa-volume-up ns-watch' + icon('volume-up', class: 'ns-watch') else - content_tag :i, nil, class: 'fa fa-circle-o ns-default' + icon('circle-o', class: 'ns-default') end end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 166e4d3087..0351384b70 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -83,7 +83,7 @@ module ProjectsHelper ' Star' end - content_tag('i', ' ', class: 'fa fa-star') + toggle_text + icon('star') + toggle_text end count_html = content_tag('span', class: 'count') do @@ -95,7 +95,7 @@ module ProjectsHelper class: cls, method: :post, remote: true, - data: {type: 'json'} + data: { type: 'json' } } @@ -107,7 +107,7 @@ module ProjectsHelper end def link_to_toggle_fork - out = content_tag(:i, '', class: 'fa fa-code-fork') + out = icon('code-fork') out << ' Fork' out << content_tag(:span, class: 'count') do @project.forks_count.to_s @@ -262,4 +262,3 @@ module ProjectsHelper end end end - diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index 727ec3fb23..b6fb7a8aa5 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -38,13 +38,8 @@ module TreeHelper # # type - String type of the tree item; either 'folder' or 'file' def tree_icon(type) - icon_class = if type == 'folder' - 'fa fa-folder' - else - 'fa fa-file-o' - end - - content_tag :i, nil, class: icon_class + icon_class = type == 'folder' ? 'folder' : 'file-o' + icon(icon_class) end def tree_hex_class(content) diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 45ae79a75c..6d4e220b16 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -4,6 +4,7 @@ # # id :integer not null, primary key # default_projects_limit :integer +# default_branch_protection :integer # signup_enabled :boolean # signin_enabled :boolean # gravatar_enabled :boolean @@ -14,7 +15,8 @@ # class ApplicationSetting < ActiveRecord::Base - validates :home_page_url, allow_blank: true, + validates :home_page_url, + allow_blank: true, format: { with: URI::regexp(%w(http https)), message: "should be a valid url" }, if: :home_page_url_column_exist @@ -25,6 +27,7 @@ class ApplicationSetting < ActiveRecord::Base def self.create_from_defaults create( default_projects_limit: Settings.gitlab['default_projects_limit'], + default_branch_protection: Settings.gitlab['default_branch_protection'], signup_enabled: Settings.gitlab['signup_enabled'], signin_enabled: Settings.gitlab['signin_enabled'], gravatar_enabled: Settings.gravatar['enabled'], diff --git a/app/models/commit.rb b/app/models/commit.rb index baccf28674..e0461809e1 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -88,11 +88,12 @@ class Commit # cut off, ellipses (`&hellp;`) are prepended to the commit message. def description title_end = safe_message.index("\n") - @description ||= if (!title_end && safe_message.length > 100) || (title_end && title_end > 100) - "…".html_safe << safe_message[80..-1] - else - safe_message.split("\n", 2)[1].try(:chomp) - end + @description ||= + if (!title_end && safe_message.length > 100) || (title_end && title_end > 100) + "…".html_safe << safe_message[80..-1] + else + safe_message.split("\n", 2)[1].try(:chomp) + end end def description? diff --git a/app/models/group.rb b/app/models/group.rb index 2c62fffd09..fae43e2d42 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -111,7 +111,7 @@ class Group < Namespace class << self def search(query) - where("LOWER(namespaces.name) LIKE :query", query: "%#{query.downcase}%") + where("LOWER(namespaces.name) LIKE :query or LOWER(namespaces.path) LIKE :query", query: "%#{query.downcase}%") end def sort(method) diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index d1d522be19..c8fa9c5091 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -44,11 +44,11 @@ class WebHook < ActiveRecord::Base } WebHook.post(post_url, body: data.to_json, - headers: {"Content-Type" => "application/json"}, + headers: { "Content-Type" => "application/json" }, verify: false, basic_auth: auth) end - rescue SocketError, Errno::ECONNREFUSED, Net::OpenTimeout => e + rescue SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e logger.error("WebHook Error => #{e}") false end diff --git a/app/models/identity.rb b/app/models/identity.rb index c7cdb63e3d..80e0e3a8a2 100644 --- a/app/models/identity.rb +++ b/app/models/identity.rb @@ -11,5 +11,5 @@ class Identity < ActiveRecord::Base belongs_to :user - validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider} + validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider } end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index acc774a634..45e2834c3c 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -79,7 +79,7 @@ class MergeRequest < ActiveRecord::Base merge_request.save end - after_transition :locked => (any - :locked) do |merge_request, transition| + after_transition locked: (any - :locked) do |merge_request, transition| merge_request.locked_at = nil merge_request.save end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index ea4b48fdd7..e7fd302475 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -20,15 +20,20 @@ class Namespace < ActiveRecord::Base belongs_to :owner, class_name: "User" validates :owner, presence: true, unless: ->(n) { n.type == "Group" } - validates :name, presence: true, uniqueness: true, - length: { within: 0..255 }, - format: { with: Gitlab::Regex.name_regex, - message: Gitlab::Regex.name_regex_message } + validates :name, + presence: true, uniqueness: true, + length: { within: 0..255 }, + format: { with: Gitlab::Regex.name_regex, + message: Gitlab::Regex.name_regex_message } + validates :description, length: { within: 0..255 } - validates :path, uniqueness: { case_sensitive: false }, presence: true, length: { within: 1..255 }, - exclusion: { in: Gitlab::Blacklist.path }, - format: { with: Gitlab::Regex.path_regex, - message: Gitlab::Regex.path_regex_message } + validates :path, + uniqueness: { case_sensitive: false }, + presence: true, + length: { within: 1..255 }, + exclusion: { in: Gitlab::Blacklist.path }, + format: { with: Gitlab::Regex.path_regex, + message: Gitlab::Regex.path_regex_message } delegate :name, to: :owner, allow_nil: true, prefix: true diff --git a/app/models/project.rb b/app/models/project.rb index 8176075dde..832b04eada 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -14,7 +14,7 @@ # merge_requests_enabled :boolean default(TRUE), not null # wiki_enabled :boolean default(TRUE), not null # namespace_id :integer -# issues_tracker :string(255) default('gitlab'), not null +# issues_tracker :string(255) default("gitlab"), not null # issues_tracker_id :string(255) # snippets_enabled :boolean default(TRUE), not null # last_activity_at :datetime @@ -115,13 +115,16 @@ class Project < ActiveRecord::Base # Validations validates :creator, presence: true, on: :create validates :description, length: { maximum: 2000 }, allow_blank: true - validates :name, presence: true, length: { within: 0..255 }, - format: { with: Gitlab::Regex.project_name_regex, - message: Gitlab::Regex.project_regex_message } - validates :path, presence: true, length: { within: 0..255 }, - exclusion: { in: Gitlab::Blacklist.path }, - format: { with: Gitlab::Regex.path_regex, - message: Gitlab::Regex.path_regex_message } + validates :name, + presence: true, + length: { within: 0..255 }, + format: { with: Gitlab::Regex.project_name_regex, + message: Gitlab::Regex.project_regex_message } + validates :path, + presence: true, + length: { within: 0..255 }, + format: { with: Gitlab::Regex.path_regex, + message: Gitlab::Regex.path_regex_message } validates :issues_enabled, :merge_requests_enabled, :wiki_enabled, inclusion: { in: [true, false] } validates :visibility_level, @@ -163,22 +166,22 @@ class Project < ActiveRecord::Base end event :import_finish do - transition :started => :finished + transition started: :finished end event :import_fail do - transition :started => :failed + transition started: :failed end event :import_retry do - transition :failed => :started + transition failed: :started end state :started state :finished state :failed - after_transition any => :started, :do => :add_import_job + after_transition any => :started, do: :add_import_job end class << self diff --git a/app/models/project_contributions.rb b/app/models/project_contributions.rb new file mode 100644 index 0000000000..8ab2d814a9 --- /dev/null +++ b/app/models/project_contributions.rb @@ -0,0 +1,23 @@ +class ProjectContributions + attr_reader :project, :user + + def initialize(project, user) + @project, @user = project, user + end + + def commits_log + repository = project.repository + + if !repository.exists? || repository.empty? + return {} + end + + Rails.cache.fetch(cache_key) do + repository.commits_per_day_for_user(user) + end + end + + def cache_key + "#{Date.today.to_s}-commits-log-#{project.id}-#{user.email}" + end +end diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index 16e1b83da4..745609e591 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -17,13 +17,19 @@ class BambooService < CiService prop_accessor :bamboo_url, :build_key, :username, :password - validates :bamboo_url, presence: true, - format: { with: URI::regexp }, if: :activated? + validates :bamboo_url, + presence: true, + format: { with: URI::regexp }, + if: :activated? validates :build_key, presence: true, if: :activated? - validates :username, presence: true, - if: ->(service) { service.password? }, if: :activated? - validates :password, presence: true, - if: ->(service) { service.username? }, if: :activated? + validates :username, + presence: true, + if: ->(service) { service.password? }, + if: :activated? + validates :password, + presence: true, + if: ->(service) { service.username? }, + if: :activated? attr_accessor :response diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb index 2476b62da8..5845e2d352 100644 --- a/app/models/project_services/custom_issue_tracker_service.rb +++ b/app/models/project_services/custom_issue_tracker_service.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# + class CustomIssueTrackerService < IssueTrackerService prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url @@ -27,8 +41,8 @@ class CustomIssueTrackerService < IssueTrackerService { type: 'text', name: 'title', placeholder: title }, { type: 'text', name: 'description', placeholder: description }, { type: 'text', name: 'project_url', placeholder: 'Project url' }, - { type: 'text', name: 'issues_url', placeholder: 'Issue url'}, - { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} + { type: 'text', name: 'issues_url', placeholder: 'Issue url' }, + { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' } ] end diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index fadebf968b..248f749b31 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -81,7 +81,7 @@ class GitlabCiService < CiService def fields [ { type: 'text', name: 'token', placeholder: 'GitLab CI project specific token' }, - { type: 'text', name: 'project_url', placeholder: 'http://ci.gitlabhq.com/projects/3'} + { type: 'text', name: 'project_url', placeholder: 'http://ci.gitlabhq.com/projects/3' } ] end end diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb index 25f5f23bdf..25e399883b 100644 --- a/app/models/project_services/gitlab_issue_tracker_service.rb +++ b/app/models/project_services/gitlab_issue_tracker_service.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# + class GitlabIssueTrackerService < IssueTrackerService include Rails.application.routes.url_helpers prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 632f053d17..b19c02bab4 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# + class IssueTrackerService < Service validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated? @@ -30,8 +44,8 @@ class IssueTrackerService < Service [ { type: 'text', name: 'description', placeholder: description }, { type: 'text', name: 'project_url', placeholder: 'Project url' }, - { type: 'text', name: 'issues_url', placeholder: 'Issue url'}, - { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} + { type: 'text', name: 'issues_url', placeholder: 'Issue url' }, + { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' } ] end diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index 12e279f0ca..0863eab0e9 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# + class JiraService < IssueTrackerService include HTTParty diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb index 11cce3e056..547b240183 100644 --- a/app/models/project_services/redmine_service.rb +++ b/app/models/project_services/redmine_service.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# + class RedmineService < IssueTrackerService prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb index dca718b5e8..287f5c0e84 100644 --- a/app/models/project_services/teamcity_service.rb +++ b/app/models/project_services/teamcity_service.rb @@ -17,13 +17,16 @@ class TeamcityService < CiService prop_accessor :teamcity_url, :build_type, :username, :password - validates :teamcity_url, presence: true, - format: { with: URI::regexp }, if: :activated? + validates :teamcity_url, + presence: true, + format: { with: URI::regexp }, if: :activated? validates :build_type, presence: true, if: :activated? - validates :username, presence: true, - if: ->(service) { service.password? }, if: :activated? - validates :password, presence: true, - if: ->(service) { service.username? }, if: :activated? + validates :username, + presence: true, + if: ->(service) { service.password? }, if: :activated? + validates :password, + presence: true, + if: ->(service) { service.username? }, if: :activated? attr_accessor :response diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index f8a28ca986..55438bee24 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -136,7 +136,7 @@ class ProjectWiki def commit_details(action, message = nil, title = nil) commit_message = message || default_message(action, title) - {email: @user.email, name: @user.name, message: commit_message} + { email: @user.email, name: @user.name, message: commit_message } end def default_message(action, title) diff --git a/app/models/repository.rb b/app/models/repository.rb index f6400f7aff..4e45a6723b 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -30,7 +30,7 @@ class Repository commit = Gitlab::Git::Commit.find(raw_repository, id) commit = Commit.new(commit) if commit commit - rescue Rugged::OdbError => ex + rescue Rugged::OdbError nil end @@ -61,25 +61,25 @@ class Repository end def add_branch(branch_name, ref) - Rails.cache.delete(cache_key(:branch_names)) + cache.expire(:branch_names) gitlab_shell.add_branch(path_with_namespace, branch_name, ref) end def add_tag(tag_name, ref, message = nil) - Rails.cache.delete(cache_key(:tag_names)) + cache.expire(:tag_names) gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message) end def rm_branch(branch_name) - Rails.cache.delete(cache_key(:branch_names)) + cache.expire(:branch_names) gitlab_shell.rm_branch(path_with_namespace, branch_name) end def rm_tag(tag_name) - Rails.cache.delete(cache_key(:tag_names)) + cache.expire(:tag_names) gitlab_shell.rm_tag(path_with_namespace, tag_name) end @@ -97,19 +97,15 @@ class Repository end def branch_names - Rails.cache.fetch(cache_key(:branch_names)) do - raw_repository.branch_names - end + cache.fetch(:branch_names) { raw_repository.branch_names } end def tag_names - Rails.cache.fetch(cache_key(:tag_names)) do - raw_repository.tag_names - end + cache.fetch(:tag_names) { raw_repository.tag_names } end def commit_count - Rails.cache.fetch(cache_key(:commit_count)) do + cache.fetch(:commit_count) do begin raw_repository.commit_count(self.root_ref) rescue @@ -121,26 +117,19 @@ class Repository # Return repo size in megabytes # Cached in redis def size - Rails.cache.fetch(cache_key(:size)) do - raw_repository.size - end + cache.fetch(:size) { raw_repository.size } end def expire_cache - Rails.cache.delete(cache_key(:size)) - Rails.cache.delete(cache_key(:branch_names)) - Rails.cache.delete(cache_key(:tag_names)) - Rails.cache.delete(cache_key(:commit_count)) - Rails.cache.delete(cache_key(:graph_log)) - Rails.cache.delete(cache_key(:readme)) - Rails.cache.delete(cache_key(:version)) - Rails.cache.delete(cache_key(:contribution_guide)) + %i(size branch_names tag_names commit_count graph_log + readme version contribution_guide).each do |key| + cache.expire(key) + end end def graph_log - Rails.cache.fetch(cache_key(:graph_log)) do - commits = raw_repository.log(limit: 6000, - skip_merges: true, + cache.fetch(:graph_log) do + commits = raw_repository.log(limit: 6000, skip_merges: true, ref: root_ref) commits.map do |rugged_commit| @@ -176,10 +165,6 @@ class Repository end end - def cache_key(type) - "#{type}:#{path_with_namespace}" - end - def method_missing(m, *args, &block) raw_repository.send(m, *args, &block) end @@ -199,13 +184,11 @@ class Repository end def readme - Rails.cache.fetch(cache_key(:readme)) do - tree(:head).readme - end + cache.fetch(:readme) { tree(:head).readme } end def version - Rails.cache.fetch(cache_key(:version)) do + cache.fetch(:version) do tree(:head).blobs.find do |file| file.name.downcase == 'version' end @@ -213,9 +196,7 @@ class Repository end def contribution_guide - Rails.cache.fetch(cache_key(:contribution_guide)) do - tree(:head).contribution_guide - end + cache.fetch(:contribution_guide) { tree(:head).contribution_guide } end def head_commit @@ -351,4 +332,10 @@ class Repository [] end end + + private + + def cache + @cache ||= RepositoryCache.new(path_with_namespace) + end end diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 9aba42a062..a3222d2989 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -29,9 +29,11 @@ class Snippet < ActiveRecord::Base validates :author, presence: true validates :title, presence: true, length: { within: 0..255 } - validates :file_name, presence: true, length: { within: 0..255 }, - format: { with: Gitlab::Regex.path_regex, - message: Gitlab::Regex.path_regex_message } + validates :file_name, + presence: true, + length: { within: 0..255 }, + format: { with: Gitlab::Regex.path_regex, + message: Gitlab::Regex.path_regex_message } validates :content, presence: true validates :visibility_level, inclusion: { in: Gitlab::VisibilityLevel.values } diff --git a/app/models/user.rb b/app/models/user.rb index f819c3c5a9..ca149eaf86 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -113,13 +113,15 @@ class User < ActiveRecord::Base # Validations # validates :name, presence: true - validates :email, presence: true, email: {strict_mode: true}, uniqueness: true + validates :email, presence: true, email: { strict_mode: true }, uniqueness: true validates :bio, length: { maximum: 255 }, allow_blank: true - validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0} - validates :username, presence: true, uniqueness: { case_sensitive: false }, - exclusion: { in: Gitlab::Blacklist.path }, - format: { with: Gitlab::Regex.username_regex, - message: Gitlab::Regex.username_regex_message } + validates :projects_limit, presence: true, numericality: { greater_than_or_equal_to: 0 } + validates :username, + presence: true, + uniqueness: { case_sensitive: false }, + exclusion: { in: Gitlab::Blacklist.path }, + format: { with: Gitlab::Regex.username_regex, + message: Gitlab::Regex.username_regex_message } validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true validate :namespace_uniq, if: ->(user) { user.username_changed? } diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index b9ab6702c5..32981a0e66 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -43,7 +43,7 @@ class WikiPage @attributes[:slug] end - alias :to_param :slug + alias_method :to_param, :slug # The formatted title of this page. def title diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index f2365cd7fd..c2ecc60bd0 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -1,5 +1,7 @@ class GitPushService attr_accessor :project, :user, :push_data, :push_commits + include Gitlab::CurrentSettings + include Gitlab::Access # This method will be called after each git update # and only if the provided user and project is present in GitLab. @@ -29,8 +31,12 @@ class GitPushService if is_default_branch?(ref) # Initial push to the default branch. Take the full history of that branch as "newly pushed". @push_commits = project.repository.commits(newrev) - # Default branch is protected by default - project.protected_branches.create({ name: project.default_branch }) + + # Set protection on the default branch if configured + if (current_application_settings.default_branch_protection != PROTECTION_NONE) + developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false + project.protected_branches.create({ name: project.default_branch, developers_can_push: developers_can_push }) + end else # Use the pushed commits that aren't reachable by the default branch # as a heuristic. This may include more commits than are actually pushed, but diff --git a/app/services/oauth2/access_token_validation_service.rb b/app/services/oauth2/access_token_validation_service.rb index 5a3b94129f..6194f6ce91 100644 --- a/app/services/oauth2/access_token_validation_service.rb +++ b/app/services/oauth2/access_token_validation_service.rb @@ -38,4 +38,4 @@ module Oauth2::AccessTokenValidationService end end end -end \ No newline at end of file +end diff --git a/app/services/projects/image_service.rb b/app/services/projects/image_service.rb index c79ddddd97..7ca7e82c4a 100644 --- a/app/services/projects/image_service.rb +++ b/app/services/projects/image_service.rb @@ -14,14 +14,14 @@ module Projects uploader.store!(image) link = { 'alt' => File.basename(alt, '.*'), - 'url' => File.join(@root_url, uploader.url) + 'url' => File.join(@root_url, uploader.url) } else link = nil end end - protected + protected def upload_path base_dir = FileUploader.generate_dir diff --git a/app/services/projects/participants_service.rb b/app/services/projects/participants_service.rb index c4d2c0963b..e3b33de8d0 100644 --- a/app/services/projects/participants_service.rb +++ b/app/services/projects/participants_service.rb @@ -5,11 +5,12 @@ module Projects end def execute(note_type, note_id) - participating = if note_type && note_id - participants_in(note_type, note_id) - else - [] - end + participating = + if note_type && note_id + participants_in(note_type, note_id) + else + [] + end team_members = sorted(@project.team.members) participants = all_members + team_members + participating participants.uniq diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 9423a20706..bf0ee49d2f 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -25,6 +25,10 @@ = f.label :default_projects_limit, class: 'control-label' .col-sm-10 = f.number_field :default_projects_limit, class: 'form-control' + .form-group + = f.label :default_branch_protection, class: 'control-label' + .col-sm-10 + = f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control' .form-group = f.label :home_page_url, class: 'control-label' .col-sm-10 diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 1ff3d4061f..d2face1927 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -91,7 +91,7 @@ %div.prepend-top-10 = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" %hr - = button_tag 'Add users into group', class: "btn btn-create" + = button_tag 'Add users to group', class: "btn btn-create" .panel.panel-default .panel-heading %h3.panel-title diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml index ddabd6e0d5..ddf4427080 100644 --- a/app/views/dashboard/_groups.html.haml +++ b/app/views/dashboard/_groups.html.haml @@ -10,7 +10,8 @@ - groups.each do |group| %li.group-row = link_to group_path(id: group.path), class: dom_class(group) do - = image_tag group_icon(group.path), class: "avatar s24" + .dash-project-avatar + = image_tag group_icon(group.path), class: "avatar s40" %span.group-name.filter-title = truncate(group.name, length: 35) %span.arrow diff --git a/app/views/dashboard/_project.html.haml b/app/views/dashboard/_project.html.haml index 76b95264fd..e9f411725a 100644 --- a/app/views/dashboard/_project.html.haml +++ b/app/views/dashboard/_project.html.haml @@ -1,8 +1,8 @@ = link_to project_path(project), class: dom_class(project) do + .dash-project-avatar + = project_icon(project.to_param, alt: '', class: 'avatar s40') .dash-project-access-icon = visibility_level_icon(project.visibility_level) - .dash-project-avatar - = project_icon(project.to_param, alt: '', class: 'avatar s24') %span.str-truncated %span.namespace-name - if project.namespace diff --git a/app/views/groups/_new_group_member.html.haml b/app/views/groups/_new_group_member.html.haml index 6df1778878..9123b3b94f 100644 --- a/app/views/groups/_new_group_member.html.haml +++ b/app/views/groups/_new_group_member.html.haml @@ -12,4 +12,4 @@ %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" .form-actions - = f.submit 'Add users into group', class: "btn btn-create" + = f.submit 'Add users to group', class: "btn btn-create" diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index 34221595fd..a2f1d28a27 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -12,10 +12,10 @@ - projects.each do |project| %li.project-row = link_to project_path(project), class: dom_class(project) do + .dash-project-avatar + = project_icon(project.to_param, alt: '', class: 'avatar s40') .dash-project-access-icon = visibility_level_icon(project.visibility_level) - .dash-project-avatar - = project_icon(project.to_param, alt: '', class: 'avatar s24') %span.str-truncated %span.project-name = project.name diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index e4b1cc889a..07f84e02d4 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -1,6 +1,6 @@ .dashboard %div - = image_tag group_icon(@group.path), class: "avatar s90" + = image_tag group_icon(@group.path), class: "avatar avatar-tile s90" .clearfix %h2 = @group.name diff --git a/app/views/layouts/_collapse_button.html.haml b/app/views/layouts/_collapse_button.html.haml new file mode 100644 index 0000000000..b3b338b55b --- /dev/null +++ b/app/views/layouts/_collapse_button.html.haml @@ -0,0 +1,4 @@ +- if nav_menu_collapsed? + = link_to icon('angle-right'), '#', class: 'toggle-nav-collapse' +- else + = link_to icon('angle-left'), '#', class: 'toggle-nav-collapse' diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 1263f44eca..98a3d2278a 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,8 +1,10 @@ - if defined?(sidebar) - .page-with-sidebar + .page-with-sidebar{ class: nav_sidebar_class } = render "layouts/broadcast" .sidebar-wrapper = render(sidebar) + .collapse-nav + = render partial: 'layouts/collapse_button' .content-wrapper .container-fluid .content diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index c507ecf2e4..51a2f20d1e 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -30,5 +30,5 @@ %code :erb <% lines.each do |line| %> - <%= highlight(@blob.name, line, true).html_safe %> + <%= highlight(@blob.name, line.force_encoding("utf-8"), true).html_safe %> <% end %> diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml index b41fb1437f..dd28a35d41 100644 --- a/app/views/projects/commit/_commit_box.html.haml +++ b/app/views/projects/commit/_commit_box.html.haml @@ -37,23 +37,8 @@ - @commit.parents.each do |parent| = link_to parent.short_id, project_commit_path(@project, parent) -.commit-info-row - - if @branches.any? - %span - - branch = commit_default_branch(@project, @branches) - = link_to(project_tree_path(@project, branch)) do - %span.label.label-gray - %i.fa.fa-code-fork - = branch - - if @branches.any? || @tags.any? - = link_to("#", class: "js-details-expand") do - %span.label.label-gray - \... - %span.js-details-content.hide - - if @branches.any? - = commit_branches_links(@project, @branches) - - if @tags.any? - = commit_tags_links(@project, @tags) +.commit-info-row.branches + %i.fa.fa-spinner.fa-spin .commit-box %h3.commit-title @@ -61,3 +46,7 @@ - if @commit.description.present? %pre.commit-description = preserve(gfm(escape_once(@commit.description))) + +:coffeescript + $ -> + $(".commit-info-row.branches").load("#{branches_project_commit_path(@project, @commit.id)}") \ No newline at end of file diff --git a/app/views/projects/commit/branches.html.haml b/app/views/projects/commit/branches.html.haml new file mode 100644 index 0000000000..b01e806210 --- /dev/null +++ b/app/views/projects/commit/branches.html.haml @@ -0,0 +1,16 @@ +- if @branches.any? + %span + - branch = commit_default_branch(@project, @branches) + = link_to(project_tree_path(@project, branch)) do + %span.label.label-gray + %i.fa.fa-code-fork + = branch + - if @branches.any? || @tags.any? + = link_to("#", class: "js-details-expand") do + %span.label.label-gray + \... + %span.js-details-content.hide + - if @branches.any? + = commit_branches_links(@project, @branches) + - if @tags.any? + = commit_tags_links(@project, @tags) \ No newline at end of file diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index e6b35fc98d..9f9bcc1fed 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -3,8 +3,7 @@ .project-edit-content %div %h3.page-title - Project settings: - %p.light Some settings, such as "Transfer Project", are hidden inside the danger area below. + Project settings %hr .panel-body = form_for @project, remote: true, html: { multipart: true, class: "edit_project form-horizontal" }, authenticity_token: true do |f| diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 36628195b4..d7dee2208d 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -10,7 +10,7 @@ You can = link_to project_new_blob_path(@project, 'master'), class: 'btn btn-new btn-lg' do add a file -  or push it via command line. +  or do a push via the command line. %h4 %strong Command line instructions diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml index b5d6a16a1e..e04e1985f1 100644 --- a/app/views/projects/issues/_discussion.html.haml +++ b/app/views/projects/issues/_discussion.html.haml @@ -13,7 +13,7 @@ = link_to_member(@project, participant, name: false, size: 24) .voting_notes#notes= render "projects/notes/notes_with_form" - .col-md-3.hidden-sm.hidden-xs + .col-md-3 %div .clearfix %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} diff --git a/app/views/projects/issues/_issue_context.html.haml b/app/views/projects/issues/_issue_context.html.haml index 98777a58f9..3daa18ba34 100644 --- a/app/views/projects/issues/_issue_context.html.haml +++ b/app/views/projects/issues/_issue_context.html.haml @@ -2,23 +2,21 @@ %div.prepend-top-20 %p Assignee: - + - if issue.assignee + = link_to_member(@project, @issue.assignee) + - else + none - if can?(current_user, :modify_issue, @issue) = project_users_select_tag('issue[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @issue.assignee_id) - - elsif issue.assignee - = link_to_member(@project, @issue.assignee) - - else - None %div.prepend-top-20 %p Milestone: + - if issue.milestone + #{link_to @issue.milestone.title, project_milestone_path(@project, @issue.milestone)} + - else + none - if can?(current_user, :modify_issue, @issue) = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'}) = hidden_field_tag :issue_context = f.submit class: 'btn' - - elsif issue.milestone - = link_to project_milestone_path(@project, @issue.milestone) do - = @issue.milestone.title - - else - None diff --git a/app/views/projects/issues/update.js.haml b/app/views/projects/issues/update.js.haml index 6e50667b08..7a5e051755 100644 --- a/app/views/projects/issues/update.js.haml +++ b/app/views/projects/issues/update.js.haml @@ -3,8 +3,15 @@ :plain $("##{dom_id(@issue)}").fadeOut(); - elsif params[:issue_context] + $('.context').html("#{escape_javascript(render partial: 'issue_context', locals: { issue: @issue })}"); $('.context').effect('highlight'); - if @issue.milestone $('.milestone-nav-link').replaceWith("| Milestone #{escape_javascript(link_to @issue.milestone.title, project_milestone_path(@issue.project, @issue.milestone))}") - else $('.milestone-nav-link').html('') + + +$('select.select2').select2({width: 'resolve', dropdownAutoWidth: true}) +$('.edit-issue.inline-update input[type="submit"]').hide(); +new ProjectUsersSelect(); +new Issue(); diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml index 64bae80078..f1f66569a9 100644 --- a/app/views/projects/merge_requests/_discussion.html.haml +++ b/app/views/projects/merge_requests/_discussion.html.haml @@ -9,7 +9,7 @@ .col-md-9 = render "projects/merge_requests/show/participants" = render "projects/notes/notes_with_form" - .col-md-3.hidden-sm.hidden-xs + .col-md-3 .clearfix %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} = cross_project_reference(@project, @merge_request) @@ -18,7 +18,7 @@ %cite.cgray = render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request } %hr - .votes-holder.hidden-sm.hidden-xs + .votes-holder %h6 Votes #votes= render 'votes/votes_block', votable: @merge_request diff --git a/app/views/projects/merge_requests/show/_context.html.haml b/app/views/projects/merge_requests/show/_context.html.haml index 5b6e64f065..21718ca2ac 100644 --- a/app/views/projects/merge_requests/show/_context.html.haml +++ b/app/views/projects/merge_requests/show/_context.html.haml @@ -2,22 +2,22 @@ %div.prepend-top-20 %p Assignee: - + - if @merge_request.assignee + = link_to_member(@project, @merge_request.assignee) + - else + none - if can?(current_user, :modify_merge_request, @merge_request) = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @merge_request.assignee_id) - - elsif merge_request.assignee - = link_to_member(@project, @merge_request.assignee) - - else - None %div.prepend-top-20 %p Milestone: + - if @merge_request.milestone + %span.back-to-milestone + #{link_to @merge_request.milestone.title, project_milestone_path(@project, @merge_request.milestone)} + - else + none - if can?(current_user, :modify_merge_request, @merge_request) = f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'}) = hidden_field_tag :merge_request_context = f.submit class: 'btn' - - elsif merge_request.milestone - = link_to merge_request.milestone.title, project_milestone_path - - else - None diff --git a/app/views/projects/merge_requests/update.js.haml b/app/views/projects/merge_requests/update.js.haml index 6f4c5dd7a3..f5cc98c7fa 100644 --- a/app/views/projects/merge_requests/update.js.haml +++ b/app/views/projects/merge_requests/update.js.haml @@ -1,2 +1,8 @@ - if params[:merge_request_context] + $('.context').html("#{escape_javascript(render partial: 'projects/merge_requests/show/context', locals: { issue: @issue })}"); $('.context').effect('highlight'); + + new ProjectUsersSelect(); + + $('select.select2').select2({width: 'resolve', dropdownAutoWidth: true}); + merge_request = new MergeRequest(); diff --git a/app/views/projects/notes/discussions/_diff.html.haml b/app/views/projects/notes/discussions/_diff.html.haml index b4d1cce798..f717c77a89 100644 --- a/app/views/projects/notes/discussions/_diff.html.haml +++ b/app/views/projects/notes/discussions/_diff.html.haml @@ -19,8 +19,10 @@ %td.new_line= "..." %td.line_content.matched= line.text - else - %td.old_line= raw(line.type == "new" ? " " : line.old_pos) - %td.new_line= raw(line.type == "old" ? " " : line.new_pos) + %td.old_line{class: line.type == "new" ? "new" : "old"} + = raw(line.type == "new" ? " " : line.old_pos) + %td.new_line{class: line.type == "new" ? "new" : "old"} + = raw(line.type == "old" ? " " : line.new_pos) %td.line_content{class: "noteable_line #{line.type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text) - if line_code == note.line_code diff --git a/app/views/users/_groups.html.haml b/app/views/users/_groups.html.haml index 32a1dc83b5..b66a8808f8 100644 --- a/app/views/users/_groups.html.haml +++ b/app/views/users/_groups.html.haml @@ -1,4 +1,4 @@ .clearfix - groups.each do |group| - = link_to group, class: 'profile-groups-avatars', title: group.name do - = image_tag group_icon(group.path), class: 'avatar avatar-inline s40' + = link_to group, class: 'profile-groups-avatars inline', title: group.name do + = image_tag group_icon(group.path), class: 'avatar avatar-tile s40' diff --git a/app/views/users/_calendar.html.haml b/app/views/users/calendar.html.haml similarity index 91% rename from app/views/users/_calendar.html.haml rename to app/views/users/calendar.html.haml index b16a7305a3..13bdc5ed1e 100644 --- a/app/views/users/_calendar.html.haml +++ b/app/views/users/calendar.html.haml @@ -1,3 +1,4 @@ +%h4 Calendar #cal-heatmap.calendar :javascript new calendar( diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index c248a28047..b05918b019 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -1,7 +1,7 @@ .row .col-md-8 %h3.page-title - = image_tag avatar_icon(@user.email, 90), class: "avatar s90", alt: '' + = image_tag avatar_icon(@user.email, 90), class: "avatar avatar-tile s90", alt: '' = @user.name - if @user == current_user .pull-right @@ -15,15 +15,16 @@ .clearfix - if @groups.any? - %h4 Groups: + %h4 Groups = render 'groups', groups: @groups %hr - %h4 Calendar: - %div= render 'calendar' + .user-calendar + %h4.center.light + %i.fa.fa-spinner.fa-spin %hr %h4 - User Activity: + User Activity - if current_user %span.rss-icon.pull-right @@ -36,3 +37,8 @@ = render 'profile', user: @user - if @projects.present? = render 'projects', projects: @projects + + +:coffeescript + $ -> + $(".user-calendar").load("#{user_calendar_path}") diff --git a/config/application.rb b/config/application.rb index a7d371c78e..24ba219cf3 100644 --- a/config/application.rb +++ b/config/application.rb @@ -70,7 +70,10 @@ module Gitlab config.middleware.use Rack::Cors do allow do origins '*' - resource '/api/*', headers: :any, methods: [:get, :post, :options, :put, :delete] + resource '/api/*', + headers: :any, + methods: [:get, :post, :options, :put, :delete], + expose: ['Link'] end end diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index ce6adfd62e..63d262d7a6 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -13,7 +13,11 @@ class Settings < Settingslogic if gitlab_shell.ssh_port != 22 "ssh://#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:#{gitlab_shell.ssh_port}/" else - "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:" + if gitlab_shell.ssh_host.include? ':' + "[#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}]:" + else + "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:" + end end end @@ -94,6 +98,7 @@ Settings['issues_tracker'] ||= {} # Settings['gitlab'] ||= Settingslogic.new({}) Settings.gitlab['default_projects_limit'] ||= 10 +Settings.gitlab['default_branch_protection'] ||= 2 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil? Settings.gitlab['default_theme'] = Gitlab::Theme::MARS if Settings.gitlab['default_theme'].nil? Settings.gitlab['host'] ||= 'localhost' @@ -155,7 +160,7 @@ Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_s Settings['backup'] ||= Settingslogic.new({}) Settings.backup['keep_time'] ||= 0 Settings.backup['path'] = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root) -Settings.backup['upload'] ||= Settingslogic.new({'remote_directory' => nil, 'connection' => nil}) +Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil }) # Convert upload connection settings to use symbol keys, to make Fog happy if Settings.backup['upload']['connection'] Settings.backup['upload']['connection'] = Hash[Settings.backup['upload']['connection'].map { |k, v| [k.to_sym, v] }] diff --git a/config/initializers/acts_as_taggable_on_patch.rb b/config/initializers/acts_as_taggable_on_patch.rb index baa77fde39..0d535cb5ca 100644 --- a/config/initializers/acts_as_taggable_on_patch.rb +++ b/config/initializers/acts_as_taggable_on_patch.rb @@ -42,11 +42,12 @@ module ActsAsTaggableOn::Taggable elsif options.delete(:any) # get tags, drop out if nothing returned (we need at least one) - tags = if options.delete(:wild) - ActsAsTaggableOn::Tag.named_like_any(tag_list) - else - ActsAsTaggableOn::Tag.named_any(tag_list) - end + tags = + if options.delete(:wild) + ActsAsTaggableOn::Tag.named_like_any(tag_list) + else + ActsAsTaggableOn::Tag.named_any(tag_list) + end return empty_result unless tags.length > 0 @@ -68,12 +69,12 @@ module ActsAsTaggableOn::Taggable select_clause = "DISTINCT #{table_name}.*" unless context and tag_types.one? if owned_by - tagging_join << " AND " + - sanitize_sql([ - "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?", - owned_by.id, - owned_by.class.base_class.to_s - ]) + tagging_join << " AND " + + sanitize_sql([ + "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?", + owned_by.id, + owned_by.class.base_class.to_s + ]) end joins << tagging_join @@ -92,12 +93,12 @@ module ActsAsTaggableOn::Taggable tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context if owned_by - tagging_join << " AND " + - sanitize_sql([ - "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?", - owned_by.id, - owned_by.class.base_class.to_s - ]) + tagging_join << " AND " + + sanitize_sql([ + "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?", + owned_by.id, + owned_by.class.base_class.to_s + ]) end joins << tagging_join diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb index d0065b63e5..bfb8656df5 100644 --- a/config/initializers/carrierwave.rb +++ b/config/initializers/carrierwave.rb @@ -12,22 +12,30 @@ if File.exists?(aws_file) aws_secret_access_key: AWS_CONFIG['secret_access_key'], # required region: AWS_CONFIG['region'], # optional, defaults to 'us-east-1' } - config.fog_directory = AWS_CONFIG['bucket'] # required - config.fog_public = false # optional, defaults to true - config.fog_attributes = {'Cache-Control'=>'max-age=315576000'} # optional, defaults to {} - config.fog_authenticated_url_expiration = 1 << 29 # optional time (in seconds) that authenticated urls will be valid. - # when fog_public is false and provider is AWS or Google, defaults to 600 + + # required + config.fog_directory = AWS_CONFIG['bucket'] + + # optional, defaults to true + config.fog_public = false + + # optional, defaults to {} + config.fog_attributes = { 'Cache-Control'=>'max-age=315576000' } + + # optional time (in seconds) that authenticated urls will be valid. + # when fog_public is false and provider is AWS or Google, defaults to 600 + config.fog_authenticated_url_expiration = 1 << 29 end # Mocking Fog requests, based on: https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Test-Fog-based-uploaders if Rails.env.test? Fog.mock! connection = ::Fog::Storage.new( - :aws_access_key_id => AWS_CONFIG['access_key_id'], - :aws_secret_access_key => AWS_CONFIG['secret_access_key'], - :provider => 'AWS', - :region => AWS_CONFIG['region'] + aws_access_key_id: AWS_CONFIG['access_key_id'], + aws_secret_access_key: AWS_CONFIG['secret_access_key'], + provider: 'AWS', + region: AWS_CONFIG['region'] ) - connection.directories.create(:key => AWS_CONFIG['bucket']) + connection.directories.create(key: AWS_CONFIG['bucket']) end end diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index 4819ab273d..e9b843e29b 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -43,10 +43,10 @@ Doorkeeper.configure do force_ssl_in_redirect_uri false # Provide support for an owner to be assigned to each registered application (disabled by default) - # Optional parameter :confirmation => true (default false) if you want to enforce ownership of + # Optional parameter confirmation: true (default false) if you want to enforce ownership of # a registered application # Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support - enable_application_owner :confirmation => false + enable_application_owner confirmation: false # Define access token scopes for your provider # For more information go to diff --git a/config/initializers/gitlab_shell_secret_token.rb b/config/initializers/gitlab_shell_secret_token.rb index 8d2b771e53..e7c9f0ba7c 100644 --- a/config/initializers/gitlab_shell_secret_token.rb +++ b/config/initializers/gitlab_shell_secret_token.rb @@ -16,4 +16,4 @@ end if File.exist?(Gitlab.config.gitlab_shell.path) && !File.exist?(gitlab_shell_symlink) FileUtils.symlink(secret_file, gitlab_shell_symlink) -end \ No newline at end of file +end diff --git a/config/routes.rb b/config/routes.rb index 8a522546d6..3b2bdb3f20 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,9 +3,9 @@ require 'api/api' Gitlab::Application.routes.draw do use_doorkeeper do - controllers :applications => 'oauth/applications', - :authorized_applications => 'oauth/authorized_applications', - :authorizations => 'oauth/authorizations' + controllers applications: 'oauth/applications', + authorized_applications: 'oauth/authorized_applications', + authorizations: 'oauth/authorizations' end # # Search @@ -167,10 +167,9 @@ Gitlab::Application.routes.draw do end end - # route for commits used by the cal-heatmap - get 'u/:username/activities' => 'users#activities', as: :user_activities, - constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }, - via: :get + get 'u/:username/calendar' => 'users#calendar', as: :user_calendar, + constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } + get '/u/:username' => 'users#show', as: :user, constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } @@ -188,7 +187,7 @@ Gitlab::Application.routes.draw do # # Groups Area # - resources :groups, constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} do + resources :groups, constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } do member do get :issues get :merge_requests @@ -239,40 +238,44 @@ Gitlab::Application.routes.draw do scope module: :projects do # Blob routes: - get '/new/:id', to: 'blob#new', constraints: {id: /.+/}, as: 'new_blob' - post '/create/:id', to: 'blob#create', constraints: {id: /.+/}, as: 'create_blob' - get '/edit/:id', to: 'blob#edit', constraints: {id: /.+/}, as: 'edit_blob' - put '/update/:id', to: 'blob#update', constraints: {id: /.+/}, as: 'update_blob' - post '/preview/:id', to: 'blob#preview', constraints: {id: /.+/}, as: 'preview_blob' + get '/new/:id', to: 'blob#new', constraints: { id: /.+/ }, as: 'new_blob' + post '/create/:id', to: 'blob#create', constraints: { id: /.+/ }, as: 'create_blob' + get '/edit/:id', to: 'blob#edit', constraints: { id: /.+/ }, as: 'edit_blob' + put '/update/:id', to: 'blob#update', constraints: { id: /.+/ }, as: 'update_blob' + post '/preview/:id', to: 'blob#preview', constraints: { id: /.+/ }, as: 'preview_blob' resources :blob, only: [:show, :destroy], constraints: { id: /.+/, format: false } do get :diff, on: :member end - resources :raw, only: [:show], constraints: {id: /.+/} - resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ } + resources :raw, only: [:show], constraints: { id: /.+/ } + resources :tree, only: [:show], constraints: { id: /.+/, format: /(html|js)/ } resource :avatar, only: [:show, :destroy] - resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/} - resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} + + resources :commit, only: [:show], constraints: { id: /[[:alnum:]]{6,40}/ } do + get :branches, on: :member + end + + resources :commits, only: [:show], constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } resources :compare, only: [:index, :create] - resources :blame, only: [:show], constraints: {id: /.+/} - resources :network, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/} - resources :graphs, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/} do + resources :blame, only: [:show], constraints: { id: /.+/ } + resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } + resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do member do get :commits end end get '/compare/:from...:to' => 'compare#show', :as => 'compare', - :constraints => {from: /.+/, to: /.+/} + :constraints => { from: /.+/, to: /.+/ } - resources :snippets, constraints: {id: /\d+/} do + resources :snippets, constraints: { id: /\d+/ } do member do get 'raw' end end - resources :wikis, only: [:show, :edit, :destroy, :create], constraints: {id: /[a-zA-Z.0-9_\-\/]+/} do + resources :wikis, only: [:show, :edit, :destroy, :create], constraints: { id: /[a-zA-Z.0-9_\-\/]+/ } do collection do get :pages put ':id' => 'wikis#update' @@ -299,7 +302,7 @@ Gitlab::Application.routes.draw do end end - resources :deploy_keys, constraints: {id: /\d+/} do + resources :deploy_keys, constraints: { id: /\d+/ } do member do put :enable put :disable @@ -318,16 +321,14 @@ Gitlab::Application.routes.draw do member do # tree viewer logs get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex } - get 'logs_tree/:path' => 'refs#logs_tree', - as: :logs_file, - constraints: { - id: Gitlab::Regex.git_reference_regex, - path: /.*/ - } + get 'logs_tree/:path' => 'refs#logs_tree', as: :logs_file, constraints: { + id: Gitlab::Regex.git_reference_regex, + path: /.*/ + } end end - resources :merge_requests, constraints: {id: /\d+/}, except: [:destroy] do + resources :merge_requests, constraints: { id: /\d+/ }, except: [:destroy] do member do get :diffs post :automerge @@ -342,29 +343,28 @@ Gitlab::Application.routes.draw do end end - resources :git_hooks, constraints: {id: /\d+/} - - resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do + resources :git_hooks, constraints: { id: /\d+/ } + resources :hooks, only: [:index, :create, :destroy], constraints: { id: /\d+/ } do member do get :test end end resources :team, controller: 'team_members', only: [:index] - resources :milestones, except: [:destroy], constraints: {id: /\d+/} do + resources :milestones, except: [:destroy], constraints: { id: /\d+/ } do member do put :sort_issues put :sort_merge_requests end end - resources :labels, constraints: {id: /\d+/} do + resources :labels, constraints: { id: /\d+/ } do collection do post :generate end end - resources :issues, constraints: {id: /\d+/}, except: [:destroy] do + resources :issues, constraints: { id: /\d+/ }, except: [:destroy] do collection do post :bulk_update end @@ -381,9 +381,9 @@ Gitlab::Application.routes.draw do end end - resources :group_links, only: [:index, :create, :destroy], constraints: {id: /\d+/} + resources :group_links, only: [:index, :create, :destroy], constraints: { id: /\d+/ } - resources :notes, only: [:index, :create, :destroy, :update], constraints: {id: /\d+/} do + resources :notes, only: [:index, :create, :destroy, :update], constraints: { id: /\d+/ } do member do delete :delete_attachment end @@ -394,7 +394,7 @@ Gitlab::Application.routes.draw do get "/audit_events" => "audit_events#project_log" end - get ':id' => 'namespaces#show', constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} + get ':id' => 'namespaces#show', constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } root to: 'dashboard#show' end diff --git a/db/migrate/20150125163100_add_default_branch_protection_setting.rb b/db/migrate/20150125163100_add_default_branch_protection_setting.rb new file mode 100644 index 0000000000..5020daf55f --- /dev/null +++ b/db/migrate/20150125163100_add_default_branch_protection_setting.rb @@ -0,0 +1,5 @@ +class AddDefaultBranchProtectionSetting < ActiveRecord::Migration + def change + add_column :application_settings, :default_branch_protection, :integer, :default => 2 + end +end diff --git a/db/schema.rb b/db/schema.rb index 67c8499b34..f0a2f703e6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150116234545) do +ActiveRecord::Schema.define(version: 20150125163100) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -27,6 +27,18 @@ ActiveRecord::Schema.define(version: 20150116234545) do t.string "light_logo" end + create_table "application_settings", force: true do |t| + t.integer "default_projects_limit" + t.boolean "signup_enabled" + t.boolean "signin_enabled" + t.boolean "gravatar_enabled" + t.text "sign_in_text" + t.datetime "created_at" + t.datetime "updated_at" + t.string "home_page_url" + t.integer "default_branch_protection", default: 2 + end + create_table "audit_events", force: true do |t| t.integer "author_id", null: false t.string "type", null: false @@ -41,17 +53,6 @@ ActiveRecord::Schema.define(version: 20150116234545) do add_index "audit_events", ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree add_index "audit_events", ["type"], name: "index_audit_events_on_type", using: :btree - create_table "application_settings", force: true do |t| - t.integer "default_projects_limit" - t.boolean "signup_enabled" - t.boolean "signin_enabled" - t.boolean "gravatar_enabled" - t.text "sign_in_text" - t.datetime "created_at" - t.datetime "updated_at" - t.string "home_page_url" - end - create_table "broadcast_messages", force: true do |t| t.text "message", null: false t.datetime "starts_at" @@ -378,14 +379,14 @@ ActiveRecord::Schema.define(version: 20150116234545) do t.string "import_url" t.integer "visibility_level", default: 0, null: false t.boolean "archived", default: false, null: false + t.string "avatar" t.string "import_status" + t.float "repository_size", default: 0.0 + t.text "merge_requests_template" + t.integer "star_count", default: 0, null: false + t.boolean "merge_requests_rebase_enabled", default: false t.string "import_type" t.string "import_source" - t.float "repository_size", default: 0.0 - t.integer "star_count", default: 0, null: false - t.text "merge_requests_template" - t.boolean "merge_requests_rebase_enabled", default: false - t.string "avatar" end add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree @@ -483,6 +484,7 @@ ActiveRecord::Schema.define(version: 20150116234545) do t.integer "notification_level", default: 1, null: false t.datetime "password_expires_at" t.integer "created_by_id" + t.datetime "last_credential_check_at" t.string "avatar" t.string "confirmation_token" t.datetime "confirmed_at" @@ -490,9 +492,8 @@ ActiveRecord::Schema.define(version: 20150116234545) do t.string "unconfirmed_email" t.boolean "hide_no_ssh_key", default: false t.string "website_url", default: "", null: false - t.datetime "last_credential_check_at" - t.string "github_access_token" t.datetime "admin_email_unsubscribed_at" + t.string "github_access_token" t.string "gitlab_access_token" end diff --git a/doc/api/README.md b/doc/api/README.md index 8f919f5257..8cbba8598d 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -97,7 +97,7 @@ Return values: ## Sudo -All API requests support performing an api call as if you were another user, if your private token is for an administration account. You need to pass `sudo` parameter by url or header with an id or username of the user you want to perform the operation as. If passed as header, the header name must be "SUDO" (capitals). +All API requests support performing an api call as if you were another user, if your private token is for an administration account. You need to pass `sudo` parameter by URL or header with an id or username of the user you want to perform the operation as. If passed as header, the header name must be "SUDO" (capitals). If a non administrative `private_token` is provided then an error message will be returned with status code 403: @@ -142,7 +142,7 @@ When listing resources you can pass the following parameters: - `page` (default: `1`) - page number - `per_page` (default: `20`, max: `100`) - number of items to list per page -[Link headers](http://www.w3.org/wiki/LinkHeader) are send back with each response. These have `rel` prev/next/first/last and contain the relevant URL. Please use these instead of generating your own urls. +[Link headers](http://www.w3.org/wiki/LinkHeader) are send back with each response. These have `rel` prev/next/first/last and contain the relevant URL. Please use these instead of generating your own URLs. ## id vs iid diff --git a/doc/api/groups.md b/doc/api/groups.md index e6893d7177..9f01b55064 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -20,7 +20,7 @@ GET /groups ] ``` -You can search for groups by name or path with: `/groups?search=Rails` +You can search for groups by name or path, see below. ## Details of a group @@ -32,7 +32,7 @@ GET /groups/:id Parameters: -- `id` (required) - The ID of a group +- `id` (required) - The ID or path of a group ## New group @@ -58,7 +58,7 @@ POST /groups/:id/projects/:project_id Parameters: -- `id` (required) - The ID of a group +- `id` (required) - The ID or path of a group - `project_id` (required) - The ID of a project ## Remove group @@ -71,7 +71,27 @@ DELETE /groups/:id Parameters: -- `id` (required) - The ID of a user group +- `id` (required) - The ID or path of a user group + +## Search for group + +Get all groups that match your string in their name or path. + +``` +GET /groups?search=foobar +``` + +```json +[ + { + "id": 1, + "name": "Foobar Group", + "path": "foo-bar", + "owner_id": 18, + "description": "An interesting group" + } +] +``` ## Group members @@ -128,7 +148,7 @@ POST /groups/:id/members Parameters: -- `id` (required) - The ID of a group +- `id` (required) - The ID or path of a group - `user_id` (required) - The ID of a user to add - `access_level` (required) - Project access level @@ -142,5 +162,5 @@ DELETE /groups/:id/members/:user_id Parameters: -- `id` (required) - The ID of a user group +- `id` (required) - The ID or path of a user group - `user_id` (required) - The ID of a group member diff --git a/doc/api/issues.md b/doc/api/issues.md index ceeb683a6b..8d073c46d3 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -56,7 +56,7 @@ Parameters: "title": "v1.0", "description": "", "due_date": "2012-07-20", - "state": "reopenend", + "state": "reopened", "updated_at": "2012-07-04T13:42:48Z", "created_at": "2012-07-04T13:42:48Z" }, diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 053fc9346b..acae55d07e 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -94,6 +94,76 @@ Parameters: } ``` +## Get single MR changes + +Shows information about the merge request including its files and changes + +``` +GET /projects/:id/merge_request/:merge_request_id/changes +``` + +Parameters: + +- `id` (required) - The ID of a project +- `merge_request_id` (required) - The ID of MR + +```json +{ + "id": 21, + "iid": 1, + "project_id": 4, + "title": "Blanditiis beatae suscipit hic assumenda et molestias nisi asperiores repellat et.", + "description": "Qui voluptatibus placeat ipsa alias quasi. Deleniti rem ut sint. Optio velit qui distinctio.", + "state": "reopened", + "created_at": "2015-02-02T19:49:39.159Z", + "updated_at": "2015-02-02T20:08:49.959Z", + "target_branch": "secret_token", + "source_branch": "version-1-9", + "upvotes": 0, + "downvotes": 0, + "author": { + "name": "Chad Hamill", + "username": "jarrett", + "id": 5, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/b95567800f828948baf5f4160ebb2473?s=40&d=identicon" + }, + "assignee": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40&d=identicon" + }, + "source_project_id": 4, + "target_project_id": 4, + "labels": [ ], + "milestone": { + "id": 5, + "iid": 1, + "project_id": 4, + "title": "v2.0", + "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.", + "state": "closed", + "created_at": "2015-02-02T19:49:26.013Z", + "updated_at": "2015-02-02T19:49:26.013Z", + "due_date": null + }, + "files": [ + { + "old_path": "VERSION", + "new_path": "VERSION", + "a_mode": "100644", + "b_mode": "100644", + "diff": "--- a/VERSION\ +++ b/VERSION\ @@ -1 +1 @@\ -1.9.7\ +1.9.8", + "new_file": false, + "renamed_file": false, + "deleted_file": false + } + ] +} +``` + ## Create MR Creates a new merge request. diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md index b2dbba9bde..7bb391054c 100644 --- a/doc/api/oauth2.md +++ b/doc/api/oauth2.md @@ -4,7 +4,7 @@ OAuth2 is a protocol that enables us to get access to private details of user's Before using the OAuth2 you should create an application in user's account. Each application getting unique App ID and App Secret parameters. You should not share them. -This functianolity is based on [doorkeeper gem](https://github.com/doorkeeper-gem/doorkeeper) +This functionality is based on [doorkeeper gem](https://github.com/doorkeeper-gem/doorkeeper) ## Web Application Flow @@ -15,7 +15,7 @@ This flow consists from 3 steps. ### 1. Registering the client -Creat an application in user's account profile. +Create an application in user's account profile. ### 2. Requesting authorization @@ -96,4 +96,4 @@ For testing you can use the oauth2 ruby gem: client = OAuth2::Client.new('the_client_id', 'the_client_secret', :site => "http://example.com") access_token = client.password.get_token('user@example.com', 'sekret') puts access_token.token -``` \ No newline at end of file +``` diff --git a/doc/api/projects.md b/doc/api/projects.md index db78778828..3a376aa9e0 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -541,7 +541,7 @@ Parameters: } ], "tree": "c68537c6534a02cc2b176ca1549f4ffa190b58ee", - "message": "give caolan credit where it's due (up top)", + "message": "give Caolan credit where it's due (up top)", "author": { "name": "Jeremy Ashkenas", "email": "jashkenas@example.com" diff --git a/doc/api/services.md b/doc/api/services.md index ab9f9c00c6..cbf767d1b2 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -13,7 +13,7 @@ PUT /projects/:id/services/gitlab-ci Parameters: - `token` (required) - CI project token -- `project_url` (required) - CI project url +- `project_url` (required) - CI project URL ### Delete GitLab CI service @@ -23,23 +23,23 @@ Delete GitLab CI service settings for a project. DELETE /projects/:id/services/gitlab-ci ``` -## Hipchat +## HipChat -### Edit Hipchat service +### Edit HipChat service -Set Hipchat service for project. +Set HipChat service for project. ``` PUT /projects/:id/services/hipchat ``` Parameters: -- `token` (required) - Hipchat token -- `room` (required) - Hipchat room name +- `token` (required) - HipChat token +- `room` (required) - HipChat room name -### Delete Hipchat service +### Delete HipChat service -Delete Hipchat service for a project. +Delete HipChat service for a project. ``` DELETE /projects/:id/services/hipchat diff --git a/doc/customization/libravatar.md b/doc/customization/libravatar.md index 4dffd3027a..ee57fdc659 100644 --- a/doc/customization/libravatar.md +++ b/doc/customization/libravatar.md @@ -16,7 +16,7 @@ the configuration options as follows: ```yml gravatar: enabled: true - # gravatar urls: possible placeholders: %{hash} %{size} %{email} + # gravatar URLs: possible placeholders: %{hash} %{size} %{email} plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon" ``` @@ -25,14 +25,14 @@ the configuration options as follows: ```yml gravatar: enabled: true - # gravatar urls: possible placeholders: %{hash} %{size} %{email} + # gravatar URLs: possible placeholders: %{hash} %{size} %{email} ssl_url: "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon" ``` ## Self-hosted -If you are [running your own libravatar service](http://wiki.libravatar.org/running_your_own/) the url will be different in the configuration -but the important part is to provide the same placeholders so GitLab can parse the url correctly. +If you are [running your own libravatar service](http://wiki.libravatar.org/running_your_own/) the URL will be different in the configuration +but the important part is to provide the same placeholders so GitLab can parse the URL correctly. For example, you host a service on `http://libravatar.example.com` the `plain_url` you need to supply in `gitlab.yml` is @@ -65,5 +65,5 @@ Run `sudo gitlab-ctl reconfigure` for changes to take effect. [Libravatar supports different sets](http://wiki.libravatar.org/api/) of `missing images` for emails not found on the Libravatar service. -In order to use a different set other than `identicon`, replace `&d=identicon` portion of the url with another supported set. -For example, you can use `retro` set in which case url would look like: `plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"` +In order to use a different set other than `identicon`, replace `&d=identicon` portion of the URL with another supported set. +For example, you can use `retro` set in which case the URL would look like: `plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"` diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 209182e774..714cc01600 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -16,8 +16,8 @@ You can imagine GitLab as a physical office. They can be stored in a warehouse. This can be either a hard disk, or something more complex, such as a NFS filesystem; -**NginX** acts like the front-desk. -Users come to NginX and request actions to be done by workers in the office; +**Nginx** acts like the front-desk. +Users come to Nginx and request actions to be done by workers in the office; **The database** is a series of metal file cabinets with information on: - The goods in the warehouse (metadata, issues, merge requests etc); @@ -70,7 +70,7 @@ To summarize here's the [directory structure of the `git` user home directory](. ps aux | grep '^git' -GitLab has several components to operate. As a system user (i.e. any user that is not the `git` user) it requires a persistent database (MySQL/PostreSQL) and redis database. It also uses Apache httpd or nginx to proxypass Unicorn. As the `git` user it starts Sidekiq and Unicorn (a simple ruby HTTP server running on port `8080` by default). Under the GitLab user there are normally 4 processes: `unicorn_rails master` (1 process), `unicorn_rails worker` (2 processes), `sidekiq` (1 process). +GitLab has several components to operate. As a system user (i.e. any user that is not the `git` user) it requires a persistent database (MySQL/PostreSQL) and redis database. It also uses Apache httpd or Nginx to proxypass Unicorn. As the `git` user it starts Sidekiq and Unicorn (a simple ruby HTTP server running on port `8080` by default). Under the GitLab user there are normally 4 processes: `unicorn_rails master` (1 process), `unicorn_rails worker` (2 processes), `sidekiq` (1 process). ### Repository access @@ -146,13 +146,13 @@ nginx Apache httpd -- [Explanation of apache logs](http://httpd.apache.org/docs/2.2/logs.html). +- [Explanation of Apache logs](http://httpd.apache.org/docs/2.2/logs.html). - `/var/log/apache2/` contains error and output logs (on Ubuntu). - `/var/log/httpd/` contains error and output logs (on RHEL). redis -- `/var/log/redis/redis.log` there are also logrotated logs there. +- `/var/log/redis/redis.log` there are also log-rotated logs there. PostgreSQL diff --git a/doc/development/ci_setup.md b/doc/development/ci_setup.md index ee16aedafe..f417667754 100644 --- a/doc/development/ci_setup.md +++ b/doc/development/ci_setup.md @@ -26,7 +26,7 @@ We use [these build scripts](https://gitlab.com/gitlab-org/gitlab-ci/blob/master # Build configuration on [Semaphore](https://semaphoreapp.com/gitlabhq/gitlabhq/) for testing the [GitHub.com repo](https://github.com/gitlabhq/gitlabhq) - Language: Ruby -- Ruby verion: 2.1.2 +- Ruby version: 2.1.2 - database.yml: pg Build commands diff --git a/doc/install/installation.md b/doc/install/installation.md index 113f48b794..831579725b 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -280,7 +280,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da GitLab Shell is an SSH access and repository management software developed specially for GitLab. # Run the installation task for gitlab-shell (replace `REDIS_URL` if needed): - sudo -u git -H bundle exec rake gitlab:shell:install[v2.4.1] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production + sudo -u git -H bundle exec rake gitlab:shell:install[v2.4.2] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production # By default, the gitlab-shell config is generated from your main GitLab config. # You can review (and modify) the gitlab-shell config as follows: diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 8eabb219b1..2cf9e82fd2 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -7,7 +7,7 @@ - Ubuntu - Debian - CentOS -- RedHat Enterprise Linux (please use the CentOS packages and instructions) +- Red Hat Enterprise Linux (please use the CentOS packages and instructions) - Scientific Linux (please use the CentOS packages and instructions) - Oracle Linux (please use the CentOS packages and instructions) diff --git a/doc/integration/README.md b/doc/integration/README.md index 00131a8d50..fe51d6f074 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -14,7 +14,7 @@ See the documentation below for details on how to configure these services. ## Project services -Integration with services such as Campfire, Flowdock, Gemnasium, HipChat, PivotalTracker and Slack are available in the from of a Project Service. +Integration with services such as Campfire, Flowdock, Gemnasium, HipChat, Pivotal Tracker, and Slack are available in the form of a Project Service. You can find these within GitLab in the Services page under Project Settings if you are at least a master on the project. Project Services are a bit like plugins in that they allow a lot of freedom in adding functionality to GitLab, for example there is also a service that can send an email every time someone pushes new commits. Because GitLab is open source we can ship with the code and tests for all plugins. diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md index 11ba0401e2..502d275bd9 100644 --- a/doc/integration/external-issue-tracker.md +++ b/doc/integration/external-issue-tracker.md @@ -6,6 +6,6 @@ GitLab has a great issue tracker but you can also use an external issue tracker - clicking 'New issue' on the project dashboard creates a new JIRA issue; - To reference JIRA issue PROJECT-1234 in comments, use syntax PROJECT-1234. Commit messages get turned into HTML links to the corresponding JIRA issue. -![jira screenshot](jira-integration-points.png) +![Jira screenshot](jira-integration-points.png) You can configure the integration in the gitlab.yml configuration file. diff --git a/doc/integration/gitlab_buttons_in_gmail.md b/doc/integration/gitlab_buttons_in_gmail.md index 0816509c55..a9885cef10 100644 --- a/doc/integration/gitlab_buttons_in_gmail.md +++ b/doc/integration/gitlab_buttons_in_gmail.md @@ -1,4 +1,4 @@ -# GitLab buttons in gmail +# GitLab buttons in Gmail GitLab supports [Google actions in email](https://developers.google.com/gmail/markup/actions/actions-overview). @@ -25,4 +25,4 @@ If you receive "No errors detected" message from the tester you can send the ema ```bash bundle exec rake gitlab:mail_google_schema_whitelisting RAILS_ENV=production SEND=true -`` +``` diff --git a/doc/integration/shibboleth.md b/doc/integration/shibboleth.md index 78317a5c0f..ea11f1afea 100644 --- a/doc/integration/shibboleth.md +++ b/doc/integration/shibboleth.md @@ -2,7 +2,7 @@ This documentation is for enabling shibboleth with gitlab-omnibus package. -In order to enable Shibboleth support in gitlab we need to use Apache instead of Nginx (It may be possible to use Nginx, however I did not found way to easily configure nginx that is bundled in gitlab-omnibus package). Apache uses mod_shib2 module for shibboleth authentication and can pass attributes as headers to omniauth-shibboleth provider. +In order to enable Shibboleth support in gitlab we need to use Apache instead of Nginx (It may be possible to use Nginx, however I did not found way to easily configure Nginx that is bundled in gitlab-omnibus package). Apache uses mod_shib2 module for shibboleth authentication and can pass attributes as headers to omniauth-shibboleth provider. To enable the Shibboleth OmniAuth provider you must: @@ -10,11 +10,11 @@ To enable the Shibboleth OmniAuth provider you must: 1. Configure Apache shibboleth module. Installation and configuration of module it self is out of scope of this document. Check https://wiki.shibboleth.net/ for more info. -1. You can find Apache config in gitlab-reciepes (https://github.com/gitlabhq/gitlab-recipes/blob/master/web-server/apache/gitlab-ssl.conf) +1. You can find Apache config in gitlab-recipes (https://github.com/gitlabhq/gitlab-recipes/blob/master/web-server/apache/gitlab-ssl.conf) Following changes are needed to enable shibboleth: -protect omniauth-shibboleth callback url: +protect omniauth-shibboleth callback URL: ``` AuthType shibboleth @@ -32,9 +32,9 @@ protect omniauth-shibboleth callback url: SetHandler shib ``` -exclude shibboleth urls from rewriting, add "RewriteCond %{REQUEST_URI} !/Shibboleth.sso" and "RewriteCond %{REQUEST_URI} !/shibboleth-sp", config should look like this: +exclude shibboleth URLs from rewriting, add "RewriteCond %{REQUEST_URI} !/Shibboleth.sso" and "RewriteCond %{REQUEST_URI} !/shibboleth-sp", config should look like this: ``` - #apache equivalent of nginx try files + # Apache equivalent of Nginx try files RewriteEngine on RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_URI} !/Shibboleth.sso @@ -50,7 +50,7 @@ File it should look like this: external_url 'https://gitlab.example.com' gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' -# disable nginx +# disable Nginx nginx['enable'] = false gitlab_rails['omniauth_allow_single_sign_on'] = true diff --git a/doc/integration/slack.md b/doc/integration/slack.md index f2e73f272e..2fd22c513a 100644 --- a/doc/integration/slack.md +++ b/doc/integration/slack.md @@ -35,7 +35,7 @@ After Slack is ready we need to setup GitLab. Here are the steps to achieve this 1. Fill in your Slack details - Mark it as active - - Paste in the webhook url you got from Slack + - Paste in the webhook URL you got from Slack Have fun :) diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index edb7a97550..2568245e9c 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -6,7 +6,7 @@ * [Newlines](#newlines) * [Multiple underscores in words](#multiple-underscores-in-words) -* [URL autolinking](#url-autolinking) +* [URL auto-linking](#url-autolinking) * [Code and Syntax Highlighting](#code-and-syntax-highlighting) * [Emoji](#emoji) * [Special GitLab references](#special-gitlab-references) @@ -40,7 +40,7 @@ You can use GFM in - milestones - wiki pages -You can also use other rich text files in GitLab. You might have to install a depency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information. +You can also use other rich text files in GitLab. You might have to install a dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information. ## Newlines @@ -68,7 +68,7 @@ It is not reasonable to italicize just _part_ of a word, especially when you're perform_complicated_task do_this_and_do_that_and_another_thing -## URL autolinking +## URL auto-linking GFM will autolink standard URLs you copy and paste into your text. So if you want to link to a URL (instead of a textural link), you can simply put the URL in verbatim and it will be turned into a link to that URL. @@ -250,17 +250,17 @@ The IDs are generated from the content of the header according to the following For example: ``` -###### ..Ab_c-d. e [anchor](url) ![alt text](url).. +###### ..Ab_c-d. e [anchor](URL) ![alt text](URL).. ``` which renders as: -###### ..Ab_c-d. e [anchor](url) ![alt text](url).. +###### ..Ab_c-d. e [anchor](URL) ![alt text](URL).. will first be converted by step 1) into a string like: ``` -..Ab_c-d. e <a href="url">anchor</a> <img src="url" alt="alt text"/>.. +..Ab_c-d. e <a href="URL">anchor</a> <img src="URL" alt="alt text"/>.. ``` After removing the tags in step 2) we get: @@ -277,8 +277,8 @@ ab_c-d-e-anchor Note in particular how: -- for markdown anchors `[text](url)`, only the `text` is used -- markdown images `![alt](url)` are completely ignored +- for markdown anchors `[text](URL)`, only the `text` is used +- markdown images `![alt](URL)` are completely ignored ## Emphasis diff --git a/doc/project_services/project_services.md b/doc/project_services/project_services.md index ec46af5fe3..93a57485cf 100644 --- a/doc/project_services/project_services.md +++ b/doc/project_services/project_services.md @@ -4,16 +4,16 @@ __Project integrations with external services for continuous integration and mor ## Services -- Assemblia -- [Atlassian Bamboo CI](bamboo.md) An Atlassian product for continous integration. +- Assembla +- [Atlassian Bamboo CI](bamboo.md) An Atlassian product for continuous integration. - Build box - Campfire - Emails on push - Flowdock - Gemnasium - GitLab CI -- Hipchat -- PivotalTracker +- HipChat +- Pivotal Tracker - Pushover - Slack -- TeamCity \ No newline at end of file +- TeamCity diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index f9d2f5dc4e..bbcf395c74 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -13,7 +13,7 @@ You can only restore a backup to exactly the same version of GitLab that you cre # use this command if you've installed GitLab with the Omnibus package sudo gitlab-rake gitlab:backup:create -# if you've installed GitLab from source or using the cookbook +# if you've installed GitLab from source sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ``` @@ -147,7 +147,7 @@ You can only restore a backup to exactly the same version of GitLab that you cre # Omnibus package installation sudo gitlab-rake gitlab:backup:restore -# installation from source or cookbook +# installation from source bundle exec rake gitlab:backup:restore RAILS_ENV=production ``` @@ -192,7 +192,7 @@ Deleting tmp directories...[DONE] For Omnibus package installations, see https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#scheduling-a-backup . -For installation from source or cookbook: +For installation from source: ``` cd /home/git/gitlab sudo -u git -H editor config/gitlab.yml # Enable keep_time in the backup section to automatically delete old backups @@ -214,19 +214,19 @@ This is recommended to reduce cron spam. If your GitLab server contains a lot of Git repository data you may find the GitLab backup script to be too slow. In this case you can consider using filesystem snapshots as part of your backup strategy. -Example: Amazone EBS +Example: Amazon EBS > A GitLab server using omnibus-gitlab hosted on Amazon AWS. > An EBS drive containing an ext4 filesystem is mounted at `/var/opt/gitlab`. > In this case you could make an application backup by taking an EBS snapshot. > The backup includes all repositories, uploads and Postgres data. -Example: LVM snapshots + Rsync +Example: LVM snapshots + rsync > A GitLab server using omnibus-gitlab, with an LVM logical volume mounted at `/var/opt/gitlab`. -> Replicating the `/var/opt/gitlab` directory usign Rsync would not be reliable because too many files would change while Rsync is running. +> Replicating the `/var/opt/gitlab` directory using rsync would not be reliable because too many files would change while rsync is running. > Instead of rsync-ing `/var/opt/gitlab`, we create a temporary LVM snapshot, which we mount as a read-only filesystem at `/mnt/gitlab_backup`. -> Now we can have a longer running Rsync job which will create a consistent replica on the remote server. +> Now we can have a longer running rsync job which will create a consistent replica on the remote server. > The replica includes all repositories, uploads and Postgres data. If you are running GitLab on a virtualized server you can possibly also create VM snapshots of the entire GitLab server. diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md index 9e48f56c95..96d67f7b5d 100644 --- a/doc/raketasks/cleanup.md +++ b/doc/raketasks/cleanup.md @@ -8,7 +8,7 @@ Remove namespaces(dirs) from `/home/git/repositories` if they don't exist in Git # omnibus-gitlab sudo gitlab-rake gitlab:cleanup:dirs -# installation from source or cookbook +# installation from source bundle exec rake gitlab:cleanup:dirs RAILS_ENV=production ``` @@ -18,6 +18,6 @@ Remove repositories (global only for now) from `/home/git/repositories` if they # omnibus-gitlab sudo gitlab-rake gitlab:cleanup:repos -# installation from source or cookbook +# installation from source bundle exec rake gitlab:cleanup:repos RAILS_ENV=production ``` diff --git a/doc/raketasks/features.md b/doc/raketasks/features.md index 99b3d5525b..f9a4619354 100644 --- a/doc/raketasks/features.md +++ b/doc/raketasks/features.md @@ -6,7 +6,7 @@ This command will enable the namespaces feature introduced in v4.0. It will move Note: -- Because the **repository location will change**, you will need to **update all your git url's** to point to the new location. +- Because the **repository location will change**, you will need to **update all your git URLs** to point to the new location. - Username can be changed at [Profile / Account](/profile/account) **Example:** diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md index 32fe4dc8d0..9a10c8d685 100644 --- a/doc/raketasks/import.md +++ b/doc/raketasks/import.md @@ -19,19 +19,26 @@ your repositories are located by looking at `config/gitlab.yml` under the `gitla New folder needs to have git user ownership and read/write/execute access for git user and its group: ``` -$ mkdir new_group -$ chown git:git new_group -$ chmod 770 new_group +sudo -u git mkdir /var/opt/gitlab/git-data/repositories/new_group ``` +If you are using an installation from source, replace `/var/opt/gitlab/git-data` +with `/home/git`. + ### Copy your bare repositories inside this newly created folder: ``` -$ cp -r /old/git/foo.git/ /home/git/repositories/new_group/ +sudo cp -r /old/git/foo.git /var/opt/gitlab/git-data/repositories/new_group/ + +# Do this once when you are done copying git repositories +sudo chown -R git:git /var/opt/gitlab/git-data/repositories/new_group/ ``` `foo.git` needs to be owned by the git user and git users group. +If you are using an installation from source, replace `/var/opt/gitlab/git-data` +with `/home/git`. + ### Run the command below depending on your type of installation: #### Omnibus Installation diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md index 8bef92e55f..41a994f3f6 100644 --- a/doc/raketasks/maintenance.md +++ b/doc/raketasks/maintenance.md @@ -8,7 +8,7 @@ This command gathers information about your GitLab installation and the System i # omnibus-gitlab sudo gitlab-rake gitlab:env:info -# installation from source or cookbook +# installation from source bundle exec rake gitlab:env:info RAILS_ENV=production ``` @@ -16,30 +16,31 @@ Example output: ``` System information -System: Debian 6.0.7 -Current User: git -Using RVM: no -Ruby Version: 2.0.0-p481 -Gem Version: 1.8.23 -Bundler Version:1.3.5 -Rake Version: 10.0.4 +System: Debian 7.8 +Current User: git +Using RVM: no +Ruby Version: 2.1.5p273 +Gem Version: 2.4.3 +Bundler Version: 1.7.6 +Rake Version: 10.3.2 +Sidekiq Version: 2.17.8 GitLab information -Version: 5.1.0.beta2 -Revision: 4da8b37 -Directory: /home/git/gitlab -DB Adapter: mysql2 -URL: http://example.com -HTTP Clone URL: http://example.com/some-project.git -SSH Clone URL: git@example.com:some-project.git -Using LDAP: no -Using Omniauth: no +Version: 7.7.1 +Revision: 41ab9e1 +Directory: /home/git/gitlab +DB Adapter: postgresql +URL: https://gitlab.example.com +HTTP Clone URL: https://gitlab.example.com/some-project.git +SSH Clone URL: git@gitlab.example.com:some-project.git +Using LDAP: no +Using Omniauth: no GitLab Shell -Version: 1.2.0 -Repositories: /home/git/repositories/ -Hooks: /home/git/gitlab-shell/hooks/ -Git: /usr/bin/git +Version: 2.4.1 +Repositories: /home/git/repositories/ +Hooks: /home/git/gitlab-shell/hooks/ +Git: /usr/bin/git ``` ## Check GitLab configuration @@ -59,7 +60,7 @@ You may also have a look at our [Trouble Shooting Guide](https://github.com/gitl # omnibus-gitlab sudo gitlab-rake gitlab:check -# installation from source or cookbook +# installation from source bundle exec rake gitlab:check RAILS_ENV=production ``` @@ -127,7 +128,6 @@ sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites In some case it is necessary to rebuild the `authorized_keys` file. - For Omnibus-packages: ``` sudo gitlab-rake gitlab:shell:setup @@ -143,6 +143,36 @@ sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production This will rebuild an authorized_keys file. You will lose any data stored in authorized_keys file. Do you want to continue (yes/no)? yes +``` -............................ +## Clear redis cache + +If for some reason the dashboard shows wrong information you might want to +clear Redis' cache. + +For Omnibus-packages: +``` +sudo gitlab-rake cache:clear +``` + +For installations from source: +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production +``` + +## Precompile the assets + +Sometimes during version upgrades you might end up with some wrong CSS or +missing some icons. In that case, try to precompile the assets again. + +For Omnibus-packages: +``` +sudo gitlab-rake assets:precompile +``` + +For installations from source: +``` +cd /home/git/gitlab +sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production ``` diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md index 3c67753ad2..80b01ca404 100644 --- a/doc/raketasks/user_management.md +++ b/doc/raketasks/user_management.md @@ -6,7 +6,7 @@ # omnibus-gitlab sudo gitlab-rake gitlab:import:user_to_projects[username@domain.tld] -# installation from source or cookbook +# installation from source bundle exec rake gitlab:import:user_to_projects[username@domain.tld] RAILS_ENV=production ``` @@ -20,7 +20,7 @@ Notes: # omnibus-gitlab sudo gitlab-rake gitlab:import:all_users_to_all_projects -# installation from source or cookbook +# installation from source bundle exec rake gitlab:import:all_users_to_all_projects RAILS_ENV=production ``` @@ -30,7 +30,7 @@ bundle exec rake gitlab:import:all_users_to_all_projects RAILS_ENV=production # omnibus-gitlab sudo gitlab-rake gitlab:import:user_to_groups[username@domain.tld] -# installation from source or cookbook +# installation from source bundle exec rake gitlab:import:user_to_groups[username@domain.tld] RAILS_ENV=production ``` @@ -44,6 +44,6 @@ Notes: # omnibus-gitlab sudo gitlab-rake gitlab:import:all_users_to_all_groups -# installation from source or cookbook +# installation from source bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production ``` diff --git a/doc/raketasks/web_hooks.md b/doc/raketasks/web_hooks.md index e1a58835d8..5a8b94af9b 100644 --- a/doc/raketasks/web_hooks.md +++ b/doc/raketasks/web_hooks.md @@ -4,42 +4,42 @@ # omnibus-gitlab sudo gitlab-rake gitlab:web_hook:add URL="http://example.com/hook" - # source installations or cookbook + # source installations bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" RAILS_ENV=production ## Add a web hook for projects in a given **NAMESPACE**: # omnibus-gitlab sudo gitlab-rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE=acme - # source installations or cookbook + # source installations bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE=acme RAILS_ENV=production ## Remove a web hook from **ALL** projects using: # omnibus-gitlab sudo gitlab-rake gitlab:web_hook:rm URL="http://example.com/hook" - # source installations or cookbook + # source installations bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" RAILS_ENV=production ## Remove a web hook from projects in a given **NAMESPACE**: # omnibus-gitlab sudo gitlab-rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE=acme - # source installations or cookbook + # source installations bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE=acme RAILS_ENV=production ## List **ALL** web hooks: # omnibus-gitlab sudo gitlab-rake gitlab:web_hook:list - # source installations or cookbook + # source installations bundle exec rake gitlab:web_hook:list RAILS_ENV=production ## List the web hooks from projects in a given **NAMESPACE**: # omnibus-gitlab sudo gitlab-rake gitlab:web_hook:list NAMESPACE=/ - # source installations or cookbook + # source installations bundle exec rake gitlab:web_hook:list NAMESPACE=/ RAILS_ENV=production > Note: `/` is the global namespace. diff --git a/doc/release/howto_rc1.md b/doc/release/howto_rc1.md index 25923d16f3..e8e8c8a821 100644 --- a/doc/release/howto_rc1.md +++ b/doc/release/howto_rc1.md @@ -104,7 +104,7 @@ bundle exec rake release["x.x.0.rc1"] ``` Now developers can use master for merging new features. -So you should use stable branch for future code chages related to release. +So you should use stable branch for future code changes related to release. ### 5. Release GitLab CI RC1 diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 175112b90c..4297bc7e2b 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -207,7 +207,7 @@ __3. Tweet to blog__ Send out a tweet to share the good news with the world. List the most important features and link to the blog post. -Proposed tweet "Release of GitLab X.X & CI Y.Y! FEATURE, FEATURE and FEATURE #gitlab" +Proposed tweet "Release of GitLab X.X & CI Y.Y! FEATURE, FEATURE and FEATURE <link-to-blog-post> #gitlab" Consider creating a post on Hacker News. diff --git a/doc/security/information_exclusivity.md b/doc/security/information_exclusivity.md index 127166ae2e..f8e7fc3fd0 100644 --- a/doc/security/information_exclusivity.md +++ b/doc/security/information_exclusivity.md @@ -4,6 +4,6 @@ Git is a distributed version control system (DVCS). This means that everyone that works with the source code has a local copy of the complete repository. In GitLab every project member that is not a guest (so reporters, developers and masters) can clone the repository to get a local copy. After obtaining this local copy the user can upload the full repository anywhere, including another project under their control or another server. -The consequense is that you can't build access controls that prevent the intentional sharing of source code by users that have access to the source code. +The consequence is that you can't build access controls that prevent the intentional sharing of source code by users that have access to the source code. This is an inherent feature of a DVCS and all git management systems have this limitation. Obviously you can take steps to prevent unintentional sharing and information destruction, this is why only some people are allowed to invite others and nobody can force push a protected branch. diff --git a/doc/ssh/README.md b/doc/ssh/README.md index c87fffd7d2..6fe23dfa2a 100644 --- a/doc/ssh/README.md +++ b/doc/ssh/README.md @@ -1,4 +1,73 @@ # SSH -- [Deploy keys](deploy_keys.md) -- [SSH](ssh.md) +## SSH keys + +An SSH key allows you to establish a secure connection between your +computer and GitLab. + +Before generating an SSH key, check if your system already has one by +running `cat ~/.ssh/id_rsa.pub`. If you see a long string starting with +`ssh-rsa` or `ssh-dsa`, you can skip the ssh-keygen step. + +To generate a new SSH key, just open your terminal and use code below. The +ssh-keygen command prompts you for a location and filename to store the key +pair and for a password. When prompted for the location and filename, you +can press enter to use the default. + +It is a best practice to use a password for an SSH key, but it is not +required and you can skip creating a password by pressing enter. Note that +the password you choose here can't be altered or retrieved. + +```bash +ssh-keygen -t rsa -C "$your_email" +``` + +Use the code below to show your public key. + +```bash +cat ~/.ssh/id_rsa.pub +``` + +Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your +user profile. Please copy the complete key starting with `ssh-` and ending +with your username and host. + +Use code below to copy your public key to the clipboard. Depending on your +OS you'll need to use a different command: + +**Windows:** +```bash +clip < ~/.ssh/id_rsa.pub +``` + +**Mac:** +```bash +pbcopy < ~/.ssh/id_rsa.pub +``` + +**Linux (requires xclip):** +```bash +xclip -sel clip < ~/.ssh/id_rsa.pub +``` + +## Deploy keys + +Deploy keys allow read-only access to multiple projects with a single SSH +key. + +This is really useful for cloning repositories to your Continuous +Integration (CI) server. By using deploy keys, you don't have to setup a +dummy user account. + +If you are a project master or owner, you can add a deploy key in the +project settings under the section 'Deploy Keys'. Press the 'New Deploy +Key' button and upload a public SSH key. After this, the machine that uses +the corresponding private key has read-only access to the project. + +You can't add the same deploy key twice with the 'New Deploy Key' option. +If you want to add the same key to another project, please enable it in the +list that says 'Deploy keys from projects available to you'. All the deploy +keys of all the projects you have access to are available. This project +access can happen through being a direct member of the projecti, or through +a group. See `def accessible_deploy_keys` in `app/models/user.rb` for more +information. diff --git a/doc/ssh/deploy_keys.md b/doc/ssh/deploy_keys.md deleted file mode 100644 index dcca8bdc61..0000000000 --- a/doc/ssh/deploy_keys.md +++ /dev/null @@ -1,9 +0,0 @@ -# Deploy keys - -Deploy keys allow read-only access one or multiple projects with a single SSH key. - -This is really useful for cloning repositories to your Continuous Integration (CI) server. By using a deploy keys you don't have to setup a dummy user account. - -If you are a project master or owner you can add a deploy key in the project settings under the section Deploy Keys. Press the 'New Deploy Key' button and upload a public ssh key. After this the machine that uses the corresponding private key has read-only access to the project. - -You can't add the same deploy key twice with the 'New Deploy Key' option. If you want to add the same key to another project please enable it in the list that says 'Deploy keys from projects available to you'. All the deploy keys of all the projects you have access to are available. This project access can happen through being a direct member of the project or through a group. See `def accessible_deploy_keys` in `app/models/user.rb` for more information. diff --git a/doc/ssh/ssh.md b/doc/ssh/ssh.md deleted file mode 100644 index f9ee627f1f..0000000000 --- a/doc/ssh/ssh.md +++ /dev/null @@ -1,38 +0,0 @@ -# SSH keys - -SSH key allows you to establish a secure connection between your computer and GitLab - -Before generating an SSH key, check if your system already has one by running `cat ~/.ssh/id_rsa.pub` If your see a long string starting with `ssh-rsa` or `ssh-dsa`, you can skip the ssh-keygen step. - -To generate a new SSH key just open your terminal and use code below. The ssh-keygen command prompts you for a location and filename to store the key pair and for a password. When prompted for the location and filename you can press enter to use the default. -It is a best practice to use a password for an SSH key but it is not required and you can skip creating a password by pressing enter. -Note that the password you choose here can't be altered or retrieved. - -```bash -ssh-keygen -t rsa -C "$your_email" -``` - -Use the code below to show your public key. - -```bash -cat ~/.ssh/id_rsa.pub -``` - -Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your user profile. Please copy the complete key starting with `ssh-` and ending with your username and host. - -Use code below to copy your public key to the clipboard. Depending on your OS you'll need to use a different command: - -**Windows:** -```bash -clip < ~/.ssh/id_rsa.pub -``` - -**Mac:** -```bash -pbcopy < ~/.ssh/id_rsa.pub -``` - -**Linux (requires xclip):** -```bash -xclip -sel clip < ~/.ssh/id_rsa.pub -``` diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md index 41c2732ef7..f9b6d37d84 100644 --- a/doc/system_hooks/system_hooks.md +++ b/doc/system_hooks/system_hooks.md @@ -15,8 +15,8 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser "name": "StoreCloud", "owner_email": "johnsmith@gmail.com", "owner_name": "John Smith", - "path": "stormcloud", - "path_with_namespace": "jsmith/stormcloud", + "path": "storecloud", + "path_with_namespace": "jsmith/storecloud", "project_id": 74, "project_visibility": "private", } @@ -126,10 +126,10 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser { "created_at": "2012-07-21T07:30:54Z", "event_name": "group_create", - "name": "StormCloud", + "name": "StoreCloud", "owner_email": "johnsmith@gmail.com", "owner_name": "John Smith", - "path": "stormcloud", + "path": "storecloud", "group_id": 78 } ``` diff --git a/doc/update/2.6-to-3.0.md b/doc/update/2.6-to-3.0.md index 6aabbe095d..2044b65946 100644 --- a/doc/update/2.6-to-3.0.md +++ b/doc/update/2.6-to-3.0.md @@ -22,29 +22,29 @@ sudo -u gitlab bundle exec rake db:migrate RAILS_ENV=production # !!! Config should be replaced with a new one. Check it after replace cp config/gitlab.yml.example config/gitlab.yml -# update gitolite hooks +# update Gitolite hooks -# GITOLITE v2: +# Gitolite v2: sudo cp ./lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive -# GITOLITE v3: +# Gitolite v3: sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive sudo chown git:git /home/git/.gitolite/hooks/common/post-receive # set valid path to hooks in gitlab.yml in git_host section # like this git_host: - # gitolite 2 + # Gitolite 2 hooks_path: /home/git/share/gitolite/hooks - # gitolite 3 + # Gitolite 3 hooks_path: /home/git/.gitolite/hooks/ -# Make some changes to gitolite config +# Make some changes to Gitolite config # For more information visit https://github.com/gitlabhq/gitlabhq/pull/1719 -# gitolite v2 +# Gitolite v2 sudo -u git -H sed -i 's/\(GL_GITCONFIG_KEYS\s*=>*\s*\).\{2\}/\\1"\.\*"/g' /home/git/.gitolite.rc # gitlite v3 diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md index cde679598f..0a929591de 100644 --- a/doc/update/4.2-to-5.0.md +++ b/doc/update/4.2-to-5.0.md @@ -41,8 +41,8 @@ git checkout v1.1.0 # copy config cp config.yml.example config.yml -# change url to GitLab instance -# ! make sure url end with '/' like 'https://gitlab.example/' +# change URL to GitLab instance +# ! make sure the URL ends with '/' like 'https://gitlab.example/' vim config.yml # rewrite hooks @@ -111,7 +111,7 @@ sudo chmod -R u+rwX /home/git/gitlab/tmp/pids ``` -## 6. Update init.d script and nginx config +## 6. Update init.d script and Nginx config ```bash # init.d @@ -123,7 +123,7 @@ sudo chmod +x /etc/init.d/gitlab sudo -u git -H cp /home/git/gitlab/config/unicorn.rb /home/git/gitlab/config/unicorn.rb.old sudo -u git -H cp /home/git/gitlab/config/unicorn.rb.example /home/git/gitlab/config/unicorn.rb -#nginx +# Nginx # Replace path from '/home/gitlab/' to '/home/git/' sudo vim /etc/nginx/sites-enabled/gitlab sudo service nginx restart @@ -137,7 +137,7 @@ sudo service gitlab start # check if unicorn and sidekiq started # If not try to logout, also check replaced path from '/home/gitlab/' to '/home/git/' -# in nginx, unicorn, init.d etc +# in Nginx, unicorn, init.d etc ps aux | grep unicorn ps aux | grep sidekiq diff --git a/doc/update/5.1-to-6.0.md b/doc/update/5.1-to-6.0.md index a76b371e6d..ef412b4569 100644 --- a/doc/update/5.1-to-6.0.md +++ b/doc/update/5.1-to-6.0.md @@ -40,7 +40,7 @@ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production The migrations in this update are very sensitive to incomplete or inconsistent data. If you have a long-running GitLab installation and some of the previous upgrades did not work out 100% correct this may bite you now. The following can help you have a more smooth upgrade. -### Find projets with invalid project names +### Find projects with invalid project names #### MySQL Login to MySQL: diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 7bf7bce6aa..ba8f8e3958 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -10,7 +10,7 @@ GitLab 6.0 is affected by critical security vulnerabilities CVE-2013-4490 and CV The root (global) namespace for projects is deprecated. -So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote url. Please make sure you disable sending email when you do a test of the upgrade. +So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote URL. Please make sure you disable sending email when you do a test of the upgrade. ### Teams diff --git a/doc/update/6.1-to-6.2.md b/doc/update/6.1-to-6.2.md index efa6e43124..11b124cf26 100644 --- a/doc/update/6.1-to-6.2.md +++ b/doc/update/6.1-to-6.2.md @@ -35,7 +35,7 @@ sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulner ## 4. Install additional packages ```bash -# Add support for lograte for better log file handling +# Add support for logrotate for better log file handling sudo apt-get install logrotate ``` diff --git a/doc/update/6.x-or-7.x-to-7.7.md b/doc/update/6.x-or-7.x-to-7.7.md index 645fece446..19c62f16ef 100644 --- a/doc/update/6.x-or-7.x-to-7.7.md +++ b/doc/update/6.x-or-7.x-to-7.7.md @@ -84,11 +84,14 @@ sudo -u git -H git checkout 7-7-stable-ee ## 4. Install additional packages ```bash -# Add support for lograte for better log file handling +# Add support for logrotate for better log file handling sudo apt-get install logrotate # Install pkg-config and cmake, which is needed for the latest versions of rugged sudo apt-get install pkg-config cmake + +# Install Kerberos header files, which are needed for GitLab EE Kerberos support +sudo apt-get install libkrb5-dev ``` ## 5. Configure Redis to use sockets @@ -219,13 +222,13 @@ mysql -u root -p # Convert all tables to use the InnoDB storage engine (added in GitLab 6.8) SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' ENGINE=InnoDB;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `ENGINE` <> 'InnoDB' AND `TABLE_TYPE` = 'BASE TABLE'; -# If previous query returned results, copy & run all outputed SQL statements +# If previous query returned results, copy & run all shown SQL statements # Convert all tables to correct character set SET foreign_key_checks = 0; SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `TABLE_COLLATION` <> 'utf8_unicode_ci' AND `TABLE_TYPE` = 'BASE TABLE'; -# If previous query returned results, copy & run all outputed SQL statements +# If previous query returned results, copy & run all shown SQL statements # turn foreign key checks back on SET foreign_key_checks = 1; diff --git a/doc/update/7.3-to-7.4.md b/doc/update/7.3-to-7.4.md index 2466050ea4..62bd98832c 100644 --- a/doc/update/7.3-to-7.4.md +++ b/doc/update/7.3-to-7.4.md @@ -114,13 +114,13 @@ mysql -u root -p # Convert all tables to use the InnoDB storage engine (added in GitLab 6.8) SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' ENGINE=InnoDB;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `ENGINE` <> 'InnoDB' AND `TABLE_TYPE` = 'BASE TABLE'; -# If previous query returned results, copy & run all outputed SQL statements +# If previous query returned results, copy & run all shown SQL statements # Convert all tables to correct character set SET foreign_key_checks = 0; SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `TABLE_COLLATION` <> 'utf8_unicode_ci' AND `TABLE_TYPE` = 'BASE TABLE'; -# If previous query returned results, copy & run all outputed SQL statements +# If previous query returned results, copy & run all shown SQL statements # turn foreign key checks back on SET foreign_key_checks = 1; diff --git a/doc/update/7.6-to-7.7.md b/doc/update/7.6-to-7.7.md index 51084576f3..5924371315 100644 --- a/doc/update/7.6-to-7.7.md +++ b/doc/update/7.6-to-7.7.md @@ -37,7 +37,7 @@ sudo -u git -H git checkout 7-7-stable-ee ```bash cd /home/git/gitlab-shell sudo -u git -H git fetch -sudo -u git -H git checkout v2.4.1 +sudo -u git -H git checkout v2.4.2 ``` ### 4. Install libs, migrations, etc. @@ -101,8 +101,8 @@ If all items are green, then congratulations upgrade is complete! ### 8. GitHub settings (if applicable) -If you are using GitHub as an OAuth provider for authentication, you should change the callback url so that it -only contains a root url (ex. `https://gitlab.example.com/`) +If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it +only contains a root URL (ex. `https://gitlab.example.com/`) ## Things went south? Revert to previous version (7.6) diff --git a/doc/update/README.md b/doc/update/README.md index 9868364c60..319b4920b3 100644 --- a/doc/update/README.md +++ b/doc/update/README.md @@ -17,4 +17,4 @@ Depending on the installation method and your GitLab version, there are multiple ## Miscellaneous -- [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating your database from MySQL to PostrgreSQL. +- [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating your database from MySQL to PostgreSQL. diff --git a/doc/workflow/README.md b/doc/workflow/README.md index d80ef2d79a..512d0753a1 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -11,3 +11,4 @@ - [Migrating from SVN to GitLab](migrating_from_svn.md) - [Project importing from GitHub to GitLab](import_projects_from_github.md) - [Protected branches](protected_branches.md) +- [Web Editor](web_editor.md) diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md index 78aff66a63..e24ce4e405 100644 --- a/doc/workflow/gitlab_flow.md +++ b/doc/workflow/gitlab_flow.md @@ -43,7 +43,7 @@ Since most tools automatically make the master branch the default one and displa The second problem of git flow is the complexity introduced by the hotfix and release branches. These branches can be a good idea for some organizations but are overkill for the vast majority of them. Nowadays most organizations practice continuous delivery which means that your default branch can be deployed. -This means that hotfixed and release branches can be prevented including all the ceremony they introduce. +This means that hotfix and release branches can be prevented including all the ceremony they introduce. An example of this ceremony is the merging back of release branches. Though specialized tools do exist to solve this, they require documentation and add complexity. Frequently developers make a mistake and for example changes are only merged into master and not into the develop branch. @@ -95,12 +95,12 @@ An 'extreme' version of environment branches are setting up an environment for e ## Release branches with GitLab flow -![Master and multiple release branches that vary in length with cherrypicks from master](release_branches.png) +![Master and multiple release branches that vary in length with cherry-picks from master](release_branches.png) Only in case you need to release software to the outside world you need to work with release branches. In this case, each branch contains a minor version (2-3-stable, 2-4-stable, etc.). The stable branch uses master as a starting point and is created as late as possible. -By branching as late as possible you minimize the time you have to apply bugfixes to multiple branches. +By branching as late as possible you minimize the time you have to apply bug fixes to multiple branches. After a release branch is announced, only serious bug fixes are included in the release branch. If possible these bug fixes are first merged into master and then cherry-picked into the release branch. This way you can't forget to cherry-pick them into master and encounter the same bug on subsequent releases. @@ -177,7 +177,7 @@ In GitLab this creates a comment in the issue that the merge requests mentions t And the merge request shows the linked issues. These issues are closed once code is merged into the default branch. -If you only want to make the reference without closing the issue you can also just mention it: "Ducktyping is preferred. #12". +If you only want to make the reference without closing the issue you can also just mention it: "Duck typing is preferred. #12". If you have an issue that spans across multiple repositories, the best thing is to create an issue for each repository and link all issues to a parent issue. diff --git a/doc/workflow/migrating_from_svn.md b/doc/workflow/migrating_from_svn.md index 207e364180..485db4834e 100644 --- a/doc/workflow/migrating_from_svn.md +++ b/doc/workflow/migrating_from_svn.md @@ -3,7 +3,7 @@ SVN stands for Subversion and is a version control system (VCS). Git is a distributed version control system. -There are some major differences between the two, for more information consult your favourite search engine. +There are some major differences between the two, for more information consult your favorite search engine. Git has tools for migrating SVN repositories to git, namely `git svn`. You can read more about this at [git documentation pages](http://git-scm.com/book/en/Git-and-Other-Systems-Git-and-Subversion). diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md index 3c3ce162df..17215de677 100644 --- a/doc/workflow/notifications.md +++ b/doc/workflow/notifications.md @@ -24,14 +24,14 @@ Each of these settings have levels of notification: #### Global Settings Global Settings are at the bottom of the hierarchy. -Any setting set here will be overriden by a setting at the group or a project level. +Any setting set here will be overridden by a setting at the group or a project level. Group or Project settings can use `global` notification setting which will then use anything that is set at Global Settings. #### Group Settings -Group Settings are taking presedence over Global Settings but are on a level below Project Settings. +Group Settings are taking precedence over Global Settings but are on a level below Project Settings. This means that you can set a different level of notifications per group while still being able to have a finer level setting per project. Organization like this is suitable for users that belong to different groups but don't have the @@ -39,7 +39,7 @@ same need for being notified for every group they are member of. #### Project Settings -Project Settings are at the top level and any setting placed at this level will take presedence of any +Project Settings are at the top level and any setting placed at this level will take precedence of any other setting. This is suitable for users that have different needs for notifications per project basis. diff --git a/doc/workflow/web_editor.md b/doc/workflow/web_editor.md new file mode 100644 index 0000000000..bcadf5e8c0 --- /dev/null +++ b/doc/workflow/web_editor.md @@ -0,0 +1,26 @@ +# GitLab Web Editor + +In GitLab you can create new files and edit existing files using our web editor. +This is especially useful if you don't have access to a command line or you just want to do a quick fix. +You can easily access the web editor, depending on the context. +Let's start from newly created project. + +Click on `Add a file` +to create the first file and open it in the web editor. + +![web editor 1](web_editor/empty_project.png) + +Fill in a file name, some content, a commit message and press the commit button. +The file will be saved to the repository. + +![web editor 2](web_editor/new_file.png) + +You can edit any text file in a repository by pressing the edit button, when +viewing the file. + +![web editor 3](web_editor/show_file.png) + +Editing a file is almost the same as creating a new file, +with as addition the ability to preview your changes in a separate tab. + +![web editor 3](web_editor/edit_file.png) diff --git a/doc/workflow/web_editor/edit_file.png b/doc/workflow/web_editor/edit_file.png new file mode 100644 index 0000000000..1522c50b62 Binary files /dev/null and b/doc/workflow/web_editor/edit_file.png differ diff --git a/doc/workflow/web_editor/empty_project.png b/doc/workflow/web_editor/empty_project.png new file mode 100644 index 0000000000..6a049f6bea Binary files /dev/null and b/doc/workflow/web_editor/empty_project.png differ diff --git a/doc/workflow/web_editor/new_file.png b/doc/workflow/web_editor/new_file.png new file mode 100644 index 0000000000..80941f37ce Binary files /dev/null and b/doc/workflow/web_editor/new_file.png differ diff --git a/doc/workflow/web_editor/show_file.png b/doc/workflow/web_editor/show_file.png new file mode 100644 index 0000000000..9cafcb5510 Binary files /dev/null and b/doc/workflow/web_editor/show_file.png differ diff --git a/docker/Dockerfile b/docker/Dockerfile index 445fdd6d06..ec0923bd4c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -11,7 +11,7 @@ RUN apt-get update -q \ # If the Omnibus package version below is outdated please contribute a merge request to update it. # If you run GitLab Enterprise Edition point it to a location where you have downloaded it. RUN TMP_FILE=$(mktemp); \ - wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.6.2-omnibus.5.3.0.ci.1-1_amd64.deb \ + wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.7.2-omnibus.5.4.2.ci-1_amd64.deb \ && dpkg -i $TMP_FILE \ && rm -f $TMP_FILE diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature index ccb29293a8..ee8d0bffa9 100644 --- a/features/project/source/browse_files.feature +++ b/features/project/source/browse_files.feature @@ -34,7 +34,7 @@ Feature: Project Source Browse Files Then I am redirected to the new file And I should see its new content - @javascript + @javascript @tricky Scenario: I can create file in empty repo Given I own an empty project And I visit my empty project page diff --git a/features/search.feature b/features/search.feature index 54708c1757..def21e0092 100644 --- a/features/search.feature +++ b/features/search.feature @@ -13,15 +13,15 @@ Feature: Search And project has issues When I search for "Foo" And I click "Issues" link - Then I should see "Foo" link - And I should not see "Bar" link + Then I should see "Foo" link in the search results + And I should not see "Bar" link in the search results Scenario: I should see merge requests I am looking for And project has merge requests When I search for "Foo" When I click "Merge requests" link - Then I should see "Foo" link - And I should not see "Bar" link + Then I should see "Foo" link in the search results + And I should not see "Bar" link in the search results Scenario: I should see project code I am looking for When I click project "Shop" link @@ -33,14 +33,14 @@ Feature: Search When I click project "Shop" link And I search for "Foo" And I click "Issues" link - Then I should see "Foo" link - And I should not see "Bar" link + Then I should see "Foo" link in the search results + And I should not see "Bar" link in the search results Scenario: I should see project merge requests And project has merge requests When I click project "Shop" link And I search for "Foo" And I click "Merge requests" link - Then I should see "Foo" link - And I should not see "Bar" link + Then I should see "Foo" link in the search results + And I should not see "Bar" link in the search results diff --git a/features/steps/admin/groups.rb b/features/steps/admin/groups.rb index 9584288a2f..97b4e391f1 100644 --- a/features/steps/admin/groups.rb +++ b/features/steps/admin/groups.rb @@ -41,7 +41,7 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps within "#new_team_member" do select "Reporter", from: "access_level" end - click_button "Add users into group" + click_button "Add users to group" end step 'I should see "John Doe" in team list in every project as "Reporter"' do diff --git a/features/steps/groups.rb b/features/steps/groups.rb index 405d74332d..93fbc52cdc 100644 --- a/features/steps/groups.rb +++ b/features/steps/groups.rb @@ -34,7 +34,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps select2(user.id, from: "#user_ids", multiple: true) select "Reporter", from: "access_level" end - click_button "Add users into group" + click_button "Add users to group" end step 'I should see user "John Doe" in team list' do diff --git a/features/steps/search.rb b/features/steps/search.rb index f3d8bd80f1..6f0e038c4d 100644 --- a/features/steps/search.rb +++ b/features/steps/search.rb @@ -59,11 +59,11 @@ class Spinach::Features::Search < Spinach::FeatureSteps create(:merge_request, :simple, title: "Bar", source_project: project, target_project: project) end - step 'I should see "Foo" link' do - page.should have_link "Foo" + step 'I should see "Foo" link in the search results' do + find(:css, '.search-results').should have_link 'Foo' end - step 'I should not see "Bar" link' do - page.should_not have_link "Bar" + step 'I should not see "Bar" link in the search results' do + find(:css, '.search-results').should_not have_link 'Bar' end end diff --git a/lib/api/api.rb b/lib/api/api.rb index 573df6bb02..01a583fecd 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -6,7 +6,7 @@ module API version 'v3', using: :path rescue_from ActiveRecord::RecordNotFound do - rack_response({'message' => '404 Not found'}.to_json, 404) + rack_response({ 'message' => '404 Not found' }.to_json, 404) end rescue_from :all do |exception| @@ -19,7 +19,7 @@ module API message << " " << trace.join("\n ") API.logger.add Logger::FATAL, message - rack_response({'message' => '500 Internal Server Error'}, 500) + rack_response({ 'message' => '500 Internal Server Error' }, 500) end format :json diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb index 2397551818..b9994fcefd 100644 --- a/lib/api/api_guard.rb +++ b/lib/api/api_guard.rb @@ -47,16 +47,12 @@ module APIGuard case validate_access_token(access_token, scopes) when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE raise InsufficientScopeError.new(scopes) - when Oauth2::AccessTokenValidationService::EXPIRED raise ExpiredError - when Oauth2::AccessTokenValidationService::REVOKED raise RevokedError - when Oauth2::AccessTokenValidationService::VALID @current_user = User.find(access_token.resource_owner_id) - end end end @@ -120,8 +116,9 @@ module APIGuard end def oauth2_bearer_token_error_handler - Proc.new {|e| - response = case e + Proc.new do |e| + response = + case e when MissingTokenError Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new @@ -146,11 +143,11 @@ module APIGuard Rack::OAuth2::Server::Resource::Bearer::Forbidden.new( :insufficient_scope, Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION[:insufficient_scope], - { :scope => e.scopes}) + { scope: e.scopes }) end response.finish - } + end end end @@ -172,4 +169,4 @@ module APIGuard @scopes = scopes end end -end \ No newline at end of file +end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 3d7abdf38f..39f6609a53 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -60,7 +60,7 @@ module API expose :path, :path_with_namespace expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at expose :namespace - expose :forked_from_project, using: Entities::ForkedFromProject, :if => lambda{ | project, options | project.forked? } + expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } end class ProjectMember < UserBasic @@ -157,6 +157,11 @@ module API expose :state, :created_at, :updated_at end + class RepoDiff < Grape::Entity + expose :old_path, :new_path, :a_mode, :b_mode, :diff + expose :new_file, :renamed_file, :deleted_file + end + class Milestone < ProjectEntity expose :due_date end @@ -176,6 +181,12 @@ module API expose :milestone, using: Entities::Milestone end + class MergeRequestChanges < MergeRequest + expose :diffs, as: :changes, using: Entities::RepoDiff do |compare, _| + compare.diffs + end + end + class SSHKey < Grape::Entity expose :id, :title, :key, :created_at end @@ -254,11 +265,6 @@ module API expose :name, :color end - class RepoDiff < Grape::Entity - expose :old_path, :new_path, :a_mode, :b_mode, :diff - expose :new_file, :renamed_file, :deleted_file - end - class Compare < Grape::Entity expose :commit, using: Entities::RepoCommit do |compare, options| Commit.decorate(compare.commits).last diff --git a/lib/api/group_members.rb b/lib/api/group_members.rb index d596517c81..4373070083 100644 --- a/lib/api/group_members.rb +++ b/lib/api/group_members.rb @@ -3,22 +3,6 @@ module API before { authenticate! } resource :groups do - helpers do - def find_group(id) - group = Group.find(id) - - if can?(current_user, :read_group, group) - group - else - render_api_error!("403 Forbidden - #{current_user.username} lacks sufficient access to #{group.name}", 403) - end - end - - def validate_access_level?(level) - Gitlab::Access.options_with_owner.values.include? level.to_i - end - end - # Get a list of group members viewable by the authenticated user. # # Example Request: diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 6f4b35f79f..4826deaa64 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -4,22 +4,6 @@ module API before { authenticate! } resource :groups do - helpers do - def find_group(id) - group = Group.find(id) - - if can?(current_user, :read_group, group) - group - else - render_api_error!("403 Forbidden - #{current_user.username} lacks sufficient access to #{group.name}", 403) - end - end - - def validate_access_level?(level) - Gitlab::Access.options_with_owner.values.include? level.to_i - end - end - # Get a groups list # # Example Request: diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 62c26ef76c..be9e4280d6 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -55,6 +55,21 @@ module API end end + def find_group(id) + begin + group = Group.find(id) + rescue ActiveRecord::RecordNotFound + group = Group.find_by!(path: id) + end + + if can?(current_user, :read_group, group) + group + else + forbidden!("#{current_user.username} lacks sufficient "\ + "access to #{group.name}") + end + end + def paginate(relation) per_page = params[:per_page].to_i paginated = relation.page(params[:page]).per(per_page) @@ -135,10 +150,16 @@ module API errors end + def validate_access_level?(level) + Gitlab::Access.options_with_owner.values.include? level.to_i + end + # error helpers - def forbidden! - render_api_error!('403 Forbidden', 403) + def forbidden!(reason = nil) + message = ['403 Forbidden'] + message << " - #{reason}" if reason + render_api_error!(message.join(' '), 403) end def bad_request!(attribute) @@ -173,7 +194,7 @@ module API end def render_api_error!(message, status) - error!({'message' => message}, status) + error!({ 'message' => message }, status) end private diff --git a/lib/api/internal.rb b/lib/api/internal.rb index a999cff09c..7a89a26fac 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -1,9 +1,7 @@ module API # Internal access API class Internal < Grape::API - before { - authenticate_by_gitlab_shell_token! - } + before { authenticate_by_gitlab_shell_token! } namespace 'internal' do # Check if git command is allowed to project diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 2a5b10c6f5..a0ebd8d0c1 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -75,6 +75,22 @@ module API present merge_request, with: Entities::MergeRequest end + # Show MR changes + # + # Parameters: + # id (required) - The ID of a project + # merge_request_id (required) - The ID of MR + # + # Example: + # GET /projects/:id/merge_request/:merge_request_id/changes + # + get ':id/merge_request/:merge_request_id/changes' do + merge_request = user_project.merge_requests. + find(params[:merge_request_id]) + authorize! :read_merge_request, merge_request + present merge_request, with: Entities::MergeRequestChanges + end + # Create MR # # Parameters: diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb index f9f2ed90cc..b90ed6af5f 100644 --- a/lib/api/namespaces.rb +++ b/lib/api/namespaces.rb @@ -1,10 +1,10 @@ module API # namespaces API class Namespaces < Grape::API - before { + before do authenticate! authenticated_as_admin! - } + end resource :namespaces do # Get a namespaces list diff --git a/lib/api/project_members.rb b/lib/api/project_members.rb index 8fe774da2f..b9ce0e16ce 100644 --- a/lib/api/project_members.rb +++ b/lib/api/project_members.rb @@ -110,7 +110,7 @@ module API unless team_member.nil? team_member.destroy else - {message: "Access revoked", id: params[:user_id].to_i} + { message: "Access revoked", id: params[:user_id].to_i } end end end diff --git a/lib/api/system_hooks.rb b/lib/api/system_hooks.rb index 3e239c5afe..518964db50 100644 --- a/lib/api/system_hooks.rb +++ b/lib/api/system_hooks.rb @@ -1,10 +1,10 @@ module API # Hooks API class SystemHooks < Grape::API - before { + before do authenticate! authenticated_as_admin! - } + end resource :hooks do # Get the list of system hooks diff --git a/lib/email_validator.rb b/lib/email_validator.rb index 0a67ebcd79..f509f0a584 100644 --- a/lib/email_validator.rb +++ b/lib/email_validator.rb @@ -1,5 +1,5 @@ # Based on https://github.com/balexand/email_validator -# +# # Extended to use only strict mode with following allowed characters: # ' - apostrophe # diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb index 411b2b9a3c..424541b4a0 100644 --- a/lib/gitlab/access.rb +++ b/lib/gitlab/access.rb @@ -11,6 +11,11 @@ module Gitlab MASTER = 40 OWNER = 50 + # Branch protection settings + PROTECTION_NONE = 0 + PROTECTION_DEV_CAN_PUSH = 1 + PROTECTION_FULL = 2 + class << self def values options.values @@ -43,6 +48,18 @@ module Gitlab master: MASTER, } end + + def protection_options + { + "Not protected, developers and masters can (force) push and delete the branch" => PROTECTION_NONE, + "Partially protected, developers can also push but prevent all force pushes and deletion" => PROTECTION_DEV_CAN_PUSH, + "Fully protected, only masters can push and prevent all force pushes and deletion" => PROTECTION_FULL, + } + end + + def protection_values + protection_options.values + end end def human_access diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb index 2e393f753e..3f207c5663 100644 --- a/lib/gitlab/backend/grack_auth.rb +++ b/lib/gitlab/backend/grack_auth.rb @@ -34,7 +34,7 @@ module Grack def auth! if @auth.provided? return bad_request unless @auth.basic? - + # Authentication with username and password login, password = @auth.credentials @@ -80,11 +80,11 @@ module Grack def authenticate_user(login, password) user = Gitlab::Auth.new.find(login, password) - + unless user user = oauth_access_token_check(login, password) end - + return user if user.present? # At this point, we know the credentials were wrong. We let Rack::Attack @@ -154,7 +154,7 @@ module Grack end def render_not_found - [404, {"Content-Type" => "text/plain"}, ["Not Found"]] + [404, { "Content-Type" => "text/plain" }, ["Not Found"]] end end end diff --git a/lib/gitlab/backend/shell_adapter.rb b/lib/gitlab/backend/shell_adapter.rb index f247f4593d..fbe2a7a0d7 100644 --- a/lib/gitlab/backend/shell_adapter.rb +++ b/lib/gitlab/backend/shell_adapter.rb @@ -9,4 +9,3 @@ module Gitlab end end end - diff --git a/lib/gitlab/commits_calendar.rb b/lib/gitlab/commits_calendar.rb index ccc80d080a..2f30d238e6 100644 --- a/lib/gitlab/commits_calendar.rb +++ b/lib/gitlab/commits_calendar.rb @@ -2,15 +2,15 @@ module Gitlab class CommitsCalendar attr_reader :timestamps - def initialize(repositories, user) + def initialize(projects, user) @timestamps = {} date_timestamps = [] - repositories.select(&:exists?).reject(&:empty?).each do |raw_repository| - commits_log = raw_repository.commits_per_day_for_user(user) - date_timestamps << commits_log + projects.reject(&:forked?).each do |project| + date_timestamps << ProjectContributions.new(project, user).commits_log end + # Sumarrize commits from all projects per days date_timestamps = date_timestamps.inject do |collection, date| collection.merge(date) { |k, old_v, new_v| old_v + new_v } end @@ -21,5 +21,13 @@ module Gitlab @timestamps[timestamp] = commits if timestamp end end + + def starting_year + (Time.now - 1.year).strftime("%Y") + end + + def starting_month + Date.today.strftime("%m").to_i + end end end diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index 2c5660df37..93e7edf508 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -12,6 +12,7 @@ module Gitlab def fake_application_settings OpenStruct.new( default_projects_limit: Settings.gitlab['default_projects_limit'], + default_branch_protection: Settings.gitlab['default_branch_protection'], signup_enabled: Settings.gitlab['signup_enabled'], signin_enabled: Settings.gitlab['signin_enabled'], gravatar_enabled: Settings.gravatar['enabled'], diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb index f7c1f20d76..887ed76b36 100644 --- a/lib/gitlab/diff/parser.rb +++ b/lib/gitlab/diff/parser.rb @@ -4,7 +4,7 @@ module Gitlab include Enumerable def parse(lines) - @lines = lines, + @lines = lines lines_obj = [] line_obj_index = 0 line_old = 1 @@ -74,7 +74,7 @@ module Gitlab def html_escape(str) replacements = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' } - str.gsub(/[&"'><]/, replacements) + str.gsub(/[&"'><]/, replacements) end end end diff --git a/lib/gitlab/force_push_check.rb b/lib/gitlab/force_push_check.rb index 6ba2c3ad00..eae9773a06 100644 --- a/lib/gitlab/force_push_check.rb +++ b/lib/gitlab/force_push_check.rb @@ -12,4 +12,3 @@ module Gitlab end end end - diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index ae592e6799..564a1b4224 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -179,14 +179,14 @@ module Gitlab def protected_branch_action(project, oldrev, newrev, branch_name) # we dont allow force push to protected branch if forced_push?(project, oldrev, newrev) - :force_push_code_to_protected_branches - # and we dont allow remove of protected branch + :force_push_code_to_protected_branches elsif newrev == Gitlab::Git::BLANK_SHA - :remove_protected_branches + # and we dont allow remove of protected branch + :remove_protected_branches elsif project.developers_can_push_to_protected_branch?(branch_name) - :push_code + :push_code else - :push_code_to_protected_branches + :push_code_to_protected_branches end end diff --git a/lib/gitlab/git_access_status.rb b/lib/gitlab/git_access_status.rb index 3d451ecebe..5a806ff6e0 100644 --- a/lib/gitlab/git_access_status.rb +++ b/lib/gitlab/git_access_status.rb @@ -9,7 +9,7 @@ module Gitlab end def to_json - {status: @status, message: @message}.to_json + { status: @status, message: @message }.to_json end end -end \ No newline at end of file +end diff --git a/lib/gitlab/github/importer.rb b/lib/gitlab/github/importer.rb index c72a1c25e9..9f0fc6c447 100644 --- a/lib/gitlab/github/importer.rb +++ b/lib/gitlab/github/importer.rb @@ -9,12 +9,12 @@ module Gitlab def execute client = octo_client(project.creator.github_access_token) - + #Issues && Comments client.list_issues(project.import_source, state: :all).each do |issue| if issue.pull_request.nil? body = "*Created by: #{issue.user.login}*\n\n#{issue.body}" - + if issue.comments > 0 body += "\n\n\n**Imported comments:**\n" client.issue_comments(project.import_source, issue.number).each do |c| @@ -23,7 +23,7 @@ module Gitlab end project.issues.create!( - description: body, + description: body, title: issue.title, state: issue.state == 'closed' ? 'closed' : 'opened', author_id: gl_user_id(project, issue.user.id) @@ -36,7 +36,7 @@ module Gitlab def octo_client(access_token) ::Octokit.auto_paginate = true - ::Octokit::Client.new(:access_token => access_token) + ::Octokit::Client.new(access_token: access_token) end def gl_user_id(project, github_id) diff --git a/lib/gitlab/ldap/adapter.rb b/lib/gitlab/ldap/adapter.rb index 6db1bc3925..b127094a51 100644 --- a/lib/gitlab/ldap/adapter.rb +++ b/lib/gitlab/ldap/adapter.rb @@ -87,8 +87,10 @@ module Gitlab end def dn_matches_filter?(dn, filter) - ldap_search(base: dn, filter: filter, - scope: Net::LDAP::SearchScope_BaseObject, attributes: %w{dn}).any? + ldap_search(base: dn, + filter: filter, + scope: Net::LDAP::SearchScope_BaseObject, + attributes: %w{dn}).any? end def ldap_search(*args) diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index 3ef494ba13..cfa8692659 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -40,12 +40,16 @@ module Gitlab def update_user_attributes gl_user.email = auth_hash.email - gl_user.identities.build(provider: auth_hash.provider, extern_uid: auth_hash.uid) + + # Build new identity only if we dont have have same one + gl_user.identities.find_or_initialize_by(provider: auth_hash.provider, + extern_uid: auth_hash.uid) + gl_user end def changed? - gl_user.changed? + gl_user.changed? || gl_user.identities.any?(&:changed?) end def needs_blocking? diff --git a/lib/gitlab/satellite/action.rb b/lib/gitlab/satellite/action.rb index be45cb5c98..4890ccf21e 100644 --- a/lib/gitlab/satellite/action.rb +++ b/lib/gitlab/satellite/action.rb @@ -44,7 +44,7 @@ module Gitlab end def default_options(options = {}) - {raise: true, timeout: true}.merge(options) + { raise: true, timeout: true }.merge(options) end def handle_exception(exception) diff --git a/lib/gitlab/satellite/files/delete_file_action.rb b/lib/gitlab/satellite/files/delete_file_action.rb index 30462999aa..0d37b9dea8 100644 --- a/lib/gitlab/satellite/files/delete_file_action.rb +++ b/lib/gitlab/satellite/files/delete_file_action.rb @@ -13,7 +13,7 @@ module Gitlab prepare_satellite!(repo) # create target branch in satellite at the corresponding commit from bare repo - repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}") + repo.git.checkout({ raise: true, timeout: true, b: true }, ref, "origin/#{ref}") # update the file in the satellite's working dir file_path_in_satellite = File.join(repo.working_dir, file_path) @@ -36,7 +36,7 @@ module Gitlab # push commit back to bare repo # will raise CommandFailed when push fails - repo.git.push({raise: true, timeout: true}, :origin, ref) + repo.git.push({ raise: true, timeout: true }, :origin, ref) # everything worked true diff --git a/lib/gitlab/satellite/files/edit_file_action.rb b/lib/gitlab/satellite/files/edit_file_action.rb index cbdf70f7d1..2834b722b2 100644 --- a/lib/gitlab/satellite/files/edit_file_action.rb +++ b/lib/gitlab/satellite/files/edit_file_action.rb @@ -15,7 +15,7 @@ module Gitlab prepare_satellite!(repo) # create target branch in satellite at the corresponding commit from bare repo - repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}") + repo.git.checkout({ raise: true, timeout: true, b: true }, ref, "origin/#{ref}") # update the file in the satellite's working dir file_path_in_satellite = File.join(repo.working_dir, file_path) @@ -36,7 +36,7 @@ module Gitlab # push commit back to bare repo # will raise CommandFailed when push fails - repo.git.push({raise: true, timeout: true}, :origin, ref) + repo.git.push({ raise: true, timeout: true }, :origin, ref) # everything worked true diff --git a/lib/gitlab/satellite/files/new_file_action.rb b/lib/gitlab/satellite/files/new_file_action.rb index 5b657c7aba..69f7ffa94e 100644 --- a/lib/gitlab/satellite/files/new_file_action.rb +++ b/lib/gitlab/satellite/files/new_file_action.rb @@ -19,7 +19,7 @@ module Gitlab # skip this step if we want to add first file to empty repo Satellite::PARKING_BRANCH else - repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}") + repo.git.checkout({ raise: true, timeout: true, b: true }, ref, "origin/#{ref}") ref end @@ -47,7 +47,7 @@ module Gitlab # push commit back to bare repo # will raise CommandFailed when push fails - repo.git.push({raise: true, timeout: true}, :origin, "#{current_ref}:#{ref}") + repo.git.push({ raise: true, timeout: true }, :origin, "#{current_ref}:#{ref}") # everything worked true diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb index 0e5dcf6d94..3d6bea318d 100644 --- a/lib/gitlab/satellite/merge_action.rb +++ b/lib/gitlab/satellite/merge_action.rb @@ -96,7 +96,7 @@ module Gitlab in_locked_and_timed_satellite do |merge_repo| prepare_satellite!(merge_repo) update_satellite_source_and_target!(merge_repo) - patch = merge_repo.git.format_patch(default_options({stdout: true}), "origin/#{merge_request.target_branch}..source/#{merge_request.source_branch}") + patch = merge_repo.git.format_patch(default_options({ stdout: true }), "origin/#{merge_request.target_branch}..source/#{merge_request.source_branch}") end rescue Grit::Git::CommandFailed => ex handle_exception(ex) @@ -138,7 +138,7 @@ module Gitlab # merge the source branch into the satellite # will raise CommandFailed when merge fails - repo.git.merge(default_options({no_ff: true}), "-m#{message}", "source/#{merge_request.source_branch}") + repo.git.merge(default_options({ no_ff: true }), "-m#{message}", "source/#{merge_request.source_branch}") rescue Grit::Git::CommandFailed => ex handle_exception(ex) end @@ -181,7 +181,7 @@ module Gitlab def update_satellite_source_and_target!(repo) repo.remote_add('source', merge_request.source_project.repository.path_to_repo) repo.remote_fetch('source') - repo.git.checkout(default_options({b: true}), merge_request.target_branch, "origin/#{merge_request.target_branch}") + repo.git.checkout(default_options({ b: true }), merge_request.target_branch, "origin/#{merge_request.target_branch}") rescue Grit::Git::CommandFailed => ex handle_exception(ex) end diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb index 1de84309d1..62d1bb364d 100644 --- a/lib/gitlab/satellite/satellite.rb +++ b/lib/gitlab/satellite/satellite.rb @@ -98,13 +98,13 @@ module Gitlab if heads.include? PARKING_BRANCH repo.git.checkout({}, PARKING_BRANCH) else - repo.git.checkout(default_options({b: true}), PARKING_BRANCH) + repo.git.checkout(default_options({ b: true }), PARKING_BRANCH) end # remove the parking branch from the list of heads ... heads.delete(PARKING_BRANCH) # ... and delete all others - heads.each { |head| repo.git.branch(default_options({D: true}), head) } + heads.each { |head| repo.git.branch(default_options({ D: true }), head) } end # Deletes all remotes except origin @@ -126,7 +126,7 @@ module Gitlab end def default_options(options = {}) - {raise: true, timeout: true}.merge(options) + { raise: true, timeout: true }.merge(options) end # Create directory for storing diff --git a/lib/gitlab/upgrader.rb b/lib/gitlab/upgrader.rb index bd89a30cc4..020dee69f6 100644 --- a/lib/gitlab/upgrader.rb +++ b/lib/gitlab/upgrader.rb @@ -62,7 +62,7 @@ module Gitlab end def env - {'RAILS_ENV' => 'production'} + { 'RAILS_ENV' => 'production' } end def upgrade diff --git a/lib/repository_cache.rb b/lib/repository_cache.rb new file mode 100644 index 0000000000..fa016a170c --- /dev/null +++ b/lib/repository_cache.rb @@ -0,0 +1,21 @@ +# Interface to the Redis-backed cache store used by the Repository model +class RepositoryCache + attr_reader :namespace, :backend + + def initialize(namespace, backend = Rails.cache) + @namespace = namespace + @backend = backend + end + + def cache_key(type) + "#{type}:#{namespace}" + end + + def expire(key) + backend.delete(cache_key(key)) + end + + def fetch(key, &block) + backend.fetch(cache_key(key), &block) + end +end diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl index 4e53d5e8b5..19af010a9f 100644 --- a/lib/support/nginx/gitlab-ssl +++ b/lib/support/nginx/gitlab-ssl @@ -39,7 +39,7 @@ upstream gitlab { ## Redirects all HTTP traffic to the HTTPS host server { listen 0.0.0.0:80; - listen [::]:80 default_server; + listen [::]:80 ipv6only=on default_server; server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com server_tokens off; ## Don't show the nginx version number, a security best practice return 301 https://$server_name$request_uri; @@ -51,7 +51,7 @@ server { ## HTTPS host server { listen 0.0.0.0:443 ssl; - listen [::]:443 ssl default_server; + listen [::]:443 ipv6only=on ssl default_server; server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com server_tokens off; ## Don't show the nginx version number, a security best practice root /home/git/gitlab/public; diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake index c01b00bd1c..b4076f8238 100644 --- a/lib/tasks/gitlab/test.rake +++ b/lib/tasks/gitlab/test.rake @@ -2,6 +2,7 @@ namespace :gitlab do desc "GITLAB | Run all tests" task :test do cmds = [ + %W(rake rubocop), %W(rake spinach), %W(rake spec), %W(rake jasmine:ci) diff --git a/lib/tasks/rubocop.rake b/lib/tasks/rubocop.rake new file mode 100644 index 0000000000..ddfaf5d51f --- /dev/null +++ b/lib/tasks/rubocop.rake @@ -0,0 +1,4 @@ +unless Rails.env.production? + require 'rubocop/rake_task' + RuboCop::RakeTask.new +end diff --git a/lib/tasks/spinach.rake b/lib/tasks/spinach.rake index 507b315759..4aefc18ce1 100644 --- a/lib/tasks/spinach.rake +++ b/lib/tasks/spinach.rake @@ -2,9 +2,15 @@ Rake::Task["spinach"].clear if Rake::Task.task_defined?('spinach') desc "GITLAB | Run spinach" task :spinach do + tags = if ENV['SEMAPHORE'] + '~@tricky' + else + '~@semaphore' + end + cmds = [ %W(rake gitlab:setup), - %W(spinach), + %W(spinach --tags #{tags}), ] run_commands(cmds) end diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake index 583f4a876d..3ea9290a81 100644 --- a/lib/tasks/test.rake +++ b/lib/tasks/test.rake @@ -9,5 +9,5 @@ unless Rails.env.production? require 'coveralls/rake/task' Coveralls::RakeTask.new desc "GITLAB | Run all tests on CI with simplecov" - task :test_ci => [:spinach, :spec, 'coveralls:push'] + task :test_ci => [:rubocop, :spinach, :spec, 'coveralls:push'] end diff --git a/spec/controllers/commit_controller_spec.rb b/spec/controllers/commit_controller_spec.rb index f5822157ea..cd8b46d767 100644 --- a/spec/controllers/commit_controller_spec.rb +++ b/spec/controllers/commit_controller_spec.rb @@ -70,4 +70,13 @@ describe Projects::CommitController do end end end + + describe "#branches" do + it "contains branch and tags information" do + get :branches, project_id: project.to_param, id: commit.id + + expect(assigns(:branches)).to include("master", "feature_conflict") + expect(assigns(:tags)).to include("v1.1.0") + end + end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 0c537a552c..44225c054f 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -9,18 +9,18 @@ describe UsersController do describe "GET #show" do render_views - before do - get :show, username: user.username - end it "renders the show template" do + get :show, username: user.username expect(response.status).to eq(200) expect(response).to render_template("show") end + end + describe "GET #calendar" do it "renders calendar" do - controller.prepend_view_path 'app/views/users' - expect(response).to render_template("_calendar") + get :calendar, username: user.username + expect(response).to render_template("calendar") end end end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 5ae57718c1..0899a7603f 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -26,6 +26,7 @@ # star_count :integer default(0), not null # import_type :string(255) # import_source :string(255) +# avatar :string(255) # FactoryGirl.define do diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb index 5850a24a42..89129cfc7c 100644 --- a/spec/features/help_pages_spec.rb +++ b/spec/features/help_pages_spec.rb @@ -6,7 +6,7 @@ describe 'Help Pages', feature: true do login_as :user end it 'replace the variable $your_email with the email of the user' do - visit help_page_path(category: 'ssh', file: 'ssh.md') + visit help_page_path(category: 'ssh', file: 'README.md') page.should have_content("ssh-keygen -t rsa -C \"#{@user.email}\"") end end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 26607b0090..e6fa376f3e 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -65,7 +65,7 @@ describe "Issues", feature: true do click_button "Save changes" - page.should have_content "Assignee: Select assignee" + page.should have_content 'Assignee: none' issue.reload.assignee.should be_nil end end @@ -249,6 +249,7 @@ describe "Issues", feature: true do click_button 'Update Issue' page.should have_content "Milestone changed to #{milestone.title}" + page.should have_content "Milestone: #{milestone.title}" has_select?('issue_assignee_id', :selected => milestone.title) end end @@ -287,7 +288,7 @@ describe "Issues", feature: true do sleep 2 # wait for ajax stuff to complete first('.user-result').click - page.should have_content "Assignee: Unassigned" + page.should have_content 'Assignee: none' sleep 2 # wait for ajax stuff to complete issue.reload.assignee.should be_nil end diff --git a/spec/helpers/nav_helper_spec.rb b/spec/helpers/nav_helper_spec.rb new file mode 100644 index 0000000000..e4d18d8bfc --- /dev/null +++ b/spec/helpers/nav_helper_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the NavHelper. For example: +# +# describe NavHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +describe NavHelper do + describe '#nav_menu_collapsed?' do + it 'returns true when the nav is collapsed in the cookie' do + helper.request.cookies[:collapsed_nav] = 'true' + expect(helper.nav_menu_collapsed?).to eq true + end + + it 'returns false when the nav is not collapsed in the cookie' do + helper.request.cookies[:collapsed_nav] = 'false' + expect(helper.nav_menu_collapsed?).to eq false + end + end +end diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb index 31ecdacf28..dcc3318e4f 100644 --- a/spec/helpers/notifications_helper_spec.rb +++ b/spec/helpers/notifications_helper_spec.rb @@ -1,6 +1,9 @@ require 'spec_helper' describe NotificationsHelper do + include FontAwesome::Rails::IconHelper + include IconsHelper + describe 'notification_icon' do let(:notification) { double(disabled?: false, participating?: false, watch?: false) } diff --git a/spec/lib/gitlab/ldap/user_spec.rb b/spec/lib/gitlab/ldap/user_spec.rb index f73884e644..63ffc21ba3 100644 --- a/spec/lib/gitlab/ldap/user_spec.rb +++ b/spec/lib/gitlab/ldap/user_spec.rb @@ -13,6 +13,23 @@ describe Gitlab::LDAP::User do double(uid: 'my-uid', provider: 'ldapmain', info: double(info)) end + describe :changed? do + it "marks existing ldap user as changed" do + existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain') + expect(gl_user.changed?).to be_true + end + + it "marks existing non-ldap user if the email matches as changed" do + existing_user = create(:user, email: 'john@example.com') + expect(gl_user.changed?).to be_true + end + + it "dont marks existing ldap user as changed" do + existing_user = create(:omniauth_user, email: 'john@example.com', extern_uid: 'my-uid', provider: 'ldapmain') + expect(gl_user.changed?).to be_false + end + end + describe :find_or_create do it "finds the user if already existing" do existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain') diff --git a/spec/lib/repository_cache_spec.rb b/spec/lib/repository_cache_spec.rb new file mode 100644 index 0000000000..af399f3a73 --- /dev/null +++ b/spec/lib/repository_cache_spec.rb @@ -0,0 +1,34 @@ +require 'rspec' +require_relative '../../lib/repository_cache' + +describe RepositoryCache do + let(:backend) { double('backend').as_null_object } + let(:cache) { RepositoryCache.new('example', backend) } + + describe '#cache_key' do + it 'includes the namespace' do + expect(cache.cache_key(:foo)).to eq 'foo:example' + end + end + + describe '#expire' do + it 'expires the given key from the cache' do + cache.expire(:foo) + expect(backend).to have_received(:delete).with('foo:example') + end + end + + describe '#fetch' do + it 'fetches the given key from the cache' do + cache.fetch(:bar) + expect(backend).to have_received(:fetch).with('bar:example') + end + + it 'accepts a block' do + p = -> {} + + cache.fetch(:baz, &p) + expect(backend).to have_received(:fetch).with('baz:example', &p) + end + end +end diff --git a/spec/lib/votes_spec.rb b/spec/lib/votes_spec.rb index 2c01a34756..a88a10d927 100644 --- a/spec/lib/votes_spec.rb +++ b/spec/lib/votes_spec.rb @@ -161,8 +161,8 @@ describe Issue, 'Votes' do add_note '+1 I still like this' add_note '+1 I really like this' add_note '+1 Give me this now!!!!' - p issue.downvotes.should == 0 - p issue.upvotes.should == 1 + issue.downvotes.should == 0 + issue.upvotes.should == 1 end it 'should count a users vote only once without caring about comments' do @@ -171,8 +171,8 @@ describe Issue, 'Votes' do add_note 'Another comment' add_note '+1 vote' add_note 'final comment' - p issue.downvotes.should == 0 - p issue.upvotes.should == 1 + issue.downvotes.should == 0 + issue.upvotes.should == 1 end end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 1723eba9ec..cd6d03e6c1 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -2,15 +2,16 @@ # # Table name: application_settings # -# id :integer not null, primary key -# default_projects_limit :integer -# signup_enabled :boolean -# signin_enabled :boolean -# gravatar_enabled :boolean -# sign_in_text :text -# created_at :datetime -# updated_at :datetime -# home_page_url :string(255) +# id :integer not null, primary key +# default_projects_limit :integer +# default_branch_protection :integer +# signup_enabled :boolean +# signin_enabled :boolean +# gravatar_enabled :boolean +# sign_in_text :text +# created_at :datetime +# updated_at :datetime +# home_page_url :string(255) # require 'spec_helper' diff --git a/spec/models/project_hook_spec.rb b/spec/models/hooks/project_hook_spec.rb similarity index 100% rename from spec/models/project_hook_spec.rb rename to spec/models/hooks/project_hook_spec.rb diff --git a/spec/models/service_hook_spec.rb b/spec/models/hooks/service_hook_spec.rb similarity index 100% rename from spec/models/service_hook_spec.rb rename to spec/models/hooks/service_hook_spec.rb diff --git a/spec/models/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb similarity index 100% rename from spec/models/system_hook_spec.rb rename to spec/models/hooks/system_hook_spec.rb diff --git a/spec/models/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb similarity index 100% rename from spec/models/web_hook_spec.rb rename to spec/models/hooks/web_hook_spec.rb diff --git a/spec/models/group_member_spec.rb b/spec/models/members/group_member_spec.rb similarity index 100% rename from spec/models/group_member_spec.rb rename to spec/models/members/group_member_spec.rb diff --git a/spec/models/project_member_spec.rb b/spec/models/members/project_member_spec.rb similarity index 100% rename from spec/models/project_member_spec.rb rename to spec/models/members/project_member_spec.rb diff --git a/spec/models/members_spec.rb b/spec/models/members_spec.rb index 6866c4794c..cea653ec28 100644 --- a/spec/models/members_spec.rb +++ b/spec/models/members_spec.rb @@ -10,7 +10,7 @@ describe Member do it { should validate_presence_of(:user) } it { should validate_presence_of(:source) } - it { should ensure_inclusion_of(:access_level).in_array(Gitlab::Access.values) } + it { should validate_inclusion_of(:access_level).in_array(Gitlab::Access.values) } end describe "Delegate methods" do diff --git a/spec/models/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb similarity index 100% rename from spec/models/assembla_service_spec.rb rename to spec/models/project_services/assembla_service_spec.rb diff --git a/spec/models/buildbox_service_spec.rb b/spec/models/project_services/buildbox_service_spec.rb similarity index 100% rename from spec/models/buildbox_service_spec.rb rename to spec/models/project_services/buildbox_service_spec.rb diff --git a/spec/models/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb similarity index 100% rename from spec/models/flowdock_service_spec.rb rename to spec/models/project_services/flowdock_service_spec.rb diff --git a/spec/models/gemnasium_service_spec.rb b/spec/models/project_services/gemnasium_service_spec.rb similarity index 100% rename from spec/models/gemnasium_service_spec.rb rename to spec/models/project_services/gemnasium_service_spec.rb diff --git a/spec/models/gitlab_ci_service_spec.rb b/spec/models/project_services/gitlab_ci_service_spec.rb similarity index 100% rename from spec/models/gitlab_ci_service_spec.rb rename to spec/models/project_services/gitlab_ci_service_spec.rb diff --git a/spec/models/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb similarity index 91% rename from spec/models/jira_service_spec.rb rename to spec/models/project_services/jira_service_spec.rb index c96f339143..592534201f 100644 --- a/spec/models/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# + require 'spec_helper' describe JiraService do diff --git a/spec/models/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb similarity index 100% rename from spec/models/pushover_service_spec.rb rename to spec/models/project_services/pushover_service_spec.rb diff --git a/spec/models/slack_message_spec.rb b/spec/models/project_services/slack_message_spec.rb similarity index 100% rename from spec/models/slack_message_spec.rb rename to spec/models/project_services/slack_message_spec.rb diff --git a/spec/models/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb similarity index 100% rename from spec/models/slack_service_spec.rb rename to spec/models/project_services/slack_service_spec.rb diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 092c02d552..4669a9fd87 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -14,7 +14,7 @@ # merge_requests_enabled :boolean default(TRUE), not null # wiki_enabled :boolean default(TRUE), not null # namespace_id :integer -# issues_tracker :string(255) default('gitlab'), not null +# issues_tracker :string(255) default("gitlab"), not null # issues_tracker_id :string(255) # snippets_enabled :boolean default(TRUE), not null # last_activity_at :datetime diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 87c28a1b82..57d5b4fb4a 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -80,6 +80,24 @@ describe API::API, api: true do response.status.should == 404 end end + + context 'when using group path in URL' do + it 'should return any existing group' do + get api("/groups/#{group1.path}", admin) + response.status.should == 200 + json_response['name'] == group2.name + end + + it 'should not return a non existing group' do + get api('/groups/unknown', admin) + response.status.should == 404 + end + + it 'should not return a group not attached to user1' do + get api("/groups/#{group2.path}", user1) + response.status.should == 403 + end + end end describe "POST /groups" do diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 5ba3a33099..5795082f5c 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -114,6 +114,19 @@ describe API::API, api: true do end end + describe 'GET /projects/:id/merge_request/:merge_request_id/changes' do + it 'should return the change information of the merge_request' do + get api("/projects/#{project.id}/merge_request/#{merge_request.id}/changes", user) + expect(response.status).to eq 200 + expect(json_response['changes'].size).to eq(merge_request.diffs.size) + end + + it 'returns a 404 when merge_request_id not found' do + get api("/projects/#{project.id}/merge_request/999/changes", user) + expect(response.status).to eq(404) + end + end + describe "POST /projects/:id/merge_requests" do context 'between branches projects' do it "should return merge_request" do diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 19b442573f..3a75d65b5b 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -106,7 +106,25 @@ describe GitPushService do it "when pushing a branch for the first time" do project.should_receive(:execute_hooks) project.default_branch.should == "master" - project.protected_branches.should_receive(:create).with({ name: "master" }) + project.protected_branches.should_receive(:create).with({ name: "master", developers_can_push: false }) + service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') + end + + it "when pushing a branch for the first time with default branch protection disabled" do + ApplicationSetting.any_instance.stub(default_branch_protection: 0) + + project.should_receive(:execute_hooks) + project.default_branch.should == "master" + project.protected_branches.should_not_receive(:create) + service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') + end + + it "when pushing a branch for the first time with default branch protection set to 'developers can push'" do + ApplicationSetting.any_instance.stub(default_branch_protection: 1) + + project.should_receive(:execute_hooks) + project.default_branch.should == "master" + project.protected_branches.should_receive(:create).with({ name: "master", developers_can_push: true }) service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') end