Commit cb8b5c32 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'ce-into-ee' into 'master'

CE into EE

See merge request !303
parents 45349abd 96a3f0e0
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'
...@@ -8,7 +8,7 @@ v 7.8.0 ...@@ -8,7 +8,7 @@ v 7.8.0
- Better UI for project services page - Better UI for project services page
- Cleaner UI for web editor - Cleaner UI for web editor
- Add diff syntax highlighting in email-on-push service notifications (Hannes Rosenögger) - 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) - Allow more variations for commit messages closing issues (Julien Bianchi and Hannes Rosenögger)
...@@ -25,10 +25,12 @@ v 7.8.0 ...@@ -25,10 +25,12 @@ v 7.8.0
- Upgrade Sidekiq gem to version 3.3.0 - Upgrade Sidekiq gem to version 3.3.0
- Stop git zombie creation during force push check - Stop git zombie creation during force push check
- Show success/error messages for test setting button in services - Show success/error messages for test setting button in services
- - Added Rubocop for code style checks
- Fix commits pagination - 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) - Add a commit calendar to the user profile (Hannes Rosenögger)
...@@ -42,7 +44,7 @@ v 7.8.0 ...@@ -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. - 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) - Add action property to merge request hook (Julien Bianchi)
...@@ -53,15 +55,20 @@ v 7.8.0 ...@@ -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) - 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) - 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 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 v 7.7.1
- Improve mention autocomplete performance - Improve mention autocomplete performance
......
...@@ -208,8 +208,6 @@ group :development do ...@@ -208,8 +208,6 @@ group :development do
gem 'better_errors' gem 'better_errors'
gem 'binding_of_caller' gem 'binding_of_caller'
gem 'rails_best_practices'
# Docs generator # Docs generator
gem "sdoc" gem "sdoc"
...@@ -219,11 +217,12 @@ end ...@@ -219,11 +217,12 @@ end
group :development, :test do group :development, :test do
gem 'coveralls', require: false gem 'coveralls', require: false
gem 'rubocop', '0.28.0', require: false
# gem 'rails-dev-tweaks' # gem 'rails-dev-tweaks'
gem 'spinach-rails' gem 'spinach-rails'
gem "rspec-rails" gem "rspec-rails"
gem "capybara", '~> 2.2.1' gem "capybara", '~> 2.2.1'
gem "pry" gem "pry-rails"
gem "awesome_print" gem "awesome_print"
gem "database_cleaner" gem "database_cleaner"
gem "launchy" gem "launchy"
...@@ -256,7 +255,7 @@ end ...@@ -256,7 +255,7 @@ end
group :test do group :test do
gem "simplecov", require: false gem "simplecov", require: false
gem "shoulda-matchers", "~> 2.1.0" gem "shoulda-matchers", "~> 2.7.0"
gem 'email_spec' gem 'email_spec'
gem "webmock" gem "webmock"
gem 'test_after_commit' gem 'test_after_commit'
......
...@@ -37,6 +37,9 @@ GEM ...@@ -37,6 +37,9 @@ GEM
rake (>= 0.8.7) rake (>= 0.8.7)
arel (5.0.1.20140414130214) arel (5.0.1.20140414130214)
asciidoctor (0.1.4) 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) attr_required (1.0.0)
awesome_print (1.2.0) awesome_print (1.2.0)
axiom-types (0.0.5) axiom-types (0.0.5)
...@@ -67,8 +70,6 @@ GEM ...@@ -67,8 +70,6 @@ GEM
timers (~> 4.0.0) timers (~> 4.0.0)
charlock_holmes (0.6.9.4) charlock_holmes (0.6.9.4)
cliver (0.3.2) cliver (0.3.2)
code_analyzer (0.4.3)
sexp_processor
coderay (1.1.0) coderay (1.1.0)
coercible (1.0.0) coercible (1.0.0)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
...@@ -354,6 +355,8 @@ GEM ...@@ -354,6 +355,8 @@ GEM
org-ruby (0.9.12) org-ruby (0.9.12)
rubypants (~> 0.2) rubypants (~> 0.2)
orm_adapter (0.5.0) orm_adapter (0.5.0)
parser (2.2.0.2)
ast (>= 1.1, < 3.0)
pg (0.15.1) pg (0.15.1)
phantomjs (1.9.2.0) phantomjs (1.9.2.0)
poltergeist (1.5.1) poltergeist (1.5.1)
...@@ -363,10 +366,13 @@ GEM ...@@ -363,10 +366,13 @@ GEM
websocket-driver (>= 0.2.0) websocket-driver (>= 0.2.0)
polyglot (0.3.4) polyglot (0.3.4)
posix-spawn (0.3.9) posix-spawn (0.3.9)
powerpack (0.0.9)
pry (0.9.12.4) pry (0.9.12.4)
coderay (~> 1.0) coderay (~> 1.0)
method_source (~> 0.8) method_source (~> 0.8)
slop (~> 3.4) slop (~> 3.4)
pry-rails (0.3.2)
pry (>= 0.9.10)
pyu-ruby-sasl (0.0.3.3) pyu-ruby-sasl (0.0.3.3)
quiet_assets (1.0.2) quiet_assets (1.0.2)
railties (>= 3.1, < 5.0) railties (>= 3.1, < 5.0)
...@@ -403,20 +409,12 @@ GEM ...@@ -403,20 +409,12 @@ GEM
sprockets-rails (~> 2.0) sprockets-rails (~> 2.0)
rails_autolink (1.1.6) rails_autolink (1.1.6)
rails (> 3.1) 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) railties (4.1.1)
actionpack (= 4.1.1) actionpack (= 4.1.1)
activesupport (= 4.1.1) activesupport (= 4.1.1)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.0.0)
raindrops (0.13.0) raindrops (0.13.0)
rake (10.3.2) rake (10.3.2)
raphael-rails (2.1.2) raphael-rails (2.1.2)
...@@ -447,7 +445,6 @@ GEM ...@@ -447,7 +445,6 @@ GEM
redis (>= 2.2) redis (>= 2.2)
ref (1.0.5) ref (1.0.5)
request_store (1.0.5) request_store (1.0.5)
require_all (1.3.2)
rest-client (1.6.7) rest-client (1.6.7)
mime-types (>= 1.16) mime-types (>= 1.16)
rinku (1.7.3) rinku (1.7.3)
...@@ -467,7 +464,13 @@ GEM ...@@ -467,7 +464,13 @@ GEM
rspec-core (~> 2.14.0) rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0) rspec-expectations (~> 2.14.0)
rspec-mocks (~> 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) rubyntlm (0.4.0)
rubypants (0.2.0) rubypants (0.2.0)
rugged (0.21.2) rugged (0.21.2)
...@@ -495,8 +498,7 @@ GEM ...@@ -495,8 +498,7 @@ GEM
semantic-ui-sass (1.8.0.0) semantic-ui-sass (1.8.0.0)
sass (~> 3.2) sass (~> 3.2)
settingslogic (2.0.9) settingslogic (2.0.9)
sexp_processor (4.4.0) shoulda-matchers (2.7.0)
shoulda-matchers (2.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
sidekiq (3.3.0) sidekiq (3.3.0)
celluloid (>= 0.16.0) celluloid (>= 0.16.0)
...@@ -700,7 +702,7 @@ DEPENDENCIES ...@@ -700,7 +702,7 @@ DEPENDENCIES
org-ruby (= 0.9.12) org-ruby (= 0.9.12)
pg pg
poltergeist (~> 1.5.1) poltergeist (~> 1.5.1)
pry pry-rails
quiet_assets (~> 1.0.1) quiet_assets (~> 1.0.1)
rack-attack rack-attack
rack-cors rack-cors
...@@ -708,7 +710,6 @@ DEPENDENCIES ...@@ -708,7 +710,6 @@ DEPENDENCIES
rack-oauth2 (~> 1.0.5) rack-oauth2 (~> 1.0.5)
rails (~> 4.1.0) rails (~> 4.1.0)
rails_autolink (~> 1.1) rails_autolink (~> 1.1)
rails_best_practices
raphael-rails (~> 2.1.2) raphael-rails (~> 2.1.2)
rb-fsevent rb-fsevent
rb-inotify rb-inotify
...@@ -717,6 +718,7 @@ DEPENDENCIES ...@@ -717,6 +718,7 @@ DEPENDENCIES
redis-rails redis-rails
request_store request_store
rspec-rails rspec-rails
rubocop (= 0.28.0)
rugments rugments
sanitize (~> 2.0) sanitize (~> 2.0)
sass-rails (~> 4.0.2) sass-rails (~> 4.0.2)
...@@ -725,7 +727,7 @@ DEPENDENCIES ...@@ -725,7 +727,7 @@ DEPENDENCIES
select2-rails select2-rails
semantic-ui-sass (~> 1.8.0) semantic-ui-sass (~> 1.8.0)
settingslogic settingslogic
shoulda-matchers (~> 2.1.0) shoulda-matchers (~> 2.7.0)
sidekiq (~> 3.3) sidekiq (~> 3.3)
sidetiq (= 0.6.3) sidetiq (= 0.6.3)
simplecov simplecov
......
...@@ -9,8 +9,6 @@ class @calendar ...@@ -9,8 +9,6 @@ class @calendar
cal.init cal.init
itemName: ["commit"] itemName: ["commit"]
data: timestamps data: timestamps
domain: "year"
subDomain: "month"
start: new Date(starting_year, starting_month) start: new Date(starting_year, starting_month)
domainLabelFormat: "%b" domainLabelFormat: "%b"
id: "cal-heatmap" id: "cal-heatmap"
......
...@@ -13,6 +13,8 @@ class @DropzoneInput ...@@ -13,6 +13,8 @@ class @DropzoneInput
form_textarea = $(form).find("textarea.markdown-area") form_textarea = $(form).find("textarea.markdown-area")
form_textarea.wrap "<div class=\"div-dropzone\"></div>" form_textarea.wrap "<div class=\"div-dropzone\"></div>"
form_textarea.bind 'paste', (event) =>
handlePaste(event)
form_dropzone = $(form).find('.div-dropzone') form_dropzone = $(form).find('.div-dropzone')
form_dropzone.parent().addClass "div-dropzone-wrapper" form_dropzone.parent().addClass "div-dropzone-wrapper"
...@@ -133,25 +135,18 @@ class @DropzoneInput ...@@ -133,25 +135,18 @@ class @DropzoneInput
formatLink = (str) -> formatLink = (str) ->
"![" + str.alt + "](" + str.url + ")" "![" + str.alt + "](" + str.url + ")"
handlePaste = (e) -> handlePaste = (event) ->
e.preventDefault() pasteEvent = event.originalEvent
my_event = e.originalEvent if pasteEvent.clipboardData and pasteEvent.clipboardData.items
image = isImage(pasteEvent)
if my_event.clipboardData and my_event.clipboardData.items
processItem(my_event)
processItem = (e) ->
image = isImage(e)
if image if image
filename = getFilename(e) or "image.png" event.preventDefault()
filename = getFilename(pasteEvent) or "image.png"
text = "{{" + filename + "}}" text = "{{" + filename + "}}"
pasteText(text) pasteText(text)
uploadFile image.getAsFile(), filename uploadFile image.getAsFile(), filename
else
text = e.clipboardData.getData("text/plain")
pasteText(text)
isImage = (data) -> isImage = (data) ->
i = 0 i = 0
while i < data.clipboardData.items.length while i < data.clipboardData.items.length
......
...@@ -24,3 +24,18 @@ $ -> ...@@ -24,3 +24,18 @@ $ ->
$(window).resize -> $(window).resize ->
responsive_resize() responsive_resize()
return 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: '/' })
)
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
&.s24 { margin-right: 4px; } &.s24 { margin-right: 4px; }
} }
&.avatar-tile {
@include border-radius(0px);
}
&.s16 { width: 16px; height: 16px; margin-right: 6px; } &.s16 { width: 16px; height: 16px; margin-right: 6px; }
&.s24 { width: 24px; height: 24px; margin-right: 8px; } &.s24 { width: 24px; height: 24px; margin-right: 8px; }
&.s26 { width: 26px; height: 26px; margin-right: 8px; } &.s26 { width: 26px; height: 26px; margin-right: 8px; }
......
...@@ -97,7 +97,17 @@ ...@@ -97,7 +97,17 @@
.dash-project-avatar { .dash-project-avatar {
float: left; float: left;
.avatar {
margin-top: -8px;
margin-left: -15px;
@include border-radius(0px);
}
.identicon {
line-height: 40px;
}
} }
.dash-project-access-icon { .dash-project-access-icon {
float: left; float: left;
margin-right: 5px; margin-right: 5px;
......
...@@ -40,12 +40,12 @@ ...@@ -40,12 +40,12 @@
font-size: $code_font_size; font-size: $code_font_size;
.old { .old {
span.idiff { span.idiff {
background-color: #F99; background-color: #f8cbcb;
} }
} }
.new { .new {
span.idiff { span.idiff {
background-color: #8F8; background-color: #a6f3a6;
} }
} }
.unfold { .unfold {
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
padding: 0px; padding: 0px;
border: none; border: none;
background: #F5F5F5; background: #F5F5F5;
color: #666; color: rgba(0,0,0,0.3);
padding: 0px 5px; padding: 0px 5px;
border-right: 1px solid #ccc; border-right: 1px solid #ccc;
text-align: right; text-align: right;
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
float: left; float: left;
width: 35px; width: 35px;
font-weight: normal; font-weight: normal;
color: #666; color: rgba(0,0,0,0.3);
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
...@@ -114,13 +114,13 @@ ...@@ -114,13 +114,13 @@
.line_holder { .line_holder {
&.old .old_line, &.old .old_line,
&.old .new_line { &.old .new_line {
background: #FCC; background: #ffdddd;
border-color: #E7BABA; border-color: #f1c0c0;
} }
&.new .old_line, &.new .old_line,
&.new .new_line { &.new .new_line {
background: #CFC; background: #dbffdb;
border-color: #B9ECB9; border-color: #c1e9c1;
} }
} }
.line_content { .line_content {
...@@ -129,10 +129,10 @@ ...@@ -129,10 +129,10 @@
padding: 0px 0.5em; padding: 0px 0.5em;
border: none; border: none;
&.new { &.new {
background: #CFD; background: #eaffea;
} }
&.old { &.old {
background: #FDD; background: #ffecec;
} }
&.matched { &.matched {
color: #ccc; color: #ccc;
......
.page-with-sidebar { .page-with-sidebar {
background: #F5F5F5; background: #F5F5F5;
...@@ -101,9 +99,7 @@ ...@@ -101,9 +99,7 @@
} }
@mixin expanded-sidebar { @mixin expanded-sidebar {
.page-with-sidebar {
padding-left: $sidebar_width; padding-left: $sidebar_width;
}
.sidebar-wrapper { .sidebar-wrapper {
width: $sidebar_width; width: $sidebar_width;
...@@ -122,9 +118,7 @@ ...@@ -122,9 +118,7 @@
} }
@mixin folded-sidebar { @mixin folded-sidebar {
.page-with-sidebar {
padding-left: 50px; padding-left: 50px;
}
.sidebar-wrapper { .sidebar-wrapper {
width: 52px; width: 52px;
...@@ -150,10 +144,33 @@ ...@@ -150,10 +144,33 @@
} }
} }
.collapse-nav a {
position: fixed;
bottom: 15px;
padding: 10px;
background: #DDD;
}
@media (max-width: $screen-md-max) { @media (max-width: $screen-md-max) {
.page-sidebar-collapsed {
@include folded-sidebar; @include folded-sidebar;
}
.page-sidebar-expanded {
@include folded-sidebar;
}
.collapse-nav {
display: none;
}
} }
@media(min-width: $screen-md-max) { @media(min-width: $screen-md-max) {
.page-sidebar-collapsed {
@include folded-sidebar;
}
.page-sidebar-expanded {
@include expanded-sidebar; @include expanded-sidebar;
}
} }
...@@ -81,7 +81,7 @@ ul.notes { ...@@ -81,7 +81,7 @@ ul.notes {
.diff-file .notes_holder { .diff-file .notes_holder {
font-size: 13px; font-size: 13px;
line-height: 18px; line-height: 18px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-family: $regular_font;
td { td {
border: 1px solid #ddd; border: 1px solid #ddd;
......
...@@ -22,6 +22,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -22,6 +22,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def application_setting_params def application_setting_params
params.require(:application_setting).permit( params.require(:application_setting).permit(
:default_projects_limit, :default_projects_limit,
:default_branch_protection,
:signup_enabled, :signup_enabled,
:signin_enabled, :signin_enabled,
:gravatar_enabled, :gravatar_enabled,
......
...@@ -23,7 +23,7 @@ class GithubImportsController < ApplicationController ...@@ -23,7 +23,7 @@ class GithubImportsController < ApplicationController
end end
def jobs 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 render json: jobs
end end
...@@ -58,7 +58,7 @@ class GithubImportsController < ApplicationController ...@@ -58,7 +58,7 @@ class GithubImportsController < ApplicationController
def octo_client def octo_client
Octokit.auto_paginate = true 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 end
def github_auth def github_auth
......
...@@ -15,4 +15,3 @@ class NamespacesController < ApplicationController ...@@ -15,4 +15,3 @@ class NamespacesController < ApplicationController
end end
end end
end end
...@@ -59,8 +59,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -59,8 +59,7 @@ class Projects::BlobController < Projects::ApplicationController
def preview def preview
@content = params[:content] @content = params[:content]
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
include_diff_info: true)
@diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/)) @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/))
render layout: false render layout: false
......
...@@ -11,8 +11,6 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -11,8 +11,6 @@ class Projects::CommitController < Projects::ApplicationController
return git_not_found! unless @commit return git_not_found! unless @commit
@line_notes = @project.notes.for_commit_id(commit.id).inline @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 @diffs = @commit.diffs
@note = @project.build_commit_note(commit) @note = @project.build_commit_note(commit)
@notes_count = @project.notes.for_commit_id(commit.id).count @notes_count = @project.notes.for_commit_id(commit.id).count
...@@ -31,6 +29,12 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -31,6 +29,12 @@ class Projects::CommitController < Projects::ApplicationController
end end
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 def commit
@commit ||= @project.repository.commit(params[:id]) @commit ||= @project.repository.commit(params[:id])
end end
......
...@@ -21,4 +21,3 @@ class Projects::GroupLinksController < Projects::ApplicationController ...@@ -21,4 +21,3 @@ class Projects::GroupLinksController < Projects::ApplicationController
redirect_to project_group_links_path(project) redirect_to project_group_links_path(project)
end end
end end
...@@ -35,4 +35,3 @@ class Projects::RawController < Projects::ApplicationController ...@@ -35,4 +35,3 @@ class Projects::RawController < Projects::ApplicationController
end end
end end
end end
...@@ -27,7 +27,7 @@ class SnippetsController < ApplicationController ...@@ -27,7 +27,7 @@ class SnippetsController < ApplicationController
@snippets = SnippetsFinder.new.execute(current_user, { @snippets = SnippetsFinder.new.execute(current_user, {
filter: :by_user, filter: :by_user,
user: @user, user: @user,
scope: params[:scope]}). scope: params[:scope] }).
page(params[:page]).per(20) page(params[:page]).per(20)
if @user == current_user if @user == current_user
......
class UsersController < ApplicationController class UsersController < ApplicationController
skip_before_filter :authenticate_user!, only: [:show, :activities] skip_before_filter :authenticate_user!
before_filter :set_user
layout :determine_layout layout :determine_layout
def show def show
@user = User.find_by_username!(params[:username])
unless current_user || @user.public_profile?
return authenticate_user!
end
# Projects user can view # Projects user can view
visible_projects = ProjectsFinder.new.execute(current_user) visible_projects = ProjectsFinder.new.execute(current_user)
authorized_projects_ids = visible_projects.pluck(:id) authorized_projects_ids = visible_projects.pluck(:id)
...@@ -25,19 +20,22 @@ class UsersController < ApplicationController ...@@ -25,19 +20,22 @@ class UsersController < ApplicationController
@title = @user.name @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| respond_to do |format|
format.html format.html
format.atom { render layout: false } format.atom { render layout: false }
end end
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 def determine_layout
if current_user if current_user
'navless' 'navless'
...@@ -45,4 +43,14 @@ class UsersController < ApplicationController ...@@ -45,4 +43,14 @@ class UsersController < ApplicationController
'public_users' 'public_users'
end end
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 end
...@@ -7,7 +7,8 @@ class NotesFinder ...@@ -7,7 +7,8 @@ class NotesFinder
# Default to 0 to remain compatible with old clients # Default to 0 to remain compatible with old clients
last_fetched_at = Time.at(params.fetch(:last_fetched_at, 0).to_i) last_fetched_at = Time.at(params.fetch(:last_fetched_at, 0).to_i)
notes = case target_type notes =
case target_type
when "commit" when "commit"
project.notes.for_commit_id(target_id).not_inline.fresh project.notes.for_commit_id(target_id).not_inline.fresh
when "issue" when "issue"
......
...@@ -75,9 +75,9 @@ module ApplicationHelper ...@@ -75,9 +75,9 @@ module ApplicationHelper
options[:class] ||= '' options[:class] ||= ''
options[:class] << ' identicon' options[:class] << ' identicon'
bg_key = project.id % 7 bg_key = project.id % 7
style = "background-color: ##{ allowed_colors.values[bg_key] }; color: #555"
content_tag(:div, class: options[:class], content_tag(:div, class: options[:class], style: style) do
style: "background-color: ##{ allowed_colors.values[bg_key] }; color: #555") do
project.name[0, 1].upcase project.name[0, 1].upcase
end end
end end
...@@ -247,15 +247,6 @@ module ApplicationHelper ...@@ -247,15 +247,6 @@ module ApplicationHelper
Gitlab::MarkdownHelper.gitlab_markdown?(filename) Gitlab::MarkdownHelper.gitlab_markdown?(filename)
end 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) def link_to(name = nil, options = nil, html_options = nil, &block)
begin begin
uri = URI(options) uri = URI(options)
...@@ -324,4 +315,12 @@ module ApplicationHelper ...@@ -324,4 +315,12 @@ module ApplicationHelper
profile_key_path(key) profile_key_path(key)
end end
end end
def nav_sidebar_class
if nav_menu_collapsed?
"page-sidebar-collapsed"
else
"page-sidebar-expanded"
end
end
end end
...@@ -65,8 +65,7 @@ module CommitsHelper ...@@ -65,8 +65,7 @@ module CommitsHelper
branches.sort.map do |branch| branches.sort.map do |branch|
link_to(project_tree_path(project, branch)) do link_to(project_tree_path(project, branch)) do
content_tag :span, class: 'label label-gray' do content_tag :span, class: 'label label-gray' do
content_tag(:i, nil, class: 'fa fa-code-fork') + ' ' + icon('code-fork') + ' ' + branch
branch
end end
end end
end.join(" ").html_safe end.join(" ").html_safe
...@@ -78,8 +77,7 @@ module CommitsHelper ...@@ -78,8 +77,7 @@ module CommitsHelper
sorted.map do |tag| sorted.map do |tag|
link_to(project_commits_path(project, project.repository.find_tag(tag).name)) do link_to(project_commits_path(project, project.repository.find_tag(tag).name)) do
content_tag :span, class: 'label label-gray' do content_tag :span, class: 'label label-gray' do
content_tag(:i, nil, class: 'fa fa-tag') + ' ' + icon('tag') + ' ' + tag
tag
end end
end end
end.join(" ").html_safe end.join(" ").html_safe
...@@ -114,7 +112,8 @@ module CommitsHelper ...@@ -114,7 +112,8 @@ module CommitsHelper
person_name = user.nil? ? source_name : user.name person_name = user.nil? ? source_name : user.name
person_email = user.nil? ? source_email : user.email person_email = user.nil? ? source_email : user.email
text = if options[:avatar] 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: "") avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>} %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>}
else else
......
...@@ -10,6 +10,6 @@ module CompareHelper ...@@ -10,6 +10,6 @@ module CompareHelper
end end
def compare_mr_path 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
end end
...@@ -31,7 +31,7 @@ module EmailsHelper ...@@ -31,7 +31,7 @@ module EmailsHelper
end end
def add_email_highlight_css def add_email_highlight_css
Rugments::Themes::Github.render(:scope => '.highlight') Rugments::Themes::Github.render(scope: '.highlight')
end end
def color_email_diff(diffcontent) def color_email_diff(diffcontent)
......
...@@ -27,18 +27,17 @@ module EventsHelper ...@@ -27,18 +27,17 @@ module EventsHelper
content_tag :li, class: "filter_icon #{active}" do 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 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]) + icon(icon_for_event[key]) + content_tag(:span, ' ' + tooltip)
content_tag(:span, ' ' + tooltip)
end end
end end
end end
def icon_for_event def icon_for_event
{ {
EventFilter.push => 'fa fa-upload', EventFilter.push => 'upload',
EventFilter.merged => 'fa fa-check-square-o', EventFilter.merged => 'check-square-o',
EventFilter.comments => 'fa fa-comments', EventFilter.comments => 'comments',
EventFilter.team => 'fa fa-user', EventFilter.team => 'user',
} }
end end
......
module IconsHelper 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) def boolean_to_icon(value)
if value.to_s == "true" if value.to_s == "true"
content_tag :i, nil, class: 'fa fa-circle cgreen' icon('circle', class: 'cgreen')
else else
content_tag :i, nil, class: 'fa fa-power-off clgray' icon('power-off', class: 'clgray')
end end
end end
def public_icon def public_icon
content_tag :i, nil, class: 'fa fa-globe' icon('globe')
end end
def internal_icon def internal_icon
content_tag :i, nil, class: 'fa fa-shield' icon('shield')
end end
def private_icon def private_icon
content_tag :i, nil, class: 'fa fa-lock' icon('lock')
end end
end end
...@@ -49,7 +49,7 @@ module IssuesHelper ...@@ -49,7 +49,7 @@ module IssuesHelper
ts << capture_haml do ts << capture_haml do
haml_tag :span do haml_tag :span do
haml_concat '&middot;' haml_concat '&middot;'
haml_concat '<i class="fa fa-edit" title="edited"></i> ' haml_concat icon('edit', title: 'edited')
haml_concat time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_edited_ago') haml_concat time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_edited_ago')
end end
end end
......
...@@ -15,12 +15,14 @@ module MergeRequestsHelper ...@@ -15,12 +15,14 @@ module MergeRequestsHelper
end end
def new_mr_from_push_event(event, target_project) def new_mr_from_push_event(event, target_project)
return :merge_request => { return {
merge_request: {
source_project_id: event.project.id, source_project_id: event.project.id,
target_project_id: target_project.id, target_project_id: target_project.id,
source_branch: event.branch_name, source_branch: event.branch_name,
target_branch: target_project.repository.root_ref target_branch: target_project.repository.root_ref
} }
}
end end
def mr_css_classes(mr) def mr_css_classes(mr)
......
module NavHelper
def nav_menu_collapsed?
cookies[:collapsed_nav] == 'true'
end
end
...@@ -22,7 +22,7 @@ module NotesHelper ...@@ -22,7 +22,7 @@ module NotesHelper
ts << capture_haml do ts << capture_haml do
haml_tag :span do haml_tag :span do
haml_concat '&middot;' haml_concat '&middot;'
haml_concat '<i class="fa fa-edit" title="edited"></i> ' haml_concat icon('edit', title: 'edited')
haml_concat time_ago_with_tooltip(note.updated_at, 'bottom', 'note_edited_ago') haml_concat time_ago_with_tooltip(note.updated_at, 'bottom', 'note_edited_ago')
end end
end end
...@@ -57,7 +57,7 @@ module NotesHelper ...@@ -57,7 +57,7 @@ module NotesHelper
button_tag(class: 'btn add-diff-note js-add-diff-note-button', button_tag(class: 'btn add-diff-note js-add-diff-note-button',
data: data, data: data,
title: 'Add a comment to this line') do title: 'Add a comment to this line') do
content_tag :i, nil, class: 'fa fa-comment-o' icon('comment-o')
end end
end end
...@@ -74,7 +74,7 @@ module NotesHelper ...@@ -74,7 +74,7 @@ module NotesHelper
button_tag class: 'btn reply-btn js-discussion-reply-button', button_tag class: 'btn reply-btn js-discussion-reply-button',
data: data, title: 'Add a reply' do data: data, title: 'Add a reply' do
link_text = content_tag(:i, nil, class: 'fa fa-comment') link_text = icon('comment')
link_text << ' Reply' link_text << ' Reply'
end end
end end
......
module NotificationsHelper module NotificationsHelper
def notification_icon(notification) def notification_icon(notification)
if notification.disabled? if notification.disabled?
content_tag :i, nil, class: 'fa fa-volume-off ns-mute' icon('volume-off', class: 'ns-mute')
elsif notification.participating? elsif notification.participating?
content_tag :i, nil, class: 'fa fa-volume-down ns-part' icon('volume-down', class: 'ns-part')
elsif notification.watch? elsif notification.watch?
content_tag :i, nil, class: 'fa fa-volume-up ns-watch' icon('volume-up', class: 'ns-watch')
else else
content_tag :i, nil, class: 'fa fa-circle-o ns-default' icon('circle-o', class: 'ns-default')
end end
end end
end end
...@@ -83,7 +83,7 @@ module ProjectsHelper ...@@ -83,7 +83,7 @@ module ProjectsHelper
' Star' ' Star'
end end
content_tag('i', ' ', class: 'fa fa-star') + toggle_text icon('star') + toggle_text
end end
count_html = content_tag('span', class: 'count') do count_html = content_tag('span', class: 'count') do
...@@ -95,7 +95,7 @@ module ProjectsHelper ...@@ -95,7 +95,7 @@ module ProjectsHelper
class: cls, class: cls,
method: :post, method: :post,
remote: true, remote: true,
data: {type: 'json'} data: { type: 'json' }
} }
...@@ -107,7 +107,7 @@ module ProjectsHelper ...@@ -107,7 +107,7 @@ module ProjectsHelper
end end
def link_to_toggle_fork def link_to_toggle_fork
out = content_tag(:i, '', class: 'fa fa-code-fork') out = icon('code-fork')
out << ' Fork' out << ' Fork'
out << content_tag(:span, class: 'count') do out << content_tag(:span, class: 'count') do
@project.forks_count.to_s @project.forks_count.to_s
...@@ -262,4 +262,3 @@ module ProjectsHelper ...@@ -262,4 +262,3 @@ module ProjectsHelper
end end
end end
end end
...@@ -38,13 +38,8 @@ module TreeHelper ...@@ -38,13 +38,8 @@ module TreeHelper
# #
# type - String type of the tree item; either 'folder' or 'file' # type - String type of the tree item; either 'folder' or 'file'
def tree_icon(type) def tree_icon(type)
icon_class = if type == 'folder' icon_class = type == 'folder' ? 'folder' : 'file-o'
'fa fa-folder' icon(icon_class)
else
'fa fa-file-o'
end
content_tag :i, nil, class: icon_class
end end
def tree_hex_class(content) def tree_hex_class(content)
......
...@@ -2,9 +2,12 @@ class Appearance < ActiveRecord::Base ...@@ -2,9 +2,12 @@ class Appearance < ActiveRecord::Base
validates :title, presence: true validates :title, presence: true
validates :description, presence: true validates :description, presence: true
validates :logo, file_size: { maximum: 1000.kilobytes.to_i } validates :logo, file_size: { maximum: 1000.kilobytes.to_i }
validates :dark_logo, file_size: { maximum: 1000.kilobytes.to_i }, validates :dark_logo,
file_size: { maximum: 1000.kilobytes.to_i },
presence: true, if: :light_logo? presence: true, if: :light_logo?
validates :light_logo, file_size: { maximum: 1000.kilobytes.to_i },
validates :light_logo,
file_size: { maximum: 1000.kilobytes.to_i },
presence: true, if: :dark_logo? presence: true, if: :dark_logo?
mount_uploader :logo, AttachmentUploader mount_uploader :logo, AttachmentUploader
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# #
# id :integer not null, primary key # id :integer not null, primary key
# default_projects_limit :integer # default_projects_limit :integer
# default_branch_protection :integer
# signup_enabled :boolean # signup_enabled :boolean
# signin_enabled :boolean # signin_enabled :boolean
# gravatar_enabled :boolean # gravatar_enabled :boolean
...@@ -14,7 +15,8 @@ ...@@ -14,7 +15,8 @@
# #
class ApplicationSetting < ActiveRecord::Base 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" }, format: { with: URI::regexp(%w(http https)), message: "should be a valid url" },
if: :home_page_url_column_exist if: :home_page_url_column_exist
...@@ -25,6 +27,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -25,6 +27,7 @@ class ApplicationSetting < ActiveRecord::Base
def self.create_from_defaults def self.create_from_defaults
create( create(
default_projects_limit: Settings.gitlab['default_projects_limit'], default_projects_limit: Settings.gitlab['default_projects_limit'],
default_branch_protection: Settings.gitlab['default_branch_protection'],
signup_enabled: Settings.gitlab['signup_enabled'], signup_enabled: Settings.gitlab['signup_enabled'],
signin_enabled: Settings.gitlab['signin_enabled'], signin_enabled: Settings.gitlab['signin_enabled'],
gravatar_enabled: Settings.gravatar['enabled'], gravatar_enabled: Settings.gravatar['enabled'],
......
...@@ -88,7 +88,8 @@ class Commit ...@@ -88,7 +88,8 @@ class Commit
# cut off, ellipses (`&hellp;`) are prepended to the commit message. # cut off, ellipses (`&hellp;`) are prepended to the commit message.
def description def description
title_end = safe_message.index("\n") title_end = safe_message.index("\n")
@description ||= if (!title_end && safe_message.length > 100) || (title_end && title_end > 100) @description ||=
if (!title_end && safe_message.length > 100) || (title_end && title_end > 100)
"&hellip;".html_safe << safe_message[80..-1] "&hellip;".html_safe << safe_message[80..-1]
else else
safe_message.split("\n", 2)[1].try(:chomp) safe_message.split("\n", 2)[1].try(:chomp)
......
...@@ -111,7 +111,7 @@ class Group < Namespace ...@@ -111,7 +111,7 @@ class Group < Namespace
class << self class << self
def search(query) 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 end
def sort(method) def sort(method)
......
...@@ -44,11 +44,11 @@ class WebHook < ActiveRecord::Base ...@@ -44,11 +44,11 @@ class WebHook < ActiveRecord::Base
} }
WebHook.post(post_url, WebHook.post(post_url,
body: data.to_json, body: data.to_json,
headers: {"Content-Type" => "application/json"}, headers: { "Content-Type" => "application/json" },
verify: false, verify: false,
basic_auth: auth) basic_auth: auth)
end end
rescue SocketError, Errno::ECONNREFUSED, Net::OpenTimeout => e rescue SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e
logger.error("WebHook Error => #{e}") logger.error("WebHook Error => #{e}")
false false
end end
......
...@@ -11,5 +11,5 @@ ...@@ -11,5 +11,5 @@
class Identity < ActiveRecord::Base class Identity < ActiveRecord::Base
belongs_to :user belongs_to :user
validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider} validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider }
end end
...@@ -79,7 +79,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -79,7 +79,7 @@ class MergeRequest < ActiveRecord::Base
merge_request.save merge_request.save
end 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.locked_at = nil
merge_request.save merge_request.save
end end
......
...@@ -20,12 +20,17 @@ class Namespace < ActiveRecord::Base ...@@ -20,12 +20,17 @@ class Namespace < ActiveRecord::Base
belongs_to :owner, class_name: "User" belongs_to :owner, class_name: "User"
validates :owner, presence: true, unless: ->(n) { n.type == "Group" } validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
validates :name, presence: true, uniqueness: true, validates :name,
presence: true, uniqueness: true,
length: { within: 0..255 }, length: { within: 0..255 },
format: { with: Gitlab::Regex.name_regex, format: { with: Gitlab::Regex.name_regex,
message: Gitlab::Regex.name_regex_message } message: Gitlab::Regex.name_regex_message }
validates :description, length: { within: 0..255 } validates :description, length: { within: 0..255 }
validates :path, uniqueness: { case_sensitive: false }, presence: true, length: { within: 1..255 }, validates :path,
uniqueness: { case_sensitive: false },
presence: true,
length: { within: 1..255 },
exclusion: { in: Gitlab::Blacklist.path }, exclusion: { in: Gitlab::Blacklist.path },
format: { with: Gitlab::Regex.path_regex, format: { with: Gitlab::Regex.path_regex,
message: Gitlab::Regex.path_regex_message } message: Gitlab::Regex.path_regex_message }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
# merge_requests_enabled :boolean default(TRUE), not null # merge_requests_enabled :boolean default(TRUE), not null
# wiki_enabled :boolean default(TRUE), not null # wiki_enabled :boolean default(TRUE), not null
# namespace_id :integer # namespace_id :integer
# issues_tracker :string(255) default('gitlab'), not null # issues_tracker :string(255) default("gitlab"), not null
# issues_tracker_id :string(255) # issues_tracker_id :string(255)
# snippets_enabled :boolean default(TRUE), not null # snippets_enabled :boolean default(TRUE), not null
# last_activity_at :datetime # last_activity_at :datetime
...@@ -115,11 +115,14 @@ class Project < ActiveRecord::Base ...@@ -115,11 +115,14 @@ class Project < ActiveRecord::Base
# Validations # Validations
validates :creator, presence: true, on: :create validates :creator, presence: true, on: :create
validates :description, length: { maximum: 2000 }, allow_blank: true validates :description, length: { maximum: 2000 }, allow_blank: true
validates :name, presence: true, length: { within: 0..255 }, validates :name,
presence: true,
length: { within: 0..255 },
format: { with: Gitlab::Regex.project_name_regex, format: { with: Gitlab::Regex.project_name_regex,
message: Gitlab::Regex.project_regex_message } message: Gitlab::Regex.project_regex_message }
validates :path, presence: true, length: { within: 0..255 }, validates :path,
exclusion: { in: Gitlab::Blacklist.path }, presence: true,
length: { within: 0..255 },
format: { with: Gitlab::Regex.path_regex, format: { with: Gitlab::Regex.path_regex,
message: Gitlab::Regex.path_regex_message } message: Gitlab::Regex.path_regex_message }
validates :issues_enabled, :merge_requests_enabled, validates :issues_enabled, :merge_requests_enabled,
...@@ -163,22 +166,22 @@ class Project < ActiveRecord::Base ...@@ -163,22 +166,22 @@ class Project < ActiveRecord::Base
end end
event :import_finish do event :import_finish do
transition :started => :finished transition started: :finished
end end
event :import_fail do event :import_fail do
transition :started => :failed transition started: :failed
end end
event :import_retry do event :import_retry do
transition :failed => :started transition failed: :started
end end
state :started state :started
state :finished state :finished
state :failed state :failed
after_transition any => :started, :do => :add_import_job after_transition any => :started, do: :add_import_job
end end
class << self class << self
......
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
...@@ -17,13 +17,19 @@ class BambooService < CiService ...@@ -17,13 +17,19 @@ class BambooService < CiService
prop_accessor :bamboo_url, :build_key, :username, :password prop_accessor :bamboo_url, :build_key, :username, :password
validates :bamboo_url, presence: true, validates :bamboo_url,
format: { with: URI::regexp }, if: :activated? presence: true,
format: { with: URI::regexp },
if: :activated?
validates :build_key, presence: true, if: :activated? validates :build_key, presence: true, if: :activated?
validates :username, presence: true, validates :username,
if: ->(service) { service.password? }, if: :activated? presence: true,
validates :password, presence: true, if: ->(service) { service.password? },
if: ->(service) { service.username? }, if: :activated? if: :activated?
validates :password,
presence: true,
if: ->(service) { service.username? },
if: :activated?
attr_accessor :response attr_accessor :response
......
# == 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 class CustomIssueTrackerService < IssueTrackerService
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
...@@ -27,8 +41,8 @@ class CustomIssueTrackerService < IssueTrackerService ...@@ -27,8 +41,8 @@ class CustomIssueTrackerService < IssueTrackerService
{ type: 'text', name: 'title', placeholder: title }, { type: 'text', name: 'title', placeholder: title },
{ type: 'text', name: 'description', placeholder: description }, { type: 'text', name: 'description', placeholder: description },
{ type: 'text', name: 'project_url', placeholder: 'Project url' }, { type: 'text', name: 'project_url', placeholder: 'Project url' },
{ type: 'text', name: 'issues_url', placeholder: 'Issue url'}, { type: 'text', name: 'issues_url', placeholder: 'Issue url' },
{ type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' }
] ]
end end
......
...@@ -81,7 +81,7 @@ class GitlabCiService < CiService ...@@ -81,7 +81,7 @@ class GitlabCiService < CiService
def fields def fields
[ [
{ type: 'text', name: 'token', placeholder: 'GitLab CI project specific token' }, { 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
end end
# == 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 class GitlabIssueTrackerService < IssueTrackerService
include Rails.application.routes.url_helpers include Rails.application.routes.url_helpers
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
......
# == 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 class IssueTrackerService < Service
validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated? validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated?
...@@ -30,8 +44,8 @@ class IssueTrackerService < Service ...@@ -30,8 +44,8 @@ class IssueTrackerService < Service
[ [
{ type: 'text', name: 'description', placeholder: description }, { type: 'text', name: 'description', placeholder: description },
{ type: 'text', name: 'project_url', placeholder: 'Project url' }, { type: 'text', name: 'project_url', placeholder: 'Project url' },
{ type: 'text', name: 'issues_url', placeholder: 'Issue url'}, { type: 'text', name: 'issues_url', placeholder: 'Issue url' },
{ type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' }
] ]
end end
......
# == 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 class JiraService < IssueTrackerService
include HTTParty include HTTParty
......
# == 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 class RedmineService < IssueTrackerService
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
......
...@@ -17,12 +17,15 @@ class TeamcityService < CiService ...@@ -17,12 +17,15 @@ class TeamcityService < CiService
prop_accessor :teamcity_url, :build_type, :username, :password prop_accessor :teamcity_url, :build_type, :username, :password
validates :teamcity_url, presence: true, validates :teamcity_url,
presence: true,
format: { with: URI::regexp }, if: :activated? format: { with: URI::regexp }, if: :activated?
validates :build_type, presence: true, if: :activated? validates :build_type, presence: true, if: :activated?
validates :username, presence: true, validates :username,
presence: true,
if: ->(service) { service.password? }, if: :activated? if: ->(service) { service.password? }, if: :activated?
validates :password, presence: true, validates :password,
presence: true,
if: ->(service) { service.username? }, if: :activated? if: ->(service) { service.username? }, if: :activated?
attr_accessor :response attr_accessor :response
......
...@@ -136,7 +136,7 @@ class ProjectWiki ...@@ -136,7 +136,7 @@ class ProjectWiki
def commit_details(action, message = nil, title = nil) def commit_details(action, message = nil, title = nil)
commit_message = message || default_message(action, title) 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 end
def default_message(action, title) def default_message(action, title)
......
...@@ -30,7 +30,7 @@ class Repository ...@@ -30,7 +30,7 @@ class Repository
commit = Gitlab::Git::Commit.find(raw_repository, id) commit = Gitlab::Git::Commit.find(raw_repository, id)
commit = Commit.new(commit) if commit commit = Commit.new(commit) if commit
commit commit
rescue Rugged::OdbError => ex rescue Rugged::OdbError
nil nil
end end
...@@ -61,25 +61,25 @@ class Repository ...@@ -61,25 +61,25 @@ class Repository
end end
def add_branch(branch_name, ref) 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) gitlab_shell.add_branch(path_with_namespace, branch_name, ref)
end end
def add_tag(tag_name, ref, message = nil) 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) gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message)
end end
def rm_branch(branch_name) 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) gitlab_shell.rm_branch(path_with_namespace, branch_name)
end end
def rm_tag(tag_name) 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) gitlab_shell.rm_tag(path_with_namespace, tag_name)
end end
...@@ -97,19 +97,15 @@ class Repository ...@@ -97,19 +97,15 @@ class Repository
end end
def branch_names def branch_names
Rails.cache.fetch(cache_key(:branch_names)) do cache.fetch(:branch_names) { raw_repository.branch_names }
raw_repository.branch_names
end
end end
def tag_names def tag_names
Rails.cache.fetch(cache_key(:tag_names)) do cache.fetch(:tag_names) { raw_repository.tag_names }
raw_repository.tag_names
end
end end
def commit_count def commit_count
Rails.cache.fetch(cache_key(:commit_count)) do cache.fetch(:commit_count) do
begin begin
raw_repository.commit_count(self.root_ref) raw_repository.commit_count(self.root_ref)
rescue rescue
...@@ -121,26 +117,19 @@ class Repository ...@@ -121,26 +117,19 @@ class Repository
# Return repo size in megabytes # Return repo size in megabytes
# Cached in redis # Cached in redis
def size def size
Rails.cache.fetch(cache_key(:size)) do cache.fetch(:size) { raw_repository.size }
raw_repository.size
end
end end
def expire_cache def expire_cache
Rails.cache.delete(cache_key(:size)) %i(size branch_names tag_names commit_count graph_log
Rails.cache.delete(cache_key(:branch_names)) readme version contribution_guide).each do |key|
Rails.cache.delete(cache_key(:tag_names)) cache.expire(key)
Rails.cache.delete(cache_key(:commit_count)) end
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))
end end
def graph_log def graph_log
Rails.cache.fetch(cache_key(:graph_log)) do cache.fetch(:graph_log) do
commits = raw_repository.log(limit: 6000, commits = raw_repository.log(limit: 6000, skip_merges: true,
skip_merges: true,
ref: root_ref) ref: root_ref)
commits.map do |rugged_commit| commits.map do |rugged_commit|
...@@ -176,10 +165,6 @@ class Repository ...@@ -176,10 +165,6 @@ class Repository
end end
end end
def cache_key(type)
"#{type}:#{path_with_namespace}"
end
def method_missing(m, *args, &block) def method_missing(m, *args, &block)
raw_repository.send(m, *args, &block) raw_repository.send(m, *args, &block)
end end
...@@ -199,13 +184,11 @@ class Repository ...@@ -199,13 +184,11 @@ class Repository
end end
def readme def readme
Rails.cache.fetch(cache_key(:readme)) do cache.fetch(:readme) { tree(:head).readme }
tree(:head).readme
end
end end
def version def version
Rails.cache.fetch(cache_key(:version)) do cache.fetch(:version) do
tree(:head).blobs.find do |file| tree(:head).blobs.find do |file|
file.name.downcase == 'version' file.name.downcase == 'version'
end end
...@@ -213,9 +196,7 @@ class Repository ...@@ -213,9 +196,7 @@ class Repository
end end
def contribution_guide def contribution_guide
Rails.cache.fetch(cache_key(:contribution_guide)) do cache.fetch(:contribution_guide) { tree(:head).contribution_guide }
tree(:head).contribution_guide
end
end end
def head_commit def head_commit
...@@ -351,4 +332,10 @@ class Repository ...@@ -351,4 +332,10 @@ class Repository
[] []
end end
end end
private
def cache
@cache ||= RepositoryCache.new(path_with_namespace)
end
end end
...@@ -29,7 +29,9 @@ class Snippet < ActiveRecord::Base ...@@ -29,7 +29,9 @@ class Snippet < ActiveRecord::Base
validates :author, presence: true validates :author, presence: true
validates :title, presence: true, length: { within: 0..255 } validates :title, presence: true, length: { within: 0..255 }
validates :file_name, presence: true, length: { within: 0..255 }, validates :file_name,
presence: true,
length: { within: 0..255 },
format: { with: Gitlab::Regex.path_regex, format: { with: Gitlab::Regex.path_regex,
message: Gitlab::Regex.path_regex_message } message: Gitlab::Regex.path_regex_message }
validates :content, presence: true validates :content, presence: true
......
...@@ -113,10 +113,12 @@ class User < ActiveRecord::Base ...@@ -113,10 +113,12 @@ class User < ActiveRecord::Base
# Validations # Validations
# #
validates :name, presence: true 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 :bio, length: { maximum: 255 }, allow_blank: true
validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0} validates :projects_limit, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :username, presence: true, uniqueness: { case_sensitive: false }, validates :username,
presence: true,
uniqueness: { case_sensitive: false },
exclusion: { in: Gitlab::Blacklist.path }, exclusion: { in: Gitlab::Blacklist.path },
format: { with: Gitlab::Regex.username_regex, format: { with: Gitlab::Regex.username_regex,
message: Gitlab::Regex.username_regex_message } message: Gitlab::Regex.username_regex_message }
......
...@@ -43,7 +43,7 @@ class WikiPage ...@@ -43,7 +43,7 @@ class WikiPage
@attributes[:slug] @attributes[:slug]
end end
alias :to_param :slug alias_method :to_param, :slug
# The formatted title of this page. # The formatted title of this page.
def title def title
......
class GitPushService class GitPushService
attr_accessor :project, :user, :push_data, :push_commits attr_accessor :project, :user, :push_data, :push_commits
include Gitlab::CurrentSettings
include Gitlab::Access
# This method will be called after each git update # This method will be called after each git update
# and only if the provided user and project is present in GitLab. # and only if the provided user and project is present in GitLab.
...@@ -29,8 +31,12 @@ class GitPushService ...@@ -29,8 +31,12 @@ class GitPushService
if is_default_branch?(ref) if is_default_branch?(ref)
# Initial push to the default branch. Take the full history of that branch as "newly pushed". # Initial push to the default branch. Take the full history of that branch as "newly pushed".
@push_commits = project.repository.commits(newrev) @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 else
# Use the pushed commits that aren't reachable by the default branch # 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 # as a heuristic. This may include more commits than are actually pushed, but
......
...@@ -5,7 +5,8 @@ module Projects ...@@ -5,7 +5,8 @@ module Projects
end end
def execute(note_type, note_id) def execute(note_type, note_id)
participating = if note_type && note_id participating =
if note_type && note_id
participants_in(note_type, note_id) participants_in(note_type, note_id)
else else
[] []
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
= f.label :default_projects_limit, class: 'control-label' = f.label :default_projects_limit, class: 'control-label'
.col-sm-10 .col-sm-10
= f.number_field :default_projects_limit, class: 'form-control' = 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 .form-group
= f.label :home_page_url, class: 'control-label' = f.label :home_page_url, class: 'control-label'
.col-sm-10 .col-sm-10
......
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
%div.prepend-top-10 %div.prepend-top-10
= select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2"
%hr %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.panel-default
.panel-heading .panel-heading
%h3.panel-title %h3.panel-title
......
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
- groups.each do |group| - groups.each do |group|
%li.group-row %li.group-row
= link_to group_path(id: group.path), class: dom_class(group) do = 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 %span.group-name.filter-title
= truncate(group.name, length: 35) = truncate(group.name, length: 35)
%span.arrow %span.arrow
......
= link_to project_path(project), class: dom_class(project) do = 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 .dash-project-access-icon
= visibility_level_icon(project.visibility_level) = visibility_level_icon(project.visibility_level)
.dash-project-avatar
= project_icon(project.to_param, alt: '', class: 'avatar s24')
%span.str-truncated %span.str-truncated
%span.namespace-name %span.namespace-name
- if project.namespace - if project.namespace
......
...@@ -12,4 +12,4 @@ ...@@ -12,4 +12,4 @@
%strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
.form-actions .form-actions
= f.submit 'Add users into group', class: "btn btn-create" = f.submit 'Add users to group', class: "btn btn-create"
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
- projects.each do |project| - projects.each do |project|
%li.project-row %li.project-row
= link_to project_path(project), class: dom_class(project) do = 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 .dash-project-access-icon
= visibility_level_icon(project.visibility_level) = visibility_level_icon(project.visibility_level)
.dash-project-avatar
= project_icon(project.to_param, alt: '', class: 'avatar s24')
%span.str-truncated %span.str-truncated
%span.project-name %span.project-name
= project.name = project.name
......
.dashboard .dashboard
%div %div
= image_tag group_icon(@group.path), class: "avatar s90" = image_tag group_icon(@group.path), class: "avatar avatar-tile s90"
.clearfix .clearfix
%h2 %h2
= @group.name = @group.name
......
- if nav_menu_collapsed?
= link_to icon('angle-right'), '#', class: 'toggle-nav-collapse'
- else
= link_to icon('angle-left'), '#', class: 'toggle-nav-collapse'
- if defined?(sidebar) - if defined?(sidebar)
.page-with-sidebar .page-with-sidebar{ class: nav_sidebar_class }
= render "layouts/broadcast" = render "layouts/broadcast"
.sidebar-wrapper .sidebar-wrapper
= render(sidebar) = render(sidebar)
.collapse-nav
= render partial: 'layouts/collapse_button'
.content-wrapper .content-wrapper
.container-fluid .container-fluid
.content .content
......
...@@ -30,5 +30,5 @@ ...@@ -30,5 +30,5 @@
%code %code
:erb :erb
<% lines.each do |line| %> <% lines.each do |line| %>
<%= highlight(@blob.name, line, true).html_safe %> <%= highlight(@blob.name, line.force_encoding("utf-8"), true).html_safe %>
<% end %> <% end %>
...@@ -37,23 +37,8 @@ ...@@ -37,23 +37,8 @@
- @commit.parents.each do |parent| - @commit.parents.each do |parent|
= link_to parent.short_id, project_commit_path(@project, parent) = link_to parent.short_id, project_commit_path(@project, parent)
.commit-info-row .commit-info-row.branches
- if @branches.any? %i.fa.fa-spinner.fa-spin
%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-box .commit-box
%h3.commit-title %h3.commit-title
...@@ -61,3 +46,7 @@ ...@@ -61,3 +46,7 @@
- if @commit.description.present? - if @commit.description.present?
%pre.commit-description %pre.commit-description
= preserve(gfm(escape_once(@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
- 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
...@@ -3,8 +3,7 @@ ...@@ -3,8 +3,7 @@
.project-edit-content .project-edit-content
%div %div
%h3.page-title %h3.page-title
Project settings: Project settings
%p.light Some settings, such as "Transfer Project", are hidden inside the danger area below.
%hr %hr
.panel-body .panel-body
= form_for @project, remote: true, html: { multipart: true, class: "edit_project form-horizontal" }, authenticity_token: true do |f| = form_for @project, remote: true, html: { multipart: true, class: "edit_project form-horizontal" }, authenticity_token: true do |f|
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
You can You can
= link_to project_new_blob_path(@project, 'master'), class: 'btn btn-new btn-lg' do = link_to project_new_blob_path(@project, 'master'), class: 'btn btn-new btn-lg' do
add a file add a file
&nbsp;or push it via command line. &nbsp;or do a push via the command line.
%h4 %h4
%strong Command line instructions %strong Command line instructions
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
= link_to_member(@project, participant, name: false, size: 24) = link_to_member(@project, participant, name: false, size: 24)
.voting_notes#notes= render "projects/notes/notes_with_form" .voting_notes#notes= render "projects/notes/notes_with_form"
.col-md-3.hidden-sm.hidden-xs .col-md-3
%div %div
.clearfix .clearfix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
......
...@@ -2,23 +2,21 @@ ...@@ -2,23 +2,21 @@
%div.prepend-top-20 %div.prepend-top-20
%p %p
Assignee: Assignee:
- if issue.assignee
- 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) = link_to_member(@project, @issue.assignee)
- else - else
None 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)
%div.prepend-top-20 %div.prepend-top-20
%p %p
Milestone: Milestone:
- if issue.milestone
#{link_to @issue.milestone.title, project_milestone_path(@project, @issue.milestone)}
- else
none
- if can?(current_user, :modify_issue, @issue) - 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'}) = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'})
= hidden_field_tag :issue_context = hidden_field_tag :issue_context
= f.submit class: 'btn' = f.submit class: 'btn'
- elsif issue.milestone
= link_to project_milestone_path(@project, @issue.milestone) do
= @issue.milestone.title
- else
None
...@@ -3,8 +3,15 @@ ...@@ -3,8 +3,15 @@
:plain :plain
$("##{dom_id(@issue)}").fadeOut(); $("##{dom_id(@issue)}").fadeOut();
- elsif params[:issue_context] - elsif params[:issue_context]
$('.context').html("#{escape_javascript(render partial: 'issue_context', locals: { issue: @issue })}");
$('.context').effect('highlight'); $('.context').effect('highlight');
- if @issue.milestone - if @issue.milestone
$('.milestone-nav-link').replaceWith("<span class='milestone-nav-link'>| <span class='light'>Milestone</span> #{escape_javascript(link_to @issue.milestone.title, project_milestone_path(@issue.project, @issue.milestone))}</span>") $('.milestone-nav-link').replaceWith("<span class='milestone-nav-link'>| <span class='light'>Milestone</span> #{escape_javascript(link_to @issue.milestone.title, project_milestone_path(@issue.project, @issue.milestone))}</span>")
- else - else
$('.milestone-nav-link').html('') $('.milestone-nav-link').html('')
$('select.select2').select2({width: 'resolve', dropdownAutoWidth: true})
$('.edit-issue.inline-update input[type="submit"]').hide();
new ProjectUsersSelect();
new Issue();
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
.col-md-9 .col-md-9
= render "projects/merge_requests/show/participants" = render "projects/merge_requests/show/participants"
= render "projects/notes/notes_with_form" = render "projects/notes/notes_with_form"
.col-md-3.hidden-sm.hidden-xs .col-md-3
.clearfix .clearfix
%span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'} %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
= cross_project_reference(@project, @merge_request) = cross_project_reference(@project, @merge_request)
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
%cite.cgray %cite.cgray
= render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request } = render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
%hr %hr
.votes-holder.hidden-sm.hidden-xs .votes-holder
%h6 Votes %h6 Votes
#votes= render 'votes/votes_block', votable: @merge_request #votes= render 'votes/votes_block', votable: @merge_request
......
...@@ -2,22 +2,22 @@ ...@@ -2,22 +2,22 @@
%div.prepend-top-20 %div.prepend-top-20
%p %p
Assignee: Assignee:
- if @merge_request.assignee
- 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) = link_to_member(@project, @merge_request.assignee)
- else - else
None 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)
%div.prepend-top-20 %div.prepend-top-20
%p %p
Milestone: 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) - 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'}) = 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 = hidden_field_tag :merge_request_context
= f.submit class: 'btn' = f.submit class: 'btn'
- elsif merge_request.milestone
= link_to merge_request.milestone.title, project_milestone_path
- else
None
- if params[:merge_request_context] - if params[:merge_request_context]
$('.context').html("#{escape_javascript(render partial: 'projects/merge_requests/show/context', locals: { issue: @issue })}");
$('.context').effect('highlight'); $('.context').effect('highlight');
new ProjectUsersSelect();
$('select.select2').select2({width: 'resolve', dropdownAutoWidth: true});
merge_request = new MergeRequest();
...@@ -19,8 +19,10 @@ ...@@ -19,8 +19,10 @@
%td.new_line= "..." %td.new_line= "..."
%td.line_content.matched= line.text %td.line_content.matched= line.text
- else - else
%td.old_line= raw(line.type == "new" ? "&nbsp;" : line.old_pos) %td.old_line{class: line.type == "new" ? "new" : "old"}
%td.new_line= raw(line.type == "old" ? "&nbsp;" : line.new_pos) = raw(line.type == "new" ? "&nbsp;" : line.old_pos)
%td.new_line{class: line.type == "new" ? "new" : "old"}
= raw(line.type == "old" ? "&nbsp;" : line.new_pos)
%td.line_content{class: "noteable_line #{line.type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text) %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 - if line_code == note.line_code
......
.clearfix .clearfix
- groups.each do |group| - groups.each do |group|
= link_to group, class: 'profile-groups-avatars', title: group.name do = link_to group, class: 'profile-groups-avatars inline', title: group.name do
= image_tag group_icon(group.path), class: 'avatar avatar-inline s40' = image_tag group_icon(group.path), class: 'avatar avatar-tile s40'
%h4 Calendar
#cal-heatmap.calendar #cal-heatmap.calendar
:javascript :javascript
new calendar( new calendar(
......
.row .row
.col-md-8 .col-md-8
%h3.page-title %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 = @user.name
- if @user == current_user - if @user == current_user
.pull-right .pull-right
...@@ -15,15 +15,16 @@ ...@@ -15,15 +15,16 @@
.clearfix .clearfix
- if @groups.any? - if @groups.any?
%h4 Groups: %h4 Groups
= render 'groups', groups: @groups = render 'groups', groups: @groups
%hr %hr
%h4 Calendar: .user-calendar
%div= render 'calendar' %h4.center.light
%i.fa.fa-spinner.fa-spin
%hr %hr
%h4 %h4
User Activity: User Activity
- if current_user - if current_user
%span.rss-icon.pull-right %span.rss-icon.pull-right
...@@ -36,3 +37,8 @@ ...@@ -36,3 +37,8 @@
= render 'profile', user: @user = render 'profile', user: @user
- if @projects.present? - if @projects.present?
= render 'projects', projects: @projects = render 'projects', projects: @projects
:coffeescript
$ ->
$(".user-calendar").load("#{user_calendar_path}")
...@@ -70,7 +70,10 @@ module Gitlab ...@@ -70,7 +70,10 @@ module Gitlab
config.middleware.use Rack::Cors do config.middleware.use Rack::Cors do
allow do allow do
origins '*' 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
end end
......
...@@ -12,10 +12,14 @@ class Settings < Settingslogic ...@@ -12,10 +12,14 @@ class Settings < Settingslogic
def build_gitlab_shell_ssh_path_prefix def build_gitlab_shell_ssh_path_prefix
if gitlab_shell.ssh_port != 22 if gitlab_shell.ssh_port != 22
"ssh://#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:#{gitlab_shell.ssh_port}/" "ssh://#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:#{gitlab_shell.ssh_port}/"
else
if gitlab_shell.ssh_host.include? ':'
"[#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}]:"
else else
"#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:" "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:"
end end
end end
end
def build_gitlab_url def build_gitlab_url
custom_port = gitlab_on_standard_port? ? nil : ":#{gitlab.port}" custom_port = gitlab_on_standard_port? ? nil : ":#{gitlab.port}"
...@@ -94,6 +98,7 @@ Settings['issues_tracker'] ||= {} ...@@ -94,6 +98,7 @@ Settings['issues_tracker'] ||= {}
# #
Settings['gitlab'] ||= Settingslogic.new({}) Settings['gitlab'] ||= Settingslogic.new({})
Settings.gitlab['default_projects_limit'] ||= 10 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_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['default_theme'] = Gitlab::Theme::MARS if Settings.gitlab['default_theme'].nil?
Settings.gitlab['host'] ||= 'localhost' Settings.gitlab['host'] ||= 'localhost'
...@@ -155,7 +160,7 @@ Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_s ...@@ -155,7 +160,7 @@ Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_s
Settings['backup'] ||= Settingslogic.new({}) Settings['backup'] ||= Settingslogic.new({})
Settings.backup['keep_time'] ||= 0 Settings.backup['keep_time'] ||= 0
Settings.backup['path'] = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root) 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 # Convert upload connection settings to use symbol keys, to make Fog happy
if Settings.backup['upload']['connection'] if Settings.backup['upload']['connection']
Settings.backup['upload']['connection'] = Hash[Settings.backup['upload']['connection'].map { |k, v| [k.to_sym, v] }] Settings.backup['upload']['connection'] = Hash[Settings.backup['upload']['connection'].map { |k, v| [k.to_sym, v] }]
......
...@@ -42,7 +42,8 @@ module ActsAsTaggableOn::Taggable ...@@ -42,7 +42,8 @@ module ActsAsTaggableOn::Taggable
elsif options.delete(:any) elsif options.delete(:any)
# get tags, drop out if nothing returned (we need at least one) # get tags, drop out if nothing returned (we need at least one)
tags = if options.delete(:wild) tags =
if options.delete(:wild)
ActsAsTaggableOn::Tag.named_like_any(tag_list) ActsAsTaggableOn::Tag.named_like_any(tag_list)
else else
ActsAsTaggableOn::Tag.named_any(tag_list) ActsAsTaggableOn::Tag.named_any(tag_list)
......
...@@ -12,22 +12,30 @@ if File.exists?(aws_file) ...@@ -12,22 +12,30 @@ if File.exists?(aws_file)
aws_secret_access_key: AWS_CONFIG['secret_access_key'], # required aws_secret_access_key: AWS_CONFIG['secret_access_key'], # required
region: AWS_CONFIG['region'], # optional, defaults to 'us-east-1' 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 # required
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'} # optional, defaults to {} config.fog_directory = AWS_CONFIG['bucket']
config.fog_authenticated_url_expiration = 1 << 29 # optional time (in seconds) that authenticated urls will be valid.
# 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 # when fog_public is false and provider is AWS or Google, defaults to 600
config.fog_authenticated_url_expiration = 1 << 29
end end
# Mocking Fog requests, based on: https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Test-Fog-based-uploaders # Mocking Fog requests, based on: https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Test-Fog-based-uploaders
if Rails.env.test? if Rails.env.test?
Fog.mock! Fog.mock!
connection = ::Fog::Storage.new( connection = ::Fog::Storage.new(
:aws_access_key_id => AWS_CONFIG['access_key_id'], aws_access_key_id: AWS_CONFIG['access_key_id'],
:aws_secret_access_key => AWS_CONFIG['secret_access_key'], aws_secret_access_key: AWS_CONFIG['secret_access_key'],
:provider => 'AWS', provider: 'AWS',
:region => AWS_CONFIG['region'] region: AWS_CONFIG['region']
) )
connection.directories.create(:key => AWS_CONFIG['bucket']) connection.directories.create(key: AWS_CONFIG['bucket'])
end end
end end
...@@ -43,10 +43,10 @@ Doorkeeper.configure do ...@@ -43,10 +43,10 @@ Doorkeeper.configure do
force_ssl_in_redirect_uri false force_ssl_in_redirect_uri false
# Provide support for an owner to be assigned to each registered application (disabled by default) # 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 # a registered application
# Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support # 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 # Define access token scopes for your provider
# For more information go to # For more information go to
......
...@@ -3,9 +3,9 @@ require 'api/api' ...@@ -3,9 +3,9 @@ require 'api/api'
Gitlab::Application.routes.draw do Gitlab::Application.routes.draw do
use_doorkeeper do use_doorkeeper do
controllers :applications => 'oauth/applications', controllers applications: 'oauth/applications',
:authorized_applications => 'oauth/authorized_applications', authorized_applications: 'oauth/authorized_applications',
:authorizations => 'oauth/authorizations' authorizations: 'oauth/authorizations'
end end
# #
# Search # Search
...@@ -167,10 +167,9 @@ Gitlab::Application.routes.draw do ...@@ -167,10 +167,9 @@ Gitlab::Application.routes.draw do
end end
end end
# route for commits used by the cal-heatmap get 'u/:username/calendar' => 'users#calendar', as: :user_calendar,
get 'u/:username/activities' => 'users#activities', as: :user_activities, constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ },
via: :get
get '/u/:username' => 'users#show', as: :user, get '/u/:username' => 'users#show', as: :user,
constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
...@@ -188,7 +187,7 @@ Gitlab::Application.routes.draw do ...@@ -188,7 +187,7 @@ Gitlab::Application.routes.draw do
# #
# Groups Area # Groups Area
# #
resources :groups, constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} do resources :groups, constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } do
member do member do
get :issues get :issues
get :merge_requests get :merge_requests
...@@ -239,40 +238,44 @@ Gitlab::Application.routes.draw do ...@@ -239,40 +238,44 @@ Gitlab::Application.routes.draw do
scope module: :projects do scope module: :projects do
# Blob routes: # Blob routes:
get '/new/:id', to: 'blob#new', constraints: {id: /.+/}, as: 'new_blob' get '/new/:id', to: 'blob#new', constraints: { id: /.+/ }, as: 'new_blob'
post '/create/:id', to: 'blob#create', constraints: {id: /.+/}, as: 'create_blob' post '/create/:id', to: 'blob#create', constraints: { id: /.+/ }, as: 'create_blob'
get '/edit/:id', to: 'blob#edit', constraints: {id: /.+/}, as: 'edit_blob' get '/edit/:id', to: 'blob#edit', constraints: { id: /.+/ }, as: 'edit_blob'
put '/update/:id', to: 'blob#update', constraints: {id: /.+/}, as: 'update_blob' put '/update/:id', to: 'blob#update', constraints: { id: /.+/ }, as: 'update_blob'
post '/preview/:id', to: 'blob#preview', constraints: {id: /.+/}, as: 'preview_blob' post '/preview/:id', to: 'blob#preview', constraints: { id: /.+/ }, as: 'preview_blob'
resources :blob, only: [:show, :destroy], constraints: { id: /.+/, format: false } do resources :blob, only: [:show, :destroy], constraints: { id: /.+/, format: false } do
get :diff, on: :member get :diff, on: :member
end end
resources :raw, only: [:show], constraints: {id: /.+/} resources :raw, only: [:show], constraints: { id: /.+/ }
resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ } resources :tree, only: [:show], constraints: { id: /.+/, format: /(html|js)/ }
resource :avatar, only: [:show, :destroy] 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 :compare, only: [:index, :create]
resources :blame, only: [:show], constraints: {id: /.+/} resources :blame, only: [:show], constraints: { id: /.+/ }
resources :network, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/} resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }
resources :graphs, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/} do resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do
member do member do
get :commits get :commits
end end
end end
get '/compare/:from...:to' => 'compare#show', :as => 'compare', 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 member do
get 'raw' get 'raw'
end end
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 collection do
get :pages get :pages
put ':id' => 'wikis#update' put ':id' => 'wikis#update'
...@@ -299,7 +302,7 @@ Gitlab::Application.routes.draw do ...@@ -299,7 +302,7 @@ Gitlab::Application.routes.draw do
end end
end end
resources :deploy_keys, constraints: {id: /\d+/} do resources :deploy_keys, constraints: { id: /\d+/ } do
member do member do
put :enable put :enable
put :disable put :disable
...@@ -318,16 +321,14 @@ Gitlab::Application.routes.draw do ...@@ -318,16 +321,14 @@ Gitlab::Application.routes.draw do
member do member do
# tree viewer logs # tree viewer logs
get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex } get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex }
get 'logs_tree/:path' => 'refs#logs_tree', get 'logs_tree/:path' => 'refs#logs_tree', as: :logs_file, constraints: {
as: :logs_file,
constraints: {
id: Gitlab::Regex.git_reference_regex, id: Gitlab::Regex.git_reference_regex,
path: /.*/ path: /.*/
} }
end end
end end
resources :merge_requests, constraints: {id: /\d+/}, except: [:destroy] do resources :merge_requests, constraints: { id: /\d+/ }, except: [:destroy] do
member do member do
get :diffs get :diffs
post :automerge post :automerge
...@@ -342,29 +343,28 @@ Gitlab::Application.routes.draw do ...@@ -342,29 +343,28 @@ Gitlab::Application.routes.draw do
end end
end end
resources :git_hooks, constraints: {id: /\d+/} resources :git_hooks, constraints: { id: /\d+/ }
resources :hooks, only: [:index, :create, :destroy], constraints: { id: /\d+/ } do
resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do
member do member do
get :test get :test
end end
end end
resources :team, controller: 'team_members', only: [:index] 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 member do
put :sort_issues put :sort_issues
put :sort_merge_requests put :sort_merge_requests
end end
end end
resources :labels, constraints: {id: /\d+/} do resources :labels, constraints: { id: /\d+/ } do
collection do collection do
post :generate post :generate
end end
end end
resources :issues, constraints: {id: /\d+/}, except: [:destroy] do resources :issues, constraints: { id: /\d+/ }, except: [:destroy] do
collection do collection do
post :bulk_update post :bulk_update
end end
...@@ -381,9 +381,9 @@ Gitlab::Application.routes.draw do ...@@ -381,9 +381,9 @@ Gitlab::Application.routes.draw do
end end
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 member do
delete :delete_attachment delete :delete_attachment
end end
...@@ -394,7 +394,7 @@ Gitlab::Application.routes.draw do ...@@ -394,7 +394,7 @@ Gitlab::Application.routes.draw do
get "/audit_events" => "audit_events#project_log" get "/audit_events" => "audit_events#project_log"
end end
get ':id' => 'namespaces#show', constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} get ':id' => 'namespaces#show', constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
root to: 'dashboard#show' root to: 'dashboard#show'
end end
class AddDefaultBranchProtectionSetting < ActiveRecord::Migration
def change
add_column :application_settings, :default_branch_protection, :integer, :default => 2
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # 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 # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -27,6 +27,18 @@ ActiveRecord::Schema.define(version: 20150116234545) do ...@@ -27,6 +27,18 @@ ActiveRecord::Schema.define(version: 20150116234545) do
t.string "light_logo" t.string "light_logo"
end 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| create_table "audit_events", force: true do |t|
t.integer "author_id", null: false t.integer "author_id", null: false
t.string "type", null: false t.string "type", null: false
...@@ -41,17 +53,6 @@ ActiveRecord::Schema.define(version: 20150116234545) do ...@@ -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", ["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 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| create_table "broadcast_messages", force: true do |t|
t.text "message", null: false t.text "message", null: false
t.datetime "starts_at" t.datetime "starts_at"
...@@ -378,14 +379,14 @@ ActiveRecord::Schema.define(version: 20150116234545) do ...@@ -378,14 +379,14 @@ ActiveRecord::Schema.define(version: 20150116234545) do
t.string "import_url" t.string "import_url"
t.integer "visibility_level", default: 0, null: false t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false t.boolean "archived", default: false, null: false
t.string "avatar"
t.string "import_status" t.string "import_status"
t.string "import_type"
t.string "import_source"
t.float "repository_size", default: 0.0 t.float "repository_size", default: 0.0
t.integer "star_count", default: 0, null: false
t.text "merge_requests_template" t.text "merge_requests_template"
t.integer "star_count", default: 0, null: false
t.boolean "merge_requests_rebase_enabled", default: false t.boolean "merge_requests_rebase_enabled", default: false
t.string "avatar" t.string "import_type"
t.string "import_source"
end end
add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
...@@ -483,6 +484,7 @@ ActiveRecord::Schema.define(version: 20150116234545) do ...@@ -483,6 +484,7 @@ ActiveRecord::Schema.define(version: 20150116234545) do
t.integer "notification_level", default: 1, null: false t.integer "notification_level", default: 1, null: false
t.datetime "password_expires_at" t.datetime "password_expires_at"
t.integer "created_by_id" t.integer "created_by_id"
t.datetime "last_credential_check_at"
t.string "avatar" t.string "avatar"
t.string "confirmation_token" t.string "confirmation_token"
t.datetime "confirmed_at" t.datetime "confirmed_at"
...@@ -490,9 +492,8 @@ ActiveRecord::Schema.define(version: 20150116234545) do ...@@ -490,9 +492,8 @@ ActiveRecord::Schema.define(version: 20150116234545) do
t.string "unconfirmed_email" t.string "unconfirmed_email"
t.boolean "hide_no_ssh_key", default: false t.boolean "hide_no_ssh_key", default: false
t.string "website_url", default: "", null: 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.datetime "admin_email_unsubscribed_at"
t.string "github_access_token"
t.string "gitlab_access_token" t.string "gitlab_access_token"
end end
......
...@@ -97,7 +97,7 @@ Return values: ...@@ -97,7 +97,7 @@ Return values:
## Sudo ## 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: 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: ...@@ -142,7 +142,7 @@ When listing resources you can pass the following parameters:
- `page` (default: `1`) - page number - `page` (default: `1`) - page number
- `per_page` (default: `20`, max: `100`) - number of items to list per page - `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 ## id vs iid
......
...@@ -20,7 +20,7 @@ GET /groups ...@@ -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 ## Details of a group
...@@ -32,7 +32,7 @@ GET /groups/:id ...@@ -32,7 +32,7 @@ GET /groups/:id
Parameters: Parameters:
- `id` (required) - The ID of a group - `id` (required) - The ID or path of a group
## New group ## New group
...@@ -58,7 +58,7 @@ POST /groups/:id/projects/:project_id ...@@ -58,7 +58,7 @@ POST /groups/:id/projects/:project_id
Parameters: 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 - `project_id` (required) - The ID of a project
## Remove group ## Remove group
...@@ -71,7 +71,27 @@ DELETE /groups/:id ...@@ -71,7 +71,27 @@ DELETE /groups/:id
Parameters: 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 ## Group members
...@@ -128,7 +148,7 @@ POST /groups/:id/members ...@@ -128,7 +148,7 @@ POST /groups/:id/members
Parameters: 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 - `user_id` (required) - The ID of a user to add
- `access_level` (required) - Project access level - `access_level` (required) - Project access level
...@@ -142,5 +162,5 @@ DELETE /groups/:id/members/:user_id ...@@ -142,5 +162,5 @@ DELETE /groups/:id/members/:user_id
Parameters: 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 - `user_id` (required) - The ID of a group member
...@@ -56,7 +56,7 @@ Parameters: ...@@ -56,7 +56,7 @@ Parameters:
"title": "v1.0", "title": "v1.0",
"description": "", "description": "",
"due_date": "2012-07-20", "due_date": "2012-07-20",
"state": "reopenend", "state": "reopened",
"updated_at": "2012-07-04T13:42:48Z", "updated_at": "2012-07-04T13:42:48Z",
"created_at": "2012-07-04T13:42:48Z" "created_at": "2012-07-04T13:42:48Z"
}, },
......
...@@ -94,6 +94,76 @@ Parameters: ...@@ -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 ## Create MR
Creates a new merge request. Creates a new merge request.
......
...@@ -4,7 +4,7 @@ OAuth2 is a protocol that enables us to get access to private details of user's ...@@ -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. 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 ## Web Application Flow
...@@ -15,7 +15,7 @@ This flow consists from 3 steps. ...@@ -15,7 +15,7 @@ This flow consists from 3 steps.
### 1. Registering the client ### 1. Registering the client
Creat an application in user's account profile. Create an application in user's account profile.
### 2. Requesting authorization ### 2. Requesting authorization
......
...@@ -541,7 +541,7 @@ Parameters: ...@@ -541,7 +541,7 @@ Parameters:
} }
], ],
"tree": "c68537c6534a02cc2b176ca1549f4ffa190b58ee", "tree": "c68537c6534a02cc2b176ca1549f4ffa190b58ee",
"message": "give caolan credit where it's due (up top)", "message": "give Caolan credit where it's due (up top)",
"author": { "author": {
"name": "Jeremy Ashkenas", "name": "Jeremy Ashkenas",
"email": "jashkenas@example.com" "email": "jashkenas@example.com"
......
...@@ -13,7 +13,7 @@ PUT /projects/:id/services/gitlab-ci ...@@ -13,7 +13,7 @@ PUT /projects/:id/services/gitlab-ci
Parameters: Parameters:
- `token` (required) - CI project token - `token` (required) - CI project token
- `project_url` (required) - CI project url - `project_url` (required) - CI project URL
### Delete GitLab CI service ### Delete GitLab CI service
...@@ -23,23 +23,23 @@ Delete GitLab CI service settings for a project. ...@@ -23,23 +23,23 @@ Delete GitLab CI service settings for a project.
DELETE /projects/:id/services/gitlab-ci 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 PUT /projects/:id/services/hipchat
``` ```
Parameters: Parameters:
- `token` (required) - Hipchat token - `token` (required) - HipChat token
- `room` (required) - Hipchat room name - `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 DELETE /projects/:id/services/hipchat
......
...@@ -16,7 +16,7 @@ the configuration options as follows: ...@@ -16,7 +16,7 @@ the configuration options as follows:
```yml ```yml
gravatar: gravatar:
enabled: true 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" plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
``` ```
...@@ -25,14 +25,14 @@ the configuration options as follows: ...@@ -25,14 +25,14 @@ the configuration options as follows:
```yml ```yml
gravatar: gravatar:
enabled: true 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" ssl_url: "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
``` ```
## Self-hosted ## 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 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. 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 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. ...@@ -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. [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. 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"` 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"`
...@@ -16,8 +16,8 @@ You can imagine GitLab as a physical office. ...@@ -16,8 +16,8 @@ You can imagine GitLab as a physical office.
They can be stored in a warehouse. They can be stored in a warehouse.
This can be either a hard disk, or something more complex, such as a NFS filesystem; This can be either a hard disk, or something more complex, such as a NFS filesystem;
**NginX** acts like the front-desk. **Nginx** acts like the front-desk.
Users come to NginX and request actions to be done by workers in the office; 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 database** is a series of metal file cabinets with information on:
- The goods in the warehouse (metadata, issues, merge requests etc); - 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](. ...@@ -70,7 +70,7 @@ To summarize here's the [directory structure of the `git` user home directory](.
ps aux | grep '^git' 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 ### Repository access
...@@ -146,13 +146,13 @@ nginx ...@@ -146,13 +146,13 @@ nginx
Apache httpd 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/apache2/` contains error and output logs (on Ubuntu).
- `/var/log/httpd/` contains error and output logs (on RHEL). - `/var/log/httpd/` contains error and output logs (on RHEL).
redis 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 PostgreSQL
......
...@@ -26,7 +26,7 @@ We use [these build scripts](https://gitlab.com/gitlab-org/gitlab-ci/blob/master ...@@ -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) # Build configuration on [Semaphore](https://semaphoreapp.com/gitlabhq/gitlabhq/) for testing the [GitHub.com repo](https://github.com/gitlabhq/gitlabhq)
- Language: Ruby - Language: Ruby
- Ruby verion: 2.1.2 - Ruby version: 2.1.2
- database.yml: pg - database.yml: pg
Build commands Build commands
......
...@@ -280,7 +280,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ...@@ -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. 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): # 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. # By default, the gitlab-shell config is generated from your main GitLab config.
# You can review (and modify) the gitlab-shell config as follows: # You can review (and modify) the gitlab-shell config as follows:
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
- Ubuntu - Ubuntu
- Debian - Debian
- CentOS - 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) - Scientific Linux (please use the CentOS packages and instructions)
- Oracle Linux (please use the CentOS packages and instructions) - Oracle Linux (please use the CentOS packages and instructions)
......
...@@ -14,7 +14,7 @@ See the documentation below for details on how to configure these services. ...@@ -14,7 +14,7 @@ See the documentation below for details on how to configure these services.
## Project 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. 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. 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. Because GitLab is open source we can ship with the code and tests for all plugins.
......
...@@ -6,6 +6,6 @@ GitLab has a great issue tracker but you can also use an external issue tracker ...@@ -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; - 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. - 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. You can configure the integration in the gitlab.yml configuration file.
# GitLab buttons in gmail # GitLab buttons in Gmail
GitLab supports [Google actions in email](https://developers.google.com/gmail/markup/actions/actions-overview). 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 ...@@ -25,4 +25,4 @@ If you receive "No errors detected" message from the tester you can send the ema
```bash ```bash
bundle exec rake gitlab:mail_google_schema_whitelisting RAILS_ENV=production SEND=true bundle exec rake gitlab:mail_google_schema_whitelisting RAILS_ENV=production SEND=true
`` ```
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
This documentation is for enabling shibboleth with gitlab-omnibus package. 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: To enable the Shibboleth OmniAuth provider you must:
...@@ -10,11 +10,11 @@ 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. 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. 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: Following changes are needed to enable shibboleth:
protect omniauth-shibboleth callback url: protect omniauth-shibboleth callback URL:
``` ```
<Location /users/auth/shibboleth/callback> <Location /users/auth/shibboleth/callback>
AuthType shibboleth AuthType shibboleth
...@@ -32,9 +32,9 @@ protect omniauth-shibboleth callback url: ...@@ -32,9 +32,9 @@ protect omniauth-shibboleth callback url:
SetHandler shib SetHandler shib
</Location> </Location>
``` ```
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 RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !/Shibboleth.sso RewriteCond %{REQUEST_URI} !/Shibboleth.sso
...@@ -50,7 +50,7 @@ File it should look like this: ...@@ -50,7 +50,7 @@ File it should look like this:
external_url 'https://gitlab.example.com' external_url 'https://gitlab.example.com'
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
# disable nginx # disable Nginx
nginx['enable'] = false nginx['enable'] = false
gitlab_rails['omniauth_allow_single_sign_on'] = true gitlab_rails['omniauth_allow_single_sign_on'] = true
......
...@@ -35,7 +35,7 @@ After Slack is ready we need to setup GitLab. Here are the steps to achieve this ...@@ -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 1. Fill in your Slack details
- Mark it as active - Mark it as active
- Paste in the webhook url you got from Slack - Paste in the webhook URL you got from Slack
Have fun :) Have fun :)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* [Newlines](#newlines) * [Newlines](#newlines)
* [Multiple underscores in words](#multiple-underscores-in-words) * [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) * [Code and Syntax Highlighting](#code-and-syntax-highlighting)
* [Emoji](#emoji) * [Emoji](#emoji)
* [Special GitLab references](#special-gitlab-references) * [Special GitLab references](#special-gitlab-references)
...@@ -40,7 +40,7 @@ You can use GFM in ...@@ -40,7 +40,7 @@ You can use GFM in
- milestones - milestones
- wiki pages - 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 ## Newlines
...@@ -68,7 +68,7 @@ It is not reasonable to italicize just _part_ of a word, especially when you're ...@@ -68,7 +68,7 @@ It is not reasonable to italicize just _part_ of a word, especially when you're
perform_complicated_task perform_complicated_task
do_this_and_do_that_and_another_thing 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. 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 ...@@ -250,17 +250,17 @@ The IDs are generated from the content of the header according to the following
For example: For example:
``` ```
###### ..Ab_c-d. e [anchor](url) ![alt text](url).. ###### ..Ab_c-d. e [anchor](URL) ![alt text](URL)..
``` ```
which renders as: 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: will first be converted by step 1) into a string like:
``` ```
..Ab_c-d. e &lt;a href="url">anchor&lt;/a> &lt;img src="url" alt="alt text"/>.. ..Ab_c-d. e &lt;a href="URL">anchor&lt;/a> &lt;img src="URL" alt="alt text"/>..
``` ```
After removing the tags in step 2) we get: After removing the tags in step 2) we get:
...@@ -277,8 +277,8 @@ ab_c-d-e-anchor ...@@ -277,8 +277,8 @@ ab_c-d-e-anchor
Note in particular how: Note in particular how:
- for markdown anchors `[text](url)`, only the `text` is used - for markdown anchors `[text](URL)`, only the `text` is used
- markdown images `![alt](url)` are completely ignored - markdown images `![alt](URL)` are completely ignored
## Emphasis ## Emphasis
......
...@@ -4,16 +4,16 @@ __Project integrations with external services for continuous integration and mor ...@@ -4,16 +4,16 @@ __Project integrations with external services for continuous integration and mor
## Services ## Services
- Assemblia - Assembla
- [Atlassian Bamboo CI](bamboo.md) An Atlassian product for continous integration. - [Atlassian Bamboo CI](bamboo.md) An Atlassian product for continuous integration.
- Build box - Build box
- Campfire - Campfire
- Emails on push - Emails on push
- Flowdock - Flowdock
- Gemnasium - Gemnasium
- GitLab CI - GitLab CI
- Hipchat - HipChat
- PivotalTracker - Pivotal Tracker
- Pushover - Pushover
- Slack - Slack
- TeamCity - TeamCity
...@@ -13,7 +13,7 @@ You can only restore a backup to exactly the same version of GitLab that you cre ...@@ -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 # use this command if you've installed GitLab with the Omnibus package
sudo gitlab-rake gitlab:backup:create 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 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 ...@@ -147,7 +147,7 @@ You can only restore a backup to exactly the same version of GitLab that you cre
# Omnibus package installation # Omnibus package installation
sudo gitlab-rake gitlab:backup:restore sudo gitlab-rake gitlab:backup:restore
# installation from source or cookbook # installation from source
bundle exec rake gitlab:backup:restore RAILS_ENV=production bundle exec rake gitlab:backup:restore RAILS_ENV=production
``` ```
...@@ -192,7 +192,7 @@ Deleting tmp directories...[DONE] ...@@ -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 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 cd /home/git/gitlab
sudo -u git -H editor config/gitlab.yml # Enable keep_time in the backup section to automatically delete old backups 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. ...@@ -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. 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. 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. > A GitLab server using omnibus-gitlab hosted on Amazon AWS.
> An EBS drive containing an ext4 filesystem is mounted at `/var/opt/gitlab`. > 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. > In this case you could make an application backup by taking an EBS snapshot.
> The backup includes all repositories, uploads and Postgres data. > 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`. > 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`. > 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. > 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. If you are running GitLab on a virtualized server you can possibly also create VM snapshots of the entire GitLab server.
......
...@@ -8,7 +8,7 @@ Remove namespaces(dirs) from `/home/git/repositories` if they don't exist in Git ...@@ -8,7 +8,7 @@ Remove namespaces(dirs) from `/home/git/repositories` if they don't exist in Git
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:cleanup:dirs sudo gitlab-rake gitlab:cleanup:dirs
# installation from source or cookbook # installation from source
bundle exec rake gitlab:cleanup:dirs RAILS_ENV=production 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 ...@@ -18,6 +18,6 @@ Remove repositories (global only for now) from `/home/git/repositories` if they
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:cleanup:repos sudo gitlab-rake gitlab:cleanup:repos
# installation from source or cookbook # installation from source
bundle exec rake gitlab:cleanup:repos RAILS_ENV=production bundle exec rake gitlab:cleanup:repos RAILS_ENV=production
``` ```
...@@ -6,7 +6,7 @@ This command will enable the namespaces feature introduced in v4.0. It will move ...@@ -6,7 +6,7 @@ This command will enable the namespaces feature introduced in v4.0. It will move
Note: 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) - Username can be changed at [Profile / Account](/profile/account)
**Example:** **Example:**
......
...@@ -19,19 +19,26 @@ your repositories are located by looking at `config/gitlab.yml` under the `gitla ...@@ -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: New folder needs to have git user ownership and read/write/execute access for git user and its group:
``` ```
$ mkdir new_group sudo -u git mkdir /var/opt/gitlab/git-data/repositories/new_group
$ chown git:git new_group
$ chmod 770 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: ### 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. `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: ### Run the command below depending on your type of installation:
#### Omnibus Installation #### Omnibus Installation
......
...@@ -8,7 +8,7 @@ This command gathers information about your GitLab installation and the System i ...@@ -8,7 +8,7 @@ This command gathers information about your GitLab installation and the System i
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:env:info sudo gitlab-rake gitlab:env:info
# installation from source or cookbook # installation from source
bundle exec rake gitlab:env:info RAILS_ENV=production bundle exec rake gitlab:env:info RAILS_ENV=production
``` ```
...@@ -16,27 +16,28 @@ Example output: ...@@ -16,27 +16,28 @@ Example output:
``` ```
System information System information
System: Debian 6.0.7 System: Debian 7.8
Current User: git Current User: git
Using RVM: no Using RVM: no
Ruby Version: 2.0.0-p481 Ruby Version: 2.1.5p273
Gem Version: 1.8.23 Gem Version: 2.4.3
Bundler Version:1.3.5 Bundler Version: 1.7.6
Rake Version: 10.0.4 Rake Version: 10.3.2
Sidekiq Version: 2.17.8
GitLab information GitLab information
Version: 5.1.0.beta2 Version: 7.7.1
Revision: 4da8b37 Revision: 41ab9e1
Directory: /home/git/gitlab Directory: /home/git/gitlab
DB Adapter: mysql2 DB Adapter: postgresql
URL: http://example.com URL: https://gitlab.example.com
HTTP Clone URL: http://example.com/some-project.git HTTP Clone URL: https://gitlab.example.com/some-project.git
SSH Clone URL: git@example.com:some-project.git SSH Clone URL: git@gitlab.example.com:some-project.git
Using LDAP: no Using LDAP: no
Using Omniauth: no Using Omniauth: no
GitLab Shell GitLab Shell
Version: 1.2.0 Version: 2.4.1
Repositories: /home/git/repositories/ Repositories: /home/git/repositories/
Hooks: /home/git/gitlab-shell/hooks/ Hooks: /home/git/gitlab-shell/hooks/
Git: /usr/bin/git Git: /usr/bin/git
...@@ -59,7 +60,7 @@ You may also have a look at our [Trouble Shooting Guide](https://github.com/gitl ...@@ -59,7 +60,7 @@ You may also have a look at our [Trouble Shooting Guide](https://github.com/gitl
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:check sudo gitlab-rake gitlab:check
# installation from source or cookbook # installation from source
bundle exec rake gitlab:check RAILS_ENV=production bundle exec rake gitlab:check RAILS_ENV=production
``` ```
...@@ -127,7 +128,6 @@ sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites ...@@ -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. In some case it is necessary to rebuild the `authorized_keys` file.
For Omnibus-packages: For Omnibus-packages:
``` ```
sudo gitlab-rake gitlab:shell:setup sudo gitlab-rake gitlab:shell:setup
...@@ -143,6 +143,36 @@ sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production ...@@ -143,6 +143,36 @@ sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production
This will rebuild an authorized_keys file. This will rebuild an authorized_keys file.
You will lose any data stored in authorized_keys file. You will lose any data stored in authorized_keys file.
Do you want to continue (yes/no)? yes 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
``` ```
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:import:user_to_projects[username@domain.tld] 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 bundle exec rake gitlab:import:user_to_projects[username@domain.tld] RAILS_ENV=production
``` ```
...@@ -20,7 +20,7 @@ Notes: ...@@ -20,7 +20,7 @@ Notes:
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:import:all_users_to_all_projects 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 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 ...@@ -30,7 +30,7 @@ bundle exec rake gitlab:import:all_users_to_all_projects RAILS_ENV=production
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:import:user_to_groups[username@domain.tld] 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 bundle exec rake gitlab:import:user_to_groups[username@domain.tld] RAILS_ENV=production
``` ```
...@@ -44,6 +44,6 @@ Notes: ...@@ -44,6 +44,6 @@ Notes:
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:import:all_users_to_all_groups 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 bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production
``` ```
...@@ -4,42 +4,42 @@ ...@@ -4,42 +4,42 @@
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:web_hook:add URL="http://example.com/hook" 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 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**: ## Add a web hook for projects in a given **NAMESPACE**:
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE=acme 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 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: ## Remove a web hook from **ALL** projects using:
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:web_hook:rm URL="http://example.com/hook" 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 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**: ## Remove a web hook from projects in a given **NAMESPACE**:
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE=acme 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 bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE=acme RAILS_ENV=production
## List **ALL** web hooks: ## List **ALL** web hooks:
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:web_hook:list sudo gitlab-rake gitlab:web_hook:list
# source installations or cookbook # source installations
bundle exec rake gitlab:web_hook:list RAILS_ENV=production bundle exec rake gitlab:web_hook:list RAILS_ENV=production
## List the web hooks from projects in a given **NAMESPACE**: ## List the web hooks from projects in a given **NAMESPACE**:
# omnibus-gitlab # omnibus-gitlab
sudo gitlab-rake gitlab:web_hook:list NAMESPACE=/ 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 bundle exec rake gitlab:web_hook:list NAMESPACE=/ RAILS_ENV=production
> Note: `/` is the global namespace. > Note: `/` is the global namespace.
...@@ -104,7 +104,7 @@ bundle exec rake release["x.x.0.rc1"] ...@@ -104,7 +104,7 @@ bundle exec rake release["x.x.0.rc1"]
``` ```
Now developers can use master for merging new features. 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 ### 5. Release GitLab CI RC1
......
...@@ -207,7 +207,7 @@ __3. Tweet to blog__ ...@@ -207,7 +207,7 @@ __3. Tweet to blog__
Send out a tweet to share the good news with the world. Send out a tweet to share the good news with the world.
List the most important features and link to the blog post. 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 <link-to-blogpost> #gitlab" Proposed tweet "Release of GitLab X.X & CI Y.Y! FEATURE, FEATURE and FEATURE &lt;link-to-blog-post&gt; #gitlab"
Consider creating a post on Hacker News. Consider creating a post on Hacker News.
......
...@@ -4,6 +4,6 @@ Git is a distributed version control system (DVCS). ...@@ -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. 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. 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. 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. 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. 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.
# SSH # SSH
- [Deploy keys](deploy_keys.md) ## SSH keys
- [SSH](ssh.md)
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.
# 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.
# 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
```
...@@ -15,8 +15,8 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser ...@@ -15,8 +15,8 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
"name": "StoreCloud", "name": "StoreCloud",
"owner_email": "johnsmith@gmail.com", "owner_email": "johnsmith@gmail.com",
"owner_name": "John Smith", "owner_name": "John Smith",
"path": "stormcloud", "path": "storecloud",
"path_with_namespace": "jsmith/stormcloud", "path_with_namespace": "jsmith/storecloud",
"project_id": 74, "project_id": 74,
"project_visibility": "private", "project_visibility": "private",
} }
...@@ -126,10 +126,10 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser ...@@ -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", "created_at": "2012-07-21T07:30:54Z",
"event_name": "group_create", "event_name": "group_create",
"name": "StormCloud", "name": "StoreCloud",
"owner_email": "johnsmith@gmail.com", "owner_email": "johnsmith@gmail.com",
"owner_name": "John Smith", "owner_name": "John Smith",
"path": "stormcloud", "path": "storecloud",
"group_id": 78 "group_id": 78
} }
``` ```
......
...@@ -22,29 +22,29 @@ sudo -u gitlab bundle exec rake db:migrate RAILS_ENV=production ...@@ -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 # !!! Config should be replaced with a new one. Check it after replace
cp config/gitlab.yml.example config/gitlab.yml 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 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 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 cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
sudo chown git:git /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 # set valid path to hooks in gitlab.yml in git_host section
# like this # like this
git_host: git_host:
# gitolite 2 # Gitolite 2
hooks_path: /home/git/share/gitolite/hooks hooks_path: /home/git/share/gitolite/hooks
# gitolite 3 # Gitolite 3
hooks_path: /home/git/.gitolite/hooks/ 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 # 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 sudo -u git -H sed -i 's/\(GL_GITCONFIG_KEYS\s*=>*\s*\).\{2\}/\\1"\.\*"/g' /home/git/.gitolite.rc
# gitlite v3 # gitlite v3
......
...@@ -41,8 +41,8 @@ git checkout v1.1.0 ...@@ -41,8 +41,8 @@ git checkout v1.1.0
# copy config # copy config
cp config.yml.example config.yml cp config.yml.example config.yml
# change url to GitLab instance # change URL to GitLab instance
# ! make sure url end with '/' like 'https://gitlab.example/' # ! make sure the URL ends with '/' like 'https://gitlab.example/'
vim config.yml vim config.yml
# rewrite hooks # rewrite hooks
...@@ -111,7 +111,7 @@ sudo chmod -R u+rwX /home/git/gitlab/tmp/pids ...@@ -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 ```bash
# init.d # init.d
...@@ -123,7 +123,7 @@ sudo chmod +x /etc/init.d/gitlab ...@@ -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 /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 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/' # Replace path from '/home/gitlab/' to '/home/git/'
sudo vim /etc/nginx/sites-enabled/gitlab sudo vim /etc/nginx/sites-enabled/gitlab
sudo service nginx restart sudo service nginx restart
...@@ -137,7 +137,7 @@ sudo service gitlab start ...@@ -137,7 +137,7 @@ sudo service gitlab start
# check if unicorn and sidekiq started # check if unicorn and sidekiq started
# If not try to logout, also check replaced path from '/home/gitlab/' to '/home/git/' # 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 unicorn
ps aux | grep sidekiq ps aux | grep sidekiq
......
...@@ -40,7 +40,7 @@ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production ...@@ -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. 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 #### MySQL
Login to MySQL: Login to MySQL:
......
...@@ -10,7 +10,7 @@ GitLab 6.0 is affected by critical security vulnerabilities CVE-2013-4490 and CV ...@@ -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. 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 ### Teams
......
...@@ -35,7 +35,7 @@ sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulner ...@@ -35,7 +35,7 @@ sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulner
## 4. Install additional packages ## 4. Install additional packages
```bash ```bash
# Add support for lograte for better log file handling # Add support for logrotate for better log file handling
sudo apt-get install logrotate sudo apt-get install logrotate
``` ```
......
...@@ -84,11 +84,14 @@ sudo -u git -H git checkout 7-7-stable-ee ...@@ -84,11 +84,14 @@ sudo -u git -H git checkout 7-7-stable-ee
## 4. Install additional packages ## 4. Install additional packages
```bash ```bash
# Add support for lograte for better log file handling # Add support for logrotate for better log file handling
sudo apt-get install logrotate sudo apt-get install logrotate
# Install pkg-config and cmake, which is needed for the latest versions of rugged # Install pkg-config and cmake, which is needed for the latest versions of rugged
sudo apt-get install pkg-config cmake 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 ## 5. Configure Redis to use sockets
...@@ -219,13 +222,13 @@ mysql -u root -p ...@@ -219,13 +222,13 @@ mysql -u root -p
# Convert all tables to use the InnoDB storage engine (added in GitLab 6.8) # 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'; 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 # Convert all tables to correct character set
SET foreign_key_checks = 0; 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'; 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 # turn foreign key checks back on
SET foreign_key_checks = 1; SET foreign_key_checks = 1;
......
...@@ -114,13 +114,13 @@ mysql -u root -p ...@@ -114,13 +114,13 @@ mysql -u root -p
# Convert all tables to use the InnoDB storage engine (added in GitLab 6.8) # 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'; 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 # Convert all tables to correct character set
SET foreign_key_checks = 0; 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'; 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 # turn foreign key checks back on
SET foreign_key_checks = 1; SET foreign_key_checks = 1;
......
...@@ -37,7 +37,7 @@ sudo -u git -H git checkout 7-7-stable-ee ...@@ -37,7 +37,7 @@ sudo -u git -H git checkout 7-7-stable-ee
```bash ```bash
cd /home/git/gitlab-shell cd /home/git/gitlab-shell
sudo -u git -H git fetch 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. ### 4. Install libs, migrations, etc.
...@@ -101,8 +101,8 @@ If all items are green, then congratulations upgrade is complete! ...@@ -101,8 +101,8 @@ If all items are green, then congratulations upgrade is complete!
### 8. GitHub settings (if applicable) ### 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 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/`) only contains a root URL (ex. `https://gitlab.example.com/`)
## Things went south? Revert to previous version (7.6) ## Things went south? Revert to previous version (7.6)
......
...@@ -17,4 +17,4 @@ Depending on the installation method and your GitLab version, there are multiple ...@@ -17,4 +17,4 @@ Depending on the installation method and your GitLab version, there are multiple
## Miscellaneous ## 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.
...@@ -11,3 +11,4 @@ ...@@ -11,3 +11,4 @@
- [Migrating from SVN to GitLab](migrating_from_svn.md) - [Migrating from SVN to GitLab](migrating_from_svn.md)
- [Project importing from GitHub to GitLab](import_projects_from_github.md) - [Project importing from GitHub to GitLab](import_projects_from_github.md)
- [Protected branches](protected_branches.md) - [Protected branches](protected_branches.md)
- [Web Editor](web_editor.md)
...@@ -43,7 +43,7 @@ Since most tools automatically make the master branch the default one and displa ...@@ -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. 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. 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. 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. 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. 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. 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 ...@@ -95,12 +95,12 @@ An 'extreme' version of environment branches are setting up an environment for e
## Release branches with GitLab flow ## 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. 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.). 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. 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. 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. 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. 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 ...@@ -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. And the merge request shows the linked issues.
These issues are closed once code is merged into the default branch. 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. 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.
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
SVN stands for Subversion and is a version control system (VCS). SVN stands for Subversion and is a version control system (VCS).
Git is a distributed version control system. 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 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). [git documentation pages](http://git-scm.com/book/en/Git-and-Other-Systems-Git-and-Subversion).
......
...@@ -24,14 +24,14 @@ Each of these settings have levels of notification: ...@@ -24,14 +24,14 @@ Each of these settings have levels of notification:
#### Global Settings #### Global Settings
Global Settings are at the bottom of the hierarchy. 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 Group or Project settings can use `global` notification setting which will then use
anything that is set at Global Settings. anything that is set at Global Settings.
#### Group 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 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. 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 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. ...@@ -39,7 +39,7 @@ same need for being notified for every group they are member of.
#### Project Settings #### 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. other setting.
This is suitable for users that have different needs for notifications per project basis. This is suitable for users that have different needs for notifications per project basis.
......
# 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)
...@@ -11,7 +11,7 @@ RUN apt-get update -q \ ...@@ -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 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. # If you run GitLab Enterprise Edition point it to a location where you have downloaded it.
RUN TMP_FILE=$(mktemp); \ 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 \ && dpkg -i $TMP_FILE \
&& rm -f $TMP_FILE && rm -f $TMP_FILE
......
...@@ -34,7 +34,7 @@ Feature: Project Source Browse Files ...@@ -34,7 +34,7 @@ Feature: Project Source Browse Files
Then I am redirected to the new file Then I am redirected to the new file
And I should see its new content And I should see its new content
@javascript @javascript @tricky
Scenario: I can create file in empty repo Scenario: I can create file in empty repo
Given I own an empty project Given I own an empty project
And I visit my empty project page And I visit my empty project page
......
...@@ -13,15 +13,15 @@ Feature: Search ...@@ -13,15 +13,15 @@ Feature: Search
And project has issues And project has issues
When I search for "Foo" When I search for "Foo"
And I click "Issues" link And I click "Issues" link
Then I should see "Foo" link Then I should see "Foo" link in the search results
And I should not see "Bar" link And I should not see "Bar" link in the search results
Scenario: I should see merge requests I am looking for Scenario: I should see merge requests I am looking for
And project has merge requests And project has merge requests
When I search for "Foo" When I search for "Foo"
When I click "Merge requests" link When I click "Merge requests" link
Then I should see "Foo" link Then I should see "Foo" link in the search results
And I should not see "Bar" link And I should not see "Bar" link in the search results
Scenario: I should see project code I am looking for Scenario: I should see project code I am looking for
When I click project "Shop" link When I click project "Shop" link
...@@ -33,14 +33,14 @@ Feature: Search ...@@ -33,14 +33,14 @@ Feature: Search
When I click project "Shop" link When I click project "Shop" link
And I search for "Foo" And I search for "Foo"
And I click "Issues" link And I click "Issues" link
Then I should see "Foo" link Then I should see "Foo" link in the search results
And I should not see "Bar" link And I should not see "Bar" link in the search results
Scenario: I should see project merge requests Scenario: I should see project merge requests
And project has merge requests And project has merge requests
When I click project "Shop" link When I click project "Shop" link
And I search for "Foo" And I search for "Foo"
And I click "Merge requests" link And I click "Merge requests" link
Then I should see "Foo" link Then I should see "Foo" link in the search results
And I should not see "Bar" link And I should not see "Bar" link in the search results
...@@ -41,7 +41,7 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps ...@@ -41,7 +41,7 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
within "#new_team_member" do within "#new_team_member" do
select "Reporter", from: "access_level" select "Reporter", from: "access_level"
end end
click_button "Add users into group" click_button "Add users to group"
end end
step 'I should see "John Doe" in team list in every project as "Reporter"' do step 'I should see "John Doe" in team list in every project as "Reporter"' do
......
...@@ -34,7 +34,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -34,7 +34,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
select2(user.id, from: "#user_ids", multiple: true) select2(user.id, from: "#user_ids", multiple: true)
select "Reporter", from: "access_level" select "Reporter", from: "access_level"
end end
click_button "Add users into group" click_button "Add users to group"
end end
step 'I should see user "John Doe" in team list' do step 'I should see user "John Doe" in team list' do
......
...@@ -59,11 +59,11 @@ class Spinach::Features::Search < Spinach::FeatureSteps ...@@ -59,11 +59,11 @@ class Spinach::Features::Search < Spinach::FeatureSteps
create(:merge_request, :simple, title: "Bar", source_project: project, target_project: project) create(:merge_request, :simple, title: "Bar", source_project: project, target_project: project)
end end
step 'I should see "Foo" link' do step 'I should see "Foo" link in the search results' do
page.should have_link "Foo" find(:css, '.search-results').should have_link 'Foo'
end end
step 'I should not see "Bar" link' do step 'I should not see "Bar" link in the search results' do
page.should_not have_link "Bar" find(:css, '.search-results').should_not have_link 'Bar'
end end
end end
...@@ -6,7 +6,7 @@ module API ...@@ -6,7 +6,7 @@ module API
version 'v3', using: :path version 'v3', using: :path
rescue_from ActiveRecord::RecordNotFound do rescue_from ActiveRecord::RecordNotFound do
rack_response({'message' => '404 Not found'}.to_json, 404) rack_response({ 'message' => '404 Not found' }.to_json, 404)
end end
rescue_from :all do |exception| rescue_from :all do |exception|
...@@ -19,7 +19,7 @@ module API ...@@ -19,7 +19,7 @@ module API
message << " " << trace.join("\n ") message << " " << trace.join("\n ")
API.logger.add Logger::FATAL, message API.logger.add Logger::FATAL, message
rack_response({'message' => '500 Internal Server Error'}, 500) rack_response({ 'message' => '500 Internal Server Error' }, 500)
end end
format :json format :json
......
...@@ -47,16 +47,12 @@ module APIGuard ...@@ -47,16 +47,12 @@ module APIGuard
case validate_access_token(access_token, scopes) case validate_access_token(access_token, scopes)
when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
raise InsufficientScopeError.new(scopes) raise InsufficientScopeError.new(scopes)
when Oauth2::AccessTokenValidationService::EXPIRED when Oauth2::AccessTokenValidationService::EXPIRED
raise ExpiredError raise ExpiredError
when Oauth2::AccessTokenValidationService::REVOKED when Oauth2::AccessTokenValidationService::REVOKED
raise RevokedError raise RevokedError
when Oauth2::AccessTokenValidationService::VALID when Oauth2::AccessTokenValidationService::VALID
@current_user = User.find(access_token.resource_owner_id) @current_user = User.find(access_token.resource_owner_id)
end end
end end
end end
...@@ -120,8 +116,9 @@ module APIGuard ...@@ -120,8 +116,9 @@ module APIGuard
end end
def oauth2_bearer_token_error_handler def oauth2_bearer_token_error_handler
Proc.new {|e| Proc.new do |e|
response = case e response =
case e
when MissingTokenError when MissingTokenError
Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new
...@@ -146,11 +143,11 @@ module APIGuard ...@@ -146,11 +143,11 @@ module APIGuard
Rack::OAuth2::Server::Resource::Bearer::Forbidden.new( Rack::OAuth2::Server::Resource::Bearer::Forbidden.new(
:insufficient_scope, :insufficient_scope,
Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION[:insufficient_scope], Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION[:insufficient_scope],
{ :scope => e.scopes}) { scope: e.scopes })
end end
response.finish response.finish
} end
end end
end end
......
...@@ -60,7 +60,7 @@ module API ...@@ -60,7 +60,7 @@ module API
expose :path, :path_with_namespace expose :path, :path_with_namespace
expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at
expose :namespace 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 end
class ProjectMember < UserBasic class ProjectMember < UserBasic
...@@ -157,6 +157,11 @@ module API ...@@ -157,6 +157,11 @@ module API
expose :state, :created_at, :updated_at expose :state, :created_at, :updated_at
end 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 class Milestone < ProjectEntity
expose :due_date expose :due_date
end end
...@@ -176,6 +181,12 @@ module API ...@@ -176,6 +181,12 @@ module API
expose :milestone, using: Entities::Milestone expose :milestone, using: Entities::Milestone
end end
class MergeRequestChanges < MergeRequest
expose :diffs, as: :changes, using: Entities::RepoDiff do |compare, _|
compare.diffs
end
end
class SSHKey < Grape::Entity class SSHKey < Grape::Entity
expose :id, :title, :key, :created_at expose :id, :title, :key, :created_at
end end
...@@ -254,11 +265,6 @@ module API ...@@ -254,11 +265,6 @@ module API
expose :name, :color expose :name, :color
end 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 class Compare < Grape::Entity
expose :commit, using: Entities::RepoCommit do |compare, options| expose :commit, using: Entities::RepoCommit do |compare, options|
Commit.decorate(compare.commits).last Commit.decorate(compare.commits).last
......
...@@ -3,22 +3,6 @@ module API ...@@ -3,22 +3,6 @@ module API
before { authenticate! } before { authenticate! }
resource :groups do 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. # Get a list of group members viewable by the authenticated user.
# #
# Example Request: # Example Request:
......
...@@ -4,22 +4,6 @@ module API ...@@ -4,22 +4,6 @@ module API
before { authenticate! } before { authenticate! }
resource :groups do 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 # Get a groups list
# #
# Example Request: # Example Request:
......
...@@ -55,6 +55,21 @@ module API ...@@ -55,6 +55,21 @@ module API
end end
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) def paginate(relation)
per_page = params[:per_page].to_i per_page = params[:per_page].to_i
paginated = relation.page(params[:page]).per(per_page) paginated = relation.page(params[:page]).per(per_page)
...@@ -135,10 +150,16 @@ module API ...@@ -135,10 +150,16 @@ module API
errors errors
end end
def validate_access_level?(level)
Gitlab::Access.options_with_owner.values.include? level.to_i
end
# error helpers # error helpers
def forbidden! def forbidden!(reason = nil)
render_api_error!('403 Forbidden', 403) message = ['403 Forbidden']
message << " - #{reason}" if reason
render_api_error!(message.join(' '), 403)
end end
def bad_request!(attribute) def bad_request!(attribute)
...@@ -173,7 +194,7 @@ module API ...@@ -173,7 +194,7 @@ module API
end end
def render_api_error!(message, status) def render_api_error!(message, status)
error!({'message' => message}, status) error!({ 'message' => message }, status)
end end
private private
......
module API module API
# Internal access API # Internal access API
class Internal < Grape::API class Internal < Grape::API
before { before { authenticate_by_gitlab_shell_token! }
authenticate_by_gitlab_shell_token!
}
namespace 'internal' do namespace 'internal' do
# Check if git command is allowed to project # Check if git command is allowed to project
......
...@@ -75,6 +75,22 @@ module API ...@@ -75,6 +75,22 @@ module API
present merge_request, with: Entities::MergeRequest present merge_request, with: Entities::MergeRequest
end 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 # Create MR
# #
# Parameters: # Parameters:
......
module API module API
# namespaces API # namespaces API
class Namespaces < Grape::API class Namespaces < Grape::API
before { before do
authenticate! authenticate!
authenticated_as_admin! authenticated_as_admin!
} end
resource :namespaces do resource :namespaces do
# Get a namespaces list # Get a namespaces list
......
...@@ -110,7 +110,7 @@ module API ...@@ -110,7 +110,7 @@ module API
unless team_member.nil? unless team_member.nil?
team_member.destroy team_member.destroy
else else
{message: "Access revoked", id: params[:user_id].to_i} { message: "Access revoked", id: params[:user_id].to_i }
end end
end end
end end
......
module API module API
# Hooks API # Hooks API
class SystemHooks < Grape::API class SystemHooks < Grape::API
before { before do
authenticate! authenticate!
authenticated_as_admin! authenticated_as_admin!
} end
resource :hooks do resource :hooks do
# Get the list of system hooks # Get the list of system hooks
......
...@@ -11,6 +11,11 @@ module Gitlab ...@@ -11,6 +11,11 @@ module Gitlab
MASTER = 40 MASTER = 40
OWNER = 50 OWNER = 50
# Branch protection settings
PROTECTION_NONE = 0
PROTECTION_DEV_CAN_PUSH = 1
PROTECTION_FULL = 2
class << self class << self
def values def values
options.values options.values
...@@ -43,6 +48,18 @@ module Gitlab ...@@ -43,6 +48,18 @@ module Gitlab
master: MASTER, master: MASTER,
} }
end 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 end
def human_access def human_access
......
...@@ -154,7 +154,7 @@ module Grack ...@@ -154,7 +154,7 @@ module Grack
end end
def render_not_found def render_not_found
[404, {"Content-Type" => "text/plain"}, ["Not Found"]] [404, { "Content-Type" => "text/plain" }, ["Not Found"]]
end end
end end
end end
...@@ -9,4 +9,3 @@ module Gitlab ...@@ -9,4 +9,3 @@ module Gitlab
end end
end end
end end
...@@ -2,15 +2,15 @@ module Gitlab ...@@ -2,15 +2,15 @@ module Gitlab
class CommitsCalendar class CommitsCalendar
attr_reader :timestamps attr_reader :timestamps
def initialize(repositories, user) def initialize(projects, user)
@timestamps = {} @timestamps = {}
date_timestamps = [] date_timestamps = []
repositories.select(&:exists?).reject(&:empty?).each do |raw_repository| projects.reject(&:forked?).each do |project|
commits_log = raw_repository.commits_per_day_for_user(user) date_timestamps << ProjectContributions.new(project, user).commits_log
date_timestamps << commits_log
end end
# Sumarrize commits from all projects per days
date_timestamps = date_timestamps.inject do |collection, date| date_timestamps = date_timestamps.inject do |collection, date|
collection.merge(date) { |k, old_v, new_v| old_v + new_v } collection.merge(date) { |k, old_v, new_v| old_v + new_v }
end end
...@@ -21,5 +21,13 @@ module Gitlab ...@@ -21,5 +21,13 @@ module Gitlab
@timestamps[timestamp] = commits if timestamp @timestamps[timestamp] = commits if timestamp
end end
end end
def starting_year
(Time.now - 1.year).strftime("%Y")
end
def starting_month
Date.today.strftime("%m").to_i
end
end end
end end
...@@ -12,6 +12,7 @@ module Gitlab ...@@ -12,6 +12,7 @@ module Gitlab
def fake_application_settings def fake_application_settings
OpenStruct.new( OpenStruct.new(
default_projects_limit: Settings.gitlab['default_projects_limit'], default_projects_limit: Settings.gitlab['default_projects_limit'],
default_branch_protection: Settings.gitlab['default_branch_protection'],
signup_enabled: Settings.gitlab['signup_enabled'], signup_enabled: Settings.gitlab['signup_enabled'],
signin_enabled: Settings.gitlab['signin_enabled'], signin_enabled: Settings.gitlab['signin_enabled'],
gravatar_enabled: Settings.gravatar['enabled'], gravatar_enabled: Settings.gravatar['enabled'],
......
...@@ -4,7 +4,7 @@ module Gitlab ...@@ -4,7 +4,7 @@ module Gitlab
include Enumerable include Enumerable
def parse(lines) def parse(lines)
@lines = lines, @lines = lines
lines_obj = [] lines_obj = []
line_obj_index = 0 line_obj_index = 0
line_old = 1 line_old = 1
......
...@@ -12,4 +12,3 @@ module Gitlab ...@@ -12,4 +12,3 @@ module Gitlab
end end
end end
end end
...@@ -180,8 +180,8 @@ module Gitlab ...@@ -180,8 +180,8 @@ module Gitlab
# we dont allow force push to protected branch # we dont allow force push to protected branch
if forced_push?(project, oldrev, newrev) if forced_push?(project, oldrev, newrev)
:force_push_code_to_protected_branches :force_push_code_to_protected_branches
# and we dont allow remove of protected branch
elsif newrev == Gitlab::Git::BLANK_SHA elsif newrev == Gitlab::Git::BLANK_SHA
# and we dont allow remove of protected branch
:remove_protected_branches :remove_protected_branches
elsif project.developers_can_push_to_protected_branch?(branch_name) elsif project.developers_can_push_to_protected_branch?(branch_name)
:push_code :push_code
......
...@@ -9,7 +9,7 @@ module Gitlab ...@@ -9,7 +9,7 @@ module Gitlab
end end
def to_json def to_json
{status: @status, message: @message}.to_json { status: @status, message: @message }.to_json
end end
end end
end end
...@@ -36,7 +36,7 @@ module Gitlab ...@@ -36,7 +36,7 @@ module Gitlab
def octo_client(access_token) def octo_client(access_token)
::Octokit.auto_paginate = true ::Octokit.auto_paginate = true
::Octokit::Client.new(:access_token => access_token) ::Octokit::Client.new(access_token: access_token)
end end
def gl_user_id(project, github_id) def gl_user_id(project, github_id)
......
...@@ -180,5 +180,3 @@ module Gitlab ...@@ -180,5 +180,3 @@ module Gitlab
end end
end end
end end
...@@ -87,8 +87,10 @@ module Gitlab ...@@ -87,8 +87,10 @@ module Gitlab
end end
def dn_matches_filter?(dn, filter) def dn_matches_filter?(dn, filter)
ldap_search(base: dn, filter: filter, ldap_search(base: dn,
scope: Net::LDAP::SearchScope_BaseObject, attributes: %w{dn}).any? filter: filter,
scope: Net::LDAP::SearchScope_BaseObject,
attributes: %w{dn}).any?
end end
def ldap_search(*args) def ldap_search(*args)
......
...@@ -40,12 +40,16 @@ module Gitlab ...@@ -40,12 +40,16 @@ module Gitlab
def update_user_attributes def update_user_attributes
gl_user.email = auth_hash.email 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 gl_user
end end
def changed? def changed?
gl_user.changed? gl_user.changed? || gl_user.identities.any?(&:changed?)
end end
def needs_blocking? def needs_blocking?
......
...@@ -44,7 +44,7 @@ module Gitlab ...@@ -44,7 +44,7 @@ module Gitlab
end end
def default_options(options = {}) def default_options(options = {})
{raise: true, timeout: true}.merge(options) { raise: true, timeout: true }.merge(options)
end end
def handle_exception(exception) def handle_exception(exception)
......
...@@ -13,7 +13,7 @@ module Gitlab ...@@ -13,7 +13,7 @@ module Gitlab
prepare_satellite!(repo) prepare_satellite!(repo)
# create target branch in satellite at the corresponding commit from bare 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 # update the file in the satellite's working dir
file_path_in_satellite = File.join(repo.working_dir, file_path) file_path_in_satellite = File.join(repo.working_dir, file_path)
...@@ -36,7 +36,7 @@ module Gitlab ...@@ -36,7 +36,7 @@ module Gitlab
# push commit back to bare repo # push commit back to bare repo
# will raise CommandFailed when push fails # 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 # everything worked
true true
......
...@@ -15,7 +15,7 @@ module Gitlab ...@@ -15,7 +15,7 @@ module Gitlab
prepare_satellite!(repo) prepare_satellite!(repo)
# create target branch in satellite at the corresponding commit from bare 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 # update the file in the satellite's working dir
file_path_in_satellite = File.join(repo.working_dir, file_path) file_path_in_satellite = File.join(repo.working_dir, file_path)
...@@ -36,7 +36,7 @@ module Gitlab ...@@ -36,7 +36,7 @@ module Gitlab
# push commit back to bare repo # push commit back to bare repo
# will raise CommandFailed when push fails # 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 # everything worked
true true
......
...@@ -19,7 +19,7 @@ module Gitlab ...@@ -19,7 +19,7 @@ module Gitlab
# skip this step if we want to add first file to empty repo # skip this step if we want to add first file to empty repo
Satellite::PARKING_BRANCH Satellite::PARKING_BRANCH
else 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 ref
end end
...@@ -47,7 +47,7 @@ module Gitlab ...@@ -47,7 +47,7 @@ module Gitlab
# push commit back to bare repo # push commit back to bare repo
# will raise CommandFailed when push fails # 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 # everything worked
true true
......
...@@ -96,7 +96,7 @@ module Gitlab ...@@ -96,7 +96,7 @@ module Gitlab
in_locked_and_timed_satellite do |merge_repo| in_locked_and_timed_satellite do |merge_repo|
prepare_satellite!(merge_repo) prepare_satellite!(merge_repo)
update_satellite_source_and_target!(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 end
rescue Grit::Git::CommandFailed => ex rescue Grit::Git::CommandFailed => ex
handle_exception(ex) handle_exception(ex)
...@@ -138,7 +138,7 @@ module Gitlab ...@@ -138,7 +138,7 @@ module Gitlab
# merge the source branch into the satellite # merge the source branch into the satellite
# will raise CommandFailed when merge fails # 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 rescue Grit::Git::CommandFailed => ex
handle_exception(ex) handle_exception(ex)
end end
...@@ -159,7 +159,7 @@ module Gitlab ...@@ -159,7 +159,7 @@ module Gitlab
# git push remote master # git push remote master
def rebase_in_satellite!(repo) def rebase_in_satellite!(repo)
update_satellite_source_and_target!(repo) update_satellite_source_and_target!(repo)
repo.git.checkout(default_options({b: true}), merge_request.source_branch, "source/#{merge_request.source_branch}") repo.git.checkout(default_options({ b: true }), merge_request.source_branch, "source/#{merge_request.source_branch}")
output, status = popen(%W(git pull --rebase origin #{merge_request.target_branch}), repo.working_dir) output, status = popen(%W(git pull --rebase origin #{merge_request.target_branch}), repo.working_dir)
if status == 0 if status == 0
...@@ -181,7 +181,7 @@ module Gitlab ...@@ -181,7 +181,7 @@ module Gitlab
def update_satellite_source_and_target!(repo) def update_satellite_source_and_target!(repo)
repo.remote_add('source', merge_request.source_project.repository.path_to_repo) repo.remote_add('source', merge_request.source_project.repository.path_to_repo)
repo.remote_fetch('source') 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 rescue Grit::Git::CommandFailed => ex
handle_exception(ex) handle_exception(ex)
end end
......
...@@ -98,13 +98,13 @@ module Gitlab ...@@ -98,13 +98,13 @@ module Gitlab
if heads.include? PARKING_BRANCH if heads.include? PARKING_BRANCH
repo.git.checkout({}, PARKING_BRANCH) repo.git.checkout({}, PARKING_BRANCH)
else else
repo.git.checkout(default_options({b: true}), PARKING_BRANCH) repo.git.checkout(default_options({ b: true }), PARKING_BRANCH)
end end
# remove the parking branch from the list of heads ... # remove the parking branch from the list of heads ...
heads.delete(PARKING_BRANCH) heads.delete(PARKING_BRANCH)
# ... and delete all others # ... 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 end
# Deletes all remotes except origin # Deletes all remotes except origin
...@@ -126,7 +126,7 @@ module Gitlab ...@@ -126,7 +126,7 @@ module Gitlab
end end
def default_options(options = {}) def default_options(options = {})
{raise: true, timeout: true}.merge(options) { raise: true, timeout: true }.merge(options)
end end
# Create directory for storing # Create directory for storing
......
...@@ -62,7 +62,7 @@ module Gitlab ...@@ -62,7 +62,7 @@ module Gitlab
end end
def env def env
{'RAILS_ENV' => 'production'} { 'RAILS_ENV' => 'production' }
end end
def upgrade def upgrade
......
# 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
...@@ -39,7 +39,7 @@ upstream gitlab { ...@@ -39,7 +39,7 @@ upstream gitlab {
## Redirects all HTTP traffic to the HTTPS host ## Redirects all HTTP traffic to the HTTPS host
server { server {
listen 0.0.0.0:80; 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_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 server_tokens off; ## Don't show the nginx version number, a security best practice
return 301 https://$server_name$request_uri; return 301 https://$server_name$request_uri;
...@@ -51,7 +51,7 @@ server { ...@@ -51,7 +51,7 @@ server {
## HTTPS host ## HTTPS host
server { server {
listen 0.0.0.0:443 ssl; 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_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 server_tokens off; ## Don't show the nginx version number, a security best practice
root /home/git/gitlab/public; root /home/git/gitlab/public;
......
...@@ -2,6 +2,7 @@ namespace :gitlab do ...@@ -2,6 +2,7 @@ namespace :gitlab do
desc "GITLAB | Run all tests" desc "GITLAB | Run all tests"
task :test do task :test do
cmds = [ cmds = [
%W(rake rubocop),
%W(rake spinach), %W(rake spinach),
%W(rake spec), %W(rake spec),
%W(rake jasmine:ci) %W(rake jasmine:ci)
......
unless Rails.env.production?
require 'rubocop/rake_task'
RuboCop::RakeTask.new
end
...@@ -2,9 +2,15 @@ Rake::Task["spinach"].clear if Rake::Task.task_defined?('spinach') ...@@ -2,9 +2,15 @@ Rake::Task["spinach"].clear if Rake::Task.task_defined?('spinach')
desc "GITLAB | Run spinach" desc "GITLAB | Run spinach"
task :spinach do task :spinach do
tags = if ENV['SEMAPHORE']
'~@tricky'
else
'~@semaphore'
end
cmds = [ cmds = [
%W(rake gitlab:setup), %W(rake gitlab:setup),
%W(spinach), %W(spinach --tags #{tags}),
] ]
run_commands(cmds) run_commands(cmds)
end end
......
...@@ -9,5 +9,5 @@ unless Rails.env.production? ...@@ -9,5 +9,5 @@ unless Rails.env.production?
require 'coveralls/rake/task' require 'coveralls/rake/task'
Coveralls::RakeTask.new Coveralls::RakeTask.new
desc "GITLAB | Run all tests on CI with simplecov" 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 end
...@@ -70,4 +70,13 @@ describe Projects::CommitController do ...@@ -70,4 +70,13 @@ describe Projects::CommitController do
end end
end 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 end
...@@ -9,18 +9,18 @@ describe UsersController do ...@@ -9,18 +9,18 @@ describe UsersController do
describe "GET #show" do describe "GET #show" do
render_views render_views
before do
get :show, username: user.username
end
it "renders the show template" do it "renders the show template" do
get :show, username: user.username
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(response).to render_template("show") expect(response).to render_template("show")
end end
end
describe "GET #calendar" do
it "renders calendar" do it "renders calendar" do
controller.prepend_view_path 'app/views/users' get :calendar, username: user.username
expect(response).to render_template("_calendar") expect(response).to render_template("calendar")
end end
end end
end end
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
# star_count :integer default(0), not null # star_count :integer default(0), not null
# import_type :string(255) # import_type :string(255)
# import_source :string(255) # import_source :string(255)
# avatar :string(255)
# #
FactoryGirl.define do FactoryGirl.define do
......
...@@ -6,7 +6,7 @@ describe 'Help Pages', feature: true do ...@@ -6,7 +6,7 @@ describe 'Help Pages', feature: true do
login_as :user login_as :user
end end
it 'replace the variable $your_email with the email of the user' do 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}\"") page.should have_content("ssh-keygen -t rsa -C \"#{@user.email}\"")
end end
end end
......
...@@ -65,7 +65,7 @@ describe "Issues", feature: true do ...@@ -65,7 +65,7 @@ describe "Issues", feature: true do
click_button "Save changes" click_button "Save changes"
page.should have_content "Assignee: Select assignee" page.should have_content 'Assignee: none'
issue.reload.assignee.should be_nil issue.reload.assignee.should be_nil
end end
end end
...@@ -249,6 +249,7 @@ describe "Issues", feature: true do ...@@ -249,6 +249,7 @@ describe "Issues", feature: true do
click_button 'Update Issue' click_button 'Update Issue'
page.should have_content "Milestone changed to #{milestone.title}" page.should have_content "Milestone changed to #{milestone.title}"
page.should have_content "Milestone: #{milestone.title}"
has_select?('issue_assignee_id', :selected => milestone.title) has_select?('issue_assignee_id', :selected => milestone.title)
end end
end end
...@@ -287,7 +288,7 @@ describe "Issues", feature: true do ...@@ -287,7 +288,7 @@ describe "Issues", feature: true do
sleep 2 # wait for ajax stuff to complete sleep 2 # wait for ajax stuff to complete
first('.user-result').click first('.user-result').click
page.should have_content "Assignee: Unassigned" page.should have_content 'Assignee: none'
sleep 2 # wait for ajax stuff to complete sleep 2 # wait for ajax stuff to complete
issue.reload.assignee.should be_nil issue.reload.assignee.should be_nil
end end
......
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
require 'spec_helper' require 'spec_helper'
describe NotificationsHelper do describe NotificationsHelper do
include FontAwesome::Rails::IconHelper
include IconsHelper
describe 'notification_icon' do describe 'notification_icon' do
let(:notification) { double(disabled?: false, participating?: false, watch?: false) } let(:notification) { double(disabled?: false, participating?: false, watch?: false) }
......
...@@ -13,6 +13,23 @@ describe Gitlab::LDAP::User do ...@@ -13,6 +13,23 @@ describe Gitlab::LDAP::User do
double(uid: 'my-uid', provider: 'ldapmain', info: double(info)) double(uid: 'my-uid', provider: 'ldapmain', info: double(info))
end 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 describe :find_or_create do
it "finds the user if already existing" do it "finds the user if already existing" do
existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain') existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain')
......
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
...@@ -161,8 +161,8 @@ describe Issue, 'Votes' do ...@@ -161,8 +161,8 @@ describe Issue, 'Votes' do
add_note '+1 I still like this' add_note '+1 I still like this'
add_note '+1 I really like this' add_note '+1 I really like this'
add_note '+1 Give me this now!!!!' add_note '+1 Give me this now!!!!'
p issue.downvotes.should == 0 issue.downvotes.should == 0
p issue.upvotes.should == 1 issue.upvotes.should == 1
end end
it 'should count a users vote only once without caring about comments' do it 'should count a users vote only once without caring about comments' do
...@@ -171,8 +171,8 @@ describe Issue, 'Votes' do ...@@ -171,8 +171,8 @@ describe Issue, 'Votes' do
add_note 'Another comment' add_note 'Another comment'
add_note '+1 vote' add_note '+1 vote'
add_note 'final comment' add_note 'final comment'
p issue.downvotes.should == 0 issue.downvotes.should == 0
p issue.upvotes.should == 1 issue.upvotes.should == 1
end end
end end
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# #
# id :integer not null, primary key # id :integer not null, primary key
# default_projects_limit :integer # default_projects_limit :integer
# default_branch_protection :integer
# signup_enabled :boolean # signup_enabled :boolean
# signin_enabled :boolean # signin_enabled :boolean
# gravatar_enabled :boolean # gravatar_enabled :boolean
......
...@@ -10,7 +10,7 @@ describe Member do ...@@ -10,7 +10,7 @@ describe Member do
it { should validate_presence_of(:user) } it { should validate_presence_of(:user) }
it { should validate_presence_of(:source) } 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 end
describe "Delegate methods" do describe "Delegate methods" do
......
# == 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' require 'spec_helper'
describe JiraService do describe JiraService do
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
# merge_requests_enabled :boolean default(TRUE), not null # merge_requests_enabled :boolean default(TRUE), not null
# wiki_enabled :boolean default(TRUE), not null # wiki_enabled :boolean default(TRUE), not null
# namespace_id :integer # namespace_id :integer
# issues_tracker :string(255) default('gitlab'), not null # issues_tracker :string(255) default("gitlab"), not null
# issues_tracker_id :string(255) # issues_tracker_id :string(255)
# snippets_enabled :boolean default(TRUE), not null # snippets_enabled :boolean default(TRUE), not null
# last_activity_at :datetime # last_activity_at :datetime
......
...@@ -80,6 +80,24 @@ describe API::API, api: true do ...@@ -80,6 +80,24 @@ describe API::API, api: true do
response.status.should == 404 response.status.should == 404
end end
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 end
describe "POST /groups" do describe "POST /groups" do
......
...@@ -114,6 +114,19 @@ describe API::API, api: true do ...@@ -114,6 +114,19 @@ describe API::API, api: true do
end end
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 describe "POST /projects/:id/merge_requests" do
context 'between branches projects' do context 'between branches projects' do
it "should return merge_request" do it "should return merge_request" do
......
...@@ -106,7 +106,25 @@ describe GitPushService do ...@@ -106,7 +106,25 @@ describe GitPushService do
it "when pushing a branch for the first time" do it "when pushing a branch for the first time" do
project.should_receive(:execute_hooks) project.should_receive(:execute_hooks)
project.default_branch.should == "master" 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') service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master')
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment