diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..7e800609e6c76c14893419965f1ce0ba400d9ace
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+CHANGELOG merge=union
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 2c6b65b7b7d7e258056bcfaa17945ac5135a4366..7a7b5c9393626f3d0cbc63b0d25ca84ec7a9feae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,42 +1,42 @@
+*.log
+*.swp
+.DS_Store
 .bundle
+.chef
+.directory
+.envrc
+.gitlab_shell_secret
+.idea
+.rbenv-version
 .rbx/
-db/*.sqlite3
-db/*.sqlite3-journal
-log/*.log*
-tmp/
-.sass-cache/
-coverage/*
-backups/*
-*.swp
-public/uploads/
-.ruby-version
 .ruby-gemset
+.ruby-version
 .rvmrc
-.rbenv-version
-.directory
-nohup.out
-Vagrantfile
+.sass-cache/
+.secret
 .vagrant
-config/gitlab.yml
+Vagrantfile
+backups/*
+config/aws.yml
 config/database.yml
+config/gitlab.yml
 config/initializers/omniauth.rb
 config/initializers/rack_attack.rb
 config/initializers/smtp_settings.rb
-config/unicorn.rb
 config/resque.yml
-config/aws.yml
+config/unicorn.rb
+coverage/*
+db/*.sqlite3
+db/*.sqlite3-journal
 db/data.yml
-.idea
-.DS_Store
-.chef
-vendor/bundle/*
-rails_best_practices_output.html
 doc/code/*
-.secret
-*.log
-public/uploads.*
-public/assets/
-.envrc
 dump.rdb
+log/*.log*
+nohup.out
+public/assets/
+public/uploads.*
+public/uploads/
+rails_best_practices_output.html
 tags
-.gitlab_shell_secret
+tmp/
+vendor/bundle/*
diff --git a/.pkgr.yml b/.pkgr.yml
index cf96e7916d8a34eb46a95ae1b909bffc1a01941e..8fc9fddf8f79d5f5dc391732879b307712d201cf 100644
--- a/.pkgr.yml
+++ b/.pkgr.yml
@@ -1,9 +1,12 @@
 user: git
 group: git
+services:
+  - postgres
 before_precompile: ./bin/pkgr_before_precompile.sh
 targets:
   debian-7: &wheezy
     build_dependencies:
+      - libkrb5-dev
       - libicu-dev
       - cmake
       - pkg-config
@@ -14,6 +17,7 @@ targets:
   ubuntu-12.04: *wheezy
   ubuntu-14.04:
     build_dependencies:
+      - libkrb5-dev
       - libicu-dev
       - cmake
       - pkg-config
@@ -23,6 +27,7 @@ targets:
       - git
   centos-6:
     build_dependencies:
+      - krb5-devel
       - libicu-devel
       - cmake
       - pkgconfig
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7290d627d2434a2cd10a81fce5fdbbf48ddb2114
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,1006 @@
+Style/AccessModifierIndentation:
+  Description: Check indentation of private/protected visibility modifiers.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-public-private-protected'
+  Enabled: true
+
+Style/AccessorMethodName:
+  Description: Check the naming of accessor methods for get_/set_.
+  Enabled: false
+
+Style/Alias:
+  Description: 'Use alias_method instead of alias.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#alias-method'
+  Enabled: true
+
+Style/AlignArray:
+  Description: >-
+                 Align the elements of an array literal if they span more than
+                 one line.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#align-multiline-arrays'
+  Enabled: true
+
+Style/AlignHash:
+  Description: >-
+                 Align the elements of a hash literal if they span more than
+                 one line.
+  Enabled: true
+
+Style/AlignParameters:
+  Description: >-
+                 Align the parameters of a method call if they span more
+                 than one line.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-double-indent'
+  Enabled: false
+
+Style/AndOr:
+  Description: 'Use &&/|| instead of and/or.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-and-or-or'
+  Enabled: false
+
+Style/ArrayJoin:
+  Description: 'Use Array#join instead of Array#*.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#array-join'
+  Enabled: false
+
+Style/AsciiComments:
+  Description: 'Use only ascii symbols in comments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-comments'
+  Enabled: true
+
+Style/AsciiIdentifiers:
+  Description: 'Use only ascii symbols in identifiers.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-identifiers'
+  Enabled: true
+
+Style/Attr:
+  Description: 'Checks for uses of Module#attr.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr'
+  Enabled: false
+
+Style/BeginBlock:
+  Description: 'Avoid the use of BEGIN blocks.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-BEGIN-blocks'
+  Enabled: true
+
+Style/BarePercentLiterals:
+  Description: 'Checks if usage of %() or %Q() matches configuration.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q-shorthand'
+  Enabled: false
+
+Style/BlockComments:
+  Description: 'Do not use block comments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-block-comments'
+  Enabled: false
+
+Style/BlockEndNewline:
+  Description: 'Put end statement of multiline block on its own line.'
+  Enabled: true
+
+Style/Blocks:
+  Description: >-
+                Avoid using {...} for multi-line blocks (multiline chaining is
+                always ugly).
+                Prefer {...} over do...end for single-line blocks.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks'
+  Enabled: true
+
+Style/BracesAroundHashParameters:
+  Description: 'Enforce braces style around hash parameters.'
+  Enabled: false
+
+Style/CaseEquality:
+  Description: 'Avoid explicit use of the case equality operator(===).'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-case-equality'
+  Enabled: false
+
+Style/CaseIndentation:
+  Description: 'Indentation of when in a case/when/[else/]end.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-when-to-case'
+  Enabled: true
+
+Style/CharacterLiteral:
+  Description: 'Checks for uses of character literals.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-character-literals'
+  Enabled: true
+
+Style/ClassAndModuleCamelCase:
+  Description: 'Use CamelCase for classes and modules.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#camelcase-classes'
+  Enabled: true
+
+Style/ClassAndModuleChildren:
+  Description: 'Checks style of children classes and modules.'
+  Enabled: false
+
+Style/ClassCheck:
+  Description: 'Enforces consistent use of `Object#is_a?` or `Object#kind_of?`.'
+  Enabled: false
+
+Style/ClassMethods:
+  Description: 'Use self when defining module/class methods.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#def-self-singletons'
+  Enabled: false
+
+Style/ClassVars:
+  Description: 'Avoid the use of class variables.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-class-vars'
+  Enabled: true
+
+Style/ColonMethodCall:
+  Description: 'Do not use :: for method call.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#double-colons'
+  Enabled: false
+
+Style/CommentAnnotation:
+  Description: >-
+                 Checks formatting of special comments
+                 (TODO, FIXME, OPTIMIZE, HACK, REVIEW).
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#annotate-keywords'
+  Enabled: false
+
+Style/CommentIndentation:
+  Description: 'Indentation of comments.'
+  Enabled: true
+
+Style/ConstantName:
+  Description: 'Constants should use SCREAMING_SNAKE_CASE.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#screaming-snake-case'
+  Enabled: true
+
+Style/DefWithParentheses:
+  Description: 'Use def with parentheses when there are arguments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens'
+  Enabled: false
+
+Style/DeprecatedHashMethods:
+  Description: 'Checks for use of deprecated Hash methods.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-key'
+  Enabled: false
+
+Style/Documentation:
+  Description: 'Document classes and non-namespace modules.'
+  Enabled: false
+
+Style/DotPosition:
+  Description: 'Checks the position of the dot in multi-line method calls.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains'
+  Enabled: false
+
+Style/DoubleNegation:
+  Description: 'Checks for uses of double negation (!!).'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-bang-bang'
+  Enabled: false
+
+Style/EachWithObject:
+  Description: 'Prefer `each_with_object` over `inject` or `reduce`.'
+  Enabled: false
+
+Style/ElseAlignment:
+  Description: 'Align elses and elsifs correctly.'
+  Enabled: true
+
+Style/EmptyElse:
+  Description: 'Avoid empty else-clauses.'
+  Enabled: false
+
+Style/EmptyLineBetweenDefs:
+  Description: 'Use empty lines between defs.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#empty-lines-between-methods'
+  Enabled: false
+
+Style/EmptyLines:
+  Description: "Don't use several empty lines in a row."
+  Enabled: false
+
+Style/EmptyLinesAroundAccessModifier:
+  Description: "Keep blank lines around access modifiers."
+  Enabled: false
+
+Style/EmptyLinesAroundBlockBody:
+  Description: "Keeps track of empty lines around block bodies."
+  Enabled: false
+
+Style/EmptyLinesAroundClassBody:
+  Description: "Keeps track of empty lines around class bodies."
+  Enabled: false
+
+Style/EmptyLinesAroundModuleBody:
+  Description: "Keeps track of empty lines around module bodies."
+  Enabled: false
+
+Style/EmptyLinesAroundMethodBody:
+  Description: "Keeps track of empty lines around method bodies."
+  Enabled: false
+
+Style/EmptyLiteral:
+  Description: 'Prefer literals to Array.new/Hash.new/String.new.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#literal-array-hash'
+  Enabled: false
+
+Style/EndBlock:
+  Description: 'Avoid the use of END blocks.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-END-blocks'
+  Enabled: false
+
+Style/EndOfLine:
+  Description: 'Use Unix-style line endings.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#crlf'
+  Enabled: false
+
+Style/EvenOdd:
+  Description: 'Favor the use of Fixnum#even? && Fixnum#odd?'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods'
+  Enabled: false
+
+Style/FileName:
+  Description: 'Use snake_case for source file names.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-files'
+  Enabled: false
+
+Style/FlipFlop:
+  Description: 'Checks for flip flops'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-flip-flops'
+  Enabled: false
+
+Style/For:
+  Description: 'Checks use of for or each in multiline loops.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-for-loops'
+  Enabled: false
+
+Style/FormatString:
+  Description: 'Enforce the use of Kernel#sprintf, Kernel#format or String#%.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#sprintf'
+  Enabled: false
+
+Style/GlobalVars:
+  Description: 'Do not introduce global variables.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#instance-vars'
+  Enabled: false
+
+Style/GuardClause:
+  Description: 'Check for conditionals that can be replaced with guard clauses'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals'
+  Enabled: false
+
+Style/HashSyntax:
+  Description: >-
+                 Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax
+                 { :a => 1, :b => 2 }.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-literals'
+  Enabled: true
+
+Style/IfUnlessModifier:
+  Description: >-
+                 Favor modifier if/unless usage when you have a
+                 single-line body.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier'
+  Enabled: false
+
+Style/IfWithSemicolon:
+  Description: 'Do not use if x; .... Use the ternary operator instead.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-semicolon-ifs'
+  Enabled: false
+
+Style/IndentationConsistency:
+  Description: 'Keep indentation straight.'
+  Enabled: true
+
+Style/IndentationWidth:
+  Description: 'Use 2 spaces for indentation.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-indentation'
+  Enabled: true
+
+Style/IndentArray:
+  Description: >-
+                 Checks the indentation of the first element in an array
+                 literal.
+  Enabled: false
+
+Style/IndentHash:
+  Description: 'Checks the indentation of the first key in a hash literal.'
+  Enabled: false
+
+Style/InfiniteLoop:
+  Description: 'Use Kernel#loop for infinite loops.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#infinite-loop'
+  Enabled: false
+
+Style/Lambda:
+  Description: 'Use the new lambda literal syntax for single-line blocks.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#lambda-multi-line'
+  Enabled: false
+
+Style/LambdaCall:
+  Description: 'Use lambda.call(...) instead of lambda.(...).'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#proc-call'
+  Enabled: false
+
+Style/LeadingCommentSpace:
+  Description: 'Comments should start with a space.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-space'
+  Enabled: false
+
+Style/LineEndConcatenation:
+  Description: >-
+                 Use \ instead of + or << to concatenate two string literals at
+                 line end.
+  Enabled: false
+
+Style/MethodCallParentheses:
+  Description: 'Do not use parentheses for method calls with no arguments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-args-no-parens'
+  Enabled: false
+
+Style/MethodDefParentheses:
+  Description: >-
+                 Checks if the method definitions have or don't have
+                 parentheses.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens'
+  Enabled: false
+
+Style/MethodName:
+  Description: 'Use the configured style when naming methods.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars'
+  Enabled: false
+
+Style/ModuleFunction:
+  Description: 'Checks for usage of `extend self` in modules.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#module-function'
+  Enabled: false
+
+Style/MultilineBlockChain:
+  Description: 'Avoid multi-line chains of blocks.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks'
+  Enabled: false
+
+Style/MultilineBlockLayout:
+  Description: 'Ensures newlines after multiline block do statements.'
+  Enabled: true
+
+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: true
+
+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: true
+
+Style/NonNilCheck:
+  Description: 'Checks for redundant nil checks.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-non-nil-checks'
+  Enabled: true
+
+Style/Not:
+  Description: 'Use ! instead of not.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bang-not-not'
+  Enabled: true
+
+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: true
+
+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: true
+
+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: true
+
+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: true
+
+Lint/RequireParentheses:
+  Description: >-
+                 Use parentheses in the method call to avoid confusion
+                 about precedence.
+  Enabled: false
+
+Lint/RescueException:
+  Description: 'Avoid rescuing the Exception class.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-blind-rescues'
+  Enabled: false
+
+Lint/ShadowingOuterLocalVariable:
+  Description: >-
+                 Do not use the same name as outer local variable
+                 for block arguments or block local variables.
+  Enabled: false
+
+Lint/SpaceBeforeFirstArg:
+  Description: >-
+                 Put a space between a method name and the first argument
+                 in a method call without parentheses.
+  Enabled: false
+
+Lint/StringConversionInInterpolation:
+  Description: 'Checks for Object#to_s usage in string interpolation.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-to-s'
+  Enabled: false
+
+Lint/UnderscorePrefixedVariableName:
+  Description: 'Do not use prefix `_` for a variable that is used.'
+  Enabled: true
+
+Lint/UnusedBlockArgument:
+  Description: 'Checks for unused block arguments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars'
+  Enabled: false
+
+Lint/UnusedMethodArgument:
+  Description: 'Checks for unused method arguments.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars'
+  Enabled: false
+
+Lint/UnreachableCode:
+  Description: 'Unreachable code.'
+  Enabled: false
+
+Lint/UselessAccessModifier:
+  Description: 'Checks for useless access modifiers.'
+  Enabled: false
+
+Lint/UselessAssignment:
+  Description: 'Checks for useless assignment to a local variable.'
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars'
+  Enabled: false
+
+Lint/UselessComparison:
+  Description: 'Checks for comparison of something with itself.'
+  Enabled: false
+
+Lint/UselessElseWithoutRescue:
+  Description: 'Checks for useless `else` in `begin..end` without `rescue`.'
+  Enabled: false
+
+Lint/UselessSetterCall:
+  Description: 'Checks for useless setter call to a local variable.'
+  Enabled: false
+
+Lint/Void:
+  Description: 'Possible use of operator/literal/variable in void context.'
+  Enabled: false
+
+##################### Rails ##################################
+
+Rails/ActionFilter:
+  Description: 'Enforces consistent use of action filter methods.'
+  Enabled: false
+
+Rails/DefaultScope:
+  Description: 'Checks if the argument passed to default_scope is a block.'
+  Enabled: false
+
+Rails/Delegate:
+  Description: 'Prefer delegate method for delegations.'
+  Enabled: false
+
+Rails/HasAndBelongsToMany:
+  Description: 'Prefer has_many :through to has_and_belongs_to_many.'
+  Enabled: true
+
+Rails/Output:
+  Description: 'Checks for calls to puts, print, etc.'
+  Enabled: true
+
+Rails/ReadWriteAttribute:
+  Description: >-
+                 Checks for read_attribute(:attr) and
+                 write_attribute(:attr, val).
+  Enabled: false
+
+Rails/ScopeArgs:
+  Description: 'Checks the arguments of ActiveRecord scopes.'
+  Enabled: false
+
+Rails/Validation:
+  Description: 'Use validates :attribute, hash of validations.'
+  Enabled: false
+
+
+# Exclude some of GitLab files
+#
+#
+AllCops:
+  RunRailsCops: true
+  Exclude:
+    - 'spec/**/*'
+    - 'features/**/*'
+    - 'vendor/**/*'
+    - 'db/**/*'
+    - 'tmp/**/*'
+    - 'bin/**/*'
+    - 'lib/backup/**/*'
+    - 'lib/tasks/**/*'
+    - 'lib/email_validator.rb'
+    - 'lib/gitlab/upgrader.rb'
+    - 'lib/gitlab/seeder.rb'
diff --git a/.ruby-version b/.ruby-version
index ac2cdeba0137a6c2cbca06867b7ab994a913e294..cd57a8b95d6d1de42ed8ae15fa6c449ed7c9863c 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.1.3
+2.1.5
diff --git a/CHANGELOG b/CHANGELOG
index 3cd32a75dde923932d80de0a9d0c6f0a92f55e07..839dd0db10701182cadabb540abfe373617cfcf1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,335 @@
+Please view this file on the master branch, on stable branches it's out of date.
+
+v 7.10.0 (unreleased)
+  - Fix broken side-by-side diff view on merge request page (Stan Hu)
+  - Set Application controller default URL options to ensure all url_for calls are consistent (Stan Hu)
+  - Allow HTML tags in Markdown input
+  - Fix code unfold not working on Compare commits page (Stan Hu)
+  - Fix dots in Wiki slugs causing errors (Stan Hu)
+  - Update poltergeist to version 1.6.0 to support PhantomJS 2.0 (Zeger-Jan van de Weg)
+  - Fix cross references when usernames, milestones, or project names contain underscores (Stan Hu)
+  - Disable reference creation for comments surrounded by code/preformatted blocks (Stan Hu)
+  - Reduce Rack Attack false positives causing 403 errors during HTTP authentication (Stan Hu)
+  - enable line wrapping per default and remove the checkbox to toggle it (Hannes Rosenögger)
+  - extend the commit calendar to show the actual commits made on a date (Hannes Rosenögger)
+  - Fix a link in the patch update guide
+  - Add a service to support external wikis (Hannes Rosenögger)
+  - Omit the "email patches" link and fix plain diff view for merge commits
+  - List new commits for newly pushed branch in activity view.
+  - Add sidetiq gem dependency to match EE
+  - Add changelog, license and contribution guide links to project sidebar.
+  - Improve diff UI
+  - Fix alignment of navbar toggle button (Cody Mize)
+  - Fix checkbox rendering for nested task lists
+  - Identical look of selectboxes in UI
+  - Upgrade the gitlab_git gem to version 7.1.3
+  - Move "Import existing repository by URL" option to button.
+  - Improve error message when save profile has error.
+  - Passing the name of pushed ref to CI service (requires GitLab CI 7.9+)
+  - Add location field to user profile
+  - Fix print view for markdown files and wiki pages
+  - Fix errors when deleting old backups
+  - Improve GitLab performance when working with git repositories
+  - Add tag message and last commit to tag hook (Kamil Trzciński)
+  - Restrict permissions on backup files
+  - Improve oauth accounts UI in profile page
+  - Add ability to unlink connected accounts
+  - Replace commits calendar with faster contribution calendar that includes issues and merge requests
+  - Add inifinite scroll to user page activity
+  - Don't include system notes in issue/MR comment count.
+  - Don't mark merge request as updated when merge status relative to target branch changes.
+  - Link note avatar to user.
+  - Make Git-over-SSH errors more descriptive.
+  - Fix EmailsOnPush.
+  - Refactor issue filtering
+  - AJAX selectbox for issue assignee and author filters
+  - Fix issue with missing options in issue filtering dropdown if selected one
+  - Prevent holding Control-Enter or Command-Enter from posting comment multiple times.
+  - Prevent note form from being cleared when submitting failed.
+  - Improve file icons rendering on tree (Sullivan Sénéchal)
+  - API: Add pagination to project events
+
+v 7.9.0
+  - Send EmailsOnPush email when branch or tag is created or deleted.
+  - Faster merge request processing for large repository
+  - Prevent doubling AJAX request with each commit visit via Turbolink
+  - Prevent unnecessary doubling of js events on import pages and user calendar
+
+v 7.9.1
+  - Include missing events and fix save functionality in admin service template settings form (Stan Hu)
+  - Fix "Import projects from" button to show the correct instructions (Stan Hu)
+  - Fix OAuth2 issue importing a new project from GitHub and GitLab (Stan Hu)
+  - Fix for LDAP with commas in DN
+  - Fix missing events and in admin Slack service template settings form (Stan Hu)
+  - Don't show commit comment button when user is not signed in.
+  - Downgrade gemnasium-gitlab-service gem
+
+v 7.9.0
+  - Add HipChat integration documentation (Stan Hu)
+  - Update documentation for object_kind field in Webhook push and tag push Webhooks (Stan Hu)
+  - Fix broken email images (Hannes Rosenögger)
+  - Automatically config git if user forgot, where possible (Zeger-Jan van de Weg)
+  - Fix mass SQL statements on initial push (Hannes Rosenögger)
+  - Add tag push notifications and normalize HipChat and Slack messages to be consistent (Stan Hu)
+  - Add comment notification events to HipChat and Slack services (Stan Hu)
+  - Add issue and merge request events to HipChat and Slack services (Stan Hu)
+  - Fix merge request URL passed to Webhooks. (Stan Hu)
+  - Fix bug that caused a server error when editing a comment to "+1" or "-1" (Stan Hu)
+  - Fix code preview theme setting for comments, issues, merge requests, and snippets (Stan Hu)
+  - Move labels/milestones tabs to sidebar
+  - Upgrade Rails gem to version 4.1.9.
+  - Improve error messages for file edit failures
+  - Improve UI for commits, issues and merge request lists
+  - Fix commit comments on first line of diff not rendering in Merge Request Discussion view.
+  - Allow admins to override restricted project visibility settings.
+  - Move restricted visibility settings from gitlab.yml into the web UI.
+  - Improve trigger merge request hook when source project branch has been updated (Kirill Zaitsev)
+  - Save web edit in new branch
+  - Fix ordering of imported but unchanged projects (Marco Wessel)
+  - Mobile UI improvements: make aside content expandable
+  - Expose avatar_url in projects API
+  - Fix checkbox alignment on the application settings page.
+  - Generalize image upload in drag and drop in markdown to all files (Hannes Rosenögger)
+  - Fix mass-unassignment of issues (Robert Speicher)
+  - Fix hidden diff comments in merge request discussion view
+  - Allow user confirmation to be skipped for new users via API
+  - Add a service to send updates to an Irker gateway (Romain Coltel)
+  - Add brakeman (security scanner for Ruby on Rails)
+  - Slack username and channel options
+  - Add grouped milestones from all projects to dashboard.
+  - Web hook sends pusher email as well as commiter
+  - Add Bitbucket omniauth provider.
+  - Add Bitbucket importer.
+  - Support referencing issues to a project whose name starts with a digit
+  - Condense commits already in target branch when updating merge request source branch.
+  - Send notifications and leave system comments when bulk updating issues.
+  - Automatically link commit ranges to compare page: sha1...sha4 or sha1..sha4 (includes sha1 in comparison)
+  - Move groups page from profile to dashboard
+  - Starred projects page at dashboard
+  - Blocking user does not remove him/her from project/groups but show blocked label
+  - Change subject of EmailsOnPush emails to include namespace, project and branch.
+  - Change subject of EmailsOnPush emails to include first commit message when multiple were pushed.
+  - Remove confusing footer from EmailsOnPush mail body.
+  - Add list of changed files to EmailsOnPush emails.
+  - Add option to send EmailsOnPush emails from committer email if domain matches.
+  - Add option to disable code diffs in EmailOnPush emails.
+  - Wrap commit message in EmailsOnPush email.
+  - Send EmailsOnPush emails when deleting commits using force push.
+  - Fix EmailsOnPush email comparison link to include first commit.
+  - Fix highliht of selected lines in file
+  - Reject access to group/project avatar if the user doesn't have access.
+  - Add database migration to clean group duplicates with same path and name (Make sure you have a backup before update)
+  - Add GitLab active users count to rake gitlab:check
+  - Starred projects page at dashboard
+  - Make email display name configurable
+  - Improve json validation in hook data
+  - Use Emoji One
+  - Updated emoji help documentation to properly reference EmojiOne.
+  - Fix missing GitHub organisation repositories on import page.
+  - Added blue theme
+  - Remove annoying notice messages when create/update merge request
+  - Allow smb:// links in Markdown text.
+  - Filter merge request by title or description at Merge Requests page
+  - Block user if he/she was blocked in Active Directory
+  - Fix import pages not working after first load.
+  - Use custom LDAP label in LDAP signin form.
+  - Execute hooks and services when branch or tag is created or deleted through web interface.
+  - Block and unblock user if he/she was blocked/unblocked in Active Directory
+  - Raise recommended number of unicorn workers from 2 to 3
+  - Use same layout and interactivity for project members as group members.
+  - Prevent gitlab-shell character encoding issues by receiving its changes as raw data.
+  - Ability to unsubscribe/subscribe to issue or merge request
+  - Delete deploy key when last connection to a project is destroyed.
+  - Fix invalid Atom feeds when using emoji, horizontal rules, or images (Christian Walther)
+  - Backup of repositories with tar instead of git bundle (only now are git-annex files included in the backup)
+  - Add canceled status for CI
+
+v 7.8.4
+  - Fix issue_tracker_id substitution in custom issue trackers
+  - Fix path and name duplication in namespaces
+
+v 7.8.3
+  - Bump version of gitlab_git fixing annotated tags without message
+
+v 7.8.2
+  - Fix service migration issue when upgrading from versions prior to 7.3
+  - Fix setting of the default use project limit via admin UI
+  - Fix showing of already imported projects for GitLab and Gitorious importers
+  - Fix response of push to repository to return "Not found" if user doesn't have access
+  - Fix check if user is allowed to view the file attachment
+  - Fix import check for case sensetive namespaces
+  - Increase timeout for Git-over-HTTP requests to 1 hour since large pulls/pushes can take a long time.
+  - Properly handle autosave local storage exceptions.
+  - Escape wildcards when searching LDAP by username.
+
+v 7.8.1
+  - Fix run of custom post receive hooks
+  - Fix migration that caused issues when upgrading to version 7.8 from versions prior to 7.3
+  - Fix the warning for LDAP users about need to set password
+  - Fix avatars which were not shown for non logged in users
+  - Fix urls for the issues when relative url was enabled
+
+v 7.8.0
+  - Fix access control and protection against XSS for note attachments and other uploads.
+  - Replace highlight.js with rouge-fork rugments (Stefan Tatschner)
+  - Make project search case insensitive (Hannes Rosenögger)
+  - Include issue/mr participants in list of recipients for reassign/close/reopen emails
+  - Expose description in groups API
+  - Better UI for project services page
+  - Cleaner UI for web editor
+  - Add diff syntax highlighting in email-on-push service notifications (Hannes Rosenögger)
+  - Add API endpoint to fetch all changes on a MergeRequest (Jeroen van Baarsen)
+  - View note image attachments in new tab when clicked instead of downloading them
+  - Improve sorting logic in UI and API. Explicitly define what sorting method is used by default
+  - Fix overflow at sidebar when have several items
+  - Add notes for label changes in issue and merge requests
+  - Show tags in commit view (Hannes Rosenögger)
+  - Only count a user's vote once on a merge request or issue (Michael Clarke)
+  - Increase font size when browse source files and diffs
+  - Service Templates now let you set default values for all services
+  - Create new file in empty repository using GitLab UI
+  - Ability to clone project using oauth2 token
+  - Upgrade Sidekiq gem to version 3.3.0
+  - Stop git zombie creation during force push check
+  - Show success/error messages for test setting button in services
+  - Added Rubocop for code style checks
+  - Fix commits pagination
+  - Async load a branch information at the commit page
+  - Disable blacklist validation for project names
+  - Allow configuring protection of the default branch upon first push (Marco Wessel)
+  - Add gitlab.com importer
+  - Add an ability to login with gitlab.com
+  - Add a commit calendar to the user profile (Hannes Rosenögger)
+  - Submit comment on command-enter
+  - Notify all members of a group when that group is mentioned in a comment, for example: `@gitlab-org` or `@sales`.
+  - Extend issue clossing pattern to include "Resolve", "Resolves", "Resolved", "Resolving" and "Close" (Julien Bianchi and Hannes Rosenögger)
+  - Fix long broadcast message cut-off on left sidebar (Visay Keo)
+  - Add Project Avatars (Steven Thonus and Hannes Rosenögger)
+  - Password reset token validity increased from 2 hours to 2 days since it is also send on account creation.
+  - Edit group members via API
+  - Enable raw image paste from clipboard, currently Chrome only (Marco Cyriacks)
+  - Add action property to merge request hook (Julien Bianchi)
+  - Remove duplicates from group milestone participants list.
+  - 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)
+  - Allow notification email to be set separately from primary email.
+  - API: Add support for editing an existing project (Mika Mäenpää and Hannes Rosenögger)
+  - Don't have Markdown preview fail for long comments/wiki pages.
+  - When test web hook - show error message instead of 500 error page if connection to hook url was reset
+  - Added support for firing system hooks on group create/destroy and adding/removing users to group (Boyan Tabakov)
+  - Added persistent collapse button for left side nav bar (Jason Blanchard)
+  - Prevent losing unsaved comments by automatically restoring them when comment page is loaded again.
+  - Don't allow page to be scaled on mobile.
+  - Clean the username acquired from OAuth/LDAP so it doesn't fail username validation and block signing up.
+  - Show assignees in merge request index page (Kelvin Mutuma)
+  - Link head panel titles to relevant root page.
+  - Allow users that signed up via OAuth to set their password in order to use Git over HTTP(S).
+  - Show users button to share their newly created public or internal projects on twitter
+  - Add quick help links to the GitLab pricing and feature comparison pages.
+  - Fix duplicate authorized applications in user profile and incorrect application client count in admin area.
+  - Make sure Markdown previews always use the same styling as the eventual destination.
+  - Remove deprecated Group#owner_id from API
+  - Show projects user contributed to on user page. Show stars near project on user page.
+  - Improve database performance for GitLab
+  - Add Asana service (Jeremy Benoist)
+  - Improve project web hooks with extra data
+
+v 7.7.2
+  - Update GitLab Shell to version 2.4.2 that fixes a bug when developers can push to protected branch
+  - Fix issue when LDAP user can't login with existing GitLab account
+
+v 7.7.1
+  - Improve mention autocomplete performance
+  - Show setup instructions for GitHub import if disabled
+  - Allow use http for OAuth applications
+
+v 7.7.0
+  - Import from GitHub.com feature
+  - Add Jetbrains Teamcity CI service (Jason Lippert)
+  - Mention notification level
+  - Markdown preview in wiki (Yuriy Glukhov)
+  - Raise group avatar filesize limit to 200kb
+  - OAuth applications feature
+  - Show user SSH keys in admin area
+  - Developer can push to protected branches option
+  - Set project path instead of project name in create form
+  - Block Git HTTP access after 10 failed authentication attempts
+  - Updates to the messages returned by API (sponsored by O'Reilly Media)
+  - New UI layout with side navigation
+  - Add alert message in case of outdated browser (IE < 10)
+  - Added API support for sorting projects
+  - Update gitlab_git to version 7.0.0.rc14
+  - Add API project search filter option for authorized projects
+  - Fix File blame not respecting branch selection
+  - Change some of application settings on fly in admin area UI
+  - Redesign signin/signup pages
+  - Close standard input in Gitlab::Popen.popen
+  - Trigger GitLab CI when push tags
+  - When accept merge request - do merge using sidaekiq job
+  - Enable web signups by default
+  - Fixes for diff comments: drag-n-drop images, selecting images
+  - Fixes for edit comments: drag-n-drop images, preview mode, selecting images, save & update
+  - Remove password strength indicator
+
+
+
+v 7.6.0
+  - Fork repository to groups
+  - New rugged version
+  - Add CRON=1 backup setting for quiet backups
+  - Fix failing wiki restore
+  - Add optional Sidekiq MemoryKiller middleware (enabled via SIDEKIQ_MAX_RSS env variable)
+  - Monokai highlighting style now more faithful to original design (Mark Riedesel)
+  - Create project with repository in synchrony
+  - Added ability to create empty repo or import existing one if project does not have repository
+  - Reactivate highlight.js language autodetection
+  - Mobile UI improvements
+  - Change maximum avatar file size from 100KB to 200KB
+  - Strict validation for snippet file names
+  - Enable Markdown preview for issues, merge requests, milestones, and notes (Vinnie Okada)
+  - In the docker directory is a container template based on the Omnibus packages.
+  - Update Sidekiq to version 2.17.8
+  - Add author filter to project issues and merge requests pages
+  - Atom feed for user activity
+  - Support multiple omniauth providers for the same user
+  - Rendering cross reference in issue title and tooltip for merge request
+  - Show username in comments
+  - Possibility to create Milestones or Labels when Issues are disabled
+  - Fix bug with showing gpg signature in tag
+
+v 7.5.3
+  - Bump gitlab_git to 7.0.0.rc12 (includes Rugged 0.21.2)
+
+v 7.5.2
+  - Don't log Sidekiq arguments by default
+  - Fix restore of wiki repositories from backups
+
+v 7.5.1
+  - Add missing timestamps to 'members' table
+v 7.5.3
+  - Update Sidekiq to version 2.17.8
+v 7.5.1
+  - Add missing timestamps to 'members' table
+v 7.5.3
+  - Bump gitlab_git to 7.0.0.rc12 (includes Rugged 0.21.2)
+
+v 7.5.2
+  - Don't log Sidekiq arguments by default
+  - Fix restore of wiki repositories from backups
+
+v 7.5.1
+  - Add missing timestamps to 'members' table
+
+1. Add "replace" functionality, user can replace existing file in the current repository.
+2. Add "upload" functionality, user can upload file into current repository.
+
+1. Add "replace" functionality, user can replace existing file in the current repository.
+2. Add "upload" functionality, user can upload file into current repository.
+
 v 7.5.0
   - API: Add support for Hipchat (Kevin Houdebert)
-  - Add time zone configuration on gitlab.yml (Sullivan Senechal)
+  - Add time zone configuration in gitlab.yml (Sullivan Senechal)
   - Fix LDAP authentication for Git HTTP access
   - Run 'GC.start' after every EmailsOnPushWorker job
   - Fix LDAP config lookup for provider 'ldap'
@@ -16,15 +345,15 @@ v 7.5.0
   - Performance improvements
   - Fix post-receive issue for projects with deleted forks
   - New gitlab-shell version with custom hooks support
-  - Improve code 
+  - Improve code
   - GitLab CI 5.2+ support (does not support older versions)
   - Fixed bug when you can not push commits starting with 000000 to protected branches
   - Added a password strength indicator
   - Change project name and path in one form
   - Display renamed files in diff views (Vinnie Okada)
-  - Add timezone configuration to gitlab.yml
   - Fix raw view for public snippets
   - Use secret token with GitLab internal API.
+  - Add missing timestamps to 'members' table
 
 v 7.4.3
   - Fix raw snippets view
@@ -51,6 +380,7 @@ v 7.4.0
   - Do not delete tmp/repositories itself during clean-up, only its contents
   - Support for backup uploads to remote storage
   - Prevent notes polling when there are not notes
+  - Internal ForkService: Prepare support for fork to a given namespace
   - API: Add support for forking a project via the API (Bernhard Kaindl)
   - API: filter project issues by milestone (Julien Bianchi)
   - Fail harder in the backup script
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 71435bc600d820df649fbb076311c35b7e2f1bfb..42b5ce22e3249326e9ecbac40614083841f33e83 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -20,6 +20,13 @@ Please treat our volunteers with courtesy and respect, it will go a long way tow
 
 Issues and merge requests should be in English and contain appropriate language for audiences of all ages.
 
+## Helping others
+
+Please help other GitLab users when you can.
+The channnels people will reach out on can be found on the [getting help page](https://about.gitlab.com/getting-help/).
+Sign up for the mailinglist, answer GitLab questions on StackOverflow or respond in the irc channel.
+You can also sign up on [CodeTriage](http://www.codetriage.com/gitlabhq/gitlabhq) to help with one issue every day.
+
 ## Issue tracker
 
 To get support for your particular problem please use the channels as detailed in the [getting help section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#getting-help). Professional [support subscriptions](http://about.gitlab.com/subscription/) and [consulting services](http://about.gitlab.com/consultancy/) are available from [GitLab.com](http://about.gitlab.com/).
@@ -37,7 +44,7 @@ Please send a merge request with a tested solution or a merge request with a fai
 **[Search the issues](https://gitlab.com/gitlab-org/gitlab-ce/issues)** for similar entries before submitting your own, there's a good chance somebody else had the same issue. Show your support with `:+1:` and/or join the discussion. Please submit issues in the following format (as the first post):
 
 1. **Summary:** Summarize your issue in one sentence (what goes wrong, what did you expect to happen)
-1. **Steps to reproduce:** How can we reproduce the issue, preferably on the [GitLab development virtual machine with vagrant](https://gitlab.com/gitlab-org/cookbook-gitlab/blob/master/doc/development.md) (start your issue with: `vagrant destroy && vagrant up && vagrant ssh`)
+1. **Steps to reproduce:** How can we reproduce the issue
 1. **Expected behavior:** Describe your issue in detail
 1. **Observed behavior**
 1. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise.
@@ -56,6 +63,8 @@ Merge requests can be filed either at [gitlab.com](https://gitlab.com/gitlab-org
 
 If you are new to GitLab development (or web development in general), search for the label `easyfix` ([gitlab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=easyfix), [github](https://github.com/gitlabhq/gitlabhq/labels/easyfix)). Those are issues easy to fix, marked by the GitLab core-team. If you are unsure how to proceed but want to help, mention one of the core-team members to give you a hint.
 
+To start with GitLab download the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit) and see [Development section](doc/development/README.md) in the help file. 
+
 ### Merge request guidelines
 
 If you can, please submit a merge request with the fix or improvements including tests. If you don't know how to fix the issue but can write a test that exposes the issue we will accept that as well. In general bug fixes that include a regression test are merged quickly while new features without proper tests are least likely to receive timely feedback. The workflow to make a merge request is as follows:
@@ -63,7 +72,7 @@ If you can, please submit a merge request with the fix or improvements including
 1. Fork the project on GitLab Cloud
 1. Create a feature branch
 1. Write [tests](README.md#run-the-tests) and code
-1. Add your changes to the [CHANGELOG](CHANGELOG) insert your line at a [random point](doc/workflow/gitlab_flow.md#do-not-order-commits-with-rebase) in the current version
+1. Add your changes to the [CHANGELOG](CHANGELOG)
 1. If you are changing the README, some documentation or other things which have no effect on the tests, add `[ci skip]` somewhere in the commit message
 1. If you have multiple commits please combine them into one commit by [squashing them](http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
 1. Push the commit to your fork
@@ -75,20 +84,49 @@ If you can, please submit a merge request with the fix or improvements including
 1. Link relevant [issues](https://gitlab.com/gitlab-org/gitlab-ce/issues) and/or [feature requests](http://feedback.gitlab.com/) from the merge request description and leave a comment on them with a link back to the MR
 1. Be prepared to answer questions and incorporate feedback even if requests for this arrive weeks or months after your MR submission
 1. If your MR touches code that executes shell commands, make sure it adheres to the [shell command guidelines](    doc/development/shell_commands.md).
+1. Also have a look at the [shell command guidelines](doc/development/shell_commands.md) if your code reads or opens files, or handles paths to files on disk.
 
 The **official merge window** is in the beginning of the month from the 1st to the 7th day of the month. The best time to submit a MR and get feedback fast. Before this time the GitLab B.V. team is still dealing with work that is created by the monthly release such as assisting subscribers with upgrade issues, the release of Enterprise Edition and the upgrade of GitLab Cloud. After the 7th it is already getting closer to the release date of the next version. This means there is less time to fix the issues created by merging large new features.
 
 Please keep the change in a single MR **as small as possible**. If you want to contribute a large feature think very hard what the minimum viable change is. Can you split functionality? Can you only submit the backend/API code? Can you start with a very simple UI? Can you do part of the refactor? The increased reviewability of small MR's that leads to higher code quality is more important to us than having a minimal commit log. The smaller a MR is the more likely it is it will be merged (quickly), after that you can send more MR's to enhance it.
 
-For examples of feedback on merge requests please look at already [closed merge requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed). If you would like quick feedback on your merge request feel free to mention one of the Merge Marshalls of [the core-team](https://about.gitlab.com/core-team/). Please ensure that your merge request meets the following contribution acceptance criteria.
+For examples of feedback on merge requests please look at already [closed merge requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed). If you would like quick feedback on your merge request feel free to mention one of the Merge Marshalls of [the core-team](https://about.gitlab.com/core-team/). Please ensure that your merge request meets the contribution acceptance criteria.
+
+## Definition of done
+
+If you contribute to GitLab please know that changes involve more than just code.
+We have the following [definition of done](http://guide.agilealliance.org/guide/definition-of-done.html).
+Please ensure you support the feature you contribute through all of these steps.
+
+1. Description explaning the relevancy (see following item)
+1. Working and clean code that is commented where needed
+1. Unit and integration tests that pass on the CI server
+1. Documented in the /doc directory
+1. Changelog entry added
+1. Reviewed and any concerns are addressed
+1. Merged by the project lead
+1. Added to the release blog article
+1. Added to [the website](https://gitlab.com/gitlab-com/www-gitlab-com/) if relevant
+1. Community questions answered
+1. Answers to questions radiated (in docs/wiki/etc.)
+
+If you add a dependency in GitLab (such as an operating system package) please consider updating the following and note the applicability of each in your merge request:
 
-**Please format your merge request description as follows:**
+1. Note the addition in the release blog post (create one if it doesn't exist yet) https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/
+1. Upgrade guide, for example https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/7.5-to-7.6.md
+1. Upgrader https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/upgrader.md#2-run-gitlab-upgrade-tool
+1. Installation guide https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies
+1. GitLab Development Kit https://gitlab.com/gitlab-org/gitlab-development-kit
+1. Test suite https://gitlab.com/gitlab-org/gitlab-ci/blob/master/doc/examples/configure_a_runner_to_run_the_gitlab_ce_test_suite.md
+1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab
+
+## Merge request description format
 
 1. What does this MR do?
 1. Are there points in the code the reviewer needs to double check?
 1. Why was this MR needed?
 1. What are the relevant issue numbers / [Feature requests](http://feedback.gitlab.com/)?
-1. Screenshots (If appropriate)
+1. Screenshots (if relevant)
 
 ## Contribution acceptance criteria
 
@@ -99,6 +137,7 @@ For examples of feedback on merge requests please look at already [closed merge
 1. Can merge without problems (if not please merge `master`, never rebase commits pushed to the remote server)
 1. Does not break any existing functionality
 1. Fixes one specific issue or implements one specific feature (do not combine things, send separate merge requests if needed)
+1. Migrations should do only one thing (eg: either create a table, move data to a new table or remove an old table) to aid retrying on failure
 1. Keeps the GitLab code base clean and well structured
 1. Contains functionality we think other users will benefit from too
 1. Doesn't add configuration options since they complicate future changes
@@ -121,5 +160,20 @@ For examples of feedback on merge requests please look at already [closed merge
 1.  [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style#coffeescript)
 1.  [Shell commands](doc/development/shell_commands.md) created by GitLab contributors to enhance security
 1.  [Markdown](http://www.cirosantilli.com/markdown-styleguide)
+1.  Interface text should be written subjectively instead of objectively. It should be the gitlab core team addressing a person. It should be written in present time and never use past tense (has been/was). For example instead of "prohibited this user from being saved due to the following errors:" the text should be "sorry, we could not create your account because:". Also these [excellent writing guidelines](https://github.com/NARKOZ/guides#writing).
 
 This is also the style used by linting tools such as [RuboCop](https://github.com/bbatsov/rubocop), [PullReview](https://www.pullreview.com/) and [Hound CI](https://houndci.com).
+
+## Code of conduct
+As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
+
+We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
+
+Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
+
+Instances of abusive, harassing, or otherwise unacceptable behavior can be
+reported by emailing contact@gitlab.com
+
+This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index ccbccc3dc62631f22ff358ac418e52401ec770b4..e70b4523ae7ffe8aa3cac8ecd1b093fba5a98737 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-2.2.0
+2.6.0
diff --git a/Gemfile b/Gemfile
index bb8aef65d2fef6fb87ad9d4a3e0864d5919ec593..924fef71fea84368c197f7cd9a76eea1ec961c10 100644
--- a/Gemfile
+++ b/Gemfile
@@ -28,22 +28,30 @@ gem 'omniauth-google-oauth2'
 gem 'omniauth-twitter'
 gem 'omniauth-github'
 gem 'omniauth-shibboleth'
+gem 'omniauth-kerberos'
+gem 'omniauth-gitlab'
+gem 'omniauth-bitbucket'
+gem 'doorkeeper', '2.1.3'
+gem "rack-oauth2", "~> 1.0.5"
+
+# Browser detection
+gem "browser"
 
 # Extracting information from a git repository
 # Provide access to Gitlab::Git library
-gem "gitlab_git", '7.0.0.rc11'
+gem "gitlab_git", '~> 7.1.3'
 
 # Ruby/Rack Git Smart-HTTP Server Handler
-gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
+gem 'gitlab-grack', '~> 2.0.0.rc2', require: 'grack'
 
 # LDAP Auth
-gem 'gitlab_omniauth-ldap', '1.2.0', require: "omniauth-ldap"
+gem 'gitlab_omniauth-ldap', '1.2.1', require: "omniauth-ldap"
 
 # Git Wiki
-gem 'gollum-lib', '~> 3.0.0'
+gem 'gollum-lib', '~> 4.0.2'
 
 # Language detection
-gem "gitlab-linguist", "~> 3.0.0", require: "linguist"
+gem "gitlab-linguist", "~> 3.0.1", require: "linguist"
 
 # API
 gem "grape", "~> 0.6.1"
@@ -80,7 +88,7 @@ gem "six"
 gem "seed-fu"
 
 # Markup pipeline for GitLab
-gem 'html-pipeline-gitlab', '~> 0.1.0'
+gem 'html-pipeline-gitlab', '~> 0.1'
 
 # Markdown to HTML
 gem "github-markup"
@@ -89,7 +97,7 @@ gem "github-markup"
 gem 'redcarpet', '~> 3.1.2'
 gem 'RedCloth'
 gem 'rdoc', '~>3.6'
-gem 'org-ruby', '= 0.9.9'
+gem 'org-ruby', '= 0.9.12'
 gem 'creole', '~>0.3.6'
 gem 'wikicloth', '=0.8.1'
 gem 'asciidoctor', '= 0.1.4'
@@ -107,12 +115,15 @@ end
 gem "state_machine"
 
 # Issue tags
-gem "acts-as-taggable-on"
+gem 'acts-as-taggable-on', '~> 3.4'
 
 # Background jobs
 gem 'slim'
 gem 'sinatra', require: nil
-gem 'sidekiq', '2.17.0'
+gem 'sidekiq', '~> 3.3'
+gem 'sidetiq', '0.6.3'
+Update Sidekiq to 2.17.8
+Revert "Update Sidekiq to 2.17.8"
 
 # HTTP requests
 gem "httparty"
@@ -134,7 +145,7 @@ gem "redis-rails"
 gem 'tinder', '~> 1.9.2'
 
 # HipChat integration
-gem "hipchat", "~> 0.14.0"
+gem "hipchat", "~> 1.4.0"
 
 # Flowdock integration
 gem "gitlab-flowdock-git-hook", "~> 0.4.2"
@@ -145,9 +156,15 @@ gem "gemnasium-gitlab-service", "~> 0.2"
 # Slack integration
 gem "slack-notifier", "~> 1.0.0"
 
+# Asana integration
+gem 'asana', '~> 0.0.6'
+
 # d3
 gem "d3_rails", "~> 3.1.4"
 
+#cal-heatmap
+gem "cal-heatmap-rails", "~> 0.0.1"
+
 # underscore-rails
 gem "underscore-rails", "~> 1.4.4"
 
@@ -163,13 +180,12 @@ gem 'ace-rails-ap'
 # Keyboard shortcuts
 gem 'mousetrap-rails'
 
-# Semantic UI Sass for Sidebar
-gem 'semantic-ui-sass', '~> 0.16.1.0'
+# Detect and convert string character encoding
+gem 'charlock_holmes'
 
 gem "sass-rails", '~> 4.0.2'
 gem "coffee-rails"
 gem "uglifier"
-gem "therubyracer"
 gem 'turbolinks'
 gem 'jquery-turbolinks'
 
@@ -181,7 +197,7 @@ gem "jquery-scrollto-rails"
 gem "raphael-rails", "~> 2.1.2"
 gem 'bootstrap-sass', '~> 3.0'
 gem "font-awesome-rails", '~> 4.2'
-gem "gitlab_emoji", "~> 0.0.1.1"
+gem "gitlab_emoji", "~> 0.1"
 gem "gon", '~> 5.0.0'
 gem 'nprogress-rails'
 gem 'request_store'
@@ -189,17 +205,17 @@ gem "virtus"
 gem 'addressable'
 
 group :development do
+  gem 'brakeman', require: false
   gem "annotate", "~> 2.6.0.beta2"
   gem "letter_opener"
   gem 'quiet_assets', '~> 1.0.1'
   gem 'rack-mini-profiler', require: false
+  gem "byebug"
 
   # Better errors handler
   gem 'better_errors'
   gem 'binding_of_caller'
 
-  gem 'rails_best_practices'
-
   # Docs generator
   gem "sdoc"
 
@@ -209,11 +225,12 @@ end
 
 group :development, :test do
   gem 'coveralls', require: false
+  gem 'rubocop', '0.28.0', require: false
   # gem 'rails-dev-tweaks'
   gem 'spinach-rails'
-  gem "rspec-rails"
+  gem "rspec-rails", '2.99'
   gem "capybara", '~> 2.2.1'
-  gem "pry"
+  gem "pry-rails"
   gem "awesome_print"
   gem "database_cleaner"
   gem "launchy"
@@ -239,14 +256,14 @@ group :development, :test do
 
   gem 'jasmine', '2.0.2'
 
-  gem "spring", '1.1.3'
-  gem "spring-commands-rspec", '1.0.1'
+  gem "spring", '~> 1.3.1'
+  gem "spring-commands-rspec", '1.0.4'
   gem "spring-commands-spinach", '1.0.0'
 end
 
 group :test do
   gem "simplecov", require: false
-  gem "shoulda-matchers", "~> 2.1.0"
+  gem "shoulda-matchers", "~> 2.7.0"
   gem 'email_spec'
   gem "webmock"
   gem 'test_after_commit'
@@ -257,3 +274,6 @@ group :production do
 end
 
 gem "newrelic_rpm"
+
+gem 'octokit', '3.7.0'
+gem "rugments"
diff --git a/Gemfile.lock b/Gemfile.lock
index a3645f7bbec99c6c9fd3ae1124e668604f097a0e..60777cf312b342ba7afa9fd639aed638b4060088 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -3,40 +3,53 @@ GEM
   specs:
     RedCloth (4.2.9)
     ace-rails-ap (2.0.1)
-    actionmailer (4.1.1)
-      actionpack (= 4.1.1)
-      actionview (= 4.1.1)
-      mail (~> 2.5.4)
-    actionpack (4.1.1)
-      actionview (= 4.1.1)
-      activesupport (= 4.1.1)
+    actionmailer (4.1.9)
+      actionpack (= 4.1.9)
+      actionview (= 4.1.9)
+      mail (~> 2.5, >= 2.5.4)
+    actionpack (4.1.9)
+      actionview (= 4.1.9)
+      activesupport (= 4.1.9)
       rack (~> 1.5.2)
       rack-test (~> 0.6.2)
-    actionview (4.1.1)
-      activesupport (= 4.1.1)
+    actionview (4.1.9)
+      activesupport (= 4.1.9)
       builder (~> 3.1)
       erubis (~> 2.7.0)
-    activemodel (4.1.1)
-      activesupport (= 4.1.1)
+    activemodel (4.1.9)
+      activesupport (= 4.1.9)
       builder (~> 3.1)
-    activerecord (4.1.1)
-      activemodel (= 4.1.1)
-      activesupport (= 4.1.1)
+    activerecord (4.1.9)
+      activemodel (= 4.1.9)
+      activesupport (= 4.1.9)
       arel (~> 5.0.0)
-    activesupport (4.1.1)
+    activeresource (4.0.0)
+      activemodel (~> 4.0)
+      activesupport (~> 4.0)
+      rails-observers (~> 0.1.1)
+    activesupport (4.1.9)
       i18n (~> 0.6, >= 0.6.9)
       json (~> 1.7, >= 1.7.7)
       minitest (~> 5.1)
       thread_safe (~> 0.1)
       tzinfo (~> 1.1)
-    acts-as-taggable-on (2.4.1)
-      rails (>= 3, < 5)
+    acts-as-taggable-on (3.5.0)
+      activerecord (>= 3.2, < 5)
     addressable (2.3.5)
     annotate (2.6.0)
       activerecord (>= 2.3.0)
       rake (>= 0.8.7)
     arel (5.0.1.20140414130214)
+    asana (0.0.6)
+      activeresource (>= 3.2.3)
     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)
+    autoprefixer-rails (5.1.6)
+      execjs
+      json
     awesome_print (1.2.0)
     axiom-types (0.0.5)
       descendants_tracker (~> 0.0.1)
@@ -47,9 +60,25 @@ GEM
       erubis (>= 2.6.6)
     binding_of_caller (0.7.2)
       debug_inspector (>= 0.0.1)
-    bootstrap-sass (3.0.3.0)
-      sass (~> 3.2)
+    bootstrap-sass (3.3.3)
+      autoprefixer-rails (>= 5.0.0.1)
+      sass (>= 3.2.19)
+    brakeman (3.0.1)
+      erubis (~> 2.6)
+      fastercsv (~> 1.5)
+      haml (>= 3.0, < 5.0)
+      highline (~> 1.6.20)
+      multi_json (~> 1.2)
+      ruby2ruby (~> 2.1.1)
+      ruby_parser (~> 3.5.0)
+      sass (~> 3.0)
+      terminal-table (~> 1.4)
+    browser (0.7.2)
     builder (3.2.2)
+    byebug (3.2.0)
+      columnize (~> 0.8)
+      debugger-linecache (~> 1.2)
+    cal-heatmap-rails (0.0.1)
     capybara (2.2.1)
       mime-types (>= 1.16)
       nokogiri (>= 1.3.3)
@@ -60,12 +89,10 @@ GEM
       activemodel (>= 3.2.0)
       activesupport (>= 3.2.0)
       json (>= 1.7)
-    celluloid (0.15.2)
-      timers (~> 1.1.0)
+    celluloid (0.16.0)
+      timers (~> 4.0.0)
     charlock_holmes (0.6.9.4)
     cliver (0.3.2)
-    code_analyzer (0.4.3)
-      sexp_processor
     coderay (1.1.0)
     coercible (1.0.0)
       descendants_tracker (~> 0.0.1)
@@ -78,7 +105,10 @@ GEM
     coffee-script-source (1.6.3)
     colored (1.2)
     colorize (0.5.8)
-    connection_pool (1.2.0)
+    columnize (0.9.0)
+    Update Sidekiq to 2.17.8
+    connection_pool (2.1.0)
+    Revert "Update Sidekiq to 2.17.8"
     coveralls (0.7.0)
       multi_json (~> 1.3)
       rest-client
@@ -93,6 +123,7 @@ GEM
     daemons (1.1.9)
     database_cleaner (1.3.0)
     debug_inspector (0.0.2)
+    debugger-linecache (1.2.0)
     default_value_for (3.0.0)
       activerecord (>= 3.2.0, < 5.0)
     descendants_tracker (0.0.3)
@@ -107,20 +138,20 @@ GEM
     diff-lcs (1.2.5)
     diffy (3.0.3)
     docile (1.1.5)
+    doorkeeper (2.1.3)
+      railties (>= 3.2)
     dotenv (0.9.0)
     dropzonejs-rails (0.4.14)
       rails (> 3.1)
     email_spec (1.5.0)
       launchy (~> 2.1)
       mail (~> 2.2)
-    emoji (1.0.1)
-      json
     enumerize (0.7.0)
       activesupport (>= 3.2)
     equalizer (0.0.8)
     erubis (2.7.0)
     escape_utils (0.2.4)
-    eventmachine (1.0.3)
+    eventmachine (1.0.4)
     excon (0.32.1)
     execjs (2.0.2)
     expression_parser (0.9.0)
@@ -133,6 +164,7 @@ GEM
       multipart-post (~> 1.2.0)
     faraday_middleware (0.9.0)
       faraday (>= 0.7.4, < 0.9)
+    fastercsv (1.5.5)
     ffaker (1.22.1)
     ffi (1.9.3)
     fog (1.21.0)
@@ -158,43 +190,48 @@ GEM
       dotenv (>= 0.7)
       thor (>= 0.13.6)
     formatador (0.2.4)
-    gemnasium-gitlab-service (0.2.2)
-      rugged (~> 0.19)
+    gemnasium-gitlab-service (0.2.4)
+      rugged (~> 0.21)
+    gemojione (2.0.0)
+      json
     gherkin-ruby (0.3.1)
       racc
-    github-markup (1.1.0)
+    github-markup (1.3.1)
+      posix-spawn (~> 0.3.8)
     gitlab-flowdock-git-hook (0.4.2.2)
       gitlab-grit (>= 2.4.1)
       multi_json
-    gitlab-grack (2.0.0.pre)
+    gitlab-grack (2.0.0)
       rack (~> 1.5.1)
-    gitlab-grit (2.6.12)
+    gitlab-grit (2.7.2)
       charlock_holmes (~> 0.6)
       diff-lcs (~> 1.1)
       mime-types (~> 1.15)
       posix-spawn (~> 0.3)
-    gitlab-linguist (3.0.0)
+    gitlab-linguist (3.0.1)
       charlock_holmes (~> 0.6.6)
       escape_utils (~> 0.2.4)
       mime-types (~> 1.19)
-    gitlab_emoji (0.0.1.1)
-      emoji (~> 1.0.1)
-    gitlab_git (7.0.0.rc11)
+    gitlab_emoji (0.1.0)
+      gemojione (~> 2.0)
+    gitlab_git (7.1.3)
       activesupport (~> 4.0)
       charlock_holmes (~> 0.6)
       gitlab-linguist (~> 3.0)
-      rugged (~> 0.21.0)
+      rugged (~> 0.21.2)
     gitlab_meta (7.0)
-    gitlab_omniauth-ldap (1.2.0)
+    gitlab_omniauth-ldap (1.2.1)
       net-ldap (~> 0.9)
       omniauth (~> 1.0)
       pyu-ruby-sasl (~> 0.0.3.1)
       rubyntlm (~> 0.3)
-    gollum-lib (3.0.0)
-      github-markup (~> 1.1.0)
-      gitlab-grit (~> 2.6.5)
-      nokogiri (~> 1.6.1)
-      rouge (~> 1.3.3)
+    gollum-grit_adapter (0.1.3)
+      gitlab-grit (~> 2.7, >= 2.7.1)
+    gollum-lib (4.0.2)
+      github-markup (~> 1.3.1)
+      gollum-grit_adapter (~> 0.1, >= 0.1.1)
+      nokogiri (~> 1.6.4)
+      rouge (~> 1.7.4)
       sanitize (~> 2.1.0)
       stringex (~> 2.5.1)
     gon (5.0.1)
@@ -234,24 +271,28 @@ GEM
       haml (>= 3.1, < 5.0)
       railties (>= 4.0.1)
     hashie (2.1.2)
+    highline (1.6.21)
     hike (1.2.3)
-    hipchat (0.14.0)
-      httparty
+    hipchat (1.4.0)
       httparty
+    hitimes (1.2.2)
     html-pipeline (1.11.0)
       activesupport (>= 2)
       nokogiri (~> 1.4)
-    html-pipeline-gitlab (0.1.5)
+    html-pipeline-gitlab (0.2.0)
       actionpack (~> 4)
-      gitlab_emoji (~> 0.0.1)
+      gitlab_emoji (~> 0.1)
       html-pipeline (~> 1.11.0)
+      mime-types
       sanitize (~> 2.1)
     http_parser.rb (0.5.3)
     httparty (0.13.0)
       json (~> 1.8)
       multi_xml (>= 0.5.2)
     httpauth (0.2.1)
-    i18n (0.6.11)
+    httpclient (2.5.3.3)
+    i18n (0.7.0)
+    ice_cube (0.11.1)
     ice_nine (0.10.0)
     jasmine (2.0.2)
       jasmine-core (~> 2.0.0)
@@ -270,42 +311,40 @@ GEM
       turbolinks
     jquery-ui-rails (4.2.1)
       railties (>= 3.2.16)
-    json (1.8.1)
+    json (1.8.2)
     jwt (0.1.13)
       multi_json (>= 1.5)
     kaminari (0.15.1)
       actionpack (>= 3.0.0)
       activesupport (>= 3.0.0)
-    kgio (2.8.1)
+    kgio (2.9.2)
     launchy (2.4.2)
       addressable (~> 2.3)
     letter_opener (1.1.2)
       launchy (~> 2.2)
-    libv8 (3.16.14.3)
     listen (2.3.1)
       celluloid (>= 0.15.2)
       rb-fsevent (>= 0.9.3)
       rb-inotify (>= 0.9)
     lumberjack (1.0.4)
-    mail (2.5.4)
-      mime-types (~> 1.16)
-      treetop (~> 1.4.8)
+    mail (2.6.3)
+      mime-types (>= 1.16, < 3)
     method_source (0.8.2)
     mime-types (1.25.1)
-    mini_portile (0.6.0)
+    mini_portile (0.6.1)
     minitest (5.3.5)
     mousetrap-rails (1.4.6)
     multi_json (1.10.1)
     multi_xml (0.5.5)
     multipart-post (1.2.0)
     mysql2 (0.3.16)
-    net-ldap (0.9.0)
+    net-ldap (0.11)
     net-scp (1.1.2)
       net-ssh (>= 2.6.5)
     net-ssh (2.8.0)
     newrelic_rpm (3.9.4.245)
-    nokogiri (1.6.2.1)
-      mini_portile (= 0.6.0)
+    nokogiri (1.6.5)
+      mini_portile (~> 0.6.0)
     nprogress-rails (0.1.2.3)
     oauth (0.4.7)
     oauth2 (0.8.1)
@@ -314,15 +353,29 @@ GEM
       jwt (~> 0.1.4)
       multi_json (~> 1.0)
       rack (~> 1.2)
+    octokit (3.7.0)
+      sawyer (~> 0.6.0, >= 0.5.3)
     omniauth (1.1.4)
       hashie (>= 1.2, < 3)
       rack
+    omniauth-bitbucket (0.0.2)
+      multi_json (~> 1.7)
+      omniauth (~> 1.1)
+      omniauth-oauth (~> 1.0)
     omniauth-github (1.1.1)
       omniauth (~> 1.0)
       omniauth-oauth2 (~> 1.1)
+    omniauth-gitlab (1.0.0)
+      omniauth (~> 1.0)
+      omniauth-oauth2 (~> 1.0)
     omniauth-google-oauth2 (0.2.5)
       omniauth (> 1.0)
       omniauth-oauth2 (~> 1.1)
+    omniauth-kerberos (0.2.0)
+      omniauth-multipassword
+      timfel-krb5-auth (~> 0.8)
+    omniauth-multipassword (0.4.1)
+      omniauth (~> 1.0)
     omniauth-oauth (1.0.1)
       oauth
       omniauth (~> 1.0)
@@ -334,9 +387,11 @@ GEM
     omniauth-twitter (1.0.1)
       multi_json (~> 1.3)
       omniauth-oauth (~> 1.0)
-    org-ruby (0.9.9)
+    org-ruby (0.9.12)
       rubypants (~> 0.2)
     orm_adapter (0.5.0)
+    parser (2.2.0.2)
+      ast (>= 1.1, < 3.0)
     pg (0.15.1)
     phantomjs (1.9.2.0)
     poltergeist (1.5.1)
@@ -344,12 +399,14 @@ GEM
       cliver (~> 0.3.1)
       multi_json (~> 1.0)
       websocket-driver (>= 0.2.0)
-    polyglot (0.3.4)
     posix-spawn (0.3.9)
+    powerpack (0.0.9)
     pry (0.9.12.4)
       coderay (~> 1.0)
       method_source (~> 0.8)
       slop (~> 3.4)
+    pry-rails (0.3.2)
+      pry (>= 0.9.10)
     pyu-ruby-sasl (0.0.3.3)
     quiet_assets (1.0.2)
       railties (>= 3.1, < 5.0)
@@ -357,45 +414,45 @@ GEM
     rack (1.5.2)
     rack-accept (0.4.5)
       rack (>= 0.4)
-    rack-attack (2.3.0)
+    rack-attack (4.2.0)
       rack
     rack-cors (0.2.9)
     rack-mini-profiler (0.9.0)
       rack (>= 1.1.3)
     rack-mount (0.8.3)
       rack (>= 1.0.0)
+    rack-oauth2 (1.0.8)
+      activesupport (>= 2.3)
+      attr_required (>= 0.0.5)
+      httpclient (>= 2.2.0.2)
+      multi_json (>= 1.3.6)
+      rack (>= 1.1)
     rack-protection (1.5.1)
       rack
-    rack-test (0.6.2)
+    rack-test (0.6.3)
       rack (>= 1.0)
-    rails (4.1.1)
-      actionmailer (= 4.1.1)
-      actionpack (= 4.1.1)
-      actionview (= 4.1.1)
-      activemodel (= 4.1.1)
-      activerecord (= 4.1.1)
-      activesupport (= 4.1.1)
+    rails (4.1.9)
+      actionmailer (= 4.1.9)
+      actionpack (= 4.1.9)
+      actionview (= 4.1.9)
+      activemodel (= 4.1.9)
+      activerecord (= 4.1.9)
+      activesupport (= 4.1.9)
       bundler (>= 1.3.0, < 2.0)
-      railties (= 4.1.1)
+      railties (= 4.1.9)
       sprockets-rails (~> 2.0)
+    rails-observers (0.1.2)
+      activemodel (~> 4.0)
     rails_autolink (1.1.6)
       rails (> 3.1)
-    rails_best_practices (1.14.4)
-      activesupport
-      awesome_print
-      code_analyzer (>= 0.4.3)
-      colored
-      erubis
-      i18n
-      require_all
-      ruby-progressbar
-    railties (4.1.1)
-      actionpack (= 4.1.1)
-      activesupport (= 4.1.1)
+    railties (4.1.9)
+      actionpack (= 4.1.9)
+      activesupport (= 4.1.9)
       rake (>= 0.8.7)
       thor (>= 0.18.1, < 2.0)
-    raindrops (0.12.0)
-    rake (10.3.2)
+    rainbow (2.0.0)
+    raindrops (0.13.0)
+    rake (10.4.2)
     raphael-rails (2.1.2)
     rb-fsevent (0.9.3)
     rb-inotify (0.9.2)
@@ -422,32 +479,46 @@ GEM
       redis-store (~> 1.1.0)
     redis-store (1.1.4)
       redis (>= 2.2)
-    ref (1.0.5)
     request_store (1.0.5)
-    require_all (1.3.2)
     rest-client (1.6.7)
       mime-types (>= 1.16)
     rinku (1.7.3)
-    rouge (1.3.3)
-    rspec (2.14.1)
-      rspec-core (~> 2.14.0)
-      rspec-expectations (~> 2.14.0)
-      rspec-mocks (~> 2.14.0)
-    rspec-core (2.14.7)
-    rspec-expectations (2.14.4)
+    rouge (1.7.7)
+    rspec (2.99.0)
+      rspec-core (~> 2.99.0)
+      rspec-expectations (~> 2.99.0)
+      rspec-mocks (~> 2.99.0)
+    rspec-collection_matchers (1.1.2)
+      rspec-expectations (>= 2.99.0.beta1)
+    rspec-core (2.99.2)
+    rspec-expectations (2.99.2)
       diff-lcs (>= 1.1.3, < 2.0)
-    rspec-mocks (2.14.4)
-    rspec-rails (2.14.0)
+    rspec-mocks (2.99.3)
+    rspec-rails (2.99.0)
       actionpack (>= 3.0)
+      activemodel (>= 3.0)
       activesupport (>= 3.0)
       railties (>= 3.0)
-      rspec-core (~> 2.14.0)
-      rspec-expectations (~> 2.14.0)
-      rspec-mocks (~> 2.14.0)
-    ruby-progressbar (1.2.0)
-    rubyntlm (0.4.0)
+      rspec-collection_matchers
+      rspec-core (~> 2.99.0)
+      rspec-expectations (~> 2.99.0)
+      rspec-mocks (~> 2.99.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)
+    ruby2ruby (2.1.3)
+      ruby_parser (~> 3.1)
+      sexp_processor (~> 4.0)
+    ruby_parser (3.5.0)
+      sexp_processor (~> 4.1)
+    rubyntlm (0.5.0)
     rubypants (0.2.0)
-    rugged (0.21.0)
+    rugged (0.21.4)
+    rugments (1.0.0.beta6)
     safe_yaml (0.9.7)
     sanitize (2.1.0)
       nokogiri (>= 1.4.4)
@@ -457,6 +528,9 @@ GEM
       sass (~> 3.2.0)
       sprockets (~> 2.8, <= 2.11.0)
       sprockets-rails (~> 2.0)
+    sawyer (0.6.0)
+      addressable (~> 2.3.5)
+      faraday (~> 0.8, < 0.10)
     sdoc (0.3.20)
       json (>= 1.1.3)
       rdoc (~> 3.10)
@@ -465,18 +539,38 @@ GEM
       activesupport (>= 3.1, < 4.2)
     select2-rails (3.5.2)
       thor (~> 0.14)
-    semantic-ui-sass (0.16.1.0)
-      sass (~> 3.2)
     settingslogic (2.0.9)
-    sexp_processor (4.4.0)
-    shoulda-matchers (2.1.0)
+    sexp_processor (4.4.5)
+    shoulda-matchers (2.7.0)
       activesupport (>= 3.0.0)
+<<<<<<< HEAD
+<<<<<<< HEAD
+    sidekiq (3.3.0)
+      celluloid (>= 0.16.0)
+      connection_pool (>= 2.0.0)
+      json
+      redis (>= 3.0.6)
+      redis-namespace (>= 1.3.1)
+    sidetiq (0.6.3)
+      celluloid (>= 0.14.1)
+      ice_cube (= 0.11.1)
+      sidekiq (>= 3.0.0)
+=======
+    sidekiq (2.17.8)
+      celluloid (= 0.15.2)
+      connection_pool (~> 2.0)
+      json
+      redis (~> 3.1)
+      redis-namespace (~> 1.3)
+>>>>>>> Update Sidekiq to 2.17.8
+=======
     sidekiq (2.17.0)
       celluloid (>= 0.15.2)
       connection_pool (>= 1.0.0)
       json
       redis (>= 3.0.4)
       redis-namespace (>= 1.3.1)
+>>>>>>> Revert "Update Sidekiq to 2.17.8"
     simple_oauth (0.1.9)
     simplecov (0.9.0)
       docile (~> 1.1.0)
@@ -492,7 +586,7 @@ GEM
     slim (2.0.2)
       temple (~> 0.6.6)
       tilt (>= 1.3.3, < 2.1)
-    slop (3.4.7)
+    slop (3.6.0)
     spinach (0.8.7)
       colorize (= 0.5.8)
       gherkin-ruby (>= 0.3.1)
@@ -500,8 +594,8 @@ GEM
       capybara (>= 2.0.0)
       railties (>= 3)
       spinach (>= 0.4)
-    spring (1.1.3)
-    spring-commands-rspec (1.0.1)
+    spring (1.3.3)
+    spring-commands-rspec (1.0.4)
       spring (>= 0.9.1)
     spring-commands-spinach (1.0.0)
       spring (>= 0.9.1)
@@ -510,28 +604,28 @@ GEM
       multi_json (~> 1.0)
       rack (~> 1.0)
       tilt (~> 1.1, != 1.3.0)
-    sprockets-rails (2.1.3)
+    sprockets-rails (2.2.4)
       actionpack (>= 3.0)
       activesupport (>= 3.0)
-      sprockets (~> 2.8)
+      sprockets (>= 2.8, < 4.0)
     stamp (0.5.0)
     state_machine (1.2.0)
-    stringex (2.5.1)
+    stringex (2.5.2)
     temple (0.6.7)
     term-ansicolor (1.2.2)
       tins (~> 0.8)
+    terminal-table (1.4.5)
     test_after_commit (0.2.2)
-    therubyracer (0.12.0)
-      libv8 (~> 3.16.14.0)
-      ref
     thin (1.6.1)
       daemons (>= 1.0.9)
       eventmachine (>= 1.0.0)
       rack (>= 1.0.0)
     thor (0.19.1)
-    thread_safe (0.3.4)
+    thread_safe (0.3.5)
     tilt (1.4.1)
-    timers (1.1.0)
+    timers (4.0.1)
+      hitimes
+    timfel-krb5-auth (0.8.3)
     tinder (1.9.3)
       eventmachine (~> 1.0)
       faraday (~> 0.8)
@@ -542,9 +636,6 @@ GEM
       multi_json (~> 1.7)
       twitter-stream (~> 0.1)
     tins (0.13.1)
-    treetop (1.4.15)
-      polyglot
-      polyglot (>= 0.3.1)
     turbolinks (2.0.0)
       coffee-rails
     twitter-stream (0.1.16)
@@ -566,7 +657,7 @@ GEM
       raindrops (~> 0.7)
     unicorn-worker-killer (0.4.2)
       unicorn (~> 4)
-    version_sorter (1.1.0)
+    version_sorter (2.0.0)
     virtus (1.0.1)
       axiom-types (~> 0.0.5)
       coercible (~> 1.0)
@@ -591,16 +682,22 @@ PLATFORMS
 DEPENDENCIES
   RedCloth
   ace-rails-ap
-  acts-as-taggable-on
+  acts-as-taggable-on (~> 3.4)
   addressable
   annotate (~> 2.6.0.beta2)
+  asana (~> 0.0.6)
   asciidoctor (= 0.1.4)
   awesome_print
   better_errors
   binding_of_caller
   bootstrap-sass (~> 3.0)
+  brakeman
+  browser
+  byebug
+  cal-heatmap-rails (~> 0.0.1)
   capybara (~> 2.2.1)
   carrierwave
+  charlock_holmes
   coffee-rails
   colored
   coveralls
@@ -611,6 +708,7 @@ DEPENDENCIES
   devise (= 3.2.4)
   devise-async (= 0.9.0)
   diffy (~> 3.0.3)
+  doorkeeper (= 2.1.3)
   dropzonejs-rails
   email_spec
   enumerize
@@ -622,13 +720,13 @@ DEPENDENCIES
   gemnasium-gitlab-service (~> 0.2)
   github-markup
   gitlab-flowdock-git-hook (~> 0.4.2)
-  gitlab-grack (~> 2.0.0.pre)
-  gitlab-linguist (~> 3.0.0)
-  gitlab_emoji (~> 0.0.1.1)
-  gitlab_git (= 7.0.0.rc11)
+  gitlab-grack (~> 2.0.0.rc2)
+  gitlab-linguist (~> 3.0.1)
+  gitlab_emoji (~> 0.1)
+  gitlab_git (~> 7.1.3)
   gitlab_meta (= 7.0)
-  gitlab_omniauth-ldap (= 1.2.0)
-  gollum-lib (~> 3.0.0)
+  gitlab_omniauth-ldap (= 1.2.1)
+  gollum-lib (~> 4.0.2)
   gon (~> 5.0.0)
   grape (~> 0.6.1)
   grape-entity (~> 0.4.2)
@@ -636,8 +734,8 @@ DEPENDENCIES
   guard-rspec
   guard-spinach
   haml-rails
-  hipchat (~> 0.14.0)
-  html-pipeline-gitlab (~> 0.1.0)
+  hipchat (~> 1.4.0)
+  html-pipeline-gitlab (~> 0.1)
   httparty
   jasmine (= 2.0.2)
   jquery-atwho-rails (~> 0.3.3)
@@ -653,22 +751,26 @@ DEPENDENCIES
   mysql2
   newrelic_rpm
   nprogress-rails
+  octokit (= 3.7.0)
   omniauth (~> 1.1.3)
+  omniauth-bitbucket
   omniauth-github
+  omniauth-gitlab
   omniauth-google-oauth2
+  omniauth-kerberos
   omniauth-shibboleth
   omniauth-twitter
-  org-ruby (= 0.9.9)
+  org-ruby (= 0.9.12)
   pg
   poltergeist (~> 1.5.1)
-  pry
+  pry-rails
   quiet_assets (~> 1.0.1)
   rack-attack
   rack-cors
   rack-mini-profiler
+  rack-oauth2 (~> 1.0.5)
   rails (~> 4.1.0)
   rails_autolink (~> 1.1)
-  rails_best_practices
   raphael-rails (~> 2.1.2)
   rb-fsevent
   rb-inotify
@@ -676,29 +778,39 @@ DEPENDENCIES
   redcarpet (~> 3.1.2)
   redis-rails
   request_store
-  rspec-rails
+  rspec-rails (= 2.99)
+  rubocop (= 0.28.0)
+  rugments
   sanitize (~> 2.0)
   sass-rails (~> 4.0.2)
   sdoc
   seed-fu
   select2-rails
-  semantic-ui-sass (~> 0.16.1.0)
   settingslogic
+<<<<<<< HEAD
+  shoulda-matchers (~> 2.7.0)
+  sidekiq (~> 3.3)
+  sidetiq (= 0.6.3)
+=======
   shoulda-matchers (~> 2.1.0)
+<<<<<<< HEAD
+  sidekiq (= 2.17.8)
+>>>>>>> Update Sidekiq to 2.17.8
+=======
   sidekiq (= 2.17.0)
+>>>>>>> Revert "Update Sidekiq to 2.17.8"
   simplecov
   sinatra
   six
   slack-notifier (~> 1.0.0)
   slim
   spinach-rails
-  spring (= 1.1.3)
-  spring-commands-rspec (= 1.0.1)
+  spring (~> 1.3.1)
+  spring-commands-rspec (= 1.0.4)
   spring-commands-spinach (= 1.0.0)
   stamp
   state_machine
   test_after_commit
-  therubyracer
   thin
   tinder (~> 1.9.2)
   turbolinks
diff --git a/LICENSE b/LICENSE
index d11b8730bf124354293154ce5f5a317c4935a780..d8cb29f36384fe739136ce15c79f41eb1ef45247 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2011-2014 GitLab B.V.
+Copyright (c) 2011-2015 GitLab B.V.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/MAINTENANCE.md b/MAINTENANCE.md
index 19200fef3891cb830702ff6c2ef25f4aaba616e2..d3d36670693aa4c9b5b51a44e37542b077d2c9cd 100644
--- a/MAINTENANCE.md
+++ b/MAINTENANCE.md
@@ -2,7 +2,7 @@
 
 GitLab is a fast moving and evolving project. We currently don't have the resources to support many releases concurrently. We support exactly one stable release at any given time.
 
-GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: `(Major).(Minor).(Patch)`.
+GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: `(Major).(Minor).(Patch)` in a [pragmatic way](https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e).
 
 - **Major version**: Whenever there is something significant or any backwards incompatible changes are introduced to the public API.
 - **Minor version**: When new, backwards compatible functionality is introduced to the public API or a minor feature is introduced, or when a set of smaller features is rolled out.
diff --git a/PROCESS.md b/PROCESS.md
index 1dd28d6b670429b75b5cb35981442dc8acda3379..1b6b3e7d32d053ac6124be3c1637b3f8db12c204 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -71,7 +71,7 @@ Thanks for the issue report. Please reformat your issue to conform to the issue
 
 ### Feature requests
 
-Thank you for your interest in improving GitLab. We don't use the issue tracker for feature requests. Things that are wrong but are not a regression compared to older versions of GitLab are considered feature requests and not issues. Please use the [feature request forum](http://feedback.gitlab.com/) for this purpose or create a merge request implementing this feature. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information.
+Thank you for your interest in improving GitLab. We don't use the issue tracker for feature requests. Things that are wrong but are not a regression compared to older versions of GitLab are considered feature requests and not issues. Please use the \[feature request forum\]\(http://feedback.gitlab.com/) for this purpose or create a merge request implementing this feature. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information.
 
 ### Issue report for old version
 
@@ -104,3 +104,10 @@ This merge request has been closed because a request for more information has no
 ### Accepting merge requests
 
 Is there a request on [the feature request forum](http://feedback.gitlab.com/forums/176466-general) that is similar to this? If so, can you make a comment with a link to it? Please be aware that new functionality that is not marked [accepting merge/pull requests](http://feedback.gitlab.com/forums/176466-general/status/796455) on the forum might not make it into GitLab. You might be asked to make changes and even after implementing them your feature might still be declined. If you want to reduce the chance of this happening please have a discussion in the forum first.
+
+### Only accepting merge requests with green tests
+
+We can only accept a merge request if all the tests are green. I've just
+restarted the build. When the tests are still not passing after this restart and
+you're sure that is does not have anything to do with your code changes, please
+rebase with master to see if that solves the issue.
diff --git a/Procfile b/Procfile
index a5693f8dbc52a91dc637bfb54d15ca5af4615466..a0ab4a734a4375f69a6b15bc4122ce4dea428f11 100644
--- a/Procfile
+++ b/Procfile
@@ -1,2 +1,2 @@
 web: bundle exec unicorn_rails -p ${PORT:="3000"} -E ${RAILS_ENV:="development"} -c ${UNICORN_CONFIG:="config/unicorn.rb"}
-worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitlab_shell
+worker: bundle exec sidekiq -q post_receive -q mailer -q system_hook -q project_web_hook -q gitlab_shell -q common -q default
diff --git a/README.md b/README.md
index 63fa5e3da86f1a2b1054b0584613a4e05a77b365..0563ceca4097c2ed5be75da2bf8177946a736bdd 100644
--- a/README.md
+++ b/README.md
@@ -9,11 +9,19 @@
 - Each project can also have an issue tracker and a wiki
 - Used by more than 100,000 organizations, GitLab is the most popular solution to manage Git repositories on-premises
 - Completely free and open source (MIT Expat license)
-- Powered by Ruby on Rails
+- Powered by [Ruby on Rails](https://github.com/rails/rails)
+
+## Editions
+
+There are two editions of GitLab.
+*GitLab [Community Edition](https://about.gitlab.com/features/) (CE)* is available without any costs under an MIT license.
+
+*GitLab Enterprise Edition (EE)* includes [extra features](https://about.gitlab.com/features/#compare) that are most useful for organizations with more than 100 users.
+To get access to the EE and support please [become a subscriber](https://about.gitlab.com/pricing/).
 
 ## Canonical source
 
-- The source of GitLab Community Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible.
+The source of GitLab Community Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/) and there are mirrors to make [contributing](CONTRIBUTING.md) as easy as possible.
 
 ## Code status
 
@@ -25,8 +33,6 @@
 
 - [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master)
 
-- [![PullReview stats](https://www.pullreview.com/gitlab/gitlab-org/gitlab-ce/badges/master.svg?)](https://www.pullreview.com/gitlab.gitlab.com/gitlab-org/gitlab-ce/reviews/master)
-
 ## Website
 
 On [about.gitlab.com](https://about.gitlab.com/) you can find more information about:
@@ -40,81 +46,45 @@ On [about.gitlab.com](https://about.gitlab.com/) you can find more information a
 
 ## Requirements
 
-- Ubuntu/Debian/CentOS/RHEL**
-- ruby 2.0+
-- git 1.7.10+
-- redis 2.0+
+GitLab requires the following software:
+
+- Ubuntu/Debian/CentOS/RHEL
+- Ruby (MRI) 2.0 or 2.1
+- Git 1.7.10+
+- Redis 2.0+
 - MySQL or PostgreSQL
 
-** More details are in the [requirements doc](doc/install/requirements.md).
+Please see the [requirements documentation](doc/install/requirements.md) for system requirements and more information about the supported operating systems.
 
 ## Installation
 
-Please see [the installation page on the GitLab website](https://about.gitlab.com/installation/) for the various options.
-Since a manual installation is a lot of work and error prone we strongly recommend the fast and reliable [Omnibus package installation](https://about.gitlab.com/downloads/) (deb/rpm).
-
-## Third-party applications
+The recommended way to install GitLab is using the provided [Omnibus packages](https://about.gitlab.com/downloads/). Compared to an installation from source, this is faster and less error prone. Just select your operating system, download the respective package (Debian or RPM) and install it using the system's package manager.
 
-There are a lot of applications and API wrappers for GitLab.
-Find them [on our website](https://about.gitlab.com/applications/).
+There are various other options to install GitLab, please refer to the [installation page on the GitLab website](https://about.gitlab.com/installation/) for more information.
 
-### New versions
+You can access a new installation with the login **`root`** and password **`5iveL!fe`**, after login you are required to set a unique password.
 
-Since 2011 a minor or major version of GitLab is released on the 22nd of every month. Patch and security releases come out when needed.  New features are detailed on the [blog](https://about.gitlab.com/blog/) and in the [changelog](CHANGELOG). For more information about the release process see the release [documentation](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/release). Features that will likely be in the next releases can be found on the [feature request forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
-
-### Upgrading
-
-For updating the the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For manual installations there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update).
-
-## Run in production mode
+## Third-party applications
 
-The Installation guide contains instructions on how to download an init script and run it automatically on boot. You can also start the init script manually:
+There are a lot of [third-party applications integrating with GitLab](https://about.gitlab.com/applications/). These include GUI Git clients, mobile applications and API wrappers for various languages.
 
-    sudo service gitlab start
+## GitLab release cycle
 
-or by directly calling the script:
+Since 2011 a minor or major version of GitLab is released on the 22nd of every month. Patch and security releases are published when needed. New features are detailed on the [blog](https://about.gitlab.com/blog/) and in the [changelog](CHANGELOG). For more information about the release process see the [release documentation](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/release). Features that will likely be in the next releases can be found on the [feature request forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
 
-     sudo /etc/init.d/gitlab start
+## Upgrading
 
-Please login with `root` / `5iveL!fe`
+For updating the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For installations from source there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update) detailing all necessary commands to migrate to the next version.
 
 ## Install a development environment
 
-We recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
-If you do not use the development kit you might need to copy the example development unicorn configuration file
+To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
+If you do not use the GitLab Development Kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone.
+One small thing you also have to do when installing it yourself is to copy the example development unicorn configuration file:
 
     cp config/unicorn.rb.example.development config/unicorn.rb
 
-## Run in development mode
-
-Start it with [Foreman](https://github.com/ddollar/foreman)
-
-    bundle exec foreman start -p 3000
-
-or start each component separately:
-
-    bundle exec rails s
-    bin/background_jobs start
-
-And surf to [localhost:3000](http://localhost:3000/) and login with `root` / `5iveL!fe`.
-
-## Run the tests
-
--   Run all tests:
-
-        bundle exec rake test
-
--   [RSpec](http://rspec.info/) unit and functional tests.
-
-    All RSpec tests: `bundle exec rake spec`
-
-    Single RSpec file: `bundle exec rspec spec/controllers/commit_controller_spec.rb`
-
--   [Spinach](https://github.com/codegram/spinach) integration tests.
-
-    All Spinach tests: `bundle exec rake spinach`
-
-    Single Spinach test: `bundle exec spinach features/project/issues/milestones.feature`
+Instructions on how to start GitLab and how to run the tests can be found in the [development section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#development).
 
 ## Documentation
 
@@ -131,4 +101,4 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on
 ## Is it awesome?
 
 Thanks for [asking this question](https://twitter.com/supersloth/status/489462789384056832) Joshua.
-[These people](https://twitter.com/gitlabhq/favorites) seem to like it.
+[These people](https://twitter.com/gitlab/favorites) seem to like it.
diff --git a/VERSION b/VERSION
index 027a8b7b3321de450a2602be95cfff28827c3704..25df36fff9d87b75312d5a06d98f9d84340f854d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-7.5.0.pre
+Version 7.5.3
diff --git a/app/assets/images/authbuttons/bitbucket_64.png b/app/assets/images/authbuttons/bitbucket_64.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b90a57bc7de93163275f99ea2971e2740af98af
Binary files /dev/null and b/app/assets/images/authbuttons/bitbucket_64.png differ
diff --git a/app/assets/images/authbuttons/github_32.png b/app/assets/images/authbuttons/github_32.png
deleted file mode 100644
index c56eef05eb981c1e2361312355dceecac3a7b5a4..0000000000000000000000000000000000000000
Binary files a/app/assets/images/authbuttons/github_32.png and /dev/null differ
diff --git a/app/assets/images/authbuttons/github_64.png b/app/assets/images/authbuttons/github_64.png
index 39de55bc7964dd263adfebcdd3f7260d7d7e21c0..dc7c03d10052a596f062207ae0fd8e9cf384b2aa 100644
Binary files a/app/assets/images/authbuttons/github_64.png and b/app/assets/images/authbuttons/github_64.png differ
diff --git a/app/assets/images/authbuttons/gitlab_64.png b/app/assets/images/authbuttons/gitlab_64.png
new file mode 100644
index 0000000000000000000000000000000000000000..31281a194441d4e23bb691de89110c6097021ac9
Binary files /dev/null and b/app/assets/images/authbuttons/gitlab_64.png differ
diff --git a/app/assets/images/authbuttons/google_32.png b/app/assets/images/authbuttons/google_32.png
deleted file mode 100644
index 6225cc9c2d77b8be6b060d212e1624b86935a46c..0000000000000000000000000000000000000000
Binary files a/app/assets/images/authbuttons/google_32.png and /dev/null differ
diff --git a/app/assets/images/authbuttons/google_64.png b/app/assets/images/authbuttons/google_64.png
index 4d608f710089bb406f9b3567270354434e7a58cd..94a0e089c6efe07dcb50af341d51c2d13b689639 100644
Binary files a/app/assets/images/authbuttons/google_64.png and b/app/assets/images/authbuttons/google_64.png differ
diff --git a/app/assets/images/authbuttons/twitter_32.png b/app/assets/images/authbuttons/twitter_32.png
deleted file mode 100644
index 696eb02484d27ee6d453cbb07189c9923780d24b..0000000000000000000000000000000000000000
Binary files a/app/assets/images/authbuttons/twitter_32.png and /dev/null differ
diff --git a/app/assets/images/authbuttons/twitter_64.png b/app/assets/images/authbuttons/twitter_64.png
index 2893274766f8bcfe2c3ee7604d912122ca9b1be3..5c9f14cb0771005efaa2ed050560298aa03131b3 100644
Binary files a/app/assets/images/authbuttons/twitter_64.png and b/app/assets/images/authbuttons/twitter_64.png differ
diff --git a/app/assets/images/bg-header.png b/app/assets/images/bg-header.png
index 9ecdaf4e2d50de747f5249860f10d6debc33cf4e..639271c6fafc58a2007f22478ba2d52e57c2a2ee 100644
Binary files a/app/assets/images/bg-header.png and b/app/assets/images/bg-header.png differ
diff --git a/app/assets/images/bg_fallback.png b/app/assets/images/bg_fallback.png
index d9066ad7d7b2e7f339bbf92c9968fd9ccd96887d..e5fe659ba63db076784a420b69bf188d898ef52f 100644
Binary files a/app/assets/images/bg_fallback.png and b/app/assets/images/bg_fallback.png differ
diff --git a/app/assets/images/brand_logo.png b/app/assets/images/brand_logo.png
index 09b1689ca455aaed6e30f7075a7972b8232fa75a..9c564bb61411bf4f0dec3e21aa86848ac70cbcb8 100644
Binary files a/app/assets/images/brand_logo.png and b/app/assets/images/brand_logo.png differ
diff --git a/app/assets/images/chosen-sprite.png b/app/assets/images/chosen-sprite.png
index d08e4b7e624c44f4fb862f23f046262780847490..3d936b07d443fb420a71cac72750537bb54ad2cd 100644
Binary files a/app/assets/images/chosen-sprite.png and b/app/assets/images/chosen-sprite.png differ
diff --git a/app/assets/images/dark-scheme-preview.png b/app/assets/images/dark-scheme-preview.png
index 6dac6cd8ca138921421a697b50181abbc357a517..2ef58e52549c6315b66a6dc960e4603de1c00d4b 100644
Binary files a/app/assets/images/dark-scheme-preview.png and b/app/assets/images/dark-scheme-preview.png differ
diff --git a/app/assets/images/diff_note_add.png b/app/assets/images/diff_note_add.png
index 8ec15b701fc0e806e45dbc10cda9ce068f606a0f..0084422e3303593e2f067c7de013413f393b0f88 100644
Binary files a/app/assets/images/diff_note_add.png and b/app/assets/images/diff_note_add.png differ
diff --git a/app/assets/images/gitorious-logo-black.png b/app/assets/images/gitorious-logo-black.png
new file mode 100644
index 0000000000000000000000000000000000000000..78f17a9af79dc2395acd9bcc2a391589dd6b6ed8
Binary files /dev/null and b/app/assets/images/gitorious-logo-black.png differ
diff --git a/app/assets/images/gitorious-logo-blue.png b/app/assets/images/gitorious-logo-blue.png
new file mode 100644
index 0000000000000000000000000000000000000000..4962cffba3153927ddd8cd5ff295fe4ca142bfa8
Binary files /dev/null and b/app/assets/images/gitorious-logo-blue.png differ
diff --git a/app/assets/images/icon-link.png b/app/assets/images/icon-link.png
index 32ade0fe9a37d114ff86789f34242a845f0c5294..60021d5ac47686cce70570d22bad6670082caf56 100644
Binary files a/app/assets/images/icon-link.png and b/app/assets/images/icon-link.png differ
diff --git a/app/assets/images/icon-search.png b/app/assets/images/icon-search.png
index 084b89e3a7cee5787bc3fae15596dab09c547cd7..3c1c146541d456a042db5768154a307b9b535e9d 100644
Binary files a/app/assets/images/icon-search.png and b/app/assets/images/icon-search.png differ
diff --git a/app/assets/images/icon_sprite.png b/app/assets/images/icon_sprite.png
index 9ad65fc443bdbbc50fa25797bced0680c8135b5c..2e7a5023398e7aa1d2794755af4f90d59b431919 100644
Binary files a/app/assets/images/icon_sprite.png and b/app/assets/images/icon_sprite.png differ
diff --git a/app/assets/images/images.png b/app/assets/images/images.png
index da91f6b1f4c31422a3890c3ad8a38bb418a1b81c..ad146246caf907144b468a121ef9524ba8ec3c74 100644
Binary files a/app/assets/images/images.png and b/app/assets/images/images.png differ
diff --git a/app/assets/images/logo-black.png b/app/assets/images/logo-black.png
deleted file mode 100644
index 4a96572d570108366da2cf5aa8213f69b591a2a3..0000000000000000000000000000000000000000
Binary files a/app/assets/images/logo-black.png and /dev/null differ
diff --git a/app/assets/images/logo-white.png b/app/assets/images/logo-white.png
index bc2ef601a538d69ef99d5bdafa605e63f902e8e4..917bcfcb7e750f8426dd79912ca525dc65183a56 100644
Binary files a/app/assets/images/logo-white.png and b/app/assets/images/logo-white.png differ
diff --git a/app/assets/images/monokai-scheme-preview.png b/app/assets/images/monokai-scheme-preview.png
index 3aeed886a02bcdc0d38467be744887a437fb99c1..fbb339c6a9170de79c5fee8fc2a5abd6a785f4e7 100644
Binary files a/app/assets/images/monokai-scheme-preview.png and b/app/assets/images/monokai-scheme-preview.png differ
diff --git a/app/assets/images/move.png b/app/assets/images/move.png
index 9d2d55ddf0b460d8effa80bca82340f5a6ca3341..6a0567f8f2534837e7280dd41e4bf4b98725a3bf 100644
Binary files a/app/assets/images/move.png and b/app/assets/images/move.png differ
diff --git a/app/assets/images/no_avatar.png b/app/assets/images/no_avatar.png
index dac3ab1bb890ee2b583ac5eaa060d972b6e35867..8287acbce13e32d0823c8f5fd449099c1c61d6cd 100644
Binary files a/app/assets/images/no_avatar.png and b/app/assets/images/no_avatar.png differ
diff --git a/app/assets/images/no_group_avatar.png b/app/assets/images/no_group_avatar.png
index a97d4515982bce6cb4973a8433b9ae0363e43d46..bfb31bb2184f6895c55c3027ddf9e357170bc338 100644
Binary files a/app/assets/images/no_group_avatar.png and b/app/assets/images/no_group_avatar.png differ
diff --git a/app/assets/images/slider_handles.png b/app/assets/images/slider_handles.png
index a6d477033fa5436fbad5409adcb549ac8d8f01e0..884378ec96a20c1cb2a419e1dc1aa68ab9d85c15 100644
Binary files a/app/assets/images/slider_handles.png and b/app/assets/images/slider_handles.png differ
diff --git a/app/assets/images/solarized-dark-scheme-preview.png b/app/assets/images/solarized-dark-scheme-preview.png
index ae092ab52139e10183efd5c175768a8e355f6678..7ed7336896b1daa3d06b3f304931bc2006a3b145 100644
Binary files a/app/assets/images/solarized-dark-scheme-preview.png and b/app/assets/images/solarized-dark-scheme-preview.png differ
diff --git a/app/assets/images/solarized-light-scheme-preview.png b/app/assets/images/solarized-light-scheme-preview.png
new file mode 100644
index 0000000000000000000000000000000000000000..c50db75449b974294a612f3215a673c7c2217f80
Binary files /dev/null and b/app/assets/images/solarized-light-scheme-preview.png differ
diff --git a/app/assets/images/switch_icon.png b/app/assets/images/switch_icon.png
index 6b8bde41bc95c15df2f7ce6d18330cce1181a76c..c6b6c8d9521f64b00990ca5352c8ce269e9a3e4a 100644
Binary files a/app/assets/images/switch_icon.png and b/app/assets/images/switch_icon.png differ
diff --git a/app/assets/images/trans_bg.gif b/app/assets/images/trans_bg.gif
index 5f6ed04a43c97debddc5c6be5697ba74d0504adf..1a1c9c15ec71a58db869578399068cf313c51599 100644
Binary files a/app/assets/images/trans_bg.gif and b/app/assets/images/trans_bg.gif differ
diff --git a/app/assets/images/white-scheme-preview.png b/app/assets/images/white-scheme-preview.png
index d1866e0015803d0180553d350dffa322b5d9f958..fc4c40b9227cced4692d9c3f0b3e09d62894fe3e 100644
Binary files a/app/assets/images/white-scheme-preview.png and b/app/assets/images/white-scheme-preview.png differ
diff --git a/app/assets/javascripts/activities.js.coffee b/app/assets/javascripts/activities.js.coffee
index 4f76d8ce48603ab849a4147a47e139d2a2238a22..777c62dc1b7773254cab7bfbe588166832a944dc 100644
--- a/app/assets/javascripts/activities.js.coffee
+++ b/app/assets/javascripts/activities.js.coffee
@@ -12,7 +12,7 @@ class @Activities
 
 
   toggleFilter: (sender) ->
-    sender.parent().toggleClass "inactive"
+    sender.parent().toggleClass "active"
     event_filters = $.cookie("event_filter")
     filter = sender.attr("id").split("_")[0]
     if event_filters
diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee
index fafa5cdfaa4c83d329af632c1269a605568c2c1d..9e5d594c861d6867308d9c47b571795fe5f51efd 100644
--- a/app/assets/javascripts/api.js.coffee
+++ b/app/assets/javascripts/api.js.coffee
@@ -1,61 +1,24 @@
 @Api =
-  users_path: "/api/:version/users.json"
-  user_path: "/api/:version/users/:id.json"
-  notes_path: "/api/:version/projects/:id/notes.json"
+  groups_path: "/api/:version/groups.json"
+  group_path: "/api/:version/groups/:id.json"
   namespaces_path: "/api/:version/namespaces.json"
-  project_users_path: "/api/:version/projects/:id/users.json"
 
-  # Get 20 (depends on api) recent notes
-  # and sort the ascending from oldest to newest
-  notes: (project_id, callback) ->
-    url = Api.buildUrl(Api.notes_path)
-    url = url.replace(':id', project_id)
-
-    $.ajax(
-      url: url,
-      data:
-        private_token: gon.api_token
-        gfm: true
-        recent: true
-      dataType: "json"
-    ).done (notes) ->
-      notes.sort (a, b) ->
-        return a.id - b.id
-      callback(notes)
-
-  user: (user_id, callback) ->
-    url = Api.buildUrl(Api.user_path)
-    url = url.replace(':id', user_id)
+  group: (group_id, callback) ->
+    url = Api.buildUrl(Api.group_path)
+    url = url.replace(':id', group_id)
 
     $.ajax(
       url: url
       data:
         private_token: gon.api_token
       dataType: "json"
-    ).done (user) ->
-      callback(user)
-
-  # Return users list. Filtered by query
-  # Only active users retrieved
-  users: (query, callback) ->
-    url = Api.buildUrl(Api.users_path)
-
-    $.ajax(
-      url: url
-      data:
-        private_token: gon.api_token
-        search: query
-        per_page: 20
-        active: true
-      dataType: "json"
-    ).done (users) ->
-      callback(users)
+    ).done (group) ->
+      callback(group)
 
-  # Return project users list. Filtered by query
-  # Only active users retrieved
-  projectUsers: (project_id, query, callback) ->
-    url = Api.buildUrl(Api.project_users_path)
-    url = url.replace(':id', project_id)
+  # Return groups list. Filtered by query
+  # Only active groups retrieved
+  groups: (query, skip_ldap, callback) ->
+    url = Api.buildUrl(Api.groups_path)
 
     $.ajax(
       url: url
@@ -63,10 +26,9 @@
         private_token: gon.api_token
         search: query
         per_page: 20
-        active: true
       dataType: "json"
-    ).done (users) ->
-      callback(users)
+    ).done (groups) ->
+      callback(groups)
 
   # Return namespaces list. Filtered by query
   namespaces: (query, callback) ->
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index e9a28c1215933da2a27689ea056e9b4c3fd41559..fda142293bc9b42daab5866d9c52f38339a8409e 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -16,16 +16,16 @@
 #= require jquery.scrollTo
 #= require jquery.blockUI
 #= require jquery.turbolinks
+#= require jquery.sticky-kit.min
 #= require turbolinks
+#= require autosave
 #= require bootstrap
-#= require password_strength
 #= require select2
 #= require raphael
 #= require g.raphael-min
 #= require g.bar-min
 #= require chart-lib.min
 #= require branch-graph
-#= require highlight.pack
 #= require ace/ace
 #= require ace/ext-searchbox
 #= require d3
@@ -33,7 +33,6 @@
 #= require nprogress
 #= require nprogress-turbolinks
 #= require dropzone
-#= require semantic-ui/sidebar
 #= require mousetrap
 #= require mousetrap/pause
 #= require shortcuts
@@ -41,6 +40,7 @@
 #= require shortcuts_dashboard_navigation
 #= require shortcuts_issueable
 #= require shortcuts_network
+#= require cal-heatmap
 #= require_tree .
 
 window.slugify = (text) ->
@@ -51,12 +51,6 @@ window.ajaxGet = (url) ->
 
 window.showAndHide = (selector) ->
 
-window.errorMessage = (message) ->
-  ehtml = $("<p>")
-  ehtml.addClass("error_message")
-  ehtml.html(message)
-  ehtml
-
 window.split = (val) ->
   return val.split( /,\s*/ )
 
@@ -82,24 +76,18 @@ window.disableButtonIfEmptyField = (field_selector, button_selector) ->
 # Disable button if any input field with given selector is empty
 window.disableButtonIfAnyEmptyField = (form, form_selector, button_selector) ->
   closest_submit = form.find(button_selector)
-  empty = false
-  form.find('input').filter(form_selector).each ->
-    empty = true if rstrip($(this).val()) is ""
-
-  if empty
-    closest_submit.disable()
-  else
-    closest_submit.enable()
-
-  form.keyup ->
-    empty = false
+  updateButtons = ->
+    filled = true
     form.find('input').filter(form_selector).each ->
-      empty = true if rstrip($(this).val()) is ""
+      filled = rstrip($(this).val()) != "" || !$(this).attr('required')
 
-    if empty
-      closest_submit.disable()
-    else
+    if filled
       closest_submit.enable()
+    else
+      closest_submit.disable()
+
+  updateButtons()
+  form.keyup(updateButtons)
 
 window.sanitize = (str) ->
   return str.replace(/<(?:.|\n)*?>/gm, '')
@@ -115,8 +103,17 @@ window.unbindEvents = ->
   $(document).unbind('scroll')
   $(document).off('scroll')
 
+window.shiftWindow = ->
+  scrollBy 0, -50
+
 document.addEventListener("page:fetch", unbindEvents)
 
+# Scroll the window to avoid the topnav bar
+# https://github.com/twitter/bootstrap/issues/1768
+if location.hash
+  setTimeout shiftWindow, 1
+window.addEventListener "hashchange", shiftWindow
+
 $ ->
   # Click a .one_click_select field, select the contents
   $(".one_click_select").on 'click', -> $(@).select()
@@ -172,9 +169,7 @@ $ ->
 
   # Show/hide comments on diff
   $("body").on "click", ".js-toggle-diff-comments", (e) ->
-    $(@).find('i').
-      toggleClass('fa fa-chevron-down').
-      toggleClass('fa fa-chevron-up')
+    $(@).toggleClass('active')
     $(@).closest(".diff-file").find(".notes_holder").toggle()
     e.preventDefault()
 
@@ -185,6 +180,8 @@ $ ->
     form = btn.closest("form")
     new ConfirmDangerModal(form, text)
 
+  new Aside()
+
 (($) ->
   # Disable an element and add the 'disabled' Bootstrap class
   $.fn.extend disable: ->
diff --git a/app/assets/javascripts/aside.js.coffee b/app/assets/javascripts/aside.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..854731019443e3ea1d49e73a3fa5a12e5fc00185
--- /dev/null
+++ b/app/assets/javascripts/aside.js.coffee
@@ -0,0 +1,17 @@
+class @Aside
+  constructor: ->
+    $(document).off "click", "a.show-aside"
+    $(document).on "click", 'a.show-aside', (e) ->
+      e.preventDefault()
+      btn = $(e.currentTarget)
+      icon = btn.find('i')
+      console.log('1')
+
+      if icon.hasClass('fa-angle-left')
+        btn.parent().find('section').hide()
+        btn.parent().find('aside').fadeIn()
+        icon.removeClass('fa-angle-left').addClass('fa-angle-right')
+      else
+        btn.parent().find('aside').hide()
+        btn.parent().find('section').fadeIn()
+        icon.removeClass('fa-angle-right').addClass('fa-angle-left')
diff --git a/app/assets/javascripts/autosave.js.coffee b/app/assets/javascripts/autosave.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..5d3fe81da74aefe071aaf29f905d29f39a898859
--- /dev/null
+++ b/app/assets/javascripts/autosave.js.coffee
@@ -0,0 +1,39 @@
+class @Autosave
+  constructor: (field, key) ->
+    @field = field
+
+    key = key.join("/") if key.join?
+    @key = "autosave/#{key}"
+
+    @field.data "autosave", this
+
+    @restore()
+
+    @field.on "input", => @save()
+
+  restore: ->
+    return unless window.localStorage?
+
+    try
+      text = window.localStorage.getItem @key
+    catch
+      return
+
+    @field.val text if text?.length > 0
+    @field.trigger "input"    
+
+  save: ->
+    return unless window.localStorage?
+
+    text = @field.val()
+    if text?.length > 0
+      try
+        window.localStorage.setItem @key, text
+    else
+      @reset()
+
+  reset: ->
+    return unless window.localStorage?
+
+    try 
+      window.localStorage.removeItem @key
diff --git a/app/assets/javascripts/behaviors/toggle_diff_line_wrap_behavior.coffee b/app/assets/javascripts/behaviors/toggle_diff_line_wrap_behavior.coffee
deleted file mode 100644
index 691ed4f98aeaee5f8db47b0dea943507cd22655d..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/behaviors/toggle_diff_line_wrap_behavior.coffee
+++ /dev/null
@@ -1,14 +0,0 @@
-$ ->
-  # Toggle line wrapping in diff.
-  #
-  # %div.diff-file
-  #   %input.js-toggle-diff-line-wrap
-  #   %td.line_content
-  #
-  $("body").on "click", ".js-toggle-diff-line-wrap", (e) ->
-    diffFile = $(@).closest(".diff-file")
-    if $(@).is(":checked")
-      diffFile.addClass("diff-wrap-lines")
-    else
-      diffFile.removeClass("diff-wrap-lines")
-
diff --git a/app/assets/javascripts/blob.js.coffee b/app/assets/javascripts/blob/blob.js.coffee
similarity index 97%
rename from app/assets/javascripts/blob.js.coffee
rename to app/assets/javascripts/blob/blob.js.coffee
index a5f15f80c5c66bfe41f8791a395dfd58826fb43a..37a175fdbc725fdaceb0187ab73547063c0821bb 100644
--- a/app/assets/javascripts/blob.js.coffee
+++ b/app/assets/javascripts/blob/blob.js.coffee
@@ -26,7 +26,7 @@ class @BlobView
       unless isNaN first_line
         $("#tree-content-holder .highlight .line").removeClass("hll")
         $("#LC#{line}").addClass("hll") for line in [first_line..last_line]
-        $.scrollTo("#L#{first_line}") unless e?
+        $.scrollTo("#L#{first_line}", offset: -50) unless e?
 
     # parse selected lines from hash
     # always return first and last line (initialized to NaN)
diff --git a/app/assets/javascripts/blob/edit_blob.js.coffee b/app/assets/javascripts/blob/edit_blob.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..2e91a06daa8b900eda0d91f1721ce26a30d842be
--- /dev/null
+++ b/app/assets/javascripts/blob/edit_blob.js.coffee
@@ -0,0 +1,44 @@
+class @EditBlob
+  constructor: (assets_path, mode)->
+    ace.config.set "modePath", assets_path + '/ace'
+    ace.config.loadModule "ace/ext/searchbox"
+    if mode
+      ace_mode = mode
+    editor = ace.edit("editor")
+    editor.focus()
+    @editor = editor
+
+    if ace_mode
+      editor.getSession().setMode "ace/mode/" + ace_mode
+
+    disableButtonIfEmptyField "#commit_message", ".js-commit-button"
+    $(".js-commit-button").click ->
+      $("#file-content").val editor.getValue()
+      $(".file-editor form").submit()
+      return false
+
+    editModePanes = $(".js-edit-mode-pane")
+    editModeLinks = $(".js-edit-mode a")
+    editModeLinks.click (event) ->
+      event.preventDefault()
+      currentLink = $(this)
+      paneId = currentLink.attr("href")
+      currentPane = editModePanes.filter(paneId)
+      editModeLinks.parent().removeClass "active hover"
+      currentLink.parent().addClass "active hover"
+      editModePanes.hide()
+      if paneId is "#preview"
+        currentPane.fadeIn 200
+        $.post currentLink.data("preview-url"),
+          content: editor.getValue()
+        , (response) ->
+          currentPane.empty().append response
+          return
+
+      else
+        currentPane.fadeIn 200
+        editor.focus()
+      return
+
+  editor: ->
+    return @editor
diff --git a/app/assets/javascripts/blob/new_blob.js.coffee b/app/assets/javascripts/blob/new_blob.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..ab8f98715e86edf03dbc0d142e079958ae50d756
--- /dev/null
+++ b/app/assets/javascripts/blob/new_blob.js.coffee
@@ -0,0 +1,21 @@
+class @NewBlob
+  constructor: (assets_path, mode)->
+    ace.config.set "modePath", assets_path + '/ace'
+    ace.config.loadModule "ace/ext/searchbox"
+    if mode
+      ace_mode = mode
+    editor = ace.edit("editor")
+    editor.focus()
+    @editor = editor
+
+    if ace_mode
+      editor.getSession().setMode "ace/mode/" + ace_mode
+
+    disableButtonIfEmptyField "#commit_message", ".js-commit-button"
+    $(".js-commit-button").click ->
+      $("#file-content").val editor.getValue()
+      $(".file-editor form").submit()
+      return false
+
+  editor: ->
+    return @editor
diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..44d75bd694f009aa8db8915c26179f1be2626f30
--- /dev/null
+++ b/app/assets/javascripts/calendar.js.coffee
@@ -0,0 +1,38 @@
+class @Calendar
+  options =
+    month: "short"
+    day: "numeric"
+    year: "numeric"
+
+  constructor: (timestamps, starting_year, starting_month, calendar_activities_path) ->
+    cal = new CalHeatMap()
+    cal.init
+      itemName: ["contribution"]
+      data: timestamps
+      start: new Date(starting_year, starting_month)
+      domainLabelFormat: "%b"
+      id: "cal-heatmap"
+      domain: "month"
+      subDomain: "day"
+      range: 12
+      tooltip: true
+      label:
+        position: "top"
+      legend: [
+        0
+        10
+        20
+        30
+      ]
+      legendCellPadding: 3
+      onClick: (date, count) ->
+        formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
+        $.ajax
+          url: calendar_activities_path
+          data:
+            date: formated_date
+          cache: false
+          dataType: "html"
+          success: (data) ->
+            $(".user-calendar-activities").html data
+
diff --git a/app/assets/javascripts/dashboard.js.coffee b/app/assets/javascripts/dashboard.js.coffee
index 6ef5a539b8fede86d194cf85ee8564a1242bc3ae..00ee503ff165c56ecafb3e63bd070cb465c8954d 100644
--- a/app/assets/javascripts/dashboard.js.coffee
+++ b/app/assets/javascripts/dashboard.js.coffee
@@ -1,30 +1,3 @@
 class @Dashboard
   constructor: ->
-    @initSidebarTab()
-
-    $(".dash-filter").keyup ->
-      terms = $(this).val()
-      uiBox = $(this).parents('.panel').first()
-      if terms == "" || terms == undefined
-        uiBox.find(".dash-list li").show()
-      else
-        uiBox.find(".dash-list li").each (index) ->
-          name = $(this).find(".filter-title").text()
-
-          if name.toLowerCase().search(terms.toLowerCase()) == -1
-            $(this).hide()
-          else
-            $(this).show()
-
-
-
-  initSidebarTab: ->
-    key = "dashboard_sidebar_filter"
-
-    # store selection in cookie
-    $('.dash-sidebar-tabs a').on 'click', (e) ->
-      $.cookie(key, $(e.target).attr('id'))
-
-    # show tab from cookie
-    sidebar_filter = $.cookie(key)
-    $("#" + sidebar_filter).tab('show') if sidebar_filter
+    new ProjectsList()
diff --git a/app/assets/javascripts/diff.js.coffee b/app/assets/javascripts/diff.js.coffee
index 52b4208524ff80afabcc076fab555094418d1a31..069f91c30e1027dc4ccca0cf5d10ad9dc9727db7 100644
--- a/app/assets/javascripts/diff.js.coffee
+++ b/app/assets/javascripts/diff.js.coffee
@@ -1,6 +1,7 @@
 class @Diff
   UNFOLD_COUNT = 20
   constructor: ->
+    $(document).off('click', '.js-unfold')
     $(document).on('click', '.js-unfold', (event) =>
       target = $(event.target)
       unfoldBottom = target.hasClass('js-unfold-bottom')
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index fb1adbc4b3d03a424de86d5ccd2feed9c393c0f5..821712f751211752ef6f2655b5b3db29e929abfc 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -4,7 +4,6 @@ $ ->
 class Dispatcher
   constructor: () ->
     @initSearch()
-    @initHighlight()
     @initPageScripts()
 
   initPageScripts: ->
@@ -27,40 +26,61 @@ class Dispatcher
         new ZenMode()
       when 'projects:milestones:show'
         new Milestone()
-      when 'projects:milestones:new'
+      when 'projects:milestones:new', 'projects:milestones:edit'
         new ZenMode()
+      when 'projects:compare:show'
+        new Diff()
       when 'projects:issues:new','projects:issues:edit'
         GitLab.GfmAutoComplete.setup()
         shortcut_handler = new ShortcutsNavigation()
         new ZenMode()
+        new DropzoneInput($('.issue-form'))
+        if page == 'projects:issues:new'
+          new IssuableForm($('.issue-form'))
       when 'projects:merge_requests:new', 'projects:merge_requests:edit'
         GitLab.GfmAutoComplete.setup()
         new Diff()
         shortcut_handler = new ShortcutsNavigation()
         new ZenMode()
+        new DropzoneInput($('.merge-request-form'))
+        if page == 'projects:merge_requests:new'
+          new IssuableForm($('.merge-request-form'))
       when 'projects:merge_requests:show'
         new Diff()
         shortcut_handler = new ShortcutsIssueable()
         new ZenMode()
       when "projects:merge_requests:diffs"
         new Diff()
+        new ZenMode()
       when 'projects:merge_requests:index'
         shortcut_handler = new ShortcutsNavigation()
+        MergeRequests.init()
       when 'dashboard:show'
         new Dashboard()
         new Activities()
+      when 'dashboard:projects:starred'
+        new Activities()
+        new ProjectsList()
       when 'projects:commit:show'
         new Commit()
         new Diff()
+        new ZenMode()
         shortcut_handler = new ShortcutsNavigation()
       when 'projects:commits:show'
         shortcut_handler = new ShortcutsNavigation()
-      when 'groups:show', 'projects:show'
+      when 'projects:show'
+        new Activities()
+        shortcut_handler = new ShortcutsNavigation()
+      when 'groups:show'
         new Activities()
         shortcut_handler = new ShortcutsNavigation()
-      when 'groups:members'
+        new ProjectsList()
+      when 'groups:group_members:index'
         new GroupMembers()
         new UsersSelect()
+      when 'projects:project_members:index'
+        new ProjectMembers()
+        new UsersSelect()
       when 'groups:new', 'groups:edit', 'admin:groups:edit'
         new GroupAvatar()
       when 'projects:tree:show'
@@ -75,8 +95,11 @@ class Dispatcher
         # Ensure we don't create a particular shortcut handler here. This is
         # already created, where the network graph is created.
         shortcut_handler = true
+      when 'projects:forks:new'
+        new ProjectFork()
       when 'users:show'
         new User()
+        new Activities()
 
     switch path.first()
       when 'admin'
@@ -92,7 +115,10 @@ class Dispatcher
         new Profile()
       when 'projects'
         new Project()
+        new ProjectAvatar()
         switch path[1]
+          when 'compare'
+            shortcut_handler = new ShortcutsNavigation()
           when 'edit'
             shortcut_handler = new ShortcutsNavigation()
             new ProjectNew()
@@ -101,16 +127,16 @@ class Dispatcher
           when 'show'
             new ProjectShow()
           when 'issues', 'merge_requests'
-            new ProjectUsersSelect()
+            new UsersSelect()
           when 'wikis'
             new Wikis()
             shortcut_handler = new ShortcutsNavigation()
             new ZenMode()
+            new DropzoneInput($('.wiki-form'))
           when 'snippets', 'labels', 'graphs'
             shortcut_handler = new ShortcutsNavigation()
-          when 'team_members', 'deploy_keys', 'hooks', 'services', 'protected_branches'
+          when 'project_members', 'deploy_keys', 'hooks', 'services', 'protected_branches'
             shortcut_handler = new ShortcutsNavigation()
-            new UsersSelect()
 
 
     # If we haven't installed a custom shortcut handler, install the default one
@@ -124,10 +150,3 @@ class Dispatcher
     project_ref = opts.data('autocomplete-project-ref')
 
     new SearchAutocomplete(path, project_id, project_ref)
-
-  initHighlight: ->
-    $('.highlight pre code').each (i, e) ->
-      $(e).html($.map($(e).html().split("\n"), (line, i) ->
-        "<span class='line' id='LC" + (i + 1) + "'>" + line + "</span>"
-      ).join("\n"))
-      hljs.highlightBlock(e)
diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..06e9f0001ae9064dbb5bb74a74267e0da98d8895
--- /dev/null
+++ b/app/assets/javascripts/dropzone_input.js.coffee
@@ -0,0 +1,240 @@
+class @DropzoneInput
+  constructor: (form) ->
+    Dropzone.autoDiscover = false
+    alertClass = "alert alert-danger alert-dismissable div-dropzone-alert"
+    alertAttr = "class=\"close\" data-dismiss=\"alert\"" + "aria-hidden=\"true\""
+    divHover = "<div class=\"div-dropzone-hover\"></div>"
+    divSpinner = "<div class=\"div-dropzone-spinner\"></div>"
+    divAlert = "<div class=\"" + alertClass + "\"></div>"
+    iconPaperclip = "<i class=\"fa fa-paperclip div-dropzone-icon\"></i>"
+    iconSpinner = "<i class=\"fa fa-spinner fa-spin div-dropzone-icon\"></i>"
+    btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>"
+    project_uploads_path = window.project_uploads_path or null
+
+    form_textarea = $(form).find("textarea.markdown-area")
+    form_textarea.wrap "<div class=\"div-dropzone\"></div>"
+    form_textarea.bind 'paste', (event) =>
+      handlePaste(event)
+
+    form_dropzone = $(form).find('.div-dropzone')
+    form_dropzone.parent().addClass "div-dropzone-wrapper"
+    form_dropzone.append divHover
+    $(".div-dropzone-hover").append iconPaperclip
+    form_dropzone.append divSpinner
+    $(".div-dropzone-spinner").append iconSpinner
+    $(".div-dropzone-spinner").css
+      "opacity": 0
+      "display": "none"
+
+    # Preview button
+    $(document).off "click", ".js-md-preview-button"
+    $(document).on "click", ".js-md-preview-button", (e) ->
+      ###
+      Shows the Markdown preview.
+
+      Lets the server render GFM into Html and displays it.
+      ###
+      e.preventDefault()
+      form = $(this).closest("form")
+      # toggle tabs
+      form.find(".js-md-write-button").parent().removeClass "active"
+      form.find(".js-md-preview-button").parent().addClass "active"
+
+      # toggle content
+      form.find(".md-write-holder").hide()
+      form.find(".md-preview-holder").show()
+
+      preview = form.find(".js-md-preview")
+      mdText = form.find(".markdown-area").val()
+      if mdText.trim().length is 0
+        preview.text "Nothing to preview."
+      else
+        preview.text "Loading..."
+        $.post($(this).data("url"),
+          md_text: mdText
+        ).success (previewData) ->
+          preview.html previewData
+
+    # Write button
+    $(document).off "click", ".js-md-write-button"
+    $(document).on "click", ".js-md-write-button", (e) ->
+      ###
+      Shows the Markdown textarea.
+      ###
+      e.preventDefault()
+      form = $(this).closest("form")
+      # toggle tabs
+      form.find(".js-md-write-button").parent().addClass "active"
+      form.find(".js-md-preview-button").parent().removeClass "active"
+
+      # toggle content
+      form.find(".md-write-holder").show()
+      form.find(".md-preview-holder").hide()
+
+    dropzone = form_dropzone.dropzone(
+      url: project_uploads_path
+      dictDefaultMessage: ""
+      clickable: true
+      paramName: "file"
+      maxFilesize: 10
+      uploadMultiple: false
+      headers:
+        "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
+
+      previewContainer: false
+
+      processing: ->
+        $(".div-dropzone-alert").alert "close"
+
+      dragover: ->
+        form_textarea.addClass "div-dropzone-focus"
+        form.find(".div-dropzone-hover").css "opacity", 0.7
+        return
+
+      dragleave: ->
+        form_textarea.removeClass "div-dropzone-focus"
+        form.find(".div-dropzone-hover").css "opacity", 0
+        return
+
+      drop: ->
+        form_textarea.removeClass "div-dropzone-focus"
+        form.find(".div-dropzone-hover").css "opacity", 0
+        form_textarea.focus()
+        return
+
+      success: (header, response) ->
+        child = $(dropzone[0]).children("textarea")
+        $(child).val $(child).val() + formatLink(response.link) + "\n"
+        return
+
+      error: (temp, errorMessage) ->
+        checkIfMsgExists = $(".error-alert").children().length
+        if checkIfMsgExists is 0
+          $(".error-alert").append divAlert
+          $(".div-dropzone-alert").append btnAlert + errorMessage
+        return
+
+      sending: ->
+        form_dropzone.find(".div-dropzone-spinner").css
+          "opacity": 0.7
+          "display": "inherit"
+        return
+
+      complete: ->
+        $(".dz-preview").remove()
+        $(".markdown-area").trigger "input"
+        $(".div-dropzone-spinner").css
+          "opacity": 0
+          "display": "none"
+        return
+    )
+
+    child = $(dropzone[0]).children("textarea")
+
+    formatLink = (link) ->
+      text = "[#{link.alt}](#{link.url})"
+      text = "!#{text}" if link.is_image
+      text
+
+    handlePaste = (event) ->
+      pasteEvent = event.originalEvent
+      if pasteEvent.clipboardData and pasteEvent.clipboardData.items
+        image = isImage(pasteEvent)
+        if image
+          event.preventDefault()
+
+          filename = getFilename(pasteEvent) or "image.png"
+          text = "{{" + filename + "}}"
+          pasteText(text)
+          uploadFile image.getAsFile(), filename
+
+    isImage = (data) ->
+      i = 0
+      while i < data.clipboardData.items.length
+        item = data.clipboardData.items[i]
+        if item.type.indexOf("image") isnt -1
+          return item
+        i++
+      return false
+
+    pasteText = (text) ->
+      caretStart = $(child)[0].selectionStart
+      caretEnd = $(child)[0].selectionEnd
+      textEnd = $(child).val().length
+
+      beforeSelection = $(child).val().substring 0, caretStart
+      afterSelection = $(child).val().substring caretEnd, textEnd
+      $(child).val beforeSelection + text + afterSelection
+      form_textarea.trigger "input"
+
+    getFilename = (e) ->
+      if window.clipboardData and window.clipboardData.getData
+        value = window.clipboardData.getData("Text")
+      else if e.clipboardData and e.clipboardData.getData
+        value = e.clipboardData.getData("text/plain")
+
+      value = value.split("\r")
+      value.first()
+
+    uploadFile = (item, filename) ->
+      formData = new FormData()
+      formData.append "file", item, filename
+      $.ajax
+        url: project_uploads_path
+        type: "POST"
+        data: formData
+        dataType: "json"
+        processData: false
+        contentType: false
+        headers:
+          "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
+
+        beforeSend: ->
+          showSpinner()
+          closeAlertMessage()
+
+        success: (e, textStatus, response) ->
+          insertToTextArea(filename, formatLink(response.responseJSON.link))
+
+        error: (response) ->
+          showError(response.responseJSON.message)
+
+        complete: ->
+          closeSpinner()
+
+    insertToTextArea = (filename, url) ->
+      $(child).val (index, val) ->
+        val.replace("{{" + filename + "}}", url + "\n")
+
+    appendToTextArea = (url) ->
+      $(child).val (index, val) ->
+        val + url + "\n"
+
+    showSpinner = (e) ->
+      form.find(".div-dropzone-spinner").css
+        "opacity": 0.7
+        "display": "inherit"
+
+    closeSpinner = ->
+      form.find(".div-dropzone-spinner").css
+        "opacity": 0
+        "display": "none"
+
+    showError = (message) ->
+      checkIfMsgExists = $(".error-alert").children().length
+      if checkIfMsgExists is 0
+        $(".error-alert").append divAlert
+        $(".div-dropzone-alert").append btnAlert + message
+
+    closeAlertMessage = ->
+      form.find(".div-dropzone-alert").alert "close"
+
+    form.find(".markdown-selector").click (e) ->
+      e.preventDefault()
+      $(@).closest('.gfm-form').find('.div-dropzone').click()
+      return
+
+  formatLink: (link) ->
+    text = "[#{link.alt}](#{link.url})"
+    text = "!#{text}" if link.is_image
+    text
\ No newline at end of file
diff --git a/app/assets/javascripts/groups_select.js.coffee b/app/assets/javascripts/groups_select.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..1084e2a17d191db263d3a039f5746b85dfaf909e
--- /dev/null
+++ b/app/assets/javascripts/groups_select.js.coffee
@@ -0,0 +1,41 @@
+class @GroupsSelect
+  constructor: ->
+    $('.ajax-groups-select').each (i, select) =>
+      skip_ldap = $(select).hasClass('skip_ldap')
+
+      $(select).select2
+        placeholder: "Search for a group"
+        multiple: $(select).hasClass('multiselect')
+        minimumInputLength: 0
+        query: (query) ->
+          Api.groups query.term, skip_ldap, (groups) ->
+            data = { results: groups }
+            query.callback(data)
+
+        initSelection: (element, callback) ->
+          id = $(element).val()
+          if id isnt ""
+            Api.group(id, callback)
+
+
+        formatResult: (args...) =>
+          @formatResult(args...)
+        formatSelection: (args...) =>
+          @formatSelection(args...)
+        dropdownCssClass: "ajax-groups-dropdown"
+        escapeMarkup: (m) -> # we do not want to escape markup since we are displaying html in results
+          m
+
+  formatResult: (group) ->
+    if group.avatar_url
+      avatar = group.avatar_url
+    else
+      avatar = gon.default_avatar_url
+
+    "<div class='group-result'>
+       <div class='group-name'>#{group.name}</div>
+       <div class='group-path'>#{group.path}</div>
+     </div>"
+
+  formatSelection: (group) ->
+    group.name
diff --git a/app/assets/javascripts/importer_status.js.coffee b/app/assets/javascripts/importer_status.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..be8d225e73b94ecd0b9a40c7a263461aae60055e
--- /dev/null
+++ b/app/assets/javascripts/importer_status.js.coffee
@@ -0,0 +1,35 @@
+class @ImporterStatus
+  constructor: (@jobs_url, @import_url) ->
+    this.initStatusPage()
+    this.setAutoUpdate()
+
+  initStatusPage: ->
+    $(".js-add-to-import").click (event) =>
+      new_namespace = null
+      tr = $(event.currentTarget).closest("tr")
+      id = tr.attr("id").replace("repo_", "")
+      if tr.find(".import-target input").length > 0
+        new_namespace = tr.find(".import-target input").prop("value")
+        tr.find(".import-target").empty().append(new_namespace + "/" + tr.find(".import-target").data("project_name"))
+      $.post @import_url, {repo_id: id, new_namespace: new_namespace}, dataType: 'script'
+
+    $(".js-import-all").click (event) =>
+      $(".js-add-to-import").each ->
+        $(this).click()
+
+  setAutoUpdate: ->
+    setInterval (=>
+      $.get @jobs_url, (data) =>
+        $.each data, (i, job) =>
+          job_item = $("#project_" + job.id)
+          status_field = job_item.find(".job-status")
+
+          if job.import_status == 'finished'
+            job_item.removeClass("active").addClass("success")
+            status_field.html('<span><i class="fa fa-check"></i> done</span>')
+          else if job.import_status == 'started'
+            status_field.html("<i class='fa fa-spinner fa-spin'></i> started")
+          else
+            status_field.html(job.import_status)
+
+    ), 4000
diff --git a/app/assets/javascripts/issuable_form.js.coffee b/app/assets/javascripts/issuable_form.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..abd58bcf9783bd3b801dfe5f214a4d34553a7ccc
--- /dev/null
+++ b/app/assets/javascripts/issuable_form.js.coffee
@@ -0,0 +1,28 @@
+class @IssuableForm
+  constructor: (@form) ->
+    @titleField       = @form.find("input[name*='[title]']")
+    @descriptionField = @form.find("textarea[name*='[description]']")
+
+    return unless @titleField.length && @descriptionField.length
+
+    @initAutosave()
+
+    @form.on "submit", @resetAutosave
+    @form.on "click", ".btn-cancel", @resetAutosave
+
+  initAutosave: ->
+    new Autosave @titleField, [
+      document.location.pathname,
+      document.location.search,
+      "title"
+    ]
+
+    new Autosave @descriptionField, [
+      document.location.pathname,
+      document.location.search,
+      "description"
+    ]
+
+  resetAutosave: =>
+    @titleField.data("autosave").reset()
+    @descriptionField.data("autosave").reset()
diff --git a/app/assets/javascripts/issue.js.coffee b/app/assets/javascripts/issue.js.coffee
index 597b4695a6daff1678d568747bc82b70a5dd9b82..bf71c144eaf314f5c99825812bb38fca011451cd 100644
--- a/app/assets/javascripts/issue.js.coffee
+++ b/app/assets/javascripts/issue.js.coffee
@@ -1,9 +1,9 @@
 class @Issue
   constructor: ->
     $('.edit-issue.inline-update input[type="submit"]').hide()
-    $(".issue-box .inline-update").on "change", "select", ->
+    $(".context .inline-update").on "change", "select", ->
       $(this).submit()
-    $(".issue-box .inline-update").on "change", "#issue_assignee_id", ->
+    $(".context .inline-update").on "change", "#issue_assignee_id", ->
       $(this).submit()
 
     if $("a.btn-close").length
@@ -15,3 +15,10 @@ class @Issue
       "issue"
       updateTaskState
     )
+
+    $('.issue-details').waitForImages ->
+      $('.issuable-affix').affix offset:
+        top: ->
+          @top = ($('.issuable-affix').offset().top - 70)
+        bottom: ->
+          @bottom = $('.footer').outerHeight(true)
diff --git a/app/assets/javascripts/issues.js.coffee b/app/assets/javascripts/issues.js.coffee
index 2499ad5ad80b7e0c363e1ff4cb4b7b6f891e486d..40bb9e9cb0cc45f1d79d96959b0635ba91379986 100644
--- a/app/assets/javascripts/issues.js.coffee
+++ b/app/assets/javascripts/issues.js.coffee
@@ -15,7 +15,7 @@
           $(this).html totalIssues + 1
         else
           $(this).html totalIssues - 1
-    $("body").on "click", ".issues-filters .dropdown-menu a", ->
+    $("body").on "click", ".issues-other-filters .dropdown-menu a", ->
       $('.issues-list').block(
         message: null,
         overlayCSS:
@@ -47,7 +47,7 @@
   initSearch: ->
     @timer = null
     $("#issue_search").keyup ->
-      clearTimeout(@timer);
+      clearTimeout(@timer)
       @timer = setTimeout(Issues.filterResults, 500)
 
   filterResults: =>
@@ -77,9 +77,9 @@
         ids.push $(value).attr("data-id")
 
       $("#update_issues_ids").val ids
-      $(".issues-filters").hide()
+      $(".issues-other-filters").hide()
       $(".issues_bulk_update").show()
     else
       $("#update_issues_ids").val []
       $(".issues_bulk_update").hide()
-      $(".issues-filters").show()
+      $(".issues-other-filters").show()
diff --git a/app/assets/javascripts/markdown_area.js.coffee b/app/assets/javascripts/markdown_area.js.coffee
deleted file mode 100644
index a0ebfc98ce6522be6c32833129d4742e6e9847d1..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/markdown_area.js.coffee
+++ /dev/null
@@ -1,196 +0,0 @@
-formatLink = (str) ->
-  "![" + str.alt + "](" + str.url + ")"
-
-$(document).ready ->
-  alertClass = "alert alert-danger alert-dismissable div-dropzone-alert"
-  alertAttr = "class=\"close\" data-dismiss=\"alert\"" + "aria-hidden=\"true\""
-  divHover = "<div class=\"div-dropzone-hover\"></div>"
-  divSpinner = "<div class=\"div-dropzone-spinner\"></div>"
-  divAlert = "<div class=\"" + alertClass + "\"></div>"
-  iconPicture = "<i class=\"fa fa-picture-o div-dropzone-icon\"></i>"
-  iconSpinner = "<i class=\"fa fa-spinner fa-spin div-dropzone-icon\"></i>"
-  btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>"
-  project_image_path_upload = window.project_image_path_upload or null
-
-  $("textarea.markdown-area").wrap "<div class=\"div-dropzone\"></div>"
-
-  $(".div-dropzone").parent().addClass "div-dropzone-wrapper"
-
-  $(".div-dropzone").append divHover
-  $(".div-dropzone-hover").append iconPicture
-  $(".div-dropzone").append divSpinner
-  $(".div-dropzone-spinner").append iconSpinner
-  $(".div-dropzone-spinner").css
-    "opacity": 0
-    "display": "none"
-
-  dropzone = $(".div-dropzone").dropzone(
-    url: project_image_path_upload
-    dictDefaultMessage: ""
-    clickable: true
-    paramName: "markdown_img"
-    maxFilesize: 10
-    uploadMultiple: false
-    acceptedFiles: "image/jpg,image/jpeg,image/gif,image/png"
-    headers:
-      "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
-
-    previewContainer: false
-
-    processing: ->
-      $(".div-dropzone-alert").alert "close"
-
-    dragover: ->
-      $(".div-dropzone > textarea").addClass "div-dropzone-focus"
-      $(".div-dropzone-hover").css "opacity", 0.7
-      return
-
-    dragleave: ->
-      $(".div-dropzone > textarea").removeClass "div-dropzone-focus"
-      $(".div-dropzone-hover").css "opacity", 0
-      return
-
-    drop: ->
-      $(".div-dropzone > textarea").removeClass "div-dropzone-focus"
-      $(".div-dropzone-hover").css "opacity", 0
-      $(".div-dropzone > textarea").focus()
-      return
-
-    success: (header, response) ->
-      child = $(dropzone[0]).children("textarea")
-      $(child).val $(child).val() + formatLink(response.link) + "\n"
-      return
-
-    error: (temp, errorMessage) ->
-      checkIfMsgExists = $(".error-alert").children().length
-      if checkIfMsgExists is 0
-        $(".error-alert").append divAlert
-        $(".div-dropzone-alert").append btnAlert + errorMessage
-      return
-
-    sending: ->
-      $(".div-dropzone-spinner").css
-        "opacity": 0.7
-        "display": "inherit"
-      return
-
-    complete: ->
-      $(".dz-preview").remove()
-      $(".markdown-area").trigger "input"
-      $(".div-dropzone-spinner").css
-        "opacity": 0
-        "display": "none"
-      return
-  )
-
-  child = $(dropzone[0]).children("textarea")
-
-  formatLink = (str) ->
-    "![" + str.alt + "](" + str.url + ")"
-
-  handlePaste = (e) ->
-    e.preventDefault()
-    my_event = e.originalEvent
-
-    if my_event.clipboardData and my_event.clipboardData.items
-      processItem(my_event)
-
-  processItem = (e) ->
-    image = isImage(e)
-    if image
-      filename = getFilename(e) or "image.png"
-      text = "{{" + filename + "}}"
-      pasteText(text)
-      uploadFile image.getAsFile(), filename
-
-    else
-      text = e.clipboardData.getData("text/plain")
-      pasteText(text)
-
-  isImage = (data) ->
-    i = 0
-    while i < data.clipboardData.items.length
-      item = data.clipboardData.items[i]
-      if item.type.indexOf("image") isnt -1
-        return item
-      i++
-    return false
-
-  pasteText = (text) ->
-    caretStart = $(child)[0].selectionStart
-    caretEnd = $(child)[0].selectionEnd
-    textEnd = $(child).val().length
-
-    beforeSelection = $(child).val().substring 0, caretStart
-    afterSelection = $(child).val().substring caretEnd, textEnd
-    $(child).val beforeSelection + text + afterSelection
-    $(".markdown-area").trigger "input"
-
-  getFilename = (e) ->
-    if window.clipboardData and window.clipboardData.getData
-      value = window.clipboardData.getData("Text")
-    else if e.clipboardData and e.clipboardData.getData
-      value = e.clipboardData.getData("text/plain")
-
-    value = value.split("\r")
-    value.first()
-
-  uploadFile = (item, filename) ->
-    formData = new FormData()
-    formData.append "markdown_img", item, filename
-    $.ajax
-      url: project_image_path_upload
-      type: "POST"
-      data: formData
-      dataType: "json"
-      processData: false
-      contentType: false
-      headers:
-        "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
-
-      beforeSend: ->
-        showSpinner()
-        closeAlertMessage()
-
-      success: (e, textStatus, response) ->
-        insertToTextArea(filename, formatLink(response.responseJSON.link))
-
-      error: (response) ->
-        showError(response.responseJSON.message)
-
-      complete: ->
-        closeSpinner()
-
-  insertToTextArea = (filename, url) ->
-    $(child).val (index, val) ->
-      val.replace("{{" + filename + "}}", url + "\n")
-
-  appendToTextArea = (url) ->
-    $(child).val (index, val) ->
-      val + url + "\n"
-
-  showSpinner = (e) ->
-    $(".div-dropzone-spinner").css
-      "opacity": 0.7
-      "display": "inherit"
-
-  closeSpinner = ->
-    $(".div-dropzone-spinner").css
-      "opacity": 0
-      "display": "none"
-
-  showError = (message) ->
-    checkIfMsgExists = $(".error-alert").children().length
-    if checkIfMsgExists is 0
-      $(".error-alert").append divAlert
-      $(".div-dropzone-alert").append btnAlert + message
-
-  closeAlertMessage = ->
-    $(".div-dropzone-alert").alert "close"
-
-  $(".markdown-selector").click (e) ->
-    e.preventDefault()
-    $(@).closest('.gfm-form').find('.div-dropzone').click()
-    return
-
-  return
diff --git a/app/assets/javascripts/merge_request.js.coffee b/app/assets/javascripts/merge_request.js.coffee
index 46e06424e5a2f83b7e0385a09e416d270d512fae..6127d2bb480a580778e8ada18cf2606cc2a04a47 100644
--- a/app/assets/javascripts/merge_request.js.coffee
+++ b/app/assets/javascripts/merge_request.js.coffee
@@ -20,15 +20,22 @@ class @MergeRequest
     if $("a.btn-close").length
       $("li.task-list-item input:checkbox").prop("disabled", false)
 
+    $('.merge-request-details').waitForImages ->
+      $('.issuable-affix').affix offset:
+        top: ->
+          @top = ($('.issuable-affix').offset().top - 70)
+        bottom: ->
+          @bottom = $('.footer').outerHeight(true)
+
   # Local jQuery finder
   $: (selector) ->
     this.$el.find(selector)
 
   initContextWidget: ->
     $('.edit-merge_request.inline-update input[type="submit"]').hide()
-    $(".issue-box .inline-update").on "change", "select", ->
+    $(".context .inline-update").on "change", "select", ->
       $(this).submit()
-    $(".issue-box .inline-update").on "change", "#merge_request_assignee_id", ->
+    $(".context .inline-update").on "change", "#merge_request_assignee_id", ->
       $(this).submit()
 
   initMergeWidget: ->
@@ -89,6 +96,10 @@ class @MergeRequest
         this.$('.merge-request-tabs .diffs-tab').addClass 'active'
         this.loadDiff() unless @diffs_loaded
         this.$('.diffs').show()
+        $(".diff-header").trigger("sticky_kit:recalc")
+      when 'commits'
+        this.$('.merge-request-tabs .commits-tab').addClass 'active'
+        this.$('.commits').show()
       else
         this.$('.merge-request-tabs .notes-tab').addClass 'active'
         this.$('.notes').show()
@@ -99,11 +110,17 @@ class @MergeRequest
 
   showCiState: (state) ->
     $('.ci_widget').hide()
-    allowed_states = ["failed", "running", "pending", "success"]
+    allowed_states = ["failed", "canceled", "running", "pending", "success"]
     if state in allowed_states
       $('.ci_widget.ci-' + state).show()
+      switch state
+        when "failed", "canceled"
+          @setMergeButtonClass('btn-danger')
+        when "running", "pending"
+          @setMergeButtonClass('btn-warning')
     else
       $('.ci_widget.ci-error').show()
+      @setMergeButtonClass('btn-danger')
 
   showCiCoverage: (coverage) ->
     cov_html = $('<span>')
@@ -114,7 +131,7 @@ class @MergeRequest
   loadDiff: (event) ->
     $.ajax
       type: 'GET'
-      url: this.$('.merge-request-tabs .diffs-tab a').attr('href')
+      url: this.$('.merge-request-tabs .diffs-tab a').attr('href') + ".json"
       beforeSend: =>
         this.$('.mr-loading-status .loading').show()
       complete: =>
@@ -132,3 +149,19 @@ class @MergeRequest
     this.$('.automerge_widget').hide()
     this.$('.merge-in-progress').hide()
     this.$('.automerge_widget.already_cannot_be_merged').show()
+
+  setMergeButtonClass: (css_class) ->
+    $('.accept_merge_request').removeClass("btn-create").addClass(css_class)
+
+  mergeInProgress: ->
+    $.ajax
+      type: 'GET'
+      url: $('.merge-request').data('url')
+      success: (data) =>
+        switch data.state
+          when 'merged'
+            location.reload()
+          else
+            setTimeout(merge_request.mergeInProgress, 3000)
+      dataType: 'json'
+
diff --git a/app/assets/javascripts/merge_requests.js.coffee b/app/assets/javascripts/merge_requests.js.coffee
index 9201c84c5edcf851d696993dda8fa7dac6aa7846..83434c1b9ba0e7b7702c63ae01f95506c400159a 100644
--- a/app/assets/javascripts/merge_requests.js.coffee
+++ b/app/assets/javascripts/merge_requests.js.coffee
@@ -1,8 +1,35 @@
 #
 # * Filter merge requests
 #
-@merge_requestsPage = ->
-  $('#assignee_id').select2()
-  $('#milestone_id').select2()
-  $('#milestone_id, #assignee_id').on 'change', ->
-    $(this).closest('form').submit()
+@MergeRequests =
+  init: ->
+    MergeRequests.initSearch()
+
+  # Make sure we trigger ajax request only after user stop typing
+  initSearch: ->
+    @timer = null
+    $("#issue_search").keyup ->
+      clearTimeout(@timer)
+      @timer = setTimeout(MergeRequests.filterResults, 500)
+
+  filterResults: =>
+    form = $("#issue_search_form")
+    search = $("#issue_search").val()
+    $('.merge-requests-holder').css("opacity", '0.5')
+    issues_url = form.attr('action') + '? '+ form.serialize()
+
+    $.ajax
+      type: "GET"
+      url: form.attr('action')
+      data: form.serialize()
+      complete: ->
+        $('.merge-requests-holder').css("opacity", '1.0')
+      success: (data) ->
+        $('.merge-requests-holder').html(data.html)
+        # Change url so if user reload a page - search results are saved
+        History.replaceState {page: issues_url}, document.title, issues_url
+        MergeRequests.reload()
+      dataType: "json"
+
+  reload: ->
+    $('#filter_issue_search').val($('#issue_search').val())
diff --git a/app/assets/javascripts/milestone.js.coffee b/app/assets/javascripts/milestone.js.coffee
index c42f31933d37b5e8f754307bdbd95e3557ca3afd..d644d50b66927a5bbb4a000630f6dec3dc9dc30e 100644
--- a/app/assets/javascripts/milestone.js.coffee
+++ b/app/assets/javascripts/milestone.js.coffee
@@ -49,6 +49,13 @@ class @Milestone
       data: data
       success: (data) ->
         if data.saved == true
+          if data.assignee_avatar_url
+            img_tag = $('<img/>')
+            img_tag.attr('src', data.assignee_avatar_url)
+            img_tag.addClass('avatar s16')
+            $(li).find('.assignee-icon').html(img_tag)
+          else
+            $(li).find('.assignee-icon').html('')
           $(li).effect 'highlight'
         else
           new Flash("Issue update failed", 'alert')
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee
index 978f83dd442c2d2570794eb2480525541b560505..6dfe10f000604a115a7799df3777089588276c95 100644
--- a/app/assets/javascripts/notes.js.coffee
+++ b/app/assets/javascripts/notes.js.coffee
@@ -36,17 +36,9 @@ class @Notes
     # delete note attachment
     $(document).on "click", ".js-note-attachment-delete", @removeAttachment
 
-    # Preview button
-    $(document).on "click", ".js-note-preview-button", @previewNote
-
-    # Preview button
-    $(document).on "click", ".js-note-write-button", @writeNote
-
     # reset main target form after submit
-    $(document).on "ajax:complete", ".js-main-target-form", @resetMainTargetForm
-
-    # attachment button
-    $(document).on "click", ".js-choose-note-attachment-button", @chooseNoteAttachment
+    $(document).on "ajax:complete", ".js-main-target-form", @reenableTargetFormSubmitButton
+    $(document).on "ajax:success", ".js-main-target-form", @resetMainTargetForm
 
     # update the file name when an attachment is selected
     $(document).on "change", ".js-note-attachment-input", @updateFormAttachment
@@ -64,8 +56,10 @@ class @Notes
     $(document).on "visibilitychange", @visibilityChange
 
     @notes_forms = '.js-main-target-form textarea, .js-discussion-note-form textarea'
-    $(document).on('keypress', @notes_forms, (e)->
-      if e.keyCode == 10 || (e.ctrlKey && e.keyCode == 13)
+    # Chrome doesn't fire keypress or keyup for Command+Enter, so we need keydown.
+    $(document).on('keydown', @notes_forms, (e) ->
+      return if e.originalEvent.repeat
+      if e.keyCode == 10 || ((e.metaKey || e.ctrlKey) && e.keyCode == 13)
         $(@).parents('form').submit()
     )
 
@@ -77,14 +71,12 @@ class @Notes
     $(document).off "click", ".note-edit-cancel"
     $(document).off "click", ".js-note-delete"
     $(document).off "click", ".js-note-attachment-delete"
-    $(document).off "click", ".js-note-preview-button"
-    $(document).off "click", ".js-note-write-button"
     $(document).off "ajax:complete", ".js-main-target-form"
-    $(document).off "click", ".js-choose-note-attachment-button"
+    $(document).off "ajax:success", ".js-main-target-form"
     $(document).off "click", ".js-discussion-reply-button"
     $(document).off "click", ".js-add-diff-note-button"
     $(document).off "visibilitychange"
-    $(document).off "keypress", @notes_forms
+    $(document).off "keydown", @notes_forms
     $(document).off "keyup", ".js-note-text"
     $(document).off "click", ".js-note-target-reopen"
     $(document).off "click", ".js-note-target-close"
@@ -122,10 +114,6 @@ class @Notes
     if @isNewNote(note)
       @note_ids.push(note.id)
       $('ul.main-notes-list').append(note.html)
-      code = "#note_" + note.id + " .highlight pre code"
-      $(code).each (i, e) ->
-        hljs.highlightBlock(e)
-
 
   ###
   Check if note does not exists on page
@@ -165,47 +153,6 @@ class @Notes
     # cleanup after successfully creating a diff/discussion note
     @removeDiscussionNoteForm(form)
 
-  ###
-  Shows write note textarea.
-  ###
-  writeNote: (e) ->
-    e.preventDefault()
-    form = $(this).closest("form")
-    # toggle tabs
-    form.find(".js-note-write-button").parent().addClass "active"
-    form.find(".js-note-preview-button").parent().removeClass "active"
-
-    # toggle content
-    form.find(".note-write-holder").show()
-    form.find(".note-preview-holder").hide()
-
-  ###
-  Shows the note preview.
-
-  Lets the server render GFM into Html and displays it.
-  ###
-  previewNote: (e) ->
-    e.preventDefault()
-    form = $(this).closest("form")
-    # toggle tabs
-    form.find(".js-note-write-button").parent().removeClass "active"
-    form.find(".js-note-preview-button").parent().addClass "active"
-
-    # toggle content
-    form.find(".note-write-holder").hide()
-    form.find(".note-preview-holder").show()
-
-    preview = form.find(".js-note-preview")
-    noteText = form.find(".js-note-text").val()
-    if noteText.trim().length is 0
-      preview.text "Nothing to preview."
-    else
-      preview.text "Loading..."
-      $.post($(this).data("url"),
-        note: noteText
-      ).success (previewData) ->
-        preview.html previewData
-
   ###
   Called in response the main target form has been successfully submitted.
 
@@ -220,17 +167,15 @@ class @Notes
     form.find(".js-errors").remove()
 
     # reset text and preview
-    form.find(".js-note-write-button").click()
+    form.find(".js-md-write-button").click()
     form.find(".js-note-text").val("").trigger "input"
 
-  ###
-  Called when clicking the "Choose File" button.
+    form.find(".js-note-text").data("autosave").reset()
 
-  Opens the file selection dialog.
-  ###
-  chooseNoteAttachment: ->
-    form = $(this).closest("form")
-    form.find(".js-note-attachment-input").click()
+  reenableTargetFormSubmitButton: ->
+    form = $(".js-main-target-form")
+
+    form.find(".js-note-text").trigger "input"
 
   ###
   Shows the main form and does some setup on it.
@@ -268,23 +213,34 @@ class @Notes
   setupNoteForm: (form) ->
     disableButtonIfEmptyField form.find(".js-note-text"), form.find(".js-comment-button")
     form.removeClass "js-new-note-form"
+    form.find('.div-dropzone').remove()
 
     # setup preview buttons
-    form.find(".js-note-write-button, .js-note-preview-button").tooltip placement: "left"
-    previewButton = form.find(".js-note-preview-button")
-    form.find(".js-note-text").on "input", ->
+    form.find(".js-md-write-button, .js-md-preview-button").tooltip placement: "left"
+    previewButton = form.find(".js-md-preview-button")
+
+    textarea = form.find(".js-note-text")
+
+    textarea.on "input", ->
       if $(this).val().trim() isnt ""
         previewButton.removeClass("turn-off").addClass "turn-on"
       else
         previewButton.removeClass("turn-on").addClass "turn-off"
 
+    new Autosave textarea, [
+      "Note"
+      form.find("#note_commit_id").val()
+      form.find("#note_line_code").val()
+      form.find("#note_noteable_type").val()
+      form.find("#note_noteable_id").val()
+    ]
 
     # remove notify commit author checkbox for non-commit notes
     form.find(".js-notify-commit-author").remove()  if form.find("#note_noteable_type").val() isnt "Commit"
     GitLab.GfmAutoComplete.setup()
+    new DropzoneInput(form)
     form.show()
 
-
   ###
   Called in response to the new note form being submitted
 
@@ -308,11 +264,10 @@ class @Notes
   Updates the current note field.
   ###
   updateNote: (xhr, note, status) =>
-    note_li = $("#note_" + note.id)
+    note_li = $(".note-row-" + note.id)
     note_li.replaceWith(note.html)
-    code = "#note_" + note.id + " .highlight pre code"
-    $(code).each (i, e) ->
-      hljs.highlightBlock(e)
+    note_li.find('.note-edit-form').hide()
+    note_li.find('.note-body > .note-text').show()
 
   ###
   Called in response to clicking the edit note link
@@ -324,12 +279,20 @@ class @Notes
   showEditForm: (e) ->
     e.preventDefault()
     note = $(this).closest(".note")
-    note.find(".note-text").hide()
+    note.find(".note-body > .note-text").hide()
+    note.find(".note-header").hide()
+    base_form = note.find(".note-edit-form")
+    form = base_form.clone().insertAfter(base_form)
+    form.addClass('current-note-edit-form')
+    form.find('.div-dropzone').remove()
 
     # Show the attachment delete link
     note.find(".js-note-attachment-delete").show()
+
+    # Setup markdown form
     GitLab.GfmAutoComplete.setup()
-    form = note.find(".note-edit-form")
+    new DropzoneInput(form)
+
     form.show()
     textarea = form.find("textarea")
     textarea.focus()
@@ -343,9 +306,9 @@ class @Notes
   cancelEdit: (e) ->
     e.preventDefault()
     note = $(this).closest(".note")
-    note.find(".note-text").show()
-    note.find(".js-note-attachment-delete").hide()
-    note.find(".note-edit-form").hide()
+    note.find(".note-body > .note-text").show()
+    note.find(".note-header").show()
+    note.find(".current-note-edit-form").remove()
 
   ###
   Called in response to deleting a note of any kind.
@@ -377,7 +340,7 @@ class @Notes
   removeAttachment: ->
     note = $(this).closest(".note")
     note.find(".note-attachment").remove()
-    note.find(".note-text").show()
+    note.find(".note-body > .note-text").show()
     note.find(".js-note-attachment-delete").hide()
     note.find(".note-edit-form").hide()
 
@@ -424,7 +387,7 @@ class @Notes
   ###
   addDiffNote: (e) =>
     e.preventDefault()
-    link = e.target
+    link = e.currentTarget
     form = $(".js-new-note-form")
     row = $(link).closest("tr")
     nextRow = row.next()
@@ -451,6 +414,8 @@ class @Notes
   removeDiscussionNoteForm: (form)->
     row = form.closest("tr")
 
+    form.find(".js-note-text").data("autosave").reset()
+
     # show the reply button (will only work for replies)
     form.prev(".js-discussion-reply-button").show()
     if row.is(".js-temp-notes-holder")
@@ -468,7 +433,7 @@ class @Notes
     @removeDiscussionNoteForm(form)
 
   updateVotes: ->
-    (new NotesVotes).updateVotes()
+    true
 
   ###
   Called after an attachment file has been selected.
diff --git a/app/assets/javascripts/notes_votes.js.coffee b/app/assets/javascripts/notes_votes.js.coffee
deleted file mode 100644
index 65c149b7886e490717b0f3d333d6ec448b90f487..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/notes_votes.js.coffee
+++ /dev/null
@@ -1,20 +0,0 @@
-class @NotesVotes
-  updateVotes: ->
-    votes = $("#votes .votes")
-    notes = $("#notes-list .note .vote")
-
-    # only update if there is a vote display
-    if votes.size()
-      upvotes = notes.filter(".upvote").size()
-      downvotes = notes.filter(".downvote").size()
-      votesCount = upvotes + downvotes
-      upvotesPercent = (if votesCount then (100.0 / votesCount * upvotes) else 0)
-      downvotesPercent = (if votesCount then (100.0 - upvotesPercent) else 0)
-
-      # change vote bar lengths
-      votes.find(".bar-success").css "width", upvotesPercent + "%"
-      votes.find(".bar-danger").css "width", downvotesPercent + "%"
-
-      # replace vote numbers
-      votes.find(".upvotes").text votes.find(".upvotes").text().replace(/\d+/, upvotes)
-      votes.find(".downvotes").text votes.find(".downvotes").text().replace(/\d+/, downvotes)
diff --git a/app/assets/javascripts/password_strength.js.coffee b/app/assets/javascripts/password_strength.js.coffee
deleted file mode 100644
index 825f56302661229a7ab620d68c22c57fe769db2f..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/password_strength.js.coffee
+++ /dev/null
@@ -1,31 +0,0 @@
-#= require pwstrength-bootstrap-1.2.2
-overwritten_messages =
-  wordSimilarToUsername: "Your password should not contain your username"
-
-overwritten_rules =
-  wordSequences: false
-
-options =
-  showProgressBar: false
-  showVerdicts: false
-  showPopover: true
-  showErrors: true
-  showStatus: true
-  errorMessages: overwritten_messages
-  
-$(document).ready ->
-  profileOptions = {}
-  profileOptions.ui = options
-  profileOptions.rules =
-    activated: overwritten_rules
-
-  deviseOptions = {}
-  deviseOptions.common =
-    usernameField: "#user_username"
-  deviseOptions.ui = options
-  deviseOptions.rules =
-    activated: overwritten_rules
-
-  $("#user_password_profile").pwstrength profileOptions
-  $("#user_password_sign_up").pwstrength deviseOptions
-  $("#user_password_recover").pwstrength deviseOptions
diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee
index 5a9cc66c8f0042e7eb3a90df9d7b1ea1e71e0708..eb8c1fa1426446ebb862f2a7b0165603e0f9edd8 100644
--- a/app/assets/javascripts/project.js.coffee
+++ b/app/assets/javascripts/project.js.coffee
@@ -16,5 +16,11 @@ class @Project
     $('.hide-no-ssh-message').on 'click', (e) ->
       path = '/'
       $.cookie('hide_no_ssh_message', 'false', { path: path })
-      $(@).parents('.no-ssh-key-message').hide()
+      $(@).parents('.no-ssh-key-message').remove()
+      e.preventDefault()
+
+    $('.hide-no-password-message').on 'click', (e) ->
+      path = '/'
+      $.cookie('hide_no_password_message', 'false', { path: path })
+      $(@).parents('.no-password-message').remove()
       e.preventDefault()
diff --git a/app/assets/javascripts/project_avatar.js.coffee b/app/assets/javascripts/project_avatar.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..8bec6e2ccca0046469046bd4b3f338cfec827a74
--- /dev/null
+++ b/app/assets/javascripts/project_avatar.js.coffee
@@ -0,0 +1,9 @@
+class @ProjectAvatar
+  constructor: ->
+    $('.js-choose-project-avatar-button').bind 'click', ->
+      form = $(this).closest('form')
+      form.find('.js-project-avatar-input').click()
+    $('.js-project-avatar-input').bind 'change', ->
+      form = $(this).closest('form')
+      filename = $(this).val().replace(/^.*[\\\/]/, '')
+      form.find('.js-avatar-filename').text(filename)
diff --git a/app/assets/javascripts/project_fork.js.coffee b/app/assets/javascripts/project_fork.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..e15a1c4ef76781725d3dac9c99471861dcfbe774
--- /dev/null
+++ b/app/assets/javascripts/project_fork.js.coffee
@@ -0,0 +1,5 @@
+class @ProjectFork
+  constructor: ->
+    $('.fork-thumbnail a').on 'click', ->
+      $('.fork-namespaces').hide()
+      $('.save-project-loader').show()
diff --git a/app/assets/javascripts/project_members.js.coffee b/app/assets/javascripts/project_members.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..896ba7e53eefeec6e78b1effb252255c7378c8cb
--- /dev/null
+++ b/app/assets/javascripts/project_members.js.coffee
@@ -0,0 +1,4 @@
+class @ProjectMembers
+  constructor: ->
+    $('li.project_member').bind 'ajax:success', ->
+      $(this).fadeOut()
diff --git a/app/assets/javascripts/project_new.js.coffee b/app/assets/javascripts/project_new.js.coffee
index f4a2ca813d2912368f8096115eb1a25e3d5ee50f..836269c44f93b22e3db6ac3b9a8a6756fbad2daa 100644
--- a/app/assets/javascripts/project_new.js.coffee
+++ b/app/assets/javascripts/project_new.js.coffee
@@ -9,17 +9,3 @@ class @ProjectNew
 
   initEvents: ->
     disableButtonIfEmptyField '#project_name', '.project-submit'
-
-    $('#project_issues_enabled').change ->
-      if ($(this).is(':checked') == true)
-        $('#project_issues_tracker').removeAttr('disabled')
-      else
-        $('#project_issues_tracker').attr('disabled', 'disabled')
-
-      $('#project_issues_tracker').change()
-
-    $('#project_issues_tracker').change ->
-      if ($(this).val() == gon.default_issues_tracker || $(this).is(':disabled'))
-        $('#project_issues_tracker_id').attr('disabled', 'disabled')
-      else
-        $('#project_issues_tracker_id').removeAttr('disabled')
diff --git a/app/assets/javascripts/project_show.js.coffee b/app/assets/javascripts/project_show.js.coffee
index 02a7d7b731d71023f2817dbb9cb10ffd0de5e290..6828ae471e51426e0c538712dd6b6b68bd1f4904 100644
--- a/app/assets/javascripts/project_show.js.coffee
+++ b/app/assets/javascripts/project_show.js.coffee
@@ -6,7 +6,7 @@ class @ProjectShow
       new Flash('Star toggle failed. Try again later.', 'alert')
 
     $("a[data-toggle='tab']").on "shown.bs.tab", (e) ->
-        $.cookie "default_view", $(e.target).attr("href")
+        $.cookie "default_view", $(e.target).attr("href"), { expires: 30, path: '/' }
 
       defaultView = $.cookie("default_view")
       if defaultView
diff --git a/app/assets/javascripts/project_users_select.js.coffee b/app/assets/javascripts/project_users_select.js.coffee
deleted file mode 100644
index 7fb33926096c1b86e3490f7337ed821863b44bd0..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/project_users_select.js.coffee
+++ /dev/null
@@ -1,58 +0,0 @@
-class @ProjectUsersSelect
-  constructor: ->
-    $('.ajax-project-users-select').each (i, select) =>
-      project_id = $(select).data('project-id') || $('body').data('project-id')
-
-      $(select).select2
-        placeholder: $(select).data('placeholder') || "Search for a user"
-        multiple: $(select).hasClass('multiselect')
-        minimumInputLength: 0
-        query: (query) ->
-          Api.projectUsers project_id, query.term, (users) ->
-            data = { results: users }
-
-            nullUser = {
-              name: 'Unassigned',
-              avatar: null,
-              username: 'none',
-              id: ''
-            }
-
-            data.results.unshift(nullUser)
-
-            query.callback(data)
-
-        initSelection: (element, callback) ->
-          id = $(element).val()
-          if id isnt ""
-            Api.user(id, callback)
-
-
-        formatResult: (args...) =>
-          @formatResult(args...)
-        formatSelection: (args...) =>
-          @formatSelection(args...)
-        dropdownCssClass: "ajax-project-users-dropdown"
-        dropdownAutoWidth: true
-        escapeMarkup: (m) -> # we do not want to escape markup since we are displaying html in results
-          m
-
-  formatResult: (user) ->
-    if user.avatar_url
-      avatar = user.avatar_url
-    else
-      avatar = gon.default_avatar_url
-
-    if user.id == ''
-      avatarMarkup = ''
-    else
-      avatarMarkup = "<div class='user-image'><img class='avatar s24' src='#{avatar}'></div>"
-
-    "<div class='user-result'>
-       #{avatarMarkup}
-       <div class='user-name'>#{user.name}</div>
-       <div class='user-username'>#{user.username}</div>
-     </div>"
-
-  formatSelection: (user) ->
-    user.name
diff --git a/app/assets/javascripts/projects_list.js.coffee b/app/assets/javascripts/projects_list.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..c0e36d1ccc5ce47b9c8ee4b2944d36829c9373ee
--- /dev/null
+++ b/app/assets/javascripts/projects_list.js.coffee
@@ -0,0 +1,24 @@
+class @ProjectsList
+  constructor: ->
+    $(".projects-list .js-expand").on 'click', (e) ->
+      e.preventDefault()
+      list = $(this).closest('.projects-list')
+      list.find("li").show()
+      list.find("li.bottom").hide()
+
+    $(".projects-list-filter").keyup ->
+      terms = $(this).val()
+      uiBox = $(this).closest('.panel')
+      if terms == "" || terms == undefined
+        uiBox.find(".projects-list li").show()
+      else
+        uiBox.find(".projects-list li").each (index) ->
+          name = $(this).find(".filter-title").text()
+
+          if name.toLowerCase().search(terms.toLowerCase()) == -1
+            $(this).hide()
+          else
+            $(this).show()
+      uiBox.find(".projects-list li.bottom").hide()
+
+
diff --git a/app/assets/javascripts/protected_branches.js.coffee b/app/assets/javascripts/protected_branches.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..5753c9d4e72140aca1c96772ffab88d36501dec4
--- /dev/null
+++ b/app/assets/javascripts/protected_branches.js.coffee
@@ -0,0 +1,21 @@
+$ ->
+  $(".protected-branches-list :checkbox").change (e) ->
+    name = $(this).attr("name")
+    if name == "developers_can_push"
+      id = $(this).val()
+      checked = $(this).is(":checked")
+      url = $(this).data("url")
+      $.ajax
+        type: "PUT"
+        url: url
+        dataType: "json"
+        data:
+          id: id
+          developers_can_push: checked
+
+        success: ->
+          row = $(e.target)
+          row.closest('tr').effect('highlight')
+
+        error: ->
+          new Flash("Failed to update branch!", "alert")
diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee
index c084d730d628a937e56c6f1ea5d005b97798f849..2e3f56082574a021af20bfee05d1f7b4225f40e6 100644
--- a/app/assets/javascripts/sidebar.js.coffee
+++ b/app/assets/javascripts/sidebar.js.coffee
@@ -1,26 +1,9 @@
-responsive_resize = ->
-  current_width = $(window).width()
-  if current_width < 985
-    $('.responsive-side').addClass("ui right wide sidebar")
-  else
-    $('.responsive-side').removeClass("ui right wide sidebar")
-
-$ ->
-  # Depending on window size, set the sidebar offscreen.
-  responsive_resize()
-
-  $('.sidebar-expand-button').click ->
-    $('.ui.sidebar')
-      .sidebar({overlay: true})
-      .sidebar('toggle')
-
-  # Hide sidebar on click outside of sidebar
-  $(document).mouseup (e) ->
-    container = $(".ui.sidebar")
-    container.sidebar "hide"  if not container.is(e.target) and container.has(e.target).length is 0
-    return
-
-# On resize, check if sidebar should be offscreen.
-$(window).resize ->
-  responsive_resize()
-  return
+$(document).on("click", '.toggle-nav-collapse', (e) ->
+  e.preventDefault()
+  collapsed = 'page-sidebar-collapsed'
+  expanded = 'page-sidebar-expanded'
+
+  $('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}")
+  $('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
+  $.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
+)
diff --git a/app/assets/javascripts/stat_graph_contributors_graph.js.coffee b/app/assets/javascripts/stat_graph_contributors_graph.js.coffee
index 9952fa0b00abd206729c3e4d973f3ff7544bdb44..8b82d20c6c25f2f9151d158ae448617bd778482b 100644
--- a/app/assets/javascripts/stat_graph_contributors_graph.js.coffee
+++ b/app/assets/javascripts/stat_graph_contributors_graph.js.coffee
@@ -46,7 +46,7 @@ class @ContributorsGraph
 
 class @ContributorsMasterGraph extends ContributorsGraph
   constructor: (@data) ->
-    @width = $('.container').width() - 70
+    @width = $('.container').width() - 345
     @height = 200
     @x = null
     @y = null
@@ -119,7 +119,7 @@ class @ContributorsMasterGraph extends ContributorsGraph
 
 class @ContributorsAuthorGraph extends ContributorsGraph
   constructor: (@data) ->
-    @width = $('.container').width()/2 - 100
+    @width = $('.container').width()/2 - 225
     @height = 200
     @x = null
     @y = null
diff --git a/app/assets/javascripts/subscription.js.coffee b/app/assets/javascripts/subscription.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..7f41616d4e781fd4565cf4f657260c15edb338ee
--- /dev/null
+++ b/app/assets/javascripts/subscription.js.coffee
@@ -0,0 +1,17 @@
+class @Subscription
+  constructor: (url) ->
+    $(".subscribe-button").unbind("click").click (event)=>
+      btn = $(event.currentTarget)
+      action = btn.find("span").text()
+      current_status = $(".subscription-status").attr("data-status")
+      btn.prop("disabled", true)
+      
+      $.post url, =>
+        btn.prop("disabled", false)
+        status = if current_status == "subscribed" then "unsubscribed" else "subscribed"
+        $(".subscription-status").attr("data-status", status)
+        action = if status == "subscribed" then "Unsubscribe" else "Subscribe"
+        btn.find("span").text(action)
+        $(".subscription-status>div").toggleClass("hidden")
+
+    
diff --git a/app/assets/javascripts/user.js.coffee b/app/assets/javascripts/user.js.coffee
index 8a2e2421c2eb454bde693a10c0aa4386a888fd35..d0d81f96921ac16630670b69567ae2ec61cee224 100644
--- a/app/assets/javascripts/user.js.coffee
+++ b/app/assets/javascripts/user.js.coffee
@@ -1,3 +1,4 @@
 class @User
   constructor: ->
     $('.profile-groups-avatars').tooltip("placement": "top")
+    new ProjectsList()
diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee
index 9eee7406511230d0fff181110e2592af4467fa3b..f464067686e622f2341a621476b7f63622ec23bf 100644
--- a/app/assets/javascripts/users_select.js.coffee
+++ b/app/assets/javascripts/users_select.js.coffee
@@ -1,20 +1,48 @@
 class @UsersSelect
   constructor: ->
+    @usersPath = "/autocomplete/users.json"
+    @userPath = "/autocomplete/users/:id.json"
+
     $('.ajax-users-select').each (i, select) =>
+      @projectId = $(select).data('project-id')
+      @groupId = $(select).data('group-id')
+      showNullUser = $(select).data('null-user')
+      showAnyUser = $(select).data('any-user')
+
       $(select).select2
         placeholder: "Search for a user"
         multiple: $(select).hasClass('multiselect')
         minimumInputLength: 0
-        query: (query) ->
-          Api.users query.term, (users) ->
+        query: (query) =>
+          @users query.term, (users) =>
             data = { results: users }
+
+            if query.term.length == 0
+              anyUser = {
+                name: 'Any',
+                avatar: null,
+                username: 'none',
+                id: null
+              }
+
+              nullUser = {
+                name: 'Unassigned',
+                avatar: null,
+                username: 'none',
+                id: 0
+              }
+
+              if showNullUser
+                data.results.unshift(nullUser)
+              if showAnyUser
+                data.results.unshift(anyUser)
+
             query.callback(data)
 
-        initSelection: (element, callback) ->
+        initSelection: (element, callback) =>
           id = $(element).val()
-          if id isnt ""
-            Api.user(id, callback)
-
+          if id != "" && id != "0"
+            @user(id, callback)
 
         formatResult: (args...) =>
           @formatResult(args...)
@@ -38,3 +66,34 @@ class @UsersSelect
 
   formatSelection: (user) ->
     user.name
+
+  user: (user_id, callback) =>
+    url = @buildUrl(@userPath)
+    url = url.replace(':id', user_id)
+
+    $.ajax(
+      url: url
+      dataType: "json"
+    ).done (user) ->
+      callback(user)
+
+  # Return users list. Filtered by query
+  # Only active users retrieved
+  users: (query, callback) =>
+    url = @buildUrl(@usersPath)
+
+    $.ajax(
+      url: url
+      data:
+        search: query
+        per_page: 20
+        active: true
+        project_id: @projectId
+        group_id: @groupId
+      dataType: "json"
+    ).done (users) ->
+      callback(users)
+
+  buildUrl: (url) ->
+    url = gon.relative_url_root + url if gon.relative_url_root?
+    return url
diff --git a/app/assets/javascripts/zen_mode.js.coffee b/app/assets/javascripts/zen_mode.js.coffee
index 0c9942a401475e160d17fb38fefcb55fd82d18c1..0fb8f7ed75fdd4c6d691d1901a173cfa00f41835 100644
--- a/app/assets/javascripts/zen_mode.js.coffee
+++ b/app/assets/javascripts/zen_mode.js.coffee
@@ -10,7 +10,15 @@ class @ZenMode
       if not @active_checkbox
         @scroll_position = window.pageYOffset
 
-    $('body').on 'change', '.zennable input[type=checkbox]', (e) =>
+    $('body').on 'click', '.zen-enter-link', (e) =>
+      e.preventDefault()
+      $(e.currentTarget).closest('.zennable').find('.zen-toggle-comment').prop('checked', true)
+
+    $('body').on 'click', '.zen-leave-link', (e) =>
+      e.preventDefault()
+      $(e.currentTarget).closest('.zennable').find('.zen-toggle-comment').prop('checked', false)
+
+    $('body').on 'change', '.zen-toggle-comment', (e) =>
       checkbox = e.currentTarget
       if checkbox.checked
         # Disable other keyboard shortcuts in ZEN mode
@@ -32,8 +40,6 @@ class @ZenMode
     @active_zen_area = @active_checkbox.parent().find('textarea')
     @active_zen_area.focus()
     window.location.hash = ZenMode.fullscreen_prefix + @active_checkbox.prop('id')
-    # Disable dropzone in ZEN mode
-    Dropzone.forElement('.div-dropzone').disable()
 
   exitZenMode: =>
     if @active_zen_area isnt null
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index 0d404f150554d218bf72514f7d1877a451941ead..015ff2ce4ec71826c58378c451f3a342e01cc737 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -6,17 +6,22 @@
  *= require jquery.ui.autocomplete
  *= require jquery.atwho
  *= require select2
- *= require highlightjs.min
  *= require_self
  *= require dropzone/basic
+ *= require cal-heatmap
 */
 
-@import "main/*";
+
+@import "base/variables";
+@import "base/mixins";
+@import "base/layout";
+
 
 /**
  * Customized Twitter bootstrap
  */
-@import 'gl_bootstrap';
+@import 'base/gl_variables';
+@import 'base/gl_bootstrap';
 
 /**
  * NProgress load bar css
@@ -39,7 +44,7 @@
  * Page specific styles (issues, projects etc):
  */
 
-@import "sections/*";
+@import "pages/*";
 
 /**
  * Code highlight
@@ -55,8 +60,3 @@
  * Styles for JS behaviors.
  */
 @import "behaviors.scss";
-
-/**
-* Styles for responsive sidebar
-*/
-@import "semantic-ui/modules/sidebar";
diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/base/gl_bootstrap.scss
similarity index 62%
rename from app/assets/stylesheets/gl_bootstrap.scss
rename to app/assets/stylesheets/base/gl_bootstrap.scss
index 9c5e76ab8e267ae0090605b991e994b9504f4357..62a3eade5c73a4c54eaf297e1722d54eb0d61323 100644
--- a/app/assets/stylesheets/gl_bootstrap.scss
+++ b/app/assets/stylesheets/base/gl_bootstrap.scss
@@ -1,16 +1,8 @@
 /*
  * Twitter bootstrap with GitLab customizations/additions
  *
- * Some unused bootstrap compontents like panels are not included.
- * Other components like tabs are modified to GitLab style.
- *
  */
 
-$font-size-base: 13px !default;
-$nav-pills-active-link-hover-bg: $bg_primary;
-$pagination-active-bg: $bg_primary;
-$list-group-active-bg: $bg_primary;
-
 // Core variables and mixins
 @import "bootstrap/variables";
 @import "bootstrap/mixins";
@@ -26,6 +18,7 @@ $list-group-active-bg: $bg_primary;
 @import "bootstrap/grid";
 @import "bootstrap/tables";
 @import "bootstrap/forms";
+@import "bootstrap/buttons";
 
 // Components
 @import "bootstrap/component-animations";
@@ -137,10 +130,6 @@ $list-group-active-bg: $bg_primary;
       }
     }
   }
-
-  &.nav-small-tabs > li > a {
-    padding: 6px 9px;
-  }
 }
 
 .nav-tabs > li > a,
@@ -148,57 +137,6 @@ $list-group-active-bg: $bg_primary;
   color: #666;
 }
 
-.nav-small > li > a {
-  padding: 3px 5px;
-  font-size: 12px;
-}
-
-
-/*
- * Callouts from Bootstrap3 docs
- *
- * Not quite alerts, but custom and helpful notes for folks reading the docs.
- * Requires a base and modifier class.
- */
-
-/* Common styles for all types */
-.bs-callout {
-  margin: 20px 0;
-  padding: 20px;
-  border-left: 3px solid #eee;
-  color: #666;
-  background: #f9f9f9;
-}
-.bs-callout h4 {
-  margin-top: 0;
-  margin-bottom: 5px;
-}
-.bs-callout p:last-child {
-  margin-bottom: 0;
-}
-
-/* Variations */
-.bs-callout-danger {
-  background-color: #fdf7f7;
-  border-color: #eed3d7;
-  color: #b94a48;
-}
-.bs-callout-warning {
-  background-color: #faf8f0;
-  border-color: #faebcc;
-  color: #8a6d3b;
-}
-.bs-callout-info {
-  background-color: #f4f8fa;
-  border-color: #bce8f1;
-  color: #34789a;
-}
-.bs-callout-success {
-  background-color: #dff0d8;
-  border-color: #5cA64d;
-  color: #3c763d;
-}
-
 /**
  * fix to keep tooltips position in top navigation bar
  *
@@ -213,16 +151,12 @@ $list-group-active-bg: $bg_primary;
  *
  */
 .panel {
-  @include border-radius(0px);
-
   .panel-heading {
-    @include border-radius(0px);
-    font-size: 14px;
-    line-height: 18px;
+    font-weight: bold;
 
     .panel-head-actions {
       position: relative;
-      top: -7px;
+      top: -5px;
       float: right;
     }
   }
@@ -248,6 +182,7 @@ $list-group-active-bg: $bg_primary;
     .panel-heading {
       padding: 6px 15px;
       font-size: 13px;
+      font-weight: normal;
       a {
         color: #777;
       }
@@ -255,40 +190,62 @@ $list-group-active-bg: $bg_primary;
   }
 }
 
-.panel-default {
-  .panel-heading {
-    background-color: #EEE;
+.panel-succes .panel-heading,
+.panel-info .panel-heading,
+.panel-danger .panel-heading,
+.panel-warning .panel-heading,
+.panel-primary .panel-heading,
+.alert {
+  a:not(.btn) {
+    @extend .alert-link;
+    color: #fff;
+    text-decoration: underline;
   }
 }
 
-.panel-danger {
-  @include panel-colored;
-  .panel-heading {
-    color: $border_danger;
-    border-color: $border_danger;
-  }
+// Typography =================================================================
+
+.text-primary,
+.text-primary:hover {
+  color: $brand-primary;
 }
 
-.panel-success {
-  @include panel-colored;
-  .panel-heading {
-    color: $border_success;
-    border-color: $border_success;
-  }
+.text-success,
+.text-success:hover {
+  color: $brand-success;
 }
 
-.panel-primary {
-  @include panel-colored;
-  .panel-heading {
-    color: $border_primary;
-    border-color: $border_primary;
-  }
+.text-danger,
+.text-danger:hover {
+  color: $brand-danger;
 }
 
-.panel-warning {
-  @include panel-colored;
-  .panel-heading {
-    color: $border_warning;
-    border-color: $border_warning;
+.text-warning,
+.text-warning:hover {
+  color: $brand-warning;
+}
+
+.text-info,
+.text-info:hover {
+  color: $brand-info;
+}
+
+// Tables =====================================================================
+
+table.table {
+  .dropdown-menu a {
+    text-decoration: none;
+  }
+
+  .success,
+  .warning,
+  .danger,
+  .info {
+    color: #fff;
+
+    a:not(.btn) {
+      text-decoration: underline;
+      color: #fff;
+    }
   }
 }
diff --git a/app/assets/stylesheets/base/gl_variables.scss b/app/assets/stylesheets/base/gl_variables.scss
new file mode 100644
index 0000000000000000000000000000000000000000..56f4c794e1b3c00109334a521a3b97366f8b5653
--- /dev/null
+++ b/app/assets/stylesheets/base/gl_variables.scss
@@ -0,0 +1,133 @@
+// Override Bootstrap variables here (defaults from bootstrap-sass v3.3.3):
+// For all variables see https://github.com/twbs/bootstrap-sass/blob/master/templates/project/_bootstrap-variables.sass
+//
+// Variables
+// --------------------------------------------------
+
+
+//== Colors
+//
+//## Gray and brand colors for use across Bootstrap.
+
+// $gray-base:              #000
+// $gray-darker:            lighten($gray-base, 13.5%) // #222
+// $gray-dark:              lighten($gray-base, 20%)   // #333
+// $gray:                   lighten($gray-base, 33.5%) // #555
+// $gray-light:             lighten($gray-base, 46.7%) // #777
+// $gray-lighter:           lighten($gray-base, 93.5%) // #eee
+
+$brand-primary:  $gl-primary;
+$brand-success:  $gl-success;
+$brand-info:     $gl-info;
+$brand-warning:  $gl-warning;
+$brand-danger:   $gl-danger;
+
+
+//== Scaffolding
+//
+$text-color:            $gl-text-color;
+$link-color:            $gl-link-color;
+
+
+//== Typography
+//
+//## Font, line-height, and color for body text, headings, and more.
+
+$font-family-sans-serif: $regular_font;
+$font-family-monospace:  $monospace_font;
+$font-size-base:         $gl-font-size;
+
+
+//== Components
+//
+//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
+
+$padding-base-vertical:     6px;
+$padding-base-horizontal:   14px;
+
+
+//== Forms
+//
+//##
+
+$input-color:                    $text-color;
+$input-border:                   #DDD;
+$input-border-focus:             $brand-info;
+$legend-color:                   $text-color;
+
+
+//== Pagination
+//
+//##
+
+$pagination-color:                     #fff;
+$pagination-bg:                        $brand-success;
+$pagination-border:                    transparent;
+
+$pagination-hover-color:               #fff;
+$pagination-hover-bg:                  darken($brand-success, 15%);
+$pagination-hover-border:              transparent;
+
+$pagination-active-color:              #fff;
+$pagination-active-bg:                 darken($brand-success, 15%);
+$pagination-active-border:             transparent;
+
+$pagination-disabled-color:            #b4bcc2;
+$pagination-disabled-bg:               lighten($brand-success, 15%);
+$pagination-disabled-border:           transparent;
+
+
+//== Form states and alerts
+//
+//## Define colors for form feedback states and, by default, alerts.
+
+$state-success-text:             #fff;
+$state-success-bg:               $brand-success;
+$state-success-border:           $brand-success;
+
+$state-info-text:                #fff;
+$state-info-bg:                  $brand-info;
+$state-info-border:              $brand-info;
+
+$state-warning-text:             #fff;
+$state-warning-bg:               $brand-warning;
+$state-warning-border:           $brand-warning;
+
+$state-danger-text:              #fff;
+$state-danger-bg:                $brand-danger;
+$state-danger-border:            $brand-danger;
+
+
+//== Alerts
+//
+//## Define alert colors, border radius, and padding.
+
+$alert-border-radius:            0;
+
+
+//== Panels
+//
+//##
+
+$panel-border-radius:            0;
+$panel-default-text:          $text-color;
+$panel-default-border:        $border-color;
+$panel-default-heading-bg:    $background-color;
+
+
+//== Wells
+//
+//##
+
+$well-bg:                     #F9F9F9;
+$well-border:                 #EEE;
+
+//== Code
+//
+//##
+
+$code-color:                  #c7254e;
+$code-bg:                     #f9f2f4;
+
+$kbd-color:                   #fff;
+$kbd-bg:                      #333;
diff --git a/app/assets/stylesheets/main/layout.scss b/app/assets/stylesheets/base/layout.scss
similarity index 69%
rename from app/assets/stylesheets/main/layout.scss
rename to app/assets/stylesheets/base/layout.scss
index 2800feb81f2c7223f5b6f3aa2ff64ae1049f630c..62c11b06368dd66cbd051f47ae89ee69c75b1e41 100644
--- a/app/assets/stylesheets/main/layout.scss
+++ b/app/assets/stylesheets/base/layout.scss
@@ -2,10 +2,10 @@ html {
   overflow-y: scroll;
 
   &.touch .tooltip { display: none !important; }
-}
 
-body {
-  padding-bottom: 20px;
+  body {
+    padding-top: 46px;
+  }
 }
 
 .container {
@@ -17,3 +17,6 @@ body {
   margin: 0 0;
 }
 
+.navless-container {
+  margin-top: 30px;
+}
diff --git a/app/assets/stylesheets/main/mixins.scss b/app/assets/stylesheets/base/mixins.scss
similarity index 84%
rename from app/assets/stylesheets/main/mixins.scss
rename to app/assets/stylesheets/base/mixins.scss
index 7f607fc4e8bb032250e57fd94d48225e88829664..ccba65e3fd573d969eb400ec5e8a111f9dde0cbd 100644
--- a/app/assets/stylesheets/main/mixins.scss
+++ b/app/assets/stylesheets/base/mixins.scss
@@ -58,8 +58,8 @@
 }
 
 @mixin md-typography {
-  font-size: 14px;
-  line-height: 1.6;
+  font-size: 15px;
+  line-height: 1.5;
 
   img {
     max-width: 100%;
@@ -69,7 +69,12 @@
     margin-top: 0;
   }
 
-  code { padding: 0 4px; }
+  code {
+    font-family: $monospace_font;
+    white-space: pre;
+    word-wrap: normal;
+    padding: 0;
+  }
 
   h1 {
     margin-top: 45px;
@@ -93,7 +98,7 @@
 
   blockquote p {
     color: #888;
-    font-size: 14px;
+    font-size: 15px;
     line-height: 1.5;
   }
 
@@ -116,14 +121,6 @@
   }
 }
 
-@mixin page-title {
-  color: #333;
-  line-height: 1.5;
-  font-weight: normal;
-  margin-top: 0px;
-  margin-bottom: 10px;
-}
-
 @mixin str-truncated($max_width: 82%) {
   display: inline-block;
   overflow: hidden;
@@ -132,14 +129,3 @@
   white-space: nowrap;
   max-width: $max_width;
 }
-
-@mixin panel-colored {
-  border: none;
-  background: $box_bg;
-  @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09));
-
-  .panel-heading {
-    font-weight: bold;
-    background-color: $box_bg;
-  }
-}
diff --git a/app/assets/stylesheets/base/variables.scss b/app/assets/stylesheets/base/variables.scss
new file mode 100644
index 0000000000000000000000000000000000000000..596376c3970b84e77d7ee414cd491f5ef08cc252
--- /dev/null
+++ b/app/assets/stylesheets/base/variables.scss
@@ -0,0 +1,34 @@
+$style_color: #474D57;
+$hover: #FFF3EB;
+$gl-text-color: #222222;
+$gl-link-color: #446e9b;
+$nprogress-color: #c0392b;
+$gl-font-size: 14px;
+$list-font-size: 15px;
+$sidebar_width: 230px;
+$avatar_radius: 50%;
+$code_font_size: 13px;
+$code_line_height: 1.5;
+$border-color: #E5E5E5;
+$background-color: #f5f5f5;
+
+/*
+ * State colors:
+ */
+$gl-primary: #446e9b;
+$gl-success: #019875;
+$gl-info: #029ACF;
+$gl-warning: #EB9532;
+$gl-danger: #d9534f;
+
+/*
+ * Commit Diff Colors
+ */
+$added: #63c363;
+$deleted: #f77;
+
+/*
+ * Fonts
+ */
+$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace;
+$regular_font: "Helvetica Neue", Helvetica, Arial, sans-serif;
diff --git a/app/assets/stylesheets/generic/avatar.scss b/app/assets/stylesheets/generic/avatar.scss
index 4f038b977e2c61f1a6c5f9eeae7db722e5a0149d..8595887c3b9cd1877f697b644b330fb895633c26 100644
--- a/app/assets/stylesheets/generic/avatar.scss
+++ b/app/assets/stylesheets/generic/avatar.scss
@@ -2,15 +2,21 @@
   float: left;
   margin-right: 12px;
   width: 40px;
-  padding: 1px;
-  @include border-radius(4px);
+  height: 40px;
+  padding: 0;
+  @include border-radius($avatar_radius);
 
   &.avatar-inline {
     float: none;
-    margin-left: 3px;
+    margin-left: 4px;
+    margin-bottom: 2px;
 
-    &.s16 { margin-right: 2px; }
-    &.s24 { margin-right: 2px; }
+    &.s16 { margin-right: 4px; }
+    &.s24 { margin-right: 4px; }
+  }
+
+  &.group-avatar, &.project-avatar, &.avatar-tile {
+    @include border-radius(0px);
   }
 
   &.s16 { width: 16px; height: 16px; margin-right: 6px; }
@@ -21,3 +27,16 @@
   &.s90 { width: 90px; height: 90px; margin-right: 15px; }
   &.s160 { width: 160px; height: 160px; margin-right: 20px; }
 }
+
+.identicon {
+  text-align: center;
+  vertical-align: top;
+
+  &.s16 { font-size: 12px; line-height: 1.33; }
+  &.s24 { font-size: 14px; line-height: 1.8; }
+  &.s26 { font-size: 20px; line-height: 1.33; }
+  &.s32 { font-size: 22px; line-height: 32px; }
+  &.s60 { font-size: 32px; line-height: 60px; }
+  &.s90 { font-size: 36px; line-height: 90px; }
+  &.s160 { font-size: 96px; line-height: 1.33; }
+}
diff --git a/app/assets/stylesheets/generic/buttons.scss b/app/assets/stylesheets/generic/buttons.scss
index d098f1ecaa2193f61ffc69527b915a421b4491e3..cd6bf64c0ae2c8c6bbb79992028da0129367aa19 100644
--- a/app/assets/stylesheets/generic/buttons.scss
+++ b/app/assets/stylesheets/generic/buttons.scss
@@ -1,127 +1,15 @@
 .btn {
-  display: inline-block;
-  margin-bottom: 0;
-  font-weight: normal;
-  text-align: center;
-  vertical-align: middle;
-  cursor: pointer;
-  background-image: none;
-  border: $btn-border;
-  white-space: nowrap;
-  padding: 6px 12px;
-  font-size: 13px;
-  line-height: 18px;
-  border-radius: 4px;
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  -o-user-select: none;
-  user-select: none;
-  color: #444444;
-  background-color: #fff;
-  text-shadow: none;
-
-  &.hover,
-  &:hover {
-    color: #444444;
-    text-decoration: none;
-    background-color: #ebebeb;
-    border-color: #adadad;
-  }
-
-  &.focus,
-  &:focus {
-    color: #444444;
-    text-decoration: none;
-    outline: thin dotted #333;
-    outline: 5px auto -webkit-focus-ring-color;
-    outline-offset: -2px;
-  }
-
-  &.active,
-  &:active {
-    outline: 0;
-    background-image: none;
-    -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-    box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-  }
-
-  &.disabled,
-  &[disabled] {
-    cursor: not-allowed;
-    pointer-events: none;
-    opacity: 0.65;
-    filter: alpha(opacity=65);
-    -webkit-box-shadow: none;
-    box-shadow: none;
-  }
-
-  &.btn-primary {
-    color: #ffffff;
-    background-color: $bg_primary;
-    border-color: $border_primary;
-
-    &.hover,
-    &:hover,
-    &.disabled,
-    &[disabled] {
-      color: #ffffff;
-    }
-  }
-
-  &.btn-success {
-    color: #ffffff;
-    background-color: $bg_success;
-    border-color: $border_success;
-
-
-    &.hover,
-    &:hover,
-    &.disabled,
-    &[disabled] {
-      color: #ffffff;
-    }
-  }
-
-  &.btn-danger {
-    color: #ffffff;
-    background-color: $bg_danger;
-    border-color: $border_danger;
-
-
-    &.hover,
-    &:hover,
-    &.disabled,
-    &[disabled] {
-      color: #ffffff;
-    }
-  }
-
-  &.btn-warning {
-    color: #ffffff;
-    background-color: $bg_warning;
-    border-color: $border_warning;
-
-
-    &.hover,
-    &:hover,
-    &.disabled,
-    &[disabled] {
-      color: #ffffff;
-    }
-  }
+  @extend .btn-default;
 
   &.btn-new {
     @extend .btn-success;
   }
 
   &.btn-create {
-    @extend .wide;
     @extend .btn-success;
   }
 
   &.btn-save {
-    @extend .wide;
     @extend .btn-primary;
   }
 
@@ -133,34 +21,17 @@
     float: right;
   }
 
-  &.wide {
-    padding-left: 20px;
-    padding-right: 20px;
-  }
-
-  &.btn-small {
-    padding: 2px 10px;
-    font-size: 12px;
-  }
-
-  &.btn-tiny {
-    font-size: 11px;
-    padding: 2px 6px;
-    line-height: 16px;
-    margin: 2px;
-  }
-
   &.btn-close {
-    color: $bg_danger;
-    border-color: $border_danger;
+    color: $gl-danger;
+    border-color: $gl-danger;
     &:hover {
       color: #B94A48;
     }
   }
 
   &.btn-reopen {
-    color: $bg_success;
-    border-color: $border_success;
+    color: $gl-success;
+    border-color: $gl-success;
     &:hover {
       color: #468847;
     }
@@ -173,6 +44,14 @@
       margin-right: 0px;
     }
   }
+
+  &.btn-save {
+    @extend .btn-primary;
+  }
+
+  &.btn-new, &.btn-create {
+    @extend .btn-success;
+  }
 }
 
 .btn-block {
@@ -193,6 +72,3 @@
     }
   }
 }
-
-.btn-group-small > .btn { @extend .btn.btn-small; }
-.btn-group-tiny > .btn { @extend .btn.btn-tiny; }
diff --git a/app/assets/stylesheets/generic/calendar.scss b/app/assets/stylesheets/generic/calendar.scss
new file mode 100644
index 0000000000000000000000000000000000000000..a36fefe22c54fe644b65bf256c8fe82ec46044e0
--- /dev/null
+++ b/app/assets/stylesheets/generic/calendar.scss
@@ -0,0 +1,90 @@
+.user-calendar-activities {
+  .calendar_onclick_hr {
+    padding: 0;
+    margin: 10px 0;
+  }
+
+  .str-truncated {
+    max-width: 70%;
+  }
+
+  .text-expander {
+    background: #eee;
+    color: #555;
+    padding: 0 5px;
+    cursor: pointer;
+    margin-left: 4px;
+    &:hover {
+      background-color: #ddd;
+    }
+  }
+}
+/**
+* This overwrites the default values of the cal-heatmap gem
+*/
+.calendar {
+  .qi {
+    background-color: #999;
+    fill: #fff;
+  }
+
+  .q1 {
+    background-color: #dae289;
+    fill: #ededed;
+  }
+
+  .q2 {
+    background-color: #cedb9c;
+    fill: #ACD5F2;
+  }
+
+  .q3 {
+    background-color: #b5cf6b;
+    fill: #7FA8D1;
+  }
+
+  .q4 {
+    background-color: #637939;
+    fill: #49729B;
+  }
+
+  .q5 {
+    background-color: #3b6427;
+    fill: #254E77;
+  }
+
+  .domain-background {
+    fill: none;
+    shape-rendering: crispedges;
+  }
+
+  .ch-tooltip {
+    position: absolute;
+    display: none;
+    margin-top: 22px;
+    margin-left: 1px;
+    font-size: 13px;
+    padding: 3px;
+    font-weight: 550;
+    background-color: #222;
+    span {
+      position: absolute;
+      width: 200px;
+      text-align: center;
+      visibility: hidden;
+      border-radius: 10px;
+      &:after {
+        content: '';
+        position: absolute;
+        top: 100%;
+        left: 50%;
+        margin-left: -8px;
+        width: 0;
+        height: 0;
+        border-top: 8px solid #000000;
+        border-right: 8px solid transparent;
+        border-left: 8px solid transparent;
+      }
+    }
+  }
+}
diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss
index cd2f4e45e3c898a609a3596490707ffca7bb44d5..db393e0881994f71e3ed1dbe1c8a3501fd738fdf 100644
--- a/app/assets/stylesheets/generic/common.scss
+++ b/app/assets/stylesheets/generic/common.scss
@@ -24,7 +24,7 @@
 
 .slead {
   color: #666;
-  font-size: 14px;
+  font-size: 15px;
   margin-bottom: 12px;
   font-weight: normal;
   line-height: 24px;
@@ -54,9 +54,14 @@ pre {
   text-shadow: none;
 }
 
+.dropdown-menu-align-right {
+  left: auto;
+  right: 0px;
+}
+
 .dropdown-menu > li > a:hover,
 .dropdown-menu > li > a:focus {
-  background: $bg_primary;
+  background: $gl-primary;
   color: #FFF
 }
 
@@ -66,7 +71,7 @@ pre {
 
 /** FLASH message **/
 .author_link {
-  color: $link_color;
+  color: $gl-link-color;
 }
 
 .help li { color:$style_color; }
@@ -162,7 +167,7 @@ li.note {
   background-color: inherit;
 }
 
-.team_member_show {
+.project_member_show {
   td:first-child {
     color: #aaa;
   }
@@ -207,24 +212,16 @@ li.note {
   }
 }
 
-.no-ssh-key-message {
-  padding: 10px 0;
-  background: #C67;
-  margin: 0;
-  color: #FFF;
-  margin-top: -1px;
+.browser-alert {
+  padding: 10px;
   text-align: center;
-
+  background: #C67;
+  color: #fff;
+  font-weight: bold;
   a {
     color: #fff;
     text-decoration: underline;
   }
-
-  .links-xs {
-    text-align: center;
-    font-size: 16px;
-    padding: 5px;
-  }
 }
 
 .warning_message {
@@ -281,10 +278,6 @@ img.emoji {
   height: 220px;
 }
 
-.navless-container {
-  margin-top: 20px;
-}
-
 .description-block {
   @extend .light-well;
   @extend .light;
@@ -300,27 +293,21 @@ table {
 
 .dashboard-intro-icon {
   float: left;
+  text-align: center;
   font-size: 32px;
   color: #AAA;
-  padding: 5px 0;
-  width: 50px;
-  min-height: 100px;
+  width: 60px;
 }
 
-.broadcast-message {
-  padding: 10px;
-  text-align: center;
-  background: #555;
-  color: #BBB;
-}
-
-.broadcast-message-preview {
-  @extend .broadcast-message;
-  margin-bottom: 20px;
+.dashboard-intro-text {
+  display: inline-block;
+  margin-left: -60px;
+  padding-left: 60px;
+  width: 100%;
 }
 
 .btn-sign-in {
-  margin-top: 7px;
+  margin-top: 5px;
   text-shadow: none;
 }
 
@@ -330,16 +317,19 @@ table {
   }
 }
 
-@media (max-width: $screen-xs-max) {
-  .container .content { margin-top: 20px; }
-}
-
 .wiki .highlight, .note-body .highlight {
   margin-bottom: 9px;
 }
 
-.footer-links a {
-  margin-right: 15px;
+.wiki .code {
+  overflow-x: auto;
+}
+
+.footer-links {
+  margin-bottom: 20px;
+  a {
+    margin-right: 15px;
+  }
 }
 
 .search_box {
@@ -359,3 +349,28 @@ table {
 .task-status {
   margin-left: 10px;
 }
+
+#nprogress .spinner {
+  top: auto !important;
+  bottom: 20px !important;
+  left: 20px !important;
+}
+
+.header-with-avatar {
+  h3 {
+    margin: 0;
+    font-weight: bold;
+  }
+
+  .username {
+    font-size: 18px;
+    color: #666;
+    margin-top: 8px;
+  }
+
+  .description {
+    font-size: 16px;
+    color: #666;
+    margin-top: 8px;
+  }
+}
diff --git a/app/assets/stylesheets/generic/files.scss b/app/assets/stylesheets/generic/files.scss
index e2b0ef0c5eaa9c987acd3009819bb9f80215a85e..8014dcb165b3845864715670d6e34340fded5f48 100644
--- a/app/assets/stylesheets/generic/files.scss
+++ b/app/assets/stylesheets/generic/files.scss
@@ -3,7 +3,7 @@
  *
  */
 .file-holder {
-  border: 1px solid #CCC;
+  border: 1px solid $border-color;
   margin-bottom: 1em;
 
   table {
@@ -11,38 +11,33 @@
   }
 
   .file-title {
-    background: #EEE;
-    border-bottom: 1px solid #CCC;
+    position: relative;
+    background: $background-color;
+    border-bottom: 1px solid $border-color;
     text-shadow: 0 1px 1px #fff;
     margin: 0;
     text-align: left;
     padding: 10px 15px;
 
-    .options {
+    .file-actions {
       float: right;
-      margin-top: -3px;
+      position: absolute;
+      top: 5px;
+      right: 15px;
+
+      .btn {
+        padding: 0px 10px;
+        font-size: 13px;
+        line-height: 28px;
+      }
     }
 
     .left-options {
       margin-top: -3px;
     }
-
-    .file_name {
-      font-weight: bold;
-      padding-left: 3px;
-      font-size: 14px;
-
-      small {
-        color: #888;
-        font-size: 13px;
-        font-weight: normal;
-        padding-left: 10px;
-      }
-    }
   }
   .file-content {
     background: #fff;
-    font-size: 11px;
 
     &.image_file {
       background: #eee;
@@ -54,8 +49,6 @@
     }
 
     &.wiki {
-      font-size: 14px;
-      line-height: 1.6;
       padding: 25px;
 
       .highlight {
@@ -101,7 +94,7 @@
       }
       .author,
       .blame_commit {
-        background: #f5f5f5;
+        background: $background-color;
         vertical-align: top;
       }
       .lines {
@@ -122,7 +115,7 @@
       ol {
         margin-left: 40px;
         padding: 10px 0;
-        border-left: 1px solid #CCC;
+        border-left: 1px solid $border-color;
         margin-bottom: 0;
         background: white;
         li {
diff --git a/app/assets/stylesheets/generic/filters.scss b/app/assets/stylesheets/generic/filters.scss
new file mode 100644
index 0000000000000000000000000000000000000000..bd93a79722dd5a3b58aead122628b91c0e9b99fb
--- /dev/null
+++ b/app/assets/stylesheets/generic/filters.scss
@@ -0,0 +1,55 @@
+.filter-item {
+  margin-right: 15px;
+}
+
+.issues-state-filters {
+  li.active a {
+    border-color: #DDD !important;
+
+    &, &:hover, &:active, &.active {
+      background: #f5f5f5 !important;
+      border-bottom: 1px solid #f5f5f5 !important;
+    }
+  }
+}
+
+.issues-details-filters {
+  font-size: 13px;
+  background: #f5f5f5;
+  margin: -10px 0;
+  padding: 10px 15px;
+  margin-top: -15px;
+  border-left: 1px solid #DDD;
+  border-right: 1px solid #DDD;
+
+  .btn {
+    font-size: 13px;
+  }
+}
+
+@media (min-width: 800px)  {
+  .issues-filters,
+  .issues_bulk_update {
+    select, .select2-container {
+      width: 120px !important;
+      display: inline-block;
+    }
+  }
+}
+
+@media (min-width: 1200px) {
+  .issues-filters,
+  .issues_bulk_update {
+    select, .select2-container {
+      width: 150px !important;
+      display: inline-block;
+    }
+  }
+}
+
+.issues-filters,
+.issues_bulk_update {
+  .select2-container .select2-choice {
+    color: #444 !important;
+  }
+}
diff --git a/app/assets/stylesheets/generic/forms.scss b/app/assets/stylesheets/generic/forms.scss
index e8b23090b0f4756a22549bf200153bdc9cf5e29f..266041403e06188e30ab24d15e7a6e36cadb99b8 100644
--- a/app/assets/stylesheets/generic/forms.scss
+++ b/app/assets/stylesheets/generic/forms.scss
@@ -15,10 +15,6 @@ input[type='text'].danger {
   text-shadow: 0 1px 1px #fff
 }
 
-fieldset legend {
-  font-size: 16px;
-}
-
 .datetime-controls {
   select {
     width: 100px;
@@ -29,9 +25,14 @@ fieldset legend {
   padding: 17px 20px 18px;
   margin-top: 18px;
   margin-bottom: 18px;
-  background-color: whitesmoke;
-  border-top: 1px solid #e5e5e5;
-  padding-left: 17%;
+  background-color: $background-color;
+  border-top: 1px solid $border-color;
+}
+
+@media (min-width: $screen-sm-min) {
+  .form-actions {
+    padding-left: 17%;
+  }
 }
 
 label {
@@ -88,139 +89,7 @@ label {
   @include box-shadow(none);
 }
 
-.issuable-description {
+.issuable-description,
+.wiki-content {
   margin-top: 35px;
 }
-
-.zennable {
-  position: relative;
-
-  input {
-    display: none;
-  }
-
-  .collapse {
-    display: none;
-    opacity: 0.5;
-
-    &:before {
-      content: '\f066';
-      font-family: FontAwesome;
-      color: #000;
-      font-size: 28px;
-      position: relative;
-      padding: 30px 40px 0 0;
-    }
-
-    &:hover {
-      opacity: 0.8;
-    }
-  }
-
-  .expand {
-    opacity: 0.5;
-
-    &:before {
-      content: '\f065';
-      font-family: FontAwesome;
-      color: #000;
-      font-size: 14px;
-      line-height: 14px;
-      padding-right: 20px;
-      position: relative;
-      vertical-align: middle;
-    }
-
-    &:hover {
-      opacity: 0.8;
-    }
-  }
-
-  input:checked ~ .zen-backdrop .expand {
-    display: none;
-  }
-
-  input:checked ~ .zen-backdrop .collapse {
-    display: block;
-    position: absolute;
-    top: 0;
-  }
-
-  label {
-    position: absolute;
-    top: -26px;
-    right: 0;
-    font-variant: small-caps;
-    text-transform: uppercase;
-    font-size: 10px;
-    padding: 4px;
-    font-weight: 500;
-    letter-spacing: 1px;
-
-    &:before {
-      display: inline-block;
-      width: 10px;
-      height: 14px;
-    }
-  }
-
-  input:checked ~ .zen-backdrop {
-    background-color: white;
-    position: fixed;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    z-index: 1031;
-
-    textarea {
-      border: none;
-      box-shadow: none;
-      border-radius: 0;
-      color: #000;
-      font-size: 20px;
-      line-height: 26px;
-      padding: 30px;
-      display: block;
-      outline: none;
-      resize: none;
-      height: 100vh;
-      max-width: 900px;
-      margin: 0 auto;
-    }
-  }
-
-  .zen-backdrop textarea::-webkit-input-placeholder {
-    color: white;
-  }
-
-  .zen-backdrop textarea:-moz-placeholder {
-    color: white;
-  }
-
-  .zen-backdrop textarea::-moz-placeholder {
-    color: white;
-  }
-
-  .zen-backdrop textarea:-ms-input-placeholder {
-    color: white;
-  }
-
-  input:checked ~ .zen-backdrop textarea::-webkit-input-placeholder {
-    color: #999;
-  }
-
-  input:checked ~ .zen-backdrop textarea:-moz-placeholder {
-    color: #999;
-    opacity: 1;
-  }
-
-  input:checked ~ .zen-backdrop textarea::-moz-placeholder {
-    color: #999;
-    opacity: 1;
-  }
-
-  input:checked ~ .zen-backdrop textarea:-ms-input-placeholder {
-    color: #999;
-  }
-}
diff --git a/app/assets/stylesheets/generic/gfm.scss b/app/assets/stylesheets/generic/gfm.scss
index e257f0536182b87e5aba10eb9c65972685353047..8fac5e534fa9c17c227db2b1d7e4c991286cb7a4 100644
--- a/app/assets/stylesheets/generic/gfm.scss
+++ b/app/assets/stylesheets/generic/gfm.scss
@@ -3,7 +3,8 @@
  */
 .issue-form, .merge-request-form, .wiki-form {
   .description {
-    height: 20em;
+    height: 16em;
+    border-top-left-radius: 0;
   }
 }
 
@@ -17,4 +18,4 @@
   .description {
     height: 14em;
   }
-}
\ No newline at end of file
+}
diff --git a/app/assets/stylesheets/generic/highlight.scss b/app/assets/stylesheets/generic/highlight.scss
index 4110bddf4f34270e3b8730cbf8d48c5f8c874231..2e13ee842e0178c72cf0508aa106ca658906dc84 100644
--- a/app/assets/stylesheets/generic/highlight.scss
+++ b/app/assets/stylesheets/generic/highlight.scss
@@ -1,4 +1,4 @@
-.highlighted-data {
+.file-content.code {
   border: none;
   box-shadow: none;
   margin: 0px;
@@ -10,11 +10,16 @@
     border: none;
     border-radius: 0;
     font-family: $monospace_font;
-    font-size: 12px !important;
-    line-height: 16px !important;
+    font-size: $code_font_size !important;
+    line-height: $code_line_height !important;
     margin: 0;
+    overflow: auto;
+    overflow-y: hidden;
+    white-space: pre;
+    word-wrap: normal;
 
     code {
+      font-family: $monospace_font;
       white-space: pre;
       word-wrap: normal;
       padding: 0;
@@ -25,10 +30,6 @@
     }
   }
 
-  .hljs {
-    padding: 0;
-  }
-
   .line-numbers {
     padding: 10px;
     text-align: right;
@@ -37,8 +38,8 @@
     a {
       font-family: $monospace_font;
       display: block;
-      font-size: 12px !important;
-      line-height: 16px !important;
+      font-size: $code_font_size !important;
+      line-height: $code_line_height !important;
       white-space: nowrap;
 
       i {
@@ -51,14 +52,19 @@
       }
     }
   }
+}
 
-  .highlight {
-    overflow: auto;
-    overflow-y: hidden;
+.note-text .code {
+  border: none;
+  box-shadow: none;
+  background: $background-color;
+  padding: 1em;
+  overflow-x: auto;
 
-    pre {
-      white-space: pre;
-      word-wrap: normal;
-    }
+  code {
+    font-family: $monospace_font;
+    white-space: pre;
+    word-wrap: normal;
+    padding: 0;
   }
 }
diff --git a/app/assets/stylesheets/generic/issue_box.scss b/app/assets/stylesheets/generic/issue_box.scss
index 94149594e24ea6bfc658231fedfcc68b30670da5..9558f241b7c7e96c3f93547dc4571ed38e3cb386 100644
--- a/app/assets/stylesheets/generic/issue_box.scss
+++ b/app/assets/stylesheets/generic/issue_box.scss
@@ -1,123 +1,32 @@
 /**
- * Issue box:
- * Huge block (one per page) for storing title, descripion and other information.
+ * Issue box for showing Open/Closed state:
  * Used for Issue#show page, MergeRequest#show page etc
  *
- * CLasses:
- *   .issue-box - Regular box
  */
 
 .issue-box {
-  color: #555;
-  margin:20px 0;
-  background: $box_bg;
-  @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09));
+  display: inline-block;
+  padding: 7px 13px;
+  font-weight: normal;
+  margin-right: 5px;
 
   &.issue-box-closed {
-    .state {
-      background-color: #F3CECE;
-      border-color: $border_danger;
-    }
-    .state-label {
-      background-color: $bg_danger;
-      color: #FFF;
-    }
+    background-color: $gl-danger;
+    color: #FFF;
   }
 
   &.issue-box-merged {
-    .state {
-      background-color: #B7CEE7;
-      border-color: $border_primary;
-    }
-    .state-label {
-      background-color: $bg_primary;
-      color: #FFF;
-    }
+    background-color: $gl-primary;
+    color: #FFF;
   }
 
   &.issue-box-open {
-    .state {
-      background-color: #D6F1D7;
-      border-color: $bg_success;
-    }
-    .state-label {
-      background-color: $bg_success;
-      color: #FFF;
-    }
+    background-color: $gl-success;
+    color: #FFF;
   }
 
   &.issue-box-expired {
-    .state {
-      background-color: #EEE9B3;
-      border-color: #faebcc;
-    }
-    .state-label {
-      background: #cea61b;
-      color: #FFF;
-    }
-  }
-
-  .control-group {
-    margin-bottom: 0;
-  }
-
-  .state {
-    background-color: #f9f9f9;
-  }
-
-  .title {
-    font-size: 28px;
-    font-weight: normal;
-    line-height: 1.5;
-    margin: 0;
-    color: #333;
-    padding: 10px 15px;
-  }
-
-  .context {
-    border: none;
-    border-top: 1px solid #eee;
-    padding: 10px 15px;
-
-    // Reset text align for children
-    .text-right > * { text-align: left; }
-
-    @media (max-width: $screen-xs-max) {
-      // Don't right align on mobile
-      .text-right { text-align: left; }
-
-      .row .col-md-6 {
-        padding-top: 5px;
-      }
-    }
-  }
-
-  .description {
-    padding: 0 15px 10px 15px;
-
-    code {
-      white-space: pre-wrap;
-    }
-  }
-
-  .title, .context, .description {
-    .clearfix {
-      margin: 0;
-    }
-  }
-
-  .state-label {
-    font-size: 14px;
-    float: left;
-    font-weight: bold;
-    padding: 10px 15px;
-  }
-
-  .creator {
-    float: right;
-    padding: 10px 15px;
-    a {
-      text-decoration: underline;
-    }
+    background: #cea61b;
+    color: #FFF;
   }
 }
diff --git a/app/assets/stylesheets/generic/jquery.scss b/app/assets/stylesheets/generic/jquery.scss
index bfbbc7d25e3619aa15b7acda7667be1bd4437476..871b808bad4c4aca098f8aacfae64d3160dfba1f 100644
--- a/app/assets/stylesheets/generic/jquery.scss
+++ b/app/assets/stylesheets/generic/jquery.scss
@@ -41,8 +41,8 @@
   }
 
   .ui-state-active {
-    border: 1px solid $bg_primary;
-    background: $bg_primary;
+    border: 1px solid $gl-primary;
+    background: $gl-primary;
     color: #FFF;
   }
 
diff --git a/app/assets/stylesheets/generic/lists.scss b/app/assets/stylesheets/generic/lists.scss
index 2653bfbf831cfda763ac8e35667ca7c94e669548..08bf6e943d2e592feb36e304b3af01ef955e3235 100644
--- a/app/assets/stylesheets/generic/lists.scss
+++ b/app/assets/stylesheets/generic/lists.scss
@@ -35,7 +35,7 @@
       color: #8a6d3b;
     }
 
-    &.smoke { background-color: #f5f5f5; }
+    &.smoke { background-color: $background-color; }
 
     &:hover {
       background: $hover;
@@ -46,7 +46,7 @@
       border-bottom: none;
 
       &.bottom {
-        background: #f5f5f5;
+        background: $background-color;
       }
     }
 
@@ -61,7 +61,7 @@
     p {
       padding-top: 1px;
       margin: 0;
-      color: #222;
+      color: $gray-dark;
       img {
         position: relative;
         top: 3px;
@@ -69,15 +69,15 @@
     }
 
     .well-title {
-      font-size: 14px;
+      font-size: $list-font-size;
       line-height: 18px;
     }
 
     .row_title {
-      font-weight: 500;
-      color: #444;
+      color: $gray-dark;
+
       &:hover {
-        color: #444;
+        color: $text-color;
         text-decoration: underline;
       }
     }
diff --git a/app/assets/stylesheets/generic/markdown_area.scss b/app/assets/stylesheets/generic/markdown_area.scss
index fbfa72c5e5e92c0dc7dcd1ff156bef14bb5c8800..eb39b6bb7e99c839fe0858fbd271800101a06c50 100644
--- a/app/assets/stylesheets/generic/markdown_area.scss
+++ b/app/assets/stylesheets/generic/markdown_area.scss
@@ -20,6 +20,7 @@
       opacity: 0;
       font-size: 50px;
       transition: opacity 200ms ease-in-out;
+      pointer-events: none;
     }
 
     .div-dropzone-spinner {
@@ -50,3 +51,37 @@
   margin-bottom: 0;
   transition: opacity 200ms ease-in-out;
 }
+
+.md-preview-holder {
+  background: #FFF;
+  border: 1px solid #ddd;
+  min-height: 100px;
+  padding: 5px;
+  box-shadow: none;
+}
+
+.new_note,
+.edit_note,
+.issuable-description,
+.milestone-description,
+.wiki-content,
+.merge-request-form {
+  .nav-tabs {
+    margin-bottom: 0;
+    border: none;
+
+    li a,
+    li.active a {
+      border: 1px solid #DDD;
+    }
+  }
+}
+
+.markdown-area {
+  background: #FFF;
+  border: 1px solid #ddd;
+  min-height: 100px;
+  padding: 5px;
+  box-shadow: none;
+  width: 100%;
+}
diff --git a/app/assets/stylesheets/generic/mobile.scss b/app/assets/stylesheets/generic/mobile.scss
new file mode 100644
index 0000000000000000000000000000000000000000..71a1fc4493f4cccf0213b2a3e4697100b1586a2b
--- /dev/null
+++ b/app/assets/stylesheets/generic/mobile.scss
@@ -0,0 +1,69 @@
+/** Common mobile (screen XS, SM) styles **/
+@media (max-width: $screen-xs-max) {
+  .container .content {
+    margin-top: 20px;
+  }
+
+  .nav.nav-tabs > li > a {
+    padding: 10px;
+    font-size: 12px;
+    margin-right: 3px;
+
+    .badge {
+      display: none;
+    }
+  }
+
+  .issues-filters,
+  .dash-projects-filters,
+  .check-all-holder {
+    display: none;
+  }
+
+  .rss-btn {
+    display: none !important;
+  }
+
+  .project-home-links {
+    display: none;
+  }
+}
+
+@media (max-width: $screen-sm-max) {
+  .issues-filters {
+    .milestone-filter, .labels-filter {
+      display: none;
+    }
+  }
+
+  .page-title {
+    .note_created_ago, .new-issue-link {
+      display: none;
+    }
+  }
+
+  .issue_edited_ago, .note_edited_ago {
+    display: none;
+  }
+
+  aside {
+    display: none;
+  }
+
+  .show-aside {
+    display: block !important;
+  }
+}
+
+.show-aside {
+  display: none;
+  position: fixed;
+  right: 0px;
+  top: 30%;
+  padding: 5px 15px;
+  background: #EEE;
+  font-size: 20px;
+  color: #777;
+  z-index: 100;
+  @include box-shadow(0 1px 2px #DDD);
+}
diff --git a/app/assets/stylesheets/generic/nav_sidebar.scss b/app/assets/stylesheets/generic/nav_sidebar.scss
new file mode 100644
index 0000000000000000000000000000000000000000..3bcb7b813330cf95bbe7e64484ac456e8f0f253c
--- /dev/null
+++ b/app/assets/stylesheets/generic/nav_sidebar.scss
@@ -0,0 +1,193 @@
+.page-with-sidebar {
+  background: $background-color;
+
+  .sidebar-wrapper {
+    position: fixed;
+    top: 0;
+    left: 0;
+    height: 100%;
+    border-right: 1px solid $border-color;
+  }
+}
+
+.sidebar-wrapper {
+  z-index: 99;
+  background: $background-color;
+}
+
+.content-wrapper {
+  width: 100%;
+  padding: 15px;
+  background: #FFF;
+}
+
+.nav-sidebar {
+  margin: 0;
+  list-style: none;
+
+  &.navbar-collapse {
+    padding: 0px !important;
+  }
+}
+
+.nav-sidebar li a .count {
+  float: right;
+  background: #eee;
+  padding: 0px 8px;
+  @include border-radius(6px);
+}
+
+.nav-sidebar li {
+  &.active a {
+    color: $text-color;
+    background: #FFF !important;
+    font-weight: bold;
+    border: 1px solid #EEE;
+    border-right: 1px solid transparent;
+    border-left: 3px solid $style_color;
+
+    &.no-highlight {
+      background: none !important;
+      border: none;
+    }
+
+    i {
+      color: $text-color;
+    }
+  }
+}
+
+.nav-sidebar li {
+  &.separate-item {
+    border-top: 1px solid $border-color;
+    padding-top: 10px;
+    margin-top: 10px;
+  }
+
+  a {
+    color: $gray;
+    display: block;
+    text-decoration: none;
+    padding: 8px 15px;
+    font-size: 13px;
+    line-height: 20px;
+    padding-left: 20px;
+
+    &:hover {
+      text-decoration: none;
+      color: $text-color;
+      background: $border-color;
+    }
+
+    &:active, &:focus {
+      text-decoration: none;
+    }
+
+    i {
+      width: 20px;
+      color: $gray-light;
+      margin-right: 23px;
+    }
+  }
+}
+
+.sidebar-subnav {
+  margin-left: 0px;
+  padding-left: 0px;
+
+  li {
+    list-style: none;
+  }
+}
+
+@mixin expanded-sidebar {
+  padding-left: $sidebar_width;
+
+  .sidebar-wrapper {
+    width: $sidebar_width;
+
+    .nav-sidebar {
+      margin-top: 29px;
+      position: fixed;
+      top: 45px;
+      width: $sidebar_width;
+    }
+  }
+
+  .content-wrapper {
+    padding: 20px;
+  }
+}
+
+@mixin folded-sidebar {
+  padding-left: 50px;
+
+  .sidebar-wrapper {
+    width: 52px;
+
+    .nav-sidebar {
+      margin-top: 29px;
+      position: fixed;
+      top: 45px;
+      width: 52px;
+
+      li a {
+        padding-left: 18px;
+        font-size: 14px;
+        padding: 8px 15px;
+        text-align: center;
+
+
+        & > span {
+          display: none;
+        }
+      }
+    }
+
+    .collapse-nav a {
+      left: 0px;
+      padding: 7px 23px 3px 22px;
+    }
+  }
+}
+
+.collapse-nav a {
+  position: fixed;
+  top: 46px;
+  padding: 5px 13px 5px 13px;
+  left: 198px;
+  font-size: 13px;
+  background: transparent;
+  color: black;
+  border-left: 1px solid $border-color;
+  border-bottom: 1px solid $border-color;
+}
+
+.collapse-nav a:hover {
+  text-decoration: none;
+  background: #f2f6f7;
+}
+
+@media (max-width: $screen-md-max) {
+  .page-sidebar-collapsed {
+    @include folded-sidebar;
+  }
+
+  .page-sidebar-expanded {
+    @include folded-sidebar;
+  }
+
+  .collapse-nav {
+    display: none;
+  }
+}
+
+@media(min-width: $screen-md-max) {
+  .page-sidebar-collapsed {
+    @include folded-sidebar;
+  }
+
+  .page-sidebar-expanded {
+    @include expanded-sidebar;
+  }
+}
diff --git a/app/assets/stylesheets/generic/selects.scss b/app/assets/stylesheets/generic/selects.scss
index e0f508d26953a466b31d7fd48e41dc6dfe0ebba3..d8e0dc028d1371683657905daa9a54523a6f39e9 100644
--- a/app/assets/stylesheets/generic/selects.scss
+++ b/app/assets/stylesheets/generic/selects.scss
@@ -2,25 +2,29 @@
 .select2-container, .select2-container.select2-drop-above {
   .select2-choice {
     background: #FFF;
-    border-color: #BBB;
-    padding: 6px 12px;
-    font-size: 13px;
-    line-height: 18px;
-    height: auto;
+    border-color: #DDD;
+    height: 34px;
+    padding: 6px 14px;
+    font-size: 14px;
+    line-height: 1.42857143;
+
+    @include border-radius(4px);
 
     .select2-arrow {
       background: #FFF;
-      border-left: 1px solid #DDD;
+      border-left: none;
+      padding-top: 3px;
     }
   }
 }
 
 .select2-container-multi .select2-choices {
-  @include border-radius(4px)
+  @include border-radius(4px);
+  border-color: #CCC;
 }
 
 .select2-container-multi .select2-choices .select2-search-field input {
-  padding: 6px 12px;
+  padding: 8px 14px;
   font-size: 13px;
   line-height: 18px;
   height: auto;
@@ -29,6 +33,7 @@
 .select2-drop-active {
   border: 1px solid #BBB !important;
   margin-top: 4px;
+  font-size: 13px;
 
   &.select2-drop-above {
     margin-bottom: 8px;
@@ -42,60 +47,18 @@
   .select2-results {
     max-height: 350px;
     .select2-highlighted {
-      background: $bg_primary;
-    }
-  }
-}
-
-select {
-  &.select2 {
-    width: 100px;
-  }
-
-  &.select2-sm {
-    width: 100px;
-  }
-}
-
-@media (min-width: $screen-sm-min) {
-  select {
-    &.select2 {
-      width: 150px;
-    }
-    &.select2-sm {
-      width: 120px;
+      background: $gl-primary;
     }
   }
 }
 
-/* Medium devices (desktops, 992px and up) */
-@media (min-width: $screen-md-min) {
-  select {
-    &.select2 {
-      width: 170px;
-    }
-    &.select2-sm {
-      width: 140px;
-    }
-  }
+.select2-container {
+  width: 100% !important;
 }
 
-/* Large devices (large desktops, 1200px and up) */
-@media (min-width: $screen-lg-min) {
-  select {
-    &.select2 {
-      width: 200px;
-    }
-    &.select2-sm {
-      width: 150px;
-    }
-  }
-}
-
-
 /** Branch/tag selector **/
 .project-refs-form .select2-container {
-  margin-right: 10px;
+  width: 160px !important;
 }
 
 .ajax-users-dropdown, .ajax-project-users-dropdown {
@@ -116,6 +79,18 @@ select {
   }
 }
 
+.group-result {
+  .group-image {
+    float: left;
+  }
+  .group-name {
+    font-weight: bold;
+  }
+  .group-path {
+    color: #999;
+  }
+}
+
 .user-result {
   .user-image {
     float: left;
@@ -137,3 +112,7 @@ select {
     font-weight: bolder;
   }
 }
+
+.ajax-users-dropdown {
+  min-width: 225px !important;
+}
diff --git a/app/assets/stylesheets/generic/sidebar.scss b/app/assets/stylesheets/generic/sidebar.scss
deleted file mode 100644
index f6311ef74e8d0277f16a26f1725e5c07ae4b0087..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/generic/sidebar.scss
+++ /dev/null
@@ -1,46 +0,0 @@
-.ui.sidebar {
-  z-index: 1000 !important;
-  background: #fff;
-  padding: 10px;
-  width: 285px;
-}
-
-.ui.right.sidebar {
-  border-left: 1px solid #e1e1e1;
-  border-right: 0;
-}
-
-.sidebar-expand-button {
-  cursor: pointer;
-  transition: all 0.4s;
-  -moz-transition: all 0.4s;
-  -webkit-transition: all 0.4s;
-}
-
-.fixed.sidebar-expand-button {
-  background: #f9f9f9;
-  color: #555;
-  padding: 9px 12px 6px 14px;
-  border: 1px solid #E1E1E1;
-  border-right: 0;
-  position: fixed;
-  top: 108px;
-  right: 0px;
-  margin-right: 0;
-  &:hover {
-    background: #ddd;
-    color: #333;
-    padding-right: 25px;
-  }
-}
-
-.btn.btn-default.sidebar-expand-button {
-  margin-left: 12px;
-  display: inline-block !important;
-}
-
-@media (min-width: 767px) {
-.btn.btn-default.sidebar-expand-button {
-  display: none!important;
- }
-}
diff --git a/app/assets/stylesheets/generic/tables.scss b/app/assets/stylesheets/generic/tables.scss
new file mode 100644
index 0000000000000000000000000000000000000000..a66e45577de181764870e87bae2937d4b3dd6ccf
--- /dev/null
+++ b/app/assets/stylesheets/generic/tables.scss
@@ -0,0 +1,20 @@
+table {
+  &.table {
+    tr {
+      td, th {
+        padding: 8px 10px;
+        line-height: 20px;
+        vertical-align: middle;
+      }
+      th {
+        font-weight: normal;
+        font-size: 15px;
+        border-bottom: 1px solid $border-color !important;
+      }
+      td {
+        border-color: #F1F1F1 !important;
+        border-bottom: 1px solid;
+      }
+    }
+  }
+}
diff --git a/app/assets/stylesheets/generic/timeline.scss b/app/assets/stylesheets/generic/timeline.scss
index f29cf25fa4c51cb2c89ddfa1484347e136270570..97831eb7c273a094c4b3f635aacd061c7fa5bafa 100644
--- a/app/assets/stylesheets/generic/timeline.scss
+++ b/app/assets/stylesheets/generic/timeline.scss
@@ -42,7 +42,7 @@
         background: #fff;
         color: #737881;
         float: left;
-        @include border-radius(40px);
+        @include border-radius($avatar_radius);
         @include box-shadow(0 0 0 3px #EEE);
         overflow: hidden;
 
@@ -54,10 +54,14 @@
 
       .timeline-content {
         position: relative;
-        background: #f5f5f6;
+        background: $background-color;
         padding: 10px 15px;
         margin-left: 60px;
 
+        img {
+          max-width: 100%;
+        }
+
         &:after {
           content: '';
           display: block;
@@ -66,7 +70,7 @@
           height: 0;
           border-style: solid;
           border-width: 9px 9px 9px 0;
-          border-color: transparent #f5f5f6 transparent transparent;
+          border-color: transparent $background-color transparent transparent;
           left: 0;
           top: 10px;
           margin-left: -9px;
@@ -74,4 +78,57 @@
       }
     }
   }
+
+  .system-note .timeline-entry-inner {
+    .timeline-icon {
+      background: none;
+      margin-left: 12px;
+      margin-top: 0;
+      @include box-shadow(none);
+
+      span {
+        margin: 0 2px;
+        font-size: 16px;
+        color: #eeeeee;
+      }
+    }
+
+    .timeline-content {
+      background: none;
+      margin-left: 45px;
+      padding: 0px 15px;
+
+      &:after { border: 0; }
+
+      .note-header {
+        span { font-size: 12px; }
+
+        .avatar {
+          margin-right: 5px;
+        }
+      }
+
+      .note-text {
+        font-size: 12px;
+        margin-left: 20px;
+      }
+    }
+  }
+}
+
+@media (max-width: $screen-xs-max) {
+  .timeline {
+    &:before {
+      background: none;
+    }
+    .timeline-entry .timeline-entry-inner {
+      .timeline-icon {
+        display: none;
+      }
+
+      .timeline-content {
+        margin-left: 0;
+      }
+    }
+  }
 }
diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss
index 385a627b4be5aa798e4490a607bbc54a7f4b4739..80190424c1b056de0591b5ac855a78fb94ffbd84 100644
--- a/app/assets/stylesheets/generic/typography.scss
+++ b/app/assets/stylesheets/generic/typography.scss
@@ -2,24 +2,11 @@
  * Headers
  *
  */
-h1.page-title {
-  @include page-title;
-  font-size: 28px;
-}
-
-h2.page-title {
-  @include page-title;
-  font-size: 24px;
-}
-
-h3.page-title {
-  @include page-title;
-  font-size: 22px;
-}
-
-h6 {
-  color: #888;
-  text-transform: uppercase;
+.page-title {
+  margin-top: 0px;
+  line-height: 1.5;
+  font-weight: normal;
+  margin-bottom: 5px;
 }
 
 /** CODE **/
@@ -28,56 +15,10 @@ pre {
 
   &.dark {
     background: #333;
-    color: #f5f5f5;
-  }
-}
-
-/**
- * Links
- *
- */
-a {
-  outline: none;
-  color: $link_color;
-  &:hover {
-    text-decoration: underline;
-    color: $link_hover_color;
-  }
-
-  &:focus {
-    text-decoration: underline;
-  }
-
-  &.darken {
-    color: $style_color;
-  }
-
-  &.lined {
-    text-decoration: underline;
-    &:hover { text-decoration: underline; }
-  }
-
-  &.gray {
-    color: gray;
-  }
-
-  &.supp_diff_link {
-    text-align: center;
-    padding: 20px 0;
-    background: #f1f1f1;
-    width: 100%;
-    float: left;
-  }
-
-  &.neib  {
-    margin-right: 15px;
+    color: $background-color;
   }
 }
 
-a:focus {
-  outline: none;
-}
-
 .monospace {
   font-family: $monospace_font;
 }
@@ -128,3 +69,7 @@ a:focus {
 textarea.js-gfm-input {
   font-family: $monospace_font;
 }
+
+.strikethrough {
+  text-decoration: line-through;
+}
diff --git a/app/assets/stylesheets/generic/zen.scss b/app/assets/stylesheets/generic/zen.scss
new file mode 100644
index 0000000000000000000000000000000000000000..26afc21a6abd00e0664ce98b87432555a3cd88e2
--- /dev/null
+++ b/app/assets/stylesheets/generic/zen.scss
@@ -0,0 +1,98 @@
+.zennable {
+  position: relative;
+
+  input {
+    display: none;
+  }
+
+  .zen-enter-link {
+    color: #888;
+    position: absolute;
+    top: -26px;
+    right: 4px;
+  }
+
+  .zen-leave-link {
+    display: none;
+    color: #888;
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    padding: 5px;
+    font-size: 36px;
+
+    &:hover {
+      color: #111;
+    }
+  }
+
+  input:checked ~ .zen-backdrop .zen-enter-link {
+    display: none;
+  }
+
+  input:checked ~ .zen-backdrop .zen-leave-link {
+    display: block;
+    position: absolute;
+    top: 0;
+  }
+
+  input:checked ~ .zen-backdrop {
+    background-color: white;
+    position: fixed;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    z-index: 1031;
+
+    textarea {
+      border: none;
+      box-shadow: none;
+      border-radius: 0;
+      color: #000;
+      font-size: 20px;
+      line-height: 26px;
+      padding: 30px;
+      display: block;
+      outline: none;
+      resize: none;
+      height: 100vh;
+      max-width: 900px;
+      margin: 0 auto;
+    }
+  }
+
+  .zen-backdrop textarea::-webkit-input-placeholder {
+    color: white;
+  }
+
+  .zen-backdrop textarea:-moz-placeholder {
+    color: white;
+  }
+
+  .zen-backdrop textarea::-moz-placeholder {
+    color: white;
+  }
+
+  .zen-backdrop textarea:-ms-input-placeholder {
+    color: white;
+  }
+
+  input:checked ~ .zen-backdrop textarea::-webkit-input-placeholder {
+    color: #999;
+  }
+
+  input:checked ~ .zen-backdrop textarea:-moz-placeholder {
+    color: #999;
+    opacity: 1;
+  }
+
+  input:checked ~ .zen-backdrop textarea::-moz-placeholder {
+    color: #999;
+    opacity: 1;
+  }
+
+  input:checked ~ .zen-backdrop textarea:-ms-input-placeholder {
+    color: #999;
+  }
+}
diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss
index ca51da3fdd4bceb5a2cb50ca49dd4d65bac5d149..c8cb18ec35ff9b866cd455e6add77c9c3ed14177 100644
--- a/app/assets/stylesheets/highlight/dark.scss
+++ b/app/assets/stylesheets/highlight/dark.scss
@@ -1,199 +1,88 @@
-.dark {
-  background-color: #232323;
+/* https://github.com/MozMorris/tomorrow-pygments */
+pre.code.highlight.dark,
+.code.dark {
 
-  .line.hll {
-    background: #558;
-  }
-
-  .highlight{
-    border-left: 1px solid #444;
-  }
-
-  .no-highlight {
-    color: #DDD;
-  }
+  background-color: #1d1f21;
+  color: #c5c8c6;
 
+  pre.code,
+  .line-numbers,
   .line-numbers a {
-    color: #666;
-  }
-
-  pre {
-    background-color: #232323;
-  }
-
-  .hljs {
-    display: block;
-    background: #232323;
-    color: #E6E1DC;
-  }
-
-  .hljs-comment,
-  .hljs-template_comment,
-  .hljs-javadoc,
-  .hljs-shebang {
-    color: #BC9458;
-    font-style: italic;
-  }
-
-  .hljs-keyword,
-  .ruby .hljs-function .hljs-keyword,
-  .hljs-request,
-  .hljs-status,
-  .nginx .hljs-title,
-  .method,
-  .hljs-list .hljs-title {
-    color: #C26230;
-  }
-
-  .hljs-string,
-  .hljs-number,
-  .hljs-regexp,
-  .hljs-tag .hljs-value,
-  .hljs-cdata,
-  .hljs-filter .hljs-argument,
-  .hljs-attr_selector,
-  .apache .hljs-cbracket,
-  .hljs-date,
-  .tex .hljs-command,
-  .markdown .hljs-link_label {
-    color: #A5C261;
-  }
-
-  .hljs-subst {
-    color: #519F50;
-  }
-
-  .hljs-tag,
-  .hljs-tag .hljs-keyword,
-  .hljs-tag .hljs-title,
-  .hljs-doctype,
-  .hljs-sub .hljs-identifier,
-  .hljs-pi,
-  .input_number {
-    color: #E8BF6A;
-  }
-
-  .hljs-identifier {
-    color: #D0D0FF;
-  }
-
-  .hljs-class .hljs-title,
-  .haskell .hljs-type,
-  .smalltalk .hljs-class,
-  .hljs-javadoctag,
-  .hljs-yardoctag,
-  .hljs-phpdoc {
-    text-decoration: none;
-  }
-
-  .hljs-constant {
-    color: #DA4939;
-  }
-
-
-  .hljs-symbol,
-  .hljs-built_in,
-  .ruby .hljs-symbol .hljs-string,
-  .ruby .hljs-symbol .hljs-identifier,
-  .markdown .hljs-link_url,
-  .hljs-attribute {
-    color: #6D9CBE;
-  }
-
-  .markdown .hljs-link_url {
-    text-decoration: underline;
-  }
-
-
-
-  .hljs-params,
-  .hljs-variable,
-  .clojure .hljs-attribute {
-    color: #D0D0FF;
-  }
-
-  .css .hljs-tag,
-  .hljs-rules .hljs-property,
-  .hljs-pseudo,
-  .tex .hljs-special {
-    color: #CDA869;
-  }
-
-  .css .hljs-class {
-    color: #9B703F;
-  }
-
-  .hljs-rules .hljs-keyword {
-    color: #C5AF75;
-  }
-
-  .hljs-rules .hljs-value {
-    color: #CF6A4C;
-  }
-
-  .css .hljs-id {
-    color: #8B98AB;
-  }
-
-  .hljs-annotation,
-  .apache .hljs-sqbracket,
-  .nginx .hljs-built_in {
-    color: #9B859D;
-  }
-
-  .hljs-preprocessor,
-  .hljs-preprocessor *,
-  .hljs-pragma {
-    color: #8996A8 !important;
-  }
-
-  .hljs-hexcolor,
-  .css .hljs-value .hljs-number {
-    color: #A5C261;
-  }
-
-  .hljs-title,
-  .hljs-decorator,
-  .css .hljs-function {
-    color: #FFC66D;
-  }
-
-  .diff .hljs-header,
-  .hljs-chunk {
-    background-color: #2F33AB;
-    color: #E6E1DC;
-    display: inline-block;
-    width: 100%;
-  }
-
-  .diff .hljs-change {
-    background-color: #4A410D;
-    color: #F8F8F8;
-    display: inline-block;
-    width: 100%;
-  }
-
-  .hljs-addition {
-    background-color: #144212;
-    color: #E6E1DC;
-    display: inline-block;
-    width: 100%;
-  }
-
-  .hljs-deletion {
-    background-color: #600;
-    color: #E6E1DC;
-    display: inline-block;
-    width: 100%;
-  }
-
-  .coffeescript .javascript,
-  .javascript .xml,
-  .tex .hljs-formula,
-  .xml .javascript,
-  .xml .vbscript,
-  .xml .css,
-  .xml .hljs-cdata {
-    opacity: 0.7;
-  }
+    background-color: #1d1f21 !important;
+    color: #c5c8c6 !important;
+  }
+
+  pre.code {
+    border-left: 1px solid #666;
+  }
+
+  // highlight line via anchor
+  pre .hll {
+    background-color: #557 !important;
+  }
+
+  .hll { background-color: #373b41 }
+  .c { color: #969896 } /* Comment */
+  .err { color: #cc6666 } /* Error */
+  .k { color: #b294bb } /* Keyword */
+  .l { color: #de935f } /* Literal */
+  .n { color: #c5c8c6 } /* Name */
+  .o { color: #8abeb7 } /* Operator */
+  .p { color: #c5c8c6 } /* Punctuation */
+  .cm { color: #969896 } /* Comment.Multiline */
+  .cp { color: #969896 } /* Comment.Preproc */
+  .c1 { color: #969896 } /* Comment.Single */
+  .cs { color: #969896 } /* Comment.Special */
+  .gd { color: #cc6666 } /* Generic.Deleted */
+  .ge { font-style: italic } /* Generic.Emph */
+  .gh { color: #c5c8c6; font-weight: bold } /* Generic.Heading */
+  .gi { color: #b5bd68 } /* Generic.Inserted */
+  .gp { color: #969896; font-weight: bold } /* Generic.Prompt */
+  .gs { font-weight: bold } /* Generic.Strong */
+  .gu { color: #8abeb7; font-weight: bold } /* Generic.Subheading */
+  .kc { color: #b294bb } /* Keyword.Constant */
+  .kd { color: #b294bb } /* Keyword.Declaration */
+  .kn { color: #8abeb7 } /* Keyword.Namespace */
+  .kp { color: #b294bb } /* Keyword.Pseudo */
+  .kr { color: #b294bb } /* Keyword.Reserved */
+  .kt { color: #f0c674 } /* Keyword.Type */
+  .ld { color: #b5bd68 } /* Literal.Date */
+  .m { color: #de935f } /* Literal.Number */
+  .s { color: #b5bd68 } /* Literal.String */
+  .na { color: #81a2be } /* Name.Attribute */
+  .nb { color: #c5c8c6 } /* Name.Builtin */
+  .nc { color: #f0c674 } /* Name.Class */
+  .no { color: #cc6666 } /* Name.Constant */
+  .nd { color: #8abeb7 } /* Name.Decorator */
+  .ni { color: #c5c8c6 } /* Name.Entity */
+  .ne { color: #cc6666 } /* Name.Exception */
+  .nf { color: #81a2be } /* Name.Function */
+  .nl { color: #c5c8c6 } /* Name.Label */
+  .nn { color: #f0c674 } /* Name.Namespace */
+  .nx { color: #81a2be } /* Name.Other */
+  .py { color: #c5c8c6 } /* Name.Property */
+  .nt { color: #8abeb7 } /* Name.Tag */
+  .nv { color: #cc6666 } /* Name.Variable */
+  .ow { color: #8abeb7 } /* Operator.Word */
+  .w { color: #c5c8c6 } /* Text.Whitespace */
+  .mf { color: #de935f } /* Literal.Number.Float */
+  .mh { color: #de935f } /* Literal.Number.Hex */
+  .mi { color: #de935f } /* Literal.Number.Integer */
+  .mo { color: #de935f } /* Literal.Number.Oct */
+  .sb { color: #b5bd68 } /* Literal.String.Backtick */
+  .sc { color: #c5c8c6 } /* Literal.String.Char */
+  .sd { color: #969896 } /* Literal.String.Doc */
+  .s2 { color: #b5bd68 } /* Literal.String.Double */
+  .se { color: #de935f } /* Literal.String.Escape */
+  .sh { color: #b5bd68 } /* Literal.String.Heredoc */
+  .si { color: #de935f } /* Literal.String.Interpol */
+  .sx { color: #b5bd68 } /* Literal.String.Other */
+  .sr { color: #b5bd68 } /* Literal.String.Regex */
+  .s1 { color: #b5bd68 } /* Literal.String.Single */
+  .ss { color: #b5bd68 } /* Literal.String.Symbol */
+  .bp { color: #c5c8c6 } /* Name.Builtin.Pseudo */
+  .vc { color: #cc6666 } /* Name.Variable.Class */
+  .vg { color: #cc6666 } /* Name.Variable.Global */
+  .vi { color: #cc6666 } /* Name.Variable.Instance */
+  .il { color: #de935f } /* Literal.Number.Integer.Long */
 }
diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss
index 36bc5df2f44136ff5c903a5ad4a523ffa48e5e6c..001e8b31020dda641c6e076f9a4a7d93b7c438cc 100644
--- a/app/assets/stylesheets/highlight/monokai.scss
+++ b/app/assets/stylesheets/highlight/monokai.scss
@@ -1,148 +1,88 @@
-.monokai {
-  background-color: #272822;
+/* https://github.com/richleland/pygments-css/blob/master/monokai.css */
+pre.code.monokai,
+.code.monokai {
 
-  .highlight{
-    border-left: 1px solid #444;
-  }
-
-  .line.hll {
-    background: #558;
-  }
-
-  .no-highlight {
-    color: #DDD;
-  }
+  background: #272822;
+  color: #f8f8f2;
 
+  pre.highlight,
+  .line-numbers,
   .line-numbers a {
-    color: #666;
+    background:#272822 !important;
+    color:#f8f8f2 !important;
   }
 
-  pre {
-    background-color: #272822;
-    color: #f8f8f2;
+  pre.code {
+    border-left: 1px solid #555;
   }
 
-  .hljs {
-    display: block;
-    background: #272822;
+  // highlight line via anchor
+  pre .hll {
+    background-color: #49483e !important;
   }
 
-  .hljs-tag,
-  .hljs-tag .hljs-title,
-  .hljs-keyword,
-  .hljs-literal,
-  .hljs-strong,
-  .hljs-change,
-  .hljs-winutils,
-  .hljs-flow,
-  .lisp .hljs-title,
-  .clojure .hljs-built_in,
-  .nginx .hljs-title,
-  .tex .hljs-special {
-    color: #F92672;
-  }
+  .hll { background-color: #49483e }
+  .c { color: #75715e } /* Comment */
+  .err { color: #960050; background-color: #1e0010 } /* Error */
+  .k { color: #66d9ef } /* Keyword */
+  .l { color: #ae81ff } /* Literal */
+  .n { color: #f8f8f2 } /* Name */
+  .o { color: #f92672 } /* Operator */
+  .p { color: #f8f8f2 } /* Punctuation */
+  .cm { color: #75715e } /* Comment.Multiline */
+  .cp { color: #75715e } /* Comment.Preproc */
+  .c1 { color: #75715e } /* Comment.Single */
+  .cs { color: #75715e } /* Comment.Special */
+  .ge { font-style: italic } /* Generic.Emph */
+  .gs { font-weight: bold } /* Generic.Strong */
+  .kc { color: #66d9ef } /* Keyword.Constant */
+  .kd { color: #66d9ef } /* Keyword.Declaration */
+  .kn { color: #f92672 } /* Keyword.Namespace */
+  .kp { color: #66d9ef } /* Keyword.Pseudo */
+  .kr { color: #66d9ef } /* Keyword.Reserved */
+  .kt { color: #66d9ef } /* Keyword.Type */
+  .ld { color: #e6db74 } /* Literal.Date */
+  .m { color: #ae81ff } /* Literal.Number */
+  .s { color: #e6db74 } /* Literal.String */
+  .na { color: #a6e22e } /* Name.Attribute */
+  .nb { color: #f8f8f2 } /* Name.Builtin */
+  .nc { color: #a6e22e } /* Name.Class */
+  .no { color: #66d9ef } /* Name.Constant */
+  .nd { color: #a6e22e } /* Name.Decorator */
+  .ni { color: #f8f8f2 } /* Name.Entity */
+  .ne { color: #a6e22e } /* Name.Exception */
+  .nf { color: #a6e22e } /* Name.Function */
+  .nl { color: #f8f8f2 } /* Name.Label */
+  .nn { color: #f8f8f2 } /* Name.Namespace */
+  .nx { color: #a6e22e } /* Name.Other */
+  .py { color: #f8f8f2 } /* Name.Property */
+  .nt { color: #f92672 } /* Name.Tag */
+  .nv { color: #f8f8f2 } /* Name.Variable */
+  .ow { color: #f92672 } /* Operator.Word */
+  .w { color: #f8f8f2 } /* Text.Whitespace */
+  .mf { color: #ae81ff } /* Literal.Number.Float */
+  .mh { color: #ae81ff } /* Literal.Number.Hex */
+  .mi { color: #ae81ff } /* Literal.Number.Integer */
+  .mo { color: #ae81ff } /* Literal.Number.Oct */
+  .sb { color: #e6db74 } /* Literal.String.Backtick */
+  .sc { color: #e6db74 } /* Literal.String.Char */
+  .sd { color: #e6db74 } /* Literal.String.Doc */
+  .s2 { color: #e6db74 } /* Literal.String.Double */
+  .se { color: #ae81ff } /* Literal.String.Escape */
+  .sh { color: #e6db74 } /* Literal.String.Heredoc */
+  .si { color: #e6db74 } /* Literal.String.Interpol */
+  .sx { color: #e6db74 } /* Literal.String.Other */
+  .sr { color: #e6db74 } /* Literal.String.Regex */
+  .s1 { color: #e6db74 } /* Literal.String.Single */
+  .ss { color: #e6db74 } /* Literal.String.Symbol */
+  .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
+  .vc { color: #f8f8f2 } /* Name.Variable.Class */
+  .vg { color: #f8f8f2 } /* Name.Variable.Global */
+  .vi { color: #f8f8f2 } /* Name.Variable.Instance */
+  .il { color: #ae81ff } /* Literal.Number.Integer.Long */
 
-  .hljs {
-    color: #DDD;
-  }
-
-  .hljs .hljs-constant,
-  .asciidoc .hljs-code {
-    color: #66D9EF;
-  }
-
-  .hljs-code,
-  .hljs-class .hljs-title,
-  .hljs-header {
-    color: white;
-  }
-
-  .hljs-link_label,
-  .hljs-attribute,
-  .hljs-symbol,
-  .hljs-symbol .hljs-string,
-  .hljs-value,
-  .hljs-regexp {
-    color: #BF79DB;
-  }
-
-  .hljs-link_url,
-  .hljs-tag .hljs-value,
-  .hljs-string,
-  .hljs-bullet,
-  .hljs-subst,
-  .hljs-title,
-  .hljs-emphasis,
-  .haskell .hljs-type,
-  .hljs-preprocessor,
-  .hljs-pragma,
-  .ruby .hljs-class .hljs-parent,
-  .hljs-built_in,
-  .sql .hljs-aggregate,
-  .django .hljs-template_tag,
-  .django .hljs-variable,
-  .smalltalk .hljs-class,
-  .hljs-javadoc,
-  .django .hljs-filter .hljs-argument,
-  .smalltalk .hljs-localvars,
-  .smalltalk .hljs-array,
-  .hljs-attr_selector,
-  .hljs-pseudo,
-  .hljs-addition,
-  .hljs-stream,
-  .hljs-envvar,
-  .apache .hljs-tag,
-  .apache .hljs-cbracket,
-  .tex .hljs-command,
-  .hljs-prompt {
-    color: #A6E22E;
-  }
-
-  .hljs-comment,
-  .java .hljs-annotation,
-  .smartquote,
-  .hljs-blockquote,
-  .hljs-horizontal_rule,
-  .python .hljs-decorator,
-  .hljs-template_comment,
-  .hljs-pi,
-  .hljs-doctype,
-  .hljs-deletion,
-  .hljs-shebang,
-  .apache .hljs-sqbracket,
-  .tex .hljs-formula {
-    color: #75715E;
-  }
-
-  .hljs-keyword,
-  .hljs-literal,
-  .css .hljs-id,
-  .hljs-phpdoc,
-  .hljs-title,
-  .hljs-header,
-  .haskell .hljs-type,
-  .vbscript .hljs-built_in,
-  .sql .hljs-aggregate,
-  .rsl .hljs-built_in,
-  .smalltalk .hljs-class,
-  .diff .hljs-header,
-  .hljs-chunk,
-  .hljs-winutils,
-  .bash .hljs-variable,
-  .apache .hljs-tag,
-  .tex .hljs-special,
-  .hljs-request,
-  .hljs-status {
-    font-weight: bold;
-  }
-
-  .coffeescript .javascript,
-  .javascript .xml,
-  .tex .hljs-formula,
-  .xml .javascript,
-  .xml .vbscript,
-  .xml .css,
-  .xml .hljs-cdata {
-    opacity: 0.5;
-  }
+  .gh { } /* Generic Heading & Diff Header */
+  .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */
+  .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */
+  .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */
 }
diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss
index b9bec225188be0caf73e231b93a9cef3c55e2d8c..f5b827e7c02e591c014a75c2b291a8293c9d3b08 100644
--- a/app/assets/stylesheets/highlight/solarized_dark.scss
+++ b/app/assets/stylesheets/highlight/solarized_dark.scss
@@ -1,125 +1,110 @@
-.solarized-dark {
-  background-color: #002B36;
+/* https://gist.github.com/qguv/7936275 */
+pre.code.highlight.solarized-dark,
+.code.solarized-dark {
 
-  .highlight{
-    border-left: 1px solid #113b46;
-  }
-
-  .line.hll {
-    background: #000;
-  }
-
-  .no-highlight {
-    color: #DDD;
-  }
-
-  pre {
-    background-color: #002B36;
-    color: #eee;
-  }
+  background-color: #002b36;
+  color: #93a1a1;
 
+  pre.code,
+  .line-numbers,
   .line-numbers a {
-    color: #666;
-  }
-
-  .hljs {
-    display: block;
-    background: #002b36;
-    color: #839496;
+    background-color: #002b36 !important;
+    color: #93a1a1 !important;
   }
 
-  .hljs-comment,
-  .hljs-template_comment,
-  .diff .hljs-header,
-  .hljs-doctype,
-  .hljs-pi,
-  .lisp .hljs-string,
-  .hljs-javadoc {
-    color: #586e75;
-  }
-
-  /* Solarized Green */
-  .hljs-keyword,
-  .hljs-winutils,
-  .method,
-  .hljs-addition,
-  .css .hljs-tag,
-  .hljs-request,
-  .hljs-status,
-  .nginx .hljs-title {
-    color: #859900;
-  }
-
-  /* Solarized Cyan */
-  .hljs-number,
-  .hljs-command,
-  .hljs-string,
-  .hljs-tag .hljs-value,
-  .hljs-rules .hljs-value,
-  .hljs-phpdoc,
-  .tex .hljs-formula,
-  .hljs-regexp,
-  .hljs-hexcolor,
-  .hljs-link_url {
-    color: #2aa198;
+  pre.code {
+    border-left: 1px solid #113b46;
   }
 
-  /* Solarized Blue */
-  .hljs-title,
-  .hljs-localvars,
-  .hljs-chunk,
-  .hljs-decorator,
-  .hljs-built_in,
-  .hljs-identifier,
-  .vhdl .hljs-literal,
-  .hljs-id,
-  .css .hljs-function {
-    color: #268bd2;
+  // highlight line via anchor
+  pre .hll {
+    background-color: #174652 !important;
   }
 
-  /* Solarized Yellow */
-  .hljs-attribute,
-  .hljs-variable,
-  .lisp .hljs-body,
-  .smalltalk .hljs-number,
-  .hljs-constant,
-  .hljs-class .hljs-title,
-  .hljs-parent,
-  .haskell .hljs-type,
-  .hljs-link_reference {
-    color: #b58900;
-  }
+  /* Solarized Dark
 
-  /* Solarized Orange */
-  .hljs-preprocessor,
-  .hljs-preprocessor .hljs-keyword,
-  .hljs-pragma,
-  .hljs-shebang,
-  .hljs-symbol,
-  .hljs-symbol .hljs-string,
-  .diff .hljs-change,
-  .hljs-special,
-  .hljs-attr_selector,
-  .hljs-subst,
-  .hljs-cdata,
-  .clojure .hljs-title,
-  .css .hljs-pseudo,
-  .hljs-header {
-    color: #cb4b16;
-  }
+  For use with Jekyll and Pygments
 
-  /* Solarized Red */
-  .hljs-deletion,
-  .hljs-important {
-    color: #dc322f;
-  }
+  http://ethanschoonover.com/solarized
 
-  /* Solarized Violet */
-  .hljs-link_label {
-    color: #6c71c4;
-  }
+  SOLARIZED HEX      ROLE
+  --------- -------- ------------------------------------------
+  base03    #002b36  background
+  base01    #586e75  comments / secondary content
+  base1     #93a1a1  body text / default code / primary content
+  orange    #cb4b16  constants
+  red       #dc322f  regex, special keywords
+  blue      #268bd2  reserved keywords
+  cyan      #2aa198  strings, numbers
+  green     #859900  operators, other keywords
+  */
 
-  .tex .hljs-formula {
-    background: #073642;
-  }
+  .c { color: #586e75 } /* Comment */
+  .err { color: #93a1a1 } /* Error */
+  .g { color: #93a1a1 } /* Generic */
+  .k { color: #859900 } /* Keyword */
+  .l { color: #93a1a1 } /* Literal */
+  .n { color: #93a1a1 } /* Name */
+  .o { color: #859900 } /* Operator */
+  .x { color: #cb4b16 } /* Other */
+  .p { color: #93a1a1 } /* Punctuation */
+  .cm { color: #586e75 } /* Comment.Multiline */
+  .cp { color: #859900 } /* Comment.Preproc */
+  .c1 { color: #586e75 } /* Comment.Single */
+  .cs { color: #859900 } /* Comment.Special */
+  .gd { color: #2aa198 } /* Generic.Deleted */
+  .ge { color: #93a1a1; font-style: italic } /* Generic.Emph */
+  .gr { color: #dc322f } /* Generic.Error */
+  .gh { color: #cb4b16 } /* Generic.Heading */
+  .gi { color: #859900 } /* Generic.Inserted */
+  .go { color: #93a1a1 } /* Generic.Output */
+  .gp { color: #93a1a1 } /* Generic.Prompt */
+  .gs { color: #93a1a1; font-weight: bold } /* Generic.Strong */
+  .gu { color: #cb4b16 } /* Generic.Subheading */
+  .gt { color: #93a1a1 } /* Generic.Traceback */
+  .kc { color: #cb4b16 } /* Keyword.Constant */
+  .kd { color: #268bd2 } /* Keyword.Declaration */
+  .kn { color: #859900 } /* Keyword.Namespace */
+  .kp { color: #859900 } /* Keyword.Pseudo */
+  .kr { color: #268bd2 } /* Keyword.Reserved */
+  .kt { color: #dc322f } /* Keyword.Type */
+  .ld { color: #93a1a1 } /* Literal.Date */
+  .m { color: #2aa198 } /* Literal.Number */
+  .s { color: #2aa198 } /* Literal.String */
+  .na { color: #93a1a1 } /* Name.Attribute */
+  .nb { color: #B58900 } /* Name.Builtin */
+  .nc { color: #268bd2 } /* Name.Class */
+  .no { color: #cb4b16 } /* Name.Constant */
+  .nd { color: #268bd2 } /* Name.Decorator */
+  .ni { color: #cb4b16 } /* Name.Entity */
+  .ne { color: #cb4b16 } /* Name.Exception */
+  .nf { color: #268bd2 } /* Name.Function */
+  .nl { color: #93a1a1 } /* Name.Label */
+  .nn { color: #93a1a1 } /* Name.Namespace */
+  .nx { color: #93a1a1 } /* Name.Other */
+  .py { color: #93a1a1 } /* Name.Property */
+  .nt { color: #268bd2 } /* Name.Tag */
+  .nv { color: #268bd2 } /* Name.Variable */
+  .ow { color: #859900 } /* Operator.Word */
+  .w { color: #93a1a1 } /* Text.Whitespace */
+  .mf { color: #2aa198 } /* Literal.Number.Float */
+  .mh { color: #2aa198 } /* Literal.Number.Hex */
+  .mi { color: #2aa198 } /* Literal.Number.Integer */
+  .mo { color: #2aa198 } /* Literal.Number.Oct */
+  .sb { color: #586e75 } /* Literal.String.Backtick */
+  .sc { color: #2aa198 } /* Literal.String.Char */
+  .sd { color: #93a1a1 } /* Literal.String.Doc */
+  .s2 { color: #2aa198 } /* Literal.String.Double */
+  .se { color: #cb4b16 } /* Literal.String.Escape */
+  .sh { color: #93a1a1 } /* Literal.String.Heredoc */
+  .si { color: #2aa198 } /* Literal.String.Interpol */
+  .sx { color: #2aa198 } /* Literal.String.Other */
+  .sr { color: #dc322f } /* Literal.String.Regex */
+  .s1 { color: #2aa198 } /* Literal.String.Single */
+  .ss { color: #2aa198 } /* Literal.String.Symbol */
+  .bp { color: #268bd2 } /* Name.Builtin.Pseudo */
+  .vc { color: #268bd2 } /* Name.Variable.Class */
+  .vg { color: #268bd2 } /* Name.Variable.Global */
+  .vi { color: #268bd2 } /* Name.Variable.Instance */
+  .il { color: #2aa198 } /* Literal.Number.Integer.Long */
 }
diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss
new file mode 100644
index 0000000000000000000000000000000000000000..6b44c00c305e3cfa618c26454496106c67ed37df
--- /dev/null
+++ b/app/assets/stylesheets/highlight/solarized_light.scss
@@ -0,0 +1,110 @@
+/* https://gist.github.com/qguv/7936275 */
+pre.code.highlight.solarized-light,
+.code.solarized-light {
+
+  background-color: #fdf6e3;
+  color: #586e75;
+
+  pre.code,
+  .line-numbers,
+  .line-numbers a {
+    background-color: #fdf6e3 !important;
+    color: #586e75 !important;
+  }
+
+  pre.code {
+    border-left: 1px solid #c5d0d4;
+  }
+
+  // highlight line via anchor
+  pre .hll {
+    background-color: #ddd8c5 !important;
+  }
+
+  /* Solarized Light
+
+  For use with Jekyll and Pygments
+
+  http://ethanschoonover.com/solarized
+
+  SOLARIZED HEX      ROLE
+  --------- -------- ------------------------------------------
+  base01    #586e75  body text / default code / primary content
+  base1     #93a1a1  comments / secondary content
+  base3     #fdf6e3  background
+  orange    #cb4b16  constants
+  red       #dc322f  regex, special keywords
+  blue      #268bd2  reserved keywords
+  cyan      #2aa198  strings, numbers
+  green     #859900  operators, other keywords
+  */
+
+  .c { color: #93a1a1 } /* Comment */
+  .err { color: #586e75 } /* Error */
+  .g { color: #586e75 } /* Generic */
+  .k { color: #859900 } /* Keyword */
+  .l { color: #586e75 } /* Literal */
+  .n { color: #586e75 } /* Name */
+  .o { color: #859900 } /* Operator */
+  .x { color: #cb4b16 } /* Other */
+  .p { color: #586e75 } /* Punctuation */
+  .cm { color: #93a1a1 } /* Comment.Multiline */
+  .cp { color: #859900 } /* Comment.Preproc */
+  .c1 { color: #93a1a1 } /* Comment.Single */
+  .cs { color: #859900 } /* Comment.Special */
+  .gd { color: #2aa198 } /* Generic.Deleted */
+  .ge { color: #586e75; font-style: italic } /* Generic.Emph */
+  .gr { color: #dc322f } /* Generic.Error */
+  .gh { color: #cb4b16 } /* Generic.Heading */
+  .gi { color: #859900 } /* Generic.Inserted */
+  .go { color: #586e75 } /* Generic.Output */
+  .gp { color: #586e75 } /* Generic.Prompt */
+  .gs { color: #586e75; font-weight: bold } /* Generic.Strong */
+  .gu { color: #cb4b16 } /* Generic.Subheading */
+  .gt { color: #586e75 } /* Generic.Traceback */
+  .kc { color: #cb4b16 } /* Keyword.Constant */
+  .kd { color: #268bd2 } /* Keyword.Declaration */
+  .kn { color: #859900 } /* Keyword.Namespace */
+  .kp { color: #859900 } /* Keyword.Pseudo */
+  .kr { color: #268bd2 } /* Keyword.Reserved */
+  .kt { color: #dc322f } /* Keyword.Type */
+  .ld { color: #586e75 } /* Literal.Date */
+  .m { color: #2aa198 } /* Literal.Number */
+  .s { color: #2aa198 } /* Literal.String */
+  .na { color: #586e75 } /* Name.Attribute */
+  .nb { color: #B58900 } /* Name.Builtin */
+  .nc { color: #268bd2 } /* Name.Class */
+  .no { color: #cb4b16 } /* Name.Constant */
+  .nd { color: #268bd2 } /* Name.Decorator */
+  .ni { color: #cb4b16 } /* Name.Entity */
+  .ne { color: #cb4b16 } /* Name.Exception */
+  .nf { color: #268bd2 } /* Name.Function */
+  .nl { color: #586e75 } /* Name.Label */
+  .nn { color: #586e75 } /* Name.Namespace */
+  .nx { color: #586e75 } /* Name.Other */
+  .py { color: #586e75 } /* Name.Property */
+  .nt { color: #268bd2 } /* Name.Tag */
+  .nv { color: #268bd2 } /* Name.Variable */
+  .ow { color: #859900 } /* Operator.Word */
+  .w { color: #586e75 } /* Text.Whitespace */
+  .mf { color: #2aa198 } /* Literal.Number.Float */
+  .mh { color: #2aa198 } /* Literal.Number.Hex */
+  .mi { color: #2aa198 } /* Literal.Number.Integer */
+  .mo { color: #2aa198 } /* Literal.Number.Oct */
+  .sb { color: #93a1a1 } /* Literal.String.Backtick */
+  .sc { color: #2aa198 } /* Literal.String.Char */
+  .sd { color: #586e75 } /* Literal.String.Doc */
+  .s2 { color: #2aa198 } /* Literal.String.Double */
+  .se { color: #cb4b16 } /* Literal.String.Escape */
+  .sh { color: #586e75 } /* Literal.String.Heredoc */
+  .si { color: #2aa198 } /* Literal.String.Interpol */
+  .sx { color: #2aa198 } /* Literal.String.Other */
+  .sr { color: #dc322f } /* Literal.String.Regex */
+  .s1 { color: #2aa198 } /* Literal.String.Single */
+  .ss { color: #2aa198 } /* Literal.String.Symbol */
+  .bp { color: #268bd2 } /* Name.Builtin.Pseudo */
+  .vc { color: #268bd2 } /* Name.Variable.Class */
+  .vg { color: #268bd2 } /* Name.Variable.Global */
+  .vi { color: #268bd2 } /* Name.Variable.Instance */
+  .il { color: #2aa198 } /* Literal.Number.Integer.Long */
+}
diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss
index 8d5822937a0c9b624bc75c1294a544e18f97f1df..a52ffc971d1a4c9f47b2a8b2afc3cd70175c2d98 100644
--- a/app/assets/stylesheets/highlight/white.scss
+++ b/app/assets/stylesheets/highlight/white.scss
@@ -1,196 +1,87 @@
-.white {
-  .line.hll {
-    background: #FFA;
-  }
-
-  pre {
-    background-color: #fff;
-    color: #333;
-  }
+/* https://github.com/aahan/pygments-github-style */
+pre.code.highlight.white,
+.code.white {
 
-  .hljs {
-    background: #FFF;
-  }
+  background-color: #fff;
+  color: #333;
 
+  pre.highlight,
+  .line-numbers,
   .line-numbers a {
-    color: #999;
-  }
-
-  .hljs {
-    display: block;
-    background: #fff; color: black;
-  }
-
-  .hljs-comment,
-  .hljs-template_comment,
-  .hljs-javadoc,
-  .hljs-comment * {
-    color: #006a00;
-  }
-
-  .hljs-keyword,
-  .hljs-literal,
-  .nginx .hljs-title {
-    color: #aa0d91;
-  }
-  .method,
-  .hljs-list .hljs-title,
-  .hljs-tag .hljs-title,
-  .setting .hljs-value,
-  .hljs-winutils,
-  .tex .hljs-command,
-  .http .hljs-title,
-  .hljs-request,
-  .hljs-status {
-    color: #008;
-  }
-
-  .hljs-envvar,
-  .tex .hljs-special {
-    color: #660;
-  }
-
-  .hljs-string {
-    color: #c41a16;
-  }
-  .hljs-tag .hljs-value,
-  .hljs-cdata,
-  .hljs-filter .hljs-argument,
-  .hljs-attr_selector,
-  .apache .hljs-cbracket,
-  .hljs-date,
-  .hljs-regexp {
-    color: #080;
-  }
-
-  .hljs-sub .hljs-identifier,
-  .hljs-pi,
-  .hljs-tag,
-  .hljs-tag .hljs-keyword,
-  .hljs-decorator,
-  .ini .hljs-title,
-  .hljs-shebang,
-  .hljs-prompt,
-  .hljs-hexcolor,
-  .hljs-rules .hljs-value,
-  .hljs-symbol,
-  .hljs-symbol .hljs-string,
-  .hljs-number,
-  .css .hljs-function,
-  .clojure .hljs-title,
-  .clojure .hljs-built_in,
-  .hljs-function .hljs-title,
-  .coffeescript .hljs-attribute {
-    color: #1c00cf;
-  }
-
-  .hljs-class .hljs-title,
-  .haskell .hljs-type,
-  .smalltalk .hljs-class,
-  .hljs-javadoctag,
-  .hljs-yardoctag,
-  .hljs-phpdoc,
-  .hljs-typename,
-  .hljs-tag .hljs-attribute,
-  .hljs-doctype,
-  .hljs-class .hljs-id,
-  .hljs-built_in,
-  .setting,
-  .hljs-params,
-  .clojure .hljs-attribute {
-    color: #5c2699;
-  }
-
-  .hljs-variable {
-   color: #3f6e74;
-  }
-  .css .hljs-tag,
-  .hljs-rules .hljs-property,
-  .hljs-pseudo,
-  .hljs-subst {
-    color: #000;
-  }
-
-  .css .hljs-class,
-  .css .hljs-id {
-    color: #9B703F;
-  }
-
-  .hljs-value .hljs-important {
-    color: #ff7700;
-    font-weight: bold;
-  }
-
-  .hljs-rules .hljs-keyword {
-    color: #C5AF75;
-  }
-
-  .hljs-annotation,
-  .apache .hljs-sqbracket,
-  .nginx .hljs-built_in {
-    color: #9B859D;
-  }
-
-  .hljs-preprocessor,
-  .hljs-preprocessor *,
-  .hljs-pragma {
-    color: #643820;
-  }
-
-  .tex .hljs-formula {
-    background-color: #EEE;
-    font-style: italic;
-  }
-
-  .diff .hljs-header,
-  .hljs-chunk {
-    color: #808080;
-    font-weight: bold;
-  }
-
-  .diff .hljs-change {
-    background-color: #BCCFF9;
-  }
-
-  .hljs-addition {
-    background-color: #BAEEBA;
-  }
-
-  .hljs-deletion {
-    background-color: #FFC8BD;
-  }
-
-  .hljs-comment .hljs-yardoctag {
-    font-weight: bold;
-  }
-
-  .method .hljs-id {
-    color: #000;
-  }
-}
-
-.shadow {
-  @include box-shadow(0 5px 15px #000);
-}
-
-.file-content {
-  &.code .white {
-    .highlight {
-      border-left: 1px solid #eee;
-    }
-  }
-
-  &.wiki .white {
-    .highlight, pre, .hljs {
-      background: #F9F9F9;
-    }
-  }
-}
-
-.readme-holder .wiki, .note-body, .wiki-holder {
-  .white {
-    .highlight, pre, .hljs {
-      background: #F9F9F9;
-    }
-  }
+    background-color: #fff !important;
+    color: #333 !important;
+  }
+
+  pre.code {
+    border-left: 1px solid #bbb;
+  }
+
+  // highlight line via anchor
+  pre .hll {
+    background-color: #f8eec7 !important;
+  }
+
+  .hll { background-color: #f8f8f8 }
+  .c { color: #999988; font-style: italic; }
+  .err { color: #a61717; background-color: #e3d2d2; }
+  .k { font-weight: bold; }
+  .o { font-weight: bold; }
+  .cm { color: #999988; font-style: italic; }
+  .cp { color: #999999; font-weight: bold; }
+  .c1 { color: #999988; font-style: italic; }
+  .cs { color: #999999; font-weight: bold; font-style: italic; }
+  .gd { color: #000000; background-color: #ffdddd; }
+  .gd .x { color: #000000; background-color: #ffaaaa; }
+  .ge { font-style: italic; }
+  .gr { color: #aa0000; }
+  .gh { color: #999999; }
+  .gi { color: #000000; background-color: #ddffdd; }
+  .gi .x { color: #000000; background-color: #aaffaa; }
+  .go { color: #888888; }
+  .gp { color: #555555; }
+  .gs { font-weight: bold; }
+  .gu { color: #800080; font-weight: bold; }
+  .gt { color: #aa0000; }
+  .kc { font-weight: bold; }
+  .kd { font-weight: bold; }
+  .kn { font-weight: bold; }
+  .kp { font-weight: bold; }
+  .kr { font-weight: bold; }
+  .kt { color: #445588; font-weight: bold; }
+  .m { color: #009999; }
+  .s { color: #dd1144; }
+  .n { color: #333333; }
+  .na { color: teal; }
+  .nb { color: #0086b3; }
+  .nc { color: #445588; font-weight: bold; }
+  .no { color: teal; }
+  .ni { color: purple; }
+  .ne { color: #990000; font-weight: bold; }
+  .nf { color: #990000; font-weight: bold; }
+  .nn { color: #555555; }
+  .nt { color: navy; }
+  .nv { color: teal; }
+  .ow { font-weight: bold; }
+  .w { color: #bbbbbb; }
+  .mf { color: #009999; }
+  .mh { color: #009999; }
+  .mi { color: #009999; }
+  .mo { color: #009999; }
+  .sb { color: #dd1144; }
+  .sc { color: #dd1144; }
+  .sd { color: #dd1144; }
+  .s2 { color: #dd1144; }
+  .se { color: #dd1144; }
+  .sh { color: #dd1144; }
+  .si { color: #dd1144; }
+  .sx { color: #dd1144; }
+  .sr { color: #009926; }
+  .s1 { color: #dd1144; }
+  .ss { color: #990073; }
+  .bp { color: #999999; }
+  .vc { color: teal; }
+  .vg { color: teal; }
+  .vi { color: teal; }
+  .il { color: #009999; }
+  .gc { color: #999; background-color: #EAF2F5; }
 }
diff --git a/app/assets/stylesheets/main/fonts.scss b/app/assets/stylesheets/main/fonts.scss
deleted file mode 100644
index f945aaca8484b3f4bc4ce0d416470379b387e397..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/main/fonts.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-/** Typo **/
-$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace;
-$regular_font: "Helvetica Neue", Helvetica, Arial, sans-serif;
diff --git a/app/assets/stylesheets/main/variables.scss b/app/assets/stylesheets/main/variables.scss
deleted file mode 100644
index c71984a5665436c8e224d0bd99bd1eccbb21bb81..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/main/variables.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * General Colors
- */
-$style_color: #474D57;
-$hover: #FFECDB;
-$box_bg: #F9F9F9;
-
-/*
- * Link colors
- */
-$link_color: #446e9b;
-$link_hover_color: darken($link-color, 10%);
-
-$btn-border: 1px solid #ccc;
-
-/*
- * Success colors (green)
- */
-$border_success: #019875;
-$bg_success: #019875;
-
-/*
- * Danger colors (red)
- */
-$border_danger: #d43f3a;
-$bg_danger: #d9534f;
-
-/*
- * Primary colors (blue)
- */
-$border_primary: #446e9b;
-$bg_primary: #446e9b;
-
-/*
- * Warning colors (yellow)
- */
-$bg_warning: #EB9532;
-$border_warning: #EB9532;
-
-/**
- * Commit Diff Colors
- */
-$added: #63c363;
-$deleted: #f77;
-
-/**
- *
- */
-$nprogress-color: #3498db;
diff --git a/app/assets/stylesheets/sections/admin.scss b/app/assets/stylesheets/pages/admin.scss
similarity index 78%
rename from app/assets/stylesheets/sections/admin.scss
rename to app/assets/stylesheets/pages/admin.scss
index a51deee7970bd0ecb5950347126c36a04f24ebdb..144852e787496222c9286ffae5cbab5650967aea 100644
--- a/app/assets/stylesheets/sections/admin.scss
+++ b/app/assets/stylesheets/pages/admin.scss
@@ -50,3 +50,14 @@
     line-height: 2;
   }
 }
+
+.broadcast-message {
+  @extend .alert-warning;
+  padding: 10px;
+  text-align: center;
+}
+
+.broadcast-message-preview {
+  @extend .broadcast-message;
+  margin-bottom: 20px;
+}
diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e7125c03993f6ae2750df72bd9df0538a25d6f66
--- /dev/null
+++ b/app/assets/stylesheets/pages/commit.scss
@@ -0,0 +1,123 @@
+.commit-title{
+  display: block;
+}
+
+.commit-title{
+  margin-bottom: 10px;
+}
+
+.commit-author, .commit-committer{
+  display: block;
+  color: #999;
+  font-weight: normal;
+  font-style: italic;
+}
+
+.commit-author strong, .commit-committer strong{
+  font-weight: bold;
+  font-style: normal;
+}
+
+.commit-description {
+  background: none;
+  border: none;
+  margin: 0;
+  padding: 0;
+  margin-top: 10px;
+}
+
+.commit-stat-summary {
+  color: #666;
+  font-size: 14px;
+  font-weight: normal;
+  padding: 3px 0;
+  margin-bottom: 10px;
+}
+
+.commit-info-row {
+  margin-bottom: 10px;
+  .avatar {
+    @extend .avatar-inline;
+  }
+  .commit-committer-link,
+  .commit-author-link {
+    color: #444;
+    font-weight: bold;
+  }
+}
+
+.commit-box {
+  margin: 10px 0;
+  border-top: 1px solid #ddd;
+  border-bottom: 1px solid #ddd;
+  padding: 20px 0;
+
+  .commit-title {
+    margin: 0;
+  }
+
+  .commit-description {
+    margin-top: 15px;
+  }
+}
+
+.file-stats a {
+  color: $style_color;
+}
+
+.file-stats {
+  .new-file {
+    a {
+      color: #090;
+    }
+    i {
+      color: #1BCF00;
+    }
+  }
+  .renamed-file {
+    i {
+      color: #FE9300;
+    }
+  }
+  .deleted-file {
+    a {
+      color: #B00;
+    }
+    i {
+      color: #EE0000;
+    }
+  }
+  .edit-file{
+    i{
+      color: #555;
+    }
+  }
+}
+
+/*
+ * Commit message textarea for web editor and
+ * custom merge request message
+ */
+.commit-message-container {
+  background-color: $body-bg;
+  position: relative;
+  font-family: $monospace_font;
+  $left: 12px;
+  .max-width-marker {
+    width: 72ch;
+    color: rgba(0, 0, 0, 0.0);
+    font-family: inherit;
+    left: $left;
+    height: 100%;
+    border-right: 1px solid mix($input-border, white);
+    position: absolute;
+    z-index: 1;
+  }
+  > textarea {
+    background-color: rgba(0, 0, 0, 0.0);
+    font-family: inherit;
+    padding-left: $left;
+    position: relative;
+    z-index: 2;
+  }
+}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
new file mode 100644
index 0000000000000000000000000000000000000000..84361e154813243dd46bf9436646ca5f7faf3306
--- /dev/null
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -0,0 +1,118 @@
+.commits-compare-switch{
+  @extend .btn;
+  background: image-url("switch_icon.png") no-repeat center center;
+  text-indent: -9999px;
+  float: left;
+  margin-right: 9px;
+}
+
+.lists-separator {
+  margin: 10px 0;
+  border-color: #DDD;
+}
+
+.commits-row {
+  ul {
+    margin: 0;
+
+    li.commit {
+      padding: 8px 0;
+    }
+  }
+
+  .commits-row-date {
+    font-size: 15px;
+    line-height: 20px;
+    margin-bottom: 5px;
+  }
+}
+
+.commits-feed-holder {
+  float: right;
+
+  .btn {
+    padding: 4px 12px;
+  }
+}
+
+li.commit {
+  .commit-row-title {
+    font-size: $list-font-size;
+    line-height: 20px;
+    margin-bottom: 2px;
+
+    .notes_count {
+      float: right;
+      margin-right: 10px;
+    }
+
+    .commit_short_id {
+      min-width: 65px;
+      font-family: $monospace_font;
+    }
+
+    .str-truncated {
+      max-width: 70%;
+    }
+
+    .commit-row-message {
+      color: #444;
+
+      &:hover {
+        text-decoration: underline;
+      }
+    }
+
+    .text-expander {
+      background: #eee;
+      color: #555;
+      padding: 0 5px;
+      cursor: pointer;
+      margin-left: 4px;
+      &:hover {
+        background-color: #ddd;
+      }
+    }
+  }
+
+  .commit-row-description {
+    font-size: 14px;
+    border-left: 1px solid #EEE;
+    padding: 10px 15px;
+    margin: 5px 0 10px 5px;
+    background: #f9f9f9;
+    display: none;
+
+    pre {
+      border: none;
+      background: inherit;
+      padding: 0;
+      margin: 0;
+    }
+  }
+
+  .commit-row-info {
+    color: #777;
+    line-height: 24px;
+    font-size: 13px;
+
+    a {
+      color: #777;
+    }
+
+    .committed_ago {
+      display: inline-block;
+    }
+  }
+
+  &.inline-commit {
+    .commit-row-title {
+      font-size: 13px;
+    }
+
+    .committed_ago {
+      float: right;
+      @extend .cgray;
+    }
+  }
+}
diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/pages/dashboard.scss
similarity index 65%
rename from app/assets/stylesheets/sections/dashboard.scss
rename to app/assets/stylesheets/pages/dashboard.scss
index d181d83e857d69b4f8dbe549c200fa5df6b0e1f6..af9c83e5dc8a4671f5027cb957d77985546a5379 100644
--- a/app/assets/stylesheets/sections/dashboard.scss
+++ b/app/assets/stylesheets/pages/dashboard.scss
@@ -23,47 +23,15 @@
   }
 }
 
-.dashboard {
-  .dash-filter {
-    width: 205px;
-    float: left;
-    height: inherit;
-  }
-}
-
-@media (max-width: 1200px) {
-  .dashboard .dash-filter {
-    width: 140px;
-  }
-}
-
-.dash-sidebar-tabs {
-  margin-bottom: 2px;
-  border: none;
-  margin: 0 !important;
-
-  li {
-    &.active {
-      a {
-        background-color: #EEE;
-        border-bottom: 1px solid #EEE !important;
-        &:hover {
-          background: #eee;
-        }
-      }
-    }
-
-    a {
-      border-color: #DDD !important;
-    }
-  }
-}
-
 .project-row, .group-row {
   padding: 0 !important;
   font-size: 14px;
   line-height: 24px;
 
+  .str-truncated {
+    max-width: 72%;
+  }
+
   a {
     display: block;
     padding: 8px 15px;
@@ -98,7 +66,6 @@
   margin-left: 10px;
   float: left;
   margin-right: 15px;
-  font-size: 20px;
   margin-bottom: 15px;
 
   i {
@@ -106,8 +73,21 @@
   }
 }
 
+.dash-project-avatar {
+  float: left;
+
+  .avatar {
+    margin-top: -8px;
+    margin-left: -15px;
+    @include border-radius(0px);
+  }
+  .identicon {
+    line-height: 40px;
+  }
+}
+
 .dash-project-access-icon {
   float: left;
-  margin-right: 3px;
+  margin-right: 5px;
   width: 16px;
 }
diff --git a/app/assets/stylesheets/sections/diff.scss b/app/assets/stylesheets/pages/diff.scss
similarity index 85%
rename from app/assets/stylesheets/sections/diff.scss
rename to app/assets/stylesheets/pages/diff.scss
index 758f15c8013e0ac0502fec4fc3cf54bcda2a2b4c..af6ea58382fde2ff8ed45b35a3ef8e96ff3310e7 100644
--- a/app/assets/stylesheets/sections/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -1,24 +1,37 @@
 .diff-file {
-  border: 1px solid #CCC;
+  border: 1px solid $border-color;
   margin-bottom: 1em;
 
   .diff-header {
-    @extend .clearfix;
-    background: #EEE;
-    border-bottom: 1px solid #CCC;
-    padding: 5px 5px 5px 10px;
+    position: relative;
+    background: $background-color;
+    border-bottom: 1px solid $border-color;
+    padding: 10px 15px;
     color: #555;
+    z-index: 10;
 
     > span {
       font-family: $monospace_font;
-      line-height: 2;
+      word-break: break-all;
+      margin-right: 200px;
+      display: block;
+
+      .file-mode {
+        margin-left: 10px;
+        color: #777;
+      }
     }
 
     .diff-btn-group {
       float: right;
+      position: absolute;
+      top: 5px;
+      right: 15px;
 
       .btn {
-        background-color: #FFF;
+        padding: 0px 10px;
+        font-size: 13px;
+        line-height: 28px;
       }
     }
 
@@ -26,26 +39,21 @@
       font-family: $monospace_font;
       font-size: smaller;
     }
-
-    .file-mode {
-      font-family: $monospace_font;
-      margin-left: 10px;
-    }
   }
   .diff-content {
     overflow: auto;
     overflow-y: hidden;
     background: #FFF;
     color: #333;
-    font-size: 12px;
+    font-size: $code_font_size;
     .old {
       span.idiff {
-        background-color: #F99;
+        background-color: #f8cbcb;
       }
     }
     .new {
       span.idiff {
-        background-color: #8F8;
+        background-color: #a6f3a6;
       }
     }
     .unfold {
@@ -64,8 +72,8 @@
       margin: 0px;
       padding: 0px;
       td {
-        line-height: 18px;
-        font-size: 12px;
+        line-height: $code_line_height;
+        font-size: $code_font_size;
       }
     }
 
@@ -83,10 +91,10 @@
       margin: 0px;
       padding: 0px;
       border: none;
-      background: #F5F5F5;
-      color: #666;
+      background: $background-color;
+      color: rgba(0,0,0,0.3);
       padding: 0px 5px;
-      border-right: 1px solid #ccc;
+      border-right: 1px solid $border-color;
       text-align: right;
       min-width: 35px;
       max-width: 50px;
@@ -96,7 +104,7 @@
         float: left;
         width: 35px;
         font-weight: normal;
-        color: #666;
+        color: rgba(0,0,0,0.3);
         &:hover {
           text-decoration: underline;
         }
@@ -114,13 +122,13 @@
     .line_holder {
       &.old .old_line,
       &.old .new_line {
-        background: #FCC;
-        border-color: #E7BABA;
+        background: #ffdddd;
+        border-color: #f1c0c0;
       }
       &.new .old_line,
       &.new .new_line {
-        background: #CFC;
-        border-color: #B9ECB9;
+        background: #dbffdb;
+        border-color: #c1e9c1;
       }
     }
     .line_content {
@@ -129,13 +137,13 @@
       padding: 0px 0.5em;
       border: none;
       &.new {
-        background: #CFD;
+        background: #eaffea;
       }
       &.old {
-        background: #FDD;
+        background: #ffecec;
       }
       &.matched {
-        color: #ccc;
+        color: $border-color;
         background: #fafafa;
       }
       &.parallel {
diff --git a/app/assets/stylesheets/sections/editor.scss b/app/assets/stylesheets/pages/editor.scss
similarity index 55%
rename from app/assets/stylesheets/sections/editor.scss
rename to app/assets/stylesheets/pages/editor.scss
index f62f46ee1685c50ad7fb41d5e5e80c361b880eb9..759ba6b1c226bb0aae58f1c477e5c951755b87ba 100644
--- a/app/assets/stylesheets/sections/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -16,8 +16,6 @@
     }
   }
   .commit-button-annotation {
-    @extend .alert;
-    @extend .alert-info;
     display: inline-block;
     margin: 0;
     padding: 2px;
@@ -31,4 +29,26 @@
       margin: 5px 8px 0 8px;
     }
   }
+
+  .file-title {
+    @extend .monospace;
+    font-size: 14px;
+    padding: 5px;
+  }
+
+  .editor-ref {
+    background: $background-color;
+    padding: 11px 15px;
+    border-right: 1px solid #CCC;
+    display: inline-block;
+    margin: -5px -5px;
+    margin-right: 10px;
+  }
+
+  .editor-file-name {
+    .new-file-name {
+      display: inline-block;
+      width: 200px;
+    }
+  }
 }
diff --git a/app/assets/stylesheets/sections/errors.scss b/app/assets/stylesheets/pages/errors.scss
similarity index 100%
rename from app/assets/stylesheets/sections/errors.scss
rename to app/assets/stylesheets/pages/errors.scss
diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/pages/events.scss
similarity index 71%
rename from app/assets/stylesheets/sections/events.scss
rename to app/assets/stylesheets/pages/events.scss
index 656aa5b18a6bcff0791953c6f86adcb5e7e92636..83daea10ed5eb85e9804c312fcdd0efc2c977660 100644
--- a/app/assets/stylesheets/sections/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -46,34 +46,37 @@
   border-bottom: 1px solid #eee;
   .event-title {
     @include str-truncated(72%);
-    color: #333;
-    font-weight: normal;
+    font-weight: 500;
     font-size: 14px;
     .author_name {
       color: #333;
     }
   }
   .event-body {
+    font-size: 13px;
     margin-left: 35px;
-    margin-right: 100px;
+    margin-right: 80px;
+    color: #777;
 
-    .event-info {
-      color: #666;
-    }
     .event-note {
-      color: #666;
       margin-top: 5px;
+      word-wrap: break-word;
 
       .md {
         font-size: 13px;
+
+        iframe.twitter-share-button {
+          vertical-align: bottom;
+        }
       }
 
       pre {
         border: none;
         background: #f9f9f9;
         border-radius: 0;
-        color: #666;
+        color: #777;
         margin: 0 20px;
+        overflow: hidden;
       }
 
       .note-image-attach {
@@ -120,7 +123,6 @@
         padding: 3px;
         padding-left: 0;
         border: none;
-        color: #666;
         .commit-row-title {
           font-size: 12px;
         }
@@ -144,49 +146,51 @@
   }
 }
 
-/**
- * Event filter
- *
- */
-.event_filter {
-  position: absolute;
-  width: 40px;
-  margin-left: -55px;
-
-  .filter_icon {
-    a {
-      text-align:center;
-      background: $bg_primary;
-      margin-bottom: 10px;
-      float: left;
-      padding: 9px 6px;
-      font-size: 18px;
-      width: 40px;
-      color: #FFF;
-      @include border-radius(3px);
-    }
-
-    &.inactive {
-      a {
-        color: #DDD;
-        background: #f9f9f9;
-      }
-    }
-  }
-}
 
 /*
  * Last push widget
  */
 .event-last-push {
+  overflow: auto;
   .event-last-push-text {
-    @include str-truncated(75%);
-    line-height: 24px;
+    @include str-truncated(100%);
+    padding: 5px 0;
+    font-size: 13px;
+    float:left;
+    margin-right: -150px;
+    padding-right: 150px;
+    line-height: 20px;
   }
 }
 
 @media (max-width: $screen-xs-max) {
-  .event-item .event-title {
-    @include str-truncated(65%);
+  .event-item {
+    .event-title {
+      white-space: normal;
+      overflow: visible;
+      max-width: 100%;
+    }
+    .avatar {
+      display: none;
+    }
+
+    .event-body {
+      margin: 0;
+      border-left: 2px solid #DDD;
+      padding-left: 10px;
+    }
+
+    .event-item-timestamp {
+      display: none;
+    }
+  }
+}
+
+.event_filter {
+  li a {
+    font-size: 13px;
+    padding: 5px 10px;
+    background: $background-color;
+    margin-left: 4px;
   }
 }
diff --git a/app/assets/stylesheets/sections/explore.scss b/app/assets/stylesheets/pages/explore.scss
similarity index 100%
rename from app/assets/stylesheets/sections/explore.scss
rename to app/assets/stylesheets/pages/explore.scss
diff --git a/app/assets/stylesheets/sections/graph.scss b/app/assets/stylesheets/pages/graph.scss
similarity index 84%
rename from app/assets/stylesheets/sections/graph.scss
rename to app/assets/stylesheets/pages/graph.scss
index 3d878d1e528885bb462150e5fef127ff5ed27448..c3b10d144e1b50de8e82d240beeb87e6ac6e6bbf 100644
--- a/app/assets/stylesheets/sections/graph.scss
+++ b/app/assets/stylesheets/pages/graph.scss
@@ -1,11 +1,11 @@
 .project-network {
-  border: 1px solid #CCC;
+  border: 1px solid $border-color;
 
   .controls {
     color: #888;
     font-size: 14px;
     padding: 5px;
-    border-bottom: 1px solid #bbb;
+    border-bottom: 1px solid $border-color;
     background: #EEE;
   }
 
diff --git a/app/assets/stylesheets/sections/groups.scss b/app/assets/stylesheets/pages/groups.scss
similarity index 87%
rename from app/assets/stylesheets/sections/groups.scss
rename to app/assets/stylesheets/pages/groups.scss
index e49fe1a9dd6cf42f0e27edc64f94e6f686ea7116..2b1b747139a71d9cc080161d2c19d253934862a1 100644
--- a/app/assets/stylesheets/sections/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -1,6 +1,5 @@
 .new-group-member-holder {
   margin-top: 50px;
-  background: #f9f9f9;
   padding-top: 20px;
 }
 
diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/pages/header.scss
similarity index 60%
rename from app/assets/stylesheets/sections/header.scss
rename to app/assets/stylesheets/pages/header.scss
index e0e0d60c3875857743692d56f5d2581bee4bb823..dde19b801f8cd639627eb5f947602192a1180c36 100644
--- a/app/assets/stylesheets/sections/header.scss
+++ b/app/assets/stylesheets/pages/header.scss
@@ -4,9 +4,11 @@
  */
 header {
   &.navbar-gitlab {
+    z-index: 100;
     margin-bottom: 0;
     min-height: 40px;
     border: none;
+    width: 100%;
 
     .navbar-inner {
       filter: none;
@@ -29,7 +31,7 @@ header {
 
       .navbar-toggle {
         color: $style_color;
-        margin: 0 -15px 0 0;
+        margin: 0;
         padding: 10px;
         border-radius: 0;
 
@@ -52,13 +54,12 @@ header {
       border-width: 0;
       font-size: 18px;
 
-      .app_logo { margin-left: -15px; }
-
       .title {
         @include str-truncated(70%);
       }
 
       .navbar-collapse {
+        margin-top: 47px;
         padding-right: 0;
         padding-left: 0;
       }
@@ -83,7 +84,10 @@ header {
     }
   }
 
-  z-index: 10;
+  .container {
+    width: 100% !important;
+    padding: 0px;
+  }
 
   /**
    *
@@ -96,18 +100,14 @@ header {
 
     a {
       float: left;
-      padding: 0px;
-      margin: 0 6px;
-
-      h1 {
-        margin: 0;
-        background: image-url('logo-black.png') no-repeat center center;
-        background-size: 32px;
-        float: left;
-        height: 46px;
-        width: 40px;
-        @include header-font;
-        text-indent: -9999px;
+      padding: 5px 0;
+      height: 46px;
+      width: 52px;
+      text-align: center;
+
+      img {
+        width: 36px;
+        height: 36px;
       }
     }
     &:hover {
@@ -130,13 +130,13 @@ header {
   }
 
   .profile-pic {
-    position: relative;
-    top: -1px;
-    padding-right: 0px !important;
+    padding: 0px !important;
+    width: 46px;
+    height: 46px;
+    margin-left: 5px;
     img {
-      width: 26px;
-      height: 26px;
-      @include border-radius(4px);
+      width: 46px;
+      height: 46px;
     }
   }
 
@@ -169,83 +169,6 @@ header {
       @include transition(all 0.15s ease-in 0s);
     }
   }
-
-
-  /*
-   * Dark header
-   *
-   */
-  &.header-dark {
-    &.navbar-gitlab {
-      .navbar-inner {
-        background: #708090;
-        border-bottom: 1px solid #AAA;
-
-        .navbar-toggle { color: #fff; }
-
-        .nav > li > a {
-          color: #AAA;
-
-          &:hover, &:focus, &:active {
-            background: none;
-            color: #FFF;
-          }
-        }
-      }
-    }
-
-    .turbolink-spinner {
-      color: #FFF;
-    }
-
-    .search {
-      .search-input {
-        background-color: #D2D5DA;
-        background-color: rgba(255, 255, 255, 0.5);
-        border: 1px solid #AAA;
-
-        &:focus {
-          background-color: white;
-        }
-      }
-    }
-    .search-input::-webkit-input-placeholder {
-      color: #666;
-    }
-    .app_logo {
-      a {
-        h1 {
-          background: image-url('logo-white.png') no-repeat center center;
-          background-size: 32px;
-          color: #fff;
-        }
-      }
-    }
-    .title {
-      a {
-        color: #FFF;
-        &:hover {
-          text-decoration: underline;
-        }
-      }
-      color: #fff;
-    }
-  }
-
-  .app_logo {
-    .separator {
-      margin-left: 0;
-      margin-right: 0;
-    }
-  }
-
-  .separator {
-    float: left;
-    height: 46px;
-    width: 2px;
-    margin-left: 10px;
-    margin-right: 10px;
-  }
 }
 
 .search .search-input {
diff --git a/app/assets/stylesheets/sections/help.scss b/app/assets/stylesheets/pages/help.scss
similarity index 95%
rename from app/assets/stylesheets/sections/help.scss
rename to app/assets/stylesheets/pages/help.scss
index 07c62f98c36d45b908811ba343c18214f0a0cb73..6da7a2511a2dd0b3c0f05f4e4c10c679f1936a43 100644
--- a/app/assets/stylesheets/sections/help.scss
+++ b/app/assets/stylesheets/pages/help.scss
@@ -12,7 +12,6 @@
     color: #888;
 
     a {
-      font-size: 14px;
       margin-right: 3px;
     }
   }
@@ -29,7 +28,6 @@
 
   th {
     padding-top: 15px;
-    font-size: 14px;
     line-height: 1.5;
     color: #333;
     text-align: left
diff --git a/app/assets/stylesheets/pages/import.scss b/app/assets/stylesheets/pages/import.scss
new file mode 100644
index 0000000000000000000000000000000000000000..3df4bb84bd21edef358f8a236d09604d63a43e16
--- /dev/null
+++ b/app/assets/stylesheets/pages/import.scss
@@ -0,0 +1,18 @@
+i.icon-gitorious {
+  display: inline-block;
+  background-position: 0px 0px;
+  background-size: contain;
+  background-repeat: no-repeat;
+}
+
+i.icon-gitorious-small {
+  background-image: image-url('gitorious-logo-blue.png');
+  width: 13px;
+  height: 13px;
+}
+
+i.icon-gitorious-big {
+  background-image: image-url('gitorious-logo-black.png');
+  width: 18px;
+  height: 18px;
+}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
new file mode 100644
index 0000000000000000000000000000000000000000..a640a4e2051c489b2d8d7dc1761dc0937b6f99db
--- /dev/null
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -0,0 +1,47 @@
+@media (max-width: $screen-sm-max) {
+  .issuable-affix {
+    margin-top: 20px;
+  }
+}
+
+@media (max-width: $screen-md-max) {
+  .issuable-affix {
+    position: static;
+  }
+}
+
+@media (min-width: $screen-md-max) {
+  .issuable-affix {
+    &.affix-top {
+      position: static;
+    }
+
+    &.affix {
+      position: fixed;
+      top: 70px;
+      width: 220px;
+    }
+  }
+}
+
+.issuable-context-title {
+  font-size: 14px;
+  line-height: 1.4;
+  margin-bottom: 5px;
+
+  .avatar {
+    margin-left: 0;
+  }
+
+  label {
+    color: #666;
+    font-weight: normal;
+    margin-right: 4px;
+  }
+}
+
+.issuable-affix .context {
+  font-size: 13px;
+
+  .btn { font-size: 13px; }
+}
diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/pages/issues.scss
similarity index 67%
rename from app/assets/stylesheets/sections/issues.scss
rename to app/assets/stylesheets/pages/issues.scss
index ebf8a6125c71b633724029cb8f9b5c22acb1f4f7..cd86a9be8b2753f2f472fa79e29d771eb4f1b752 100644
--- a/app/assets/stylesheets/sections/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -5,11 +5,13 @@
 
     .issue-title {
       margin-bottom: 5px;
-      font-size: 14px;
+      font-size: $list-font-size;
+      font-weight: bold;
     }
 
     .issue-info {
       color: #999;
+      font-size: 13px;
     }
 
     .issue-check {
@@ -39,12 +41,9 @@
 }
 
 .check-all-holder {
-  height: 32px;
+  line-height: 36px;
   float: left;
-  margin-right: 12px;
-  padding: 6px 15px;
-  border: 1px solid #ccc;
-  @include border-radius(4px);
+  margin-right: 15px;
 }
 
 .issues_content {
@@ -57,33 +56,10 @@
   }
 }
 
-@media (min-width: 800px)  { .issues_filters select { width: 160px; }  }
-@media (min-width: 1200px) { .issues_filters select { width: 220px; }  }
-
-@media (min-width: 800px)  { .issues_bulk_update .select2-container { min-width: 120px; }  }
-@media (min-width: 1200px) { .issues_bulk_update .select2-container { min-width: 160px; }  }
-
-.issues_bulk_update {
-  .select2-container .select2-choice {
-    color: #444 !important;
-    font-weight: 500;
-  }
-}
-
-#update_status {
-  width: 100px;
-}
-
 .participants {
   margin-bottom: 20px;
 }
 
-.issues_bulk_update {
-  .select2-container {
-    text-shadow: none;
-  }
-}
-
 .issue-search-form {
   margin: 0;
   height: 24px;
@@ -94,8 +70,15 @@
   }
 }
 
-.issue-show-labels .color-label {
-  padding: 6px 10px;
+.issue-show-labels {
+  a {
+    margin-right: 5px;
+    margin-bottom: 5px;
+    display: inline-block;
+    .color-label {
+      padding: 6px 10px;
+    }
+  }
 }
 
 form.edit-issue {
@@ -110,12 +93,12 @@ form.edit-issue {
   }
 
   &.closed {
-    background: #F5f5f5;
+    background: #F9F9F9;
     border-color: #E5E5E5;
   }
 
   &.merged {
-    background: #F5f5f5;
+    background: #F9F9F9;
     border-color: #E5E5E5;
   }
 }
@@ -151,4 +134,23 @@ form.edit-issue {
       }
     }
   }
+
+  .issue {
+    &:hover  .issue-actions {
+      display: none !important;
+    }
+
+    .issue-updated-at {
+      display: none;
+    }
+  }
+}
+
+h2.issue-title {
+  margin-top: 0;
+  font-weight: bold;
+}
+
+.issue-form .select2-container {
+  width: 250px !important;
 }
diff --git a/app/assets/stylesheets/sections/labels.scss b/app/assets/stylesheets/pages/labels.scss
similarity index 100%
rename from app/assets/stylesheets/sections/labels.scss
rename to app/assets/stylesheets/pages/labels.scss
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
new file mode 100644
index 0000000000000000000000000000000000000000..83b866c3a6466f18ffde7359d517774d80a7f373
--- /dev/null
+++ b/app/assets/stylesheets/pages/login.scss
@@ -0,0 +1,124 @@
+/* Login Page */
+.login-page {
+  .container {
+    max-width: 960px;
+  }
+
+  .navbar-gitlab .container {
+    max-width: none;
+  }
+
+  .brand-holder {
+    font-size: 18px;
+    line-height: 1.5;
+
+    p {
+      color: #888;
+    }
+
+    h1:first-child {
+      font-weight: normal;
+      margin-bottom: 30px;
+    }
+
+    img {
+      max-width: 100%;
+      margin-bottom:  30px;
+    }
+
+    a {
+      font-weight: bold;
+    }
+  }
+
+  .login-box{
+    background: #fafafa;
+    border-radius: 10px;
+    box-shadow: 0 0px 2px #CCC;
+    padding: 15px;
+
+    .login-heading h3 {
+      font-weight: 300;
+      line-height: 1.5;
+      margin: 0 0 10px 0;
+    }
+
+    .login-footer {
+      margin-top: 10px;
+
+      p:last-child {
+        margin-bottom: 0;
+      }
+    }
+
+    a.forgot {
+      float: right;
+      padding-top: 6px
+    }
+
+    .nav .active a {
+      background: transparent;
+    }
+  }
+
+  .form-control {
+    font-size: 14px;
+    padding: 10px 8px;
+    width: 100%;
+    height: auto;
+
+    &.top {
+      @include border-radius(5px 5px 0 0);
+      margin-bottom: 0px;
+    }
+
+    &.bottom {
+      @include border-radius(0 0 5px 5px);
+      border-top: 0;
+      margin-bottom: 20px;
+    }
+
+    &.middle {
+      border-top: 0;
+      margin-bottom:0px;
+      @include border-radius(0);
+    }
+
+    &:active, &:focus {
+      background-color: #FFF;
+    }
+  }
+
+  .devise-errors {
+    h2 {
+      margin-top: 0;
+      font-size: 14px;
+      color: #a00;
+    }
+  }
+
+  .remember-me {
+    margin-top: -10px;
+
+    label {
+      font-weight: normal;
+    }
+  }
+}
+
+@media (max-width: $screen-xs-max) {
+  .login-page {
+    .col-sm-5.pull-right {
+      float: none !important;
+    }
+  }
+}
+
+.oauth-image-link {
+  margin-right: 10px;
+
+  img {
+    width: 32px;
+    height: 32px;
+  }
+}
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
similarity index 63%
rename from app/assets/stylesheets/sections/merge_requests.scss
rename to app/assets/stylesheets/pages/merge_requests.scss
index ec844cc00b090c662013f00ae07f7040b9a7a47d..8abd4207beb15f41f2761f07f36edb7d3871520e 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -11,25 +11,36 @@
     }
   }
 
-  .accept-group {
-    label {
-      margin: 5px;
+  .accept-merge-holder {
+    .accept-action {
+      display: inline-block;
+    }
+
+    .accept-control {
+      display: inline-block;
+      margin: 0;
       margin-left: 20px;
+      padding: 10px 0;
+      line-height: 20px;
+      font-weight: bold;
+
+      .remove_source_checkbox {
+        margin: 0;
+        font-weight: bold;
+      }
     }
   }
 }
 
-.merge-request .merge-request-tabs{
-  border-bottom: 2px solid $border_primary;
-  margin: 20px 0;
-
-  li {
-    a {
-      padding: 15px 40px;
-      font-size: 14px;
-      margin-bottom: -2px;
-      border-bottom: 2px solid $border_primary;
-      @include border-radius(0px);
+@media(min-width: $screen-sm-max) {
+  .merge-request .merge-request-tabs{
+    margin: 20px 0;
+
+    li {
+      a {
+        padding: 15px 40px;
+        font-size: 14px;
+      }
     }
   }
 }
@@ -73,11 +84,13 @@
 
     .merge-request-title {
       margin-bottom: 5px;
-      font-size: 14px;
+      font-size: $list-font-size;
+      font-weight: bold;
     }
 
     .merge-request-info {
       color: #999;
+      font-size: 13px;
 
       .merge-request-labels {
         display: inline-block;
@@ -104,8 +117,11 @@
 }
 
 .mr-state-widget {
-  background: $box_bg;
+  font-size: 13px;
+  background: #F9F9F9;
   margin-bottom: 20px;
+  color: #666;
+  border: 1px solid #EEE;
   @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09));
 
   .ci_widget {
@@ -113,35 +129,26 @@
     font-size: 15px;
     border-bottom: 1px solid #BBB;
     color: #777;
-    background-color: #F5F5F5;
+    background-color: $background-color;
 
     &.ci-success {
-      color: $bg_success;
-      border-color: $border_success;
+      color: $gl-success;
+      border-color: $gl-success;
       background-color: #F1FAF1;
     }
 
-    &.ci-pending {
-      color: #548;
-      border-color: #548;
-      background-color: #F4F1FA;
-    }
-
+    &.ci-pending,
     &.ci-running {
-      color: $bg_warning;
-      border-color: $border_warning;
+      color: $gl-warning;
+      border-color: $gl-warning;
       background-color: #FAF5F1;
     }
 
-    &.ci-failed {
-      color: $bg_danger;
-      border-color: $border_danger;
-      background-color: #FAF1F1;
-    }
-
+    &.ci-failed,
+    &.ci-canceled,
     &.ci-error {
-      color: $bg_danger;
-      border-color: $border_danger;
+      color: $gl-danger;
+      border-color: $gl-danger;
       background-color: #FAF1F1;
     }
   }
@@ -150,7 +157,6 @@
     padding: 10px 15px;
 
     h4 {
-      font-size: 20px;
       font-weight: normal;
     }
 
@@ -169,10 +175,17 @@
   }
 }
 
-.merge-request-show-labels .label {
-  padding: 6px 10px;
+.merge-request-show-labels {
+  a {
+    margin-right: 5px;
+    margin-bottom: 5px;
+    display: inline-block;
+    .color-label {
+      padding: 6px 10px;
+    }
+  }
 }
 
-.mr-commits .commit {
-  padding: 10px 15px;
+.merge-request-form .select2-container {
+  width: 250px !important;
 }
diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss
new file mode 100644
index 0000000000000000000000000000000000000000..15e3948e4027e18c716d8d3f0354216b75f41f01
--- /dev/null
+++ b/app/assets/stylesheets/pages/milestone.scss
@@ -0,0 +1,9 @@
+.issues-sortable-list .str-truncated {
+  max-width: 90%;
+}
+
+li.milestone {
+  h4 {
+    font-weight: bold;
+  }
+}
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
new file mode 100644
index 0000000000000000000000000000000000000000..a0522030785629a8b1eab56c1a879531c3a5ac78
--- /dev/null
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -0,0 +1,175 @@
+/**
+ * Note Form
+ */
+
+.comment-btn {
+  @extend .btn-create;
+}
+.reply-btn {
+  @extend .btn-primary;
+}
+.diff-file .diff-content {
+  tr.line_holder:hover {
+    &> td.line_content {
+      background: $hover !important;
+      border-color: darken($hover, 10%) !important;
+    }
+    &> td.new_line,
+    &> td.old_line {
+      background: darken($hover, 4%) !important;
+      border-color: darken($hover, 10%) !important;
+    }
+  }
+
+  tr.line_holder:hover > td .line_note_link {
+    opacity: 1.0;
+    filter: alpha(opacity=100);
+  }
+}
+.diff-file,
+.discussion {
+  .new_note {
+    margin: 0;
+    border: none;
+  }
+}
+.new_note {
+  display: none;
+}
+
+.new_note, .edit_note {
+  .buttons {
+    float: left;
+    margin-top: 8px;
+  }
+  .clearfix {
+    margin-bottom: 0;
+  }
+
+  .note-preview-holder {
+    > p {
+      overflow-x: auto;
+    }
+  }
+
+  img {
+    max-width: 100%;
+  }
+
+  .note_text {
+    width: 100%;
+  }
+}
+
+/* loading indicator */
+.notes-busy {
+  margin: 18px;
+}
+
+.note-image-attach {
+  @extend .col-md-4;
+  @extend .thumbnail;
+  margin-left: 45px;
+  float: none;
+}
+
+.common-note-form {
+  margin: 0;
+  background: #F9F9F9;
+  padding: 5px;
+  border: 1px solid #DDD;
+}
+
+.note-form-actions {
+  background: #F9F9F9;
+  height: 45px;
+
+  .note-form-option {
+    margin-top: 8px;
+    margin-left: 30px;
+    @extend .pull-left;
+  }
+
+  .js-notify-commit-author {
+    float: left;
+  }
+
+  .write-preview-btn {
+    // makes the "absolute" position for links relative to this
+    position: relative;
+
+    // preview/edit buttons
+    > a {
+      position: absolute;
+      right: 5px;
+      top: 8px;
+    }
+  }
+}
+
+.note-edit-form {
+  display: none;
+  font-size: 13px;
+
+  .form-actions {
+    padding-left: 20px;
+
+    .btn-save {
+      float: left;
+    }
+
+    .note-form-option {
+      float: left;
+      padding: 2px 0 0 25px;
+    }
+  }
+}
+
+.js-note-attachment-delete {
+  display: none;
+}
+
+.parallel-comment {
+  padding: 6px;
+}
+
+.error-alert > .alert {
+  margin-top: 5px;
+  margin-bottom: 5px;
+}
+
+.discussion-body,
+.diff-file {
+  .notes .note {
+    border-color: #ddd;
+    padding: 10px 15px;
+  }
+
+  .discussion-reply-holder {
+    background: #f9f9f9;
+    padding: 10px 15px;
+    border-top: 1px solid #DDD;
+  }
+}
+
+.discussion-notes-count {
+  font-size: 16px;
+}
+
+.edit_note {
+  .markdown-area {
+    min-height: 140px;
+  }
+  .note-form-actions {
+    background: transparent;
+  }
+}
+
+.comment-hints {
+  color: #999;
+  background: #FFF;
+  padding: 5px;
+  margin-top: -11px;
+  border: 1px solid #DDD;
+  font-size: 13px;
+}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
new file mode 100644
index 0000000000000000000000000000000000000000..d66093bc2e5cd8eeda909794db51edb3bf3f23f3
--- /dev/null
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -0,0 +1,218 @@
+/**
+ * Notes
+ */
+
+@-webkit-keyframes targe3-note {
+  from { background:#fffff0; }
+  50% { background:#ffffd3; }
+  to { background:#fffff0; }
+}
+
+ul.notes {
+  display: block;
+  list-style: none;
+  margin: 0px;
+  padding: 0px;
+
+  .discussion-header,
+  .note-header {
+    @extend .cgray;
+    padding-bottom: 15px;
+
+    a:hover {
+      text-decoration: none;
+    }
+
+    .avatar {
+      float: left;
+      margin-right: 10px;
+    }
+
+    .discussion-last-update,
+    .note-last-update {
+      &:before {
+        content: "\00b7";
+      }
+      font-size: 13px;
+    }
+    .author {
+      color: #333;
+      font-weight: bold;
+      &:hover {
+        color: $gl-link-color;
+      }
+    }
+    .author-username {
+    }
+  }
+
+  .discussion {
+    overflow: hidden;
+    display: block;
+    position:relative;
+  }
+
+  .note {
+    display: block;
+    position:relative;
+    .note-body {
+      overflow: auto;
+      .note-text {
+        overflow: auto;
+        word-wrap: break-word;
+        @include md-typography;
+
+        a[href*="/uploads/"] {
+          &:before {
+            margin-right: 4px;
+
+            font: normal normal normal 14px/1 FontAwesome;
+            font-size: inherit;
+            text-rendering: auto;
+            -webkit-font-smoothing: antialiased;
+            content: "\f0c6";
+          }
+
+          &:hover:before {
+            text-decoration: none;
+          }
+        }
+      }
+    }
+    .note-header {
+      padding-bottom: 3px;
+    }
+
+    &:last-child {
+      border-bottom: none;
+    }
+  }
+}
+
+// Diff code in discussion view
+.discussion-body .diff-file {
+  .diff-header > span {
+    margin-right: 10px;
+  }
+  .line_content {
+    white-space: pre-wrap;
+  }
+}
+
+.diff-file .notes_holder {
+  font-size: 13px;
+  line-height: 18px;
+  font-family: $regular_font;
+
+  td {
+    border: 1px solid #ddd;
+    border-left: none;
+
+    &.notes_line {
+      text-align: center;
+      padding: 10px 0;
+      background: #FFF;
+    }
+    &.notes_line2 {
+      text-align: center;
+      padding: 10px 0;
+      border-left: 1px solid #ddd !important;
+    }
+    &.notes_content {
+      background-color: #fff;
+      border-width: 1px 0;
+      padding-top: 0;
+      vertical-align: top;
+      &.parallel{
+        border-width: 1px;
+      }
+    }
+  }
+}
+
+/**
+ * Actions for Discussions/Notes
+ */
+
+.discussion,
+.note {
+  &.note:hover {
+    .note-actions { display: block; }
+  }
+  .discussion-header:hover {
+    .discussion-actions { display: block; }
+  }
+
+  .discussion-actions,
+  .note-actions {
+    display: none;
+    float: right;
+
+    [class~="fa"] {
+      font-size: 16px;
+      line-height: 16px;
+      vertical-align: middle;
+    }
+
+    a {
+      @extend .cgray;
+
+      &:hover {
+        &.danger { @extend .cred; }
+      }
+    }
+  }
+}
+.diff-file .note .note-actions {
+  right: 0;
+  top: 0;
+}
+
+
+/**
+ * Line note button on the side of diffs
+ */
+
+.diff-file tr.line_holder {
+  @mixin show-add-diff-note {
+    filter: alpha(opacity=100);
+    opacity: 1.0;
+  }
+
+  .add-diff-note {
+    margin-top: -4px;
+    @include border-radius(40px);
+    background: #FFF;
+    padding: 4px;
+    font-size: 16px;
+    color: $gl-link-color;
+    margin-left: -60px;
+    position: absolute;
+    z-index: 10;
+    width: 32px;
+
+    transition: all 0.2s ease;
+
+    // "hide" it by default
+    opacity: 0.0;
+    filter: alpha(opacity=0);
+
+    &:hover {
+      width: 38px;
+      font-size: 20px;
+      background: $gl-info;
+      color: #FFF;
+      @include show-add-diff-note;
+    }
+  }
+
+  // "show" the icon also if we just hover somewhere over the line
+  &:hover > td {
+    background: $hover !important;
+
+    .add-diff-note {
+      @include show-add-diff-note;
+    }
+  }
+}
+
diff --git a/app/assets/stylesheets/sections/notifications.scss b/app/assets/stylesheets/pages/notifications.scss
similarity index 75%
rename from app/assets/stylesheets/sections/notifications.scss
rename to app/assets/stylesheets/pages/notifications.scss
index f11c5dff4ab029d4e75c8d8bcf4df623cf007c82..cc273f552227d7cca5b802939a4ef80ae2851b7b 100644
--- a/app/assets/stylesheets/sections/notifications.scss
+++ b/app/assets/stylesheets/pages/notifications.scss
@@ -10,13 +10,13 @@
 }
 
 .ns-part {
-  color: $bg_primary;
+  color: $gl-primary;
 }
 
 .ns-watch {
-  color: $bg_success;
+  color: $gl-success;
 }
 
 .ns-mute {
-  color: $bg_danger;
+  color: $gl-danger;
 }
diff --git a/app/assets/stylesheets/sections/profile.scss b/app/assets/stylesheets/pages/profile.scss
similarity index 58%
rename from app/assets/stylesheets/sections/profile.scss
rename to app/assets/stylesheets/pages/profile.scss
index b9f4e317e9c7db053842d9aa7e2188dee026f97c..65655d4bfa394dca919b8a12edc878325d0f5073 100644
--- a/app/assets/stylesheets/sections/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -1,31 +1,7 @@
 .account-page {
   fieldset {
     margin-bottom: 15px;
-    border-bottom: 1px dashed #ddd;
     padding-bottom: 15px;
-
-    &:last-child {
-      border: none;
-    }
-
-    legend {
-      border: none;
-      margin-bottom: 10px;
-    }
-  }
-}
-
-.oauth_select_holder {
-  img {
-    padding: 2px;
-    margin-right: 10px;
-  }
-  .active {
-    img {
-      border: 1px solid #4BD;
-      background: $hover;
-      @include border-radius(5px);
-    }
   }
 }
 
@@ -41,11 +17,6 @@
   }
 }
 
-.user-show-username {
-  font-weight: 200;
-  color: #666;
-}
-
 /*
  * Appearance settings
  *
@@ -80,6 +51,10 @@
       &.violet {
         background: #548;
       }
+
+      &.blue {
+        background: #2980b9;
+      }
     }
   }
 }
@@ -103,28 +78,18 @@
   }
 }
 
-.profile-groups-avatars {
-  margin: 0 5px 10px 0;
-
-  img {
-    width: 50px;
-    height: 50px;
+.oauth-buttons {
+  .btn-group {
+    margin-right: 10px;
   }
-}
 
-//CSS for password-strength indicator
-#password-strength {
-  margin-bottom: 0;
-}
+  .btn {
+    line-height: 36px;
+    height: 56px;
 
-.has-success input {
-  background-color: #D6F1D7 !important;
-}
-
-.has-error input {
-  background-color: #F3CECE !important;
-}
-
-.has-warning input {
-  background-color: #FFE9A4 !important;
+    img {
+      width: 32px;
+      height: 32px;
+    }
+  }
 }
diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/pages/projects.scss
similarity index 72%
rename from app/assets/stylesheets/sections/projects.scss
rename to app/assets/stylesheets/pages/projects.scss
index b4ee5ccc8d72c4ee636eb4b932cc17c639107291..5bd725d1222a162a0490238ec5e7fe797b431f1b 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -16,6 +16,8 @@
 
 .project-home-panel {
   margin-bottom: 15px;
+  position: relative;
+  padding-left: 85px;
 
   &.empty-project {
     border-bottom: 0px;
@@ -23,6 +25,21 @@
     margin-bottom: 0px;
   }
 
+  .project-identicon-holder {
+    position: absolute;
+    left: 0;
+
+    .avatar {
+      width: 70px;
+      height: 70px;
+    }
+
+    .identicon {
+      font-size: 45px;
+      line-height: 1.6;
+    }
+  }
+
   .project-home-dropdown {
     margin-left: 10px;
     float: right;
@@ -32,30 +49,19 @@
     @extend .clearfix;
     margin-bottom: 15px;
 
+    &.project-home-row-top {
+      margin-bottom: 15px;
+    }
+
     .project-home-desc {
-      float: left;
-      color: #666;
       font-size: 16px;
+      line-height: 1.3;
+      margin-right: 215px;
     }
 
-    .star-fork-buttons {
-      float: right;
-      min-width: 200px;
-      font-size: 14px;
-      font-weight: bold;
-
-      .star-buttons, .fork-buttons {
-        float: right;
-        margin-left: 20px;
-
-        a:hover {
-          text-decoration: none;
-        }
-
-        .count {
-          margin-left: 5px;
-        }
-      }
+    .project-home-desc {
+      float: left;
+      color: #666;
     }
   }
 
@@ -66,6 +72,27 @@
       color: inherit;
     }
   }
+
+  .project-repo-buttons {
+    margin-top: -3px;
+    position: absolute;
+    right: 0;
+    width: 260px;
+    text-align: right;
+
+    .btn {
+      font-weight: bold;
+      font-size: 14px;
+      line-height: 16px;
+
+      .count {
+        padding-left: 10px;
+        border-left: 1px solid #ccc;
+        display: inline-block;
+        margin-left: 10px;
+      }
+    }
+  }
 }
 
 .project-home-links {
@@ -82,23 +109,6 @@
     margin-right: 45px;
   }
 
-  .btn,
-  .form-control {
-    border: 1px solid #E1E1E1;
-    box-shadow: none;
-    padding: 6px 9px;
-  }
-
-  .btn {
-    background: none;
-    color: $link_color;
-
-    &.active {
-      color: #333;
-      font-weight: bold;
-    }
-  }
-
   .form-control {
     cursor: auto;
     @extend .monospace;
@@ -156,7 +166,7 @@ ul.nav.nav-projects-tabs {
   }
 }
 
-.team_member_row form {
+.project_member_row form {
   margin: 0px;
 }
 
@@ -248,15 +258,15 @@ ul.nav.nav-projects-tabs {
 }
 
 .vs-public {
-  color: $bg_primary;
+  color: $gl-primary;
 }
 
 .vs-internal {
-  color: $bg_warning;
+  color: $gl-warning;
 }
 
 .vs-private {
-  color: $bg_success;
+  color: $gl-success;
 }
 
 .breadcrumb.repo-breadcrumb {
@@ -270,3 +280,39 @@ ul.nav.nav-projects-tabs {
     color: #999;
   }
 }
+
+.fork-namespaces {
+  .thumbnail {
+
+    &.fork-exists-thumbnail {
+      border-color: #EEE;
+
+      .caption {
+        color: #999;
+      }
+    }
+
+    &.fork-thumbnail {
+      border-color: #AAA;
+
+      &:hover {
+        background-color: $hover;
+      }
+    }
+
+    a {
+      text-decoration: none;
+    }
+  }
+}
+
+table.table.protected-branches-list tr.no-border {
+  th, td {
+    border: 0;
+  }
+}
+
+.project-import .btn {
+  float: left;
+  margin-right: 10px;
+}
diff --git a/app/assets/stylesheets/sections/search.scss b/app/assets/stylesheets/pages/search.scss
similarity index 100%
rename from app/assets/stylesheets/sections/search.scss
rename to app/assets/stylesheets/pages/search.scss
diff --git a/app/assets/stylesheets/sections/snippets.scss b/app/assets/stylesheets/pages/snippets.scss
similarity index 100%
rename from app/assets/stylesheets/sections/snippets.scss
rename to app/assets/stylesheets/pages/snippets.scss
diff --git a/app/assets/stylesheets/sections/stat_graph.scss b/app/assets/stylesheets/pages/stat_graph.scss
similarity index 100%
rename from app/assets/stylesheets/sections/stat_graph.scss
rename to app/assets/stylesheets/pages/stat_graph.scss
diff --git a/app/assets/stylesheets/sections/themes.scss b/app/assets/stylesheets/pages/themes.scss
similarity index 100%
rename from app/assets/stylesheets/sections/themes.scss
rename to app/assets/stylesheets/pages/themes.scss
diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/pages/tree.scss
similarity index 79%
rename from app/assets/stylesheets/sections/tree.scss
rename to app/assets/stylesheets/pages/tree.scss
index 678a6cd716da8d16fce59b8b11f983580787b3ff..57f63b52aa13974c519a90807d58396e4714d923 100644
--- a/app/assets/stylesheets/sections/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -17,19 +17,6 @@
     @include border-radius(0);
 
     tr {
-      td, th {
-        padding: 8px 10px;
-        line-height: 20px;
-      }
-      th {
-        font-weight: normal;
-        font-size: 15px;
-        border-bottom: 1px solid #CCC !important;
-      }
-      td {
-        border-color: #F1F1F1 !important;
-        border-bottom: 1px solid;
-      }
       &:hover {
         td {
           background: $hover;
@@ -40,7 +27,7 @@
       }
       &.selected {
         td {
-          background: #f5f5f5;
+          background: $background-color;
           border-top: 1px solid #EEE;
           border-bottom: 1px solid #EEE;
         }
@@ -52,14 +39,9 @@
     .tree-item-file-name {
       max-width: 320px;
       vertical-align: middle;
-      a {
-        &:hover {
-          color: $link_hover_color;
-        }
-      }
 
-      i {
-        color: $bg_primary;
+      i, a {
+        color: $gl-link-color;
       }
 
       img {
@@ -79,13 +61,18 @@
 
   .tree_author {
     padding-right: 8px;
+
+    .commit-author-name {
+      color: gray;
+    }
   }
 
   .tree_commit {
     color: gray;
 
     .tree-commit-link {
-      color: #444;
+      color: gray;
+
       &:hover {
         text-decoration: underline;
       }
@@ -111,6 +98,11 @@
       background: #f1f1f1;
       border-left: 1px solid #DDD;
     }
+    td.lines {
+      code {
+        font-family: $monospace_font;
+      }
+    }
   }
 }
 
@@ -120,7 +112,7 @@
 
 .tree-ref-holder {
   float: left;
-  margin-right: 6px;
+  margin-right: 15px;
 
   .select2-container .select2-choice, .select2-container.select2-drop-above .select2-choice {
     padding: 4px 12px;
@@ -128,13 +120,13 @@
 }
 
 .readme-holder {
-  border-top: 1px dashed #CCC;
-  padding-top: 10px;
-
   .readme-file-title {
     font-size: 14px;
+    font-weight: bold;
     margin-bottom: 20px;
     color: #777;
+    border-bottom: 1px solid #DDD;
+    padding: 10px 0;
   }
 }
 
diff --git a/app/assets/stylesheets/pages/ui_dev_kit.scss b/app/assets/stylesheets/pages/ui_dev_kit.scss
new file mode 100644
index 0000000000000000000000000000000000000000..277afa1db9e5cce2fea4627a381afae859a8f6a1
--- /dev/null
+++ b/app/assets/stylesheets/pages/ui_dev_kit.scss
@@ -0,0 +1,9 @@
+.gitlab-ui-dev-kit {
+  > h2 {
+    font-size: 27px;
+    border-bottom: 1px solid #CCC;
+    color: #666;
+    margin: 30px 0;
+    font-weight: bold;
+  }
+}
diff --git a/app/assets/stylesheets/pages/votes.scss b/app/assets/stylesheets/pages/votes.scss
new file mode 100644
index 0000000000000000000000000000000000000000..dc9a7d71e8ba3989d15458dcf4f72def5a01a269
--- /dev/null
+++ b/app/assets/stylesheets/pages/votes.scss
@@ -0,0 +1,4 @@
+.votes-inline {
+  display: inline-block;
+  margin: 0 8px;
+}
diff --git a/app/assets/stylesheets/sections/wiki.scss b/app/assets/stylesheets/pages/wiki.scss
similarity index 100%
rename from app/assets/stylesheets/sections/wiki.scss
rename to app/assets/stylesheets/pages/wiki.scss
diff --git a/app/assets/stylesheets/print.scss b/app/assets/stylesheets/print.scss
index 42dbf4d6ef3578f07a8761b3aaef06d1d2cbce78..1be0551ad3be5a0f0504ae730420ff19a8e6a02a 100644
--- a/app/assets/stylesheets/print.scss
+++ b/app/assets/stylesheets/print.scss
@@ -11,3 +11,7 @@ header, nav, nav.main-nav, nav.navbar-collapse, nav.navbar-collapse.collapse {di
 .wiki h1 {font-size: 30px;}
 .wiki h2 {font-size: 22px;}
 .wiki h3 {font-size: 18px; font-weight: bold; }
+
+.sidebar-wrapper { display: none; }
+.nav { display: none; }
+.btn { display: none; }
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
deleted file mode 100644
index 684e8377a7bb3da0f72680b52fda8822dfc27155..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/sections/commits.scss
+++ /dev/null
@@ -1,249 +0,0 @@
-/**
- * Commit file
- */
-.commit-committer-link,
-.commit-author-link {
-  font-size: 13px;
-  color: #555;
-  &:hover {
-    color: #999;
-  }
-}
-
-/** COMMIT BLOCK **/
-.commit-title{
-  display: block;
-}
-.commit-title{
-  margin-bottom: 10px;
-}
-.commit-author, .commit-committer{
-  display: block;
-  color: #999;
-  font-weight: normal;
-  font-style: italic;
-}
-.commit-author strong, .commit-committer strong{
-  font-weight: bold;
-  font-style: normal;
-}
-
-
-.file-stats a {
-  color: $style_color;
-}
-
-.file-stats {
-  .new-file {
-    a {
-      color: #090;
-    }
-    i {
-      color: #1BCF00;
-    }
-  }
-  .renamed-file {
-    i {
-      color: #FE9300;
-    }
-  }
-  .deleted-file {
-    a {
-      color: #B00;
-    }
-    i {
-      color: #EE0000;
-    }
-  }
-  .edit-file{
-    i{
-      color: #555;
-    }
-  }
-}
-
-.label_commit {
-  @include border-radius(4px);
-  padding: 2px 4px;
-  font-size: 13px;
-  background: #474D57;
-  color: #fff;
-  font-family: $monospace_font;
-}
-
-
-.commits-compare-switch{
-  background: image-url("switch_icon.png") no-repeat center center;
-  width: 32px;
-  height: 32px;
-  text-indent: -9999px;
-  float: left;
-  margin-right: 9px;
-  border: 1px solid #DDD;
-  @include border-radius(4px);
-  padding: 4px;
-  background-color: #EEE;
-}
-
-.commit-description {
-  background: none;
-  border: none;
-  margin: 0;
-  padding: 0;
-  margin-top: 10px;
-}
-
-.commit-box {
-  margin: 10px 0;
-  border-top: 1px solid #ddd;
-  border-bottom: 1px solid #ddd;
-  padding: 20px 0;
-
-  .commit-title {
-    margin: 0;
-    font-size: 20px;
-  }
-
-  .commit-description {
-    margin-top: 15px;
-  }
-}
-
-
-.commit-stat-summary {
-  color: #666;
-  font-size: 14px;
-  font-weight: normal;
-  padding: 10px 0;
-}
-
-.commit-info-row {
-  margin-bottom: 10px;
-  .avatar {
-    @extend .avatar-inline;
-  }
-  .commit-committer-link,
-  .commit-author-link {
-    color: #444;
-    font-weight: bold;
-  }
-}
-
-.lists-separator {
-  margin: 10px 0;
-  border-top: 1px dashed #CCC;
-}
-
-/**
- * COMMIT ROW
- */
-li.commit {
-  .commit-row-title {
-    font-size: 14px;
-    margin-bottom: 2px;
-
-    .notes_count {
-      float: right;
-      margin-right: 10px;
-    }
-
-    .commit_short_id {
-      min-width: 65px;
-      font-family: $monospace_font;
-    }
-
-    .str-truncated {
-      max-width: 70%;
-    }
-
-    .commit-row-message {
-      color: #333;
-      font-weight: 500;
-      &:hover {
-        color: #444;
-        text-decoration: underline;
-      }
-    }
-
-    .text-expander {
-      background: #eee;
-      color: #555;
-      padding: 0 5px;
-      cursor: pointer;
-      margin-left: 4px;
-      &:hover {
-        background-color: #ddd;
-      }
-    }
-  }
-
-  .commit-row-description {
-    font-size: 14px;
-    border-left: 1px solid #EEE;
-    padding: 10px 15px;
-    margin: 5px 0 10px 5px;
-    background: #f9f9f9;
-    display: none;
-
-    pre {
-      border: none;
-      background: inherit;
-      padding: 0;
-      margin: 0;
-    }
-  }
-
-  .commit-row-info {
-    color: #777;
-
-    a {
-      color: #777;
-    }
-
-    .committed_ago {
-      float: right;
-    }
-  }
-
-  &.inline-commit {
-    .commit-row-title {
-      font-size: 13px;
-    }
-
-    .committed_ago {
-      float: right;
-      @extend .cgray;
-    }
-  }
-}
-
-.commits-feed-holder {
-  float: right;
-  .btn {
-    padding: 4px 12px;
-  }
-}
-
-.commit-message-container {
-  background-color: $body-bg;
-  position: relative;
-  font-family: $monospace_font;
-  $left: 12px;
-  .max-width-marker {
-    width: 72ch;
-    color: rgba(0, 0, 0, 0.0);
-    font-family: inherit;
-    left: $left;
-    height: 100%;
-    border-right: 1px solid mix($input-border, white);
-    position: absolute;
-    z-index: 1;
-  }
-  > textarea {
-    background-color: rgba(0, 0, 0, 0.0);
-    font-family: inherit;
-    padding-left: $left;
-    position: relative;
-    z-index: 2;
-  }
-}
diff --git a/app/assets/stylesheets/sections/login.scss b/app/assets/stylesheets/sections/login.scss
deleted file mode 100644
index 1bcb1f6d68e35859bf56a9bb1646e5c988562943..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/sections/login.scss
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Login Page */
-.login-page {
-  h1 {
-    font-size: 3em;
-    font-weight: 200;
-  }
-
-  .login-box{
-    padding: 0 15px;
-
-    .login-heading h3 {
-      font-weight: 300;
-      line-height: 2;
-    }
-
-    .login-footer {
-      margin-top: 10px;
-    }
-
-    .btn {
-      padding: 12px !important;
-      @extend .btn-block;
-    }
-  }
-
-  .brand-image {
-    img {
-      max-width: 100%;
-      margin-bottom:  20px;
-    }
-
-    &.default-brand-image {
-      margin: 0 80px;
-    }
-  }
-
-  .login-logo {
-    margin: 10px 0 30px 0;
-    display: block;
-  }
-
-  .form-control {
-    background-color: #F5F5F5;
-    font-size: 16px;
-    padding: 14px 10px;
-    width: 100%;
-    height: auto;
-
-    &.top {
-      @include border-radius(5px 5px 0 0);
-      margin-bottom: 0px;
-    }
-
-    &.bottom {
-      @include border-radius(0 0 5px 5px);
-      border-top: 0;
-      margin-bottom: 20px;
-    }
-
-    &.middle {
-      border-top: 0;
-      margin-bottom:0px;
-      @include border-radius(0);
-    }
-
-    &:active, &:focus {
-      background-color: #FFF;
-    }
-  }
-
-  .login-box a.forgot {
-    float: right;
-    padding-top: 6px
-  }
-
-  .devise-errors {
-    h2 {
-      font-size: 14px;
-      color: #a00;
-    }
-  }
-
-  .brand-holder {
-    border-right: 1px solid #EEE;
-  }
-}
diff --git a/app/assets/stylesheets/sections/milestone.scss b/app/assets/stylesheets/sections/milestone.scss
deleted file mode 100644
index d20391e38fd0cbb627b8514627a4b3ca41081f4e..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/sections/milestone.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.issues-sortable-list .str-truncated {
-  max-width: 70%;
-}
diff --git a/app/assets/stylesheets/sections/nav.scss b/app/assets/stylesheets/sections/nav.scss
deleted file mode 100644
index 31c0a0835dbf5a1f656e020c68c150bb80124716..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/sections/nav.scss
+++ /dev/null
@@ -1,96 +0,0 @@
-.main-nav {
-  background: #f5f5f5;
-  margin: 20px 0;
-  margin-top: 0;
-  padding-top: 4px;
-  border-bottom: 1px solid #E9E9E9;
-
-  ul {
-    padding: 0;
-    margin: auto;
-    .count {
-      font-weight: normal;
-      display: inline-block;
-      height: 15px;
-      padding: 1px 6px;
-      height: auto;
-      font-size: 0.82em;
-      line-height: 14px;
-      text-align: center;
-      color: #777;
-      background: #eee;
-      @include border-radius(8px);
-    }
-    .label {
-      background: $hover;
-      text-shadow: none;
-      color: $style_color;
-    }
-    li {
-      list-style-type: none;
-      margin: 0;
-      display: table-cell;
-      width: 1%;
-      &.active {
-        a {
-          color: $link_color;
-          font-weight: bold;
-          border-bottom: 3px solid $link_color;
-        }
-      }
-
-      &:hover {
-        a {
-          color: $link_hover_color;
-          border-bottom: 3px solid $link_hover_color;
-        }
-      }
-    }
-    a {
-      display: block;
-      text-align: center;
-      font-weight: bold;
-      height: 42px;
-      line-height: 39px;
-      color: #777;
-      text-shadow: 0 1px 1px white;
-      text-decoration: none;
-      overflow: hidden;
-      margin-bottom: -1px;
-    }
-  }
-
-  @media (max-width: $screen-xs-max) {
-    font-size: 18px;
-    margin: 0;
-
-    max-height: none;
-
-    &, .container {
-      padding: 0;
-      border-top: 0;
-    }
-
-    ul {
-      height: auto;
-
-      li {
-        display: list-item;
-        width: auto;
-        padding: 5px 0;
-
-        &.active {
-          background-color: $link_hover_color;
-
-          a {
-            color: #fff;
-            font-weight: normal;
-            text-shadow: none;
-
-            &:after { display: none; }
-          }
-        }
-      }
-    }
-  }
-}
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
deleted file mode 100644
index 7eb42fddade75b9f679679448d8f85d3e990665c..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/sections/notes.scss
+++ /dev/null
@@ -1,357 +0,0 @@
-/**
- * Notes
- */
-
-@-webkit-keyframes targe3-note {
-  from { background:#fffff0; }
-  50% { background:#ffffd3; }
-  to { background:#fffff0; }
-}
-
-ul.notes {
-  display: block;
-  list-style: none;
-  margin: 0px;
-  padding: 0px;
-
-  .discussion-header,
-  .note-header {
-    @extend .cgray;
-    padding-bottom: 15px;
-
-    a:hover {
-      text-decoration: none;
-    }
-
-    .avatar {
-      float: left;
-      margin-right: 10px;
-    }
-
-    .discussion-last-update,
-    .note-last-update {
-      &:before {
-        content: "\00b7";
-      }
-      font-size: 13px;
-    }
-    .author {
-      color: #555;
-      font-weight: bold;
-      font-size: 14px;
-      &:hover {
-        color: $link_hover_color;
-      }
-    }
-  }
-
-  .discussion {
-    overflow: hidden;
-    display: block;
-    position:relative;
-  }
-
-  .note {
-    display: block;
-    position:relative;
-    .attachment {
-      font-size: 14px;
-    }
-    .note-body {
-      @include md-typography;
-    }
-    .note-header {
-      padding-bottom: 3px;
-    }
-
-    &:last-child {
-      border-bottom: none;
-    }
-  }
-}
-
-.diff-file .notes_holder {
-  font-size: 13px;
-  line-height: 18px;
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-
-  td {
-    border: 1px solid #ddd;
-    border-left: none;
-
-    &.notes_line {
-      text-align: center;
-      padding: 10px 0;
-      background: #FFF;
-    }
-    &.notes_line2 {
-      text-align: center;
-      padding: 10px 0;
-      border-left: 1px solid #ddd !important;
-    }
-    &.notes_content {
-      background-color: #fff;
-      border-width: 1px 0;
-      padding-top: 0;
-      vertical-align: top;
-      &.parallel{
-        border-width: 1px;
-      }
-    }
-  }
-}
-
-/**
- * Actions for Discussions/Notes
- */
-
-.discussion,
-.note {
-  &.note:hover {
-    .note-actions { display: block; }
-  }
-  .discussion-header:hover {
-    .discussion-actions { display: block; }
-  }
-
-  .discussion-actions,
-  .note-actions {
-    display: none;
-    float: right;
-
-    [class~="fa"] {
-      font-size: 16px;
-      line-height: 16px;
-      vertical-align: middle;
-    }
-
-    a {
-      @extend .cgray;
-
-      &:hover {
-        color: $link_hover_color;
-        &.danger { @extend .cred; }
-      }
-    }
-  }
-}
-.diff-file .note .note-actions {
-  right: 0;
-  top: 0;
-}
-
-
-/**
- * Line note button on the side of diffs
- */
-
-.diff-file tr.line_holder {
-  @mixin show-add-diff-note {
-    filter: alpha(opacity=100);
-    opacity: 1.0;
-  }
-
-  .add-diff-note {
-    background: image-url("diff_note_add.png") no-repeat left 0;
-    border: none;
-    height: 22px;
-    margin-left: -65px;
-    position: absolute;
-    width: 22px;
-    z-index: 10;
-
-    // "hide" it by default
-    opacity: 0.0;
-    filter: alpha(opacity=0);
-
-    &:hover {
-      @include show-add-diff-note;
-    }
-  }
-
-  // "show" the icon also if we just hover somewhere over the line
-  &:hover > td {
-    background: $hover !important;
-
-    .add-diff-note {
-      @include show-add-diff-note;
-    }
-  }
-}
-
-/**
- * Note Form
- */
-
-.comment-btn {
-  @extend .btn-create;
-}
-.reply-btn {
-  @extend .btn-primary;
-}
-.diff-file .diff-content {
-  tr.line_holder:hover {
-    &> td.line_content {
-      background: $hover !important;
-      border-color: darken($hover, 10%) !important;
-    }
-    &> td.new_line,
-    &> td.old_line {
-      background: darken($hover, 4%) !important;
-      border-color: darken($hover, 10%) !important;
-    }
-  }
-
-  tr.line_holder:hover > td .line_note_link {
-    opacity: 1.0;
-    filter: alpha(opacity=100);
-  }
-}
-.diff-file,
-.discussion {
-  .new_note {
-    margin: 0;
-    border: none;
-  }
-}
-.new_note {
-  display: none;
-  .buttons {
-    float: left;
-    margin-top: 8px;
-  }
-  .clearfix {
-    margin-bottom: 0;
-  }
-
-  .note-preview-holder,
-  .note_text {
-    background: #FFF;
-    border: 1px solid #ddd;
-    min-height: 100px;
-    padding: 5px;
-    font-size: 14px;
-    box-shadow: none;
-  }
-
-  .note-preview-holder {
-    > p {
-      overflow-x: auto;
-    }
-  }
-
-  .note_text {
-    width: 100%;
-  }
-  .nav-tabs {
-    margin-bottom: 0;
-    border: none;
-
-    li a,
-    li.active a {
-      border: 1px solid #DDD;
-    }
-  }
-}
-
-/* loading indicator */
-.notes-busy {
-  margin: 18px;
-}
-
-.note-image-attach {
-  @extend .col-md-4;
-  @extend .thumbnail;
-  margin-left: 45px;
-  float: none;
-}
-
-.common-note-form {
-  margin: 0;
-  background: #F9F9F9;
-  padding: 5px;
-  border: 1px solid #DDD;
-}
-
-.note-form-actions {
-  background: #F9F9F9;
-  height: 45px;
-
-  .note-form-option {
-    margin-top: 8px;
-    margin-left: 30px;
-    @extend .pull-left;
-  }
-
-  .js-notify-commit-author {
-    float: left;
-  }
-
-  .write-preview-btn {
-    // makes the "absolute" position for links relative to this
-    position: relative;
-
-    // preview/edit buttons
-    > a {
-      position: absolute;
-      right: 5px;
-      top: 8px;
-    }
-  }
-}
-
-.note-edit-form {
-  display: none;
-
-  .note_text {
-    border: 1px solid #DDD;
-    box-shadow: none;
-    font-size: 14px;
-    height: 80px;
-    width: 100%;
-  }
-
-  .form-actions {
-    padding-left: 20px;
-
-    .btn-save {
-      float: left;
-    }
-
-    .note-form-option {
-      float: left;
-      padding: 2px 0 0 25px;
-    }
-  }
-}
-
-.js-note-attachment-delete {
-  display: none;
-}
-
-.parallel-comment {
-  padding: 6px;
-}
-
-.error-alert > .alert {
-  margin-top: 5px;
-  margin-bottom: 5px;
-}
-
-.discussion-body,
-.diff-file {
-  .notes .note {
-    border-color: #ddd;
-    padding: 10px 15px;
-  }
-
-  .discussion-reply-holder {
-    background: #f9f9f9;
-    padding: 10px 15px;
-    border-top: 1px solid #DDD;
-  }
-}
-
-.discussion-notes-count {
-  font-size: 16px;
-}
diff --git a/app/assets/stylesheets/sections/votes.scss b/app/assets/stylesheets/sections/votes.scss
deleted file mode 100644
index d683e33e1f05276ac1f9acf7010b7d78b4c1c41b..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/sections/votes.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-.votes {
-  font-size: 13px;
-  line-height: 15px;
-  .progress {
-    height: 4px;
-    margin: 0;
-    .bar {
-      float: left;
-      height: 100%;
-    }
-    .bar-success {
-      @include linear-gradient(#62C462, #51A351);
-      background-color: #468847;
-    }
-    .bar-danger {
-      @include linear-gradient(#EE5F5B, #BD362F);
-      background-color: #B94A48;
-    }
-  }
-  .upvotes {
-    display: inline-block;
-    color: #468847;
-  }
-  .downvotes {
-    display: inline-block;
-    color: #B94A48;
-  }
-}
-.votes-block {
-  margin: 6px;
-  .downvotes {
-    float: right;
-  }
-}
-.votes-inline {
-  display: inline-block;
-  margin: 0 8px;
-}
-
-.votes-holder {
-  float: right;
-  width: 250px;
-
-  @media (max-width: $screen-xs-max) {
-    width: 100%;
-    margin-top: 5px;
-    margin-bottom: 10px;
-  }
-}
diff --git a/app/assets/stylesheets/themes/dark-theme.scss b/app/assets/stylesheets/themes/dark-theme.scss
new file mode 100644
index 0000000000000000000000000000000000000000..b7b22a8724eb71eb55df740782def2e3f30aee0d
--- /dev/null
+++ b/app/assets/stylesheets/themes/dark-theme.scss
@@ -0,0 +1,63 @@
+@mixin dark-theme($color-light, $color, $color-darker, $color-dark) {
+  header {
+    &.navbar-gitlab {
+      .navbar-inner {
+        background: $color;
+
+        .navbar-toggle {
+          color: #FFF;
+        }
+
+        .app_logo, .navbar-toggle {
+          &:hover {
+            background-color: $color-darker;
+          }
+        }
+
+        .app_logo {
+          background-color: $color-dark;
+        }
+
+        .title {
+          color: #FFF;
+
+          a {
+            color: #FFF;
+            &:hover {
+              text-decoration: underline;
+            }
+          }
+        }
+
+        .search {
+          .search-input {
+            background-color: $color-light;
+            background-color: rgba(255, 255, 255, 0.5);
+            border: 1px solid $color-light;
+
+            &:focus {
+              background-color: white;
+            }
+          }
+        }
+
+        .search-input::-webkit-input-placeholder {
+          color: #666;
+        }
+
+        .nav > li > a {
+          color: $color-light;
+
+          &:hover, &:focus, &:active {
+            background: none;
+            color: #FFF;
+          }
+        }
+
+        .search-input {
+          border-color: $color-light;
+        }
+      }
+    }
+  }
+}
diff --git a/app/assets/stylesheets/themes/ui_basic.scss b/app/assets/stylesheets/themes/ui_basic.scss
index 3e3744fdc33f8541237e9d4c252c04e077dadba9..097d5c5b73ca41cb830de5f611d0163c1e4d0e42 100644
--- a/app/assets/stylesheets/themes/ui_basic.scss
+++ b/app/assets/stylesheets/themes/ui_basic.scss
@@ -9,17 +9,22 @@
       .navbar-inner {
         background: #F1F1F1;
         border-bottom: 1px solid #DDD;
+
+        .title {
+          color: #555;
+
+          a {
+            color: #555;
+            &:hover {
+              text-decoration: underline;
+            }
+          }
+        }
+
         .nav > li > a {
           color: $style_color;
         }
-        .separator {
-          background: #F9F9F9;
-          border-left: 1px solid #DDD;
-        }
       }
     }
   }
-  .main-nav {
-    background: #FFF;
-  }
 }
diff --git a/app/assets/stylesheets/themes/ui_blue.scss b/app/assets/stylesheets/themes/ui_blue.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e223058be8b79cf17fef23b0c6debc610836cea0
--- /dev/null
+++ b/app/assets/stylesheets/themes/ui_blue.scss
@@ -0,0 +1,6 @@
+/**
+ * Blue GitLab UI theme
+ */
+.ui_blue {
+  @include dark-theme(#BECDE9, #2980b9, #1970a9, #096099);
+}
diff --git a/app/assets/stylesheets/themes/ui_color.scss b/app/assets/stylesheets/themes/ui_color.scss
index a08f3ff3d48b1d063e09af73806f8dd70871b8a1..7ac6903b2e422c6a66793614d847053c71c028aa 100644
--- a/app/assets/stylesheets/themes/ui_color.scss
+++ b/app/assets/stylesheets/themes/ui_color.scss
@@ -1,43 +1,6 @@
 /**
- * This file represent some UI that can be changed
- * during web app restyle or theme select.
- *
- * Next items should be placed there
- * - link colors
- * - header restyles
- *
+ * Violet GitLab UI theme
  */
 .ui_color {
-  /*
-   *  Application Header
-   *
-   */
-  header {
-    @extend .header-dark;
-    &.navbar-gitlab {
-      .navbar-inner {
-        background: #548;
-        border-bottom: 1px solid #436;
-        .app_logo, .navbar-toggle {
-          &:hover {
-            background-color: #436;
-          }
-        }
-        .separator {
-          background: #436;
-          border-left: 1px solid #659;
-        }
-        .nav > li > a {
-          color: #98C;
-        }
-        .search-input {
-          border-color: #98C;
-        }
-      }
-    }
-  }
-
-  .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {
-    background: #659;
-  }
+  @include dark-theme(#98C, #548, #436, #325);
 }
diff --git a/app/assets/stylesheets/themes/ui_gray.scss b/app/assets/stylesheets/themes/ui_gray.scss
index 959febad6fe7dcf25a5aca64508b428e5e9b9741..9257e5f4d401193664c84ce4e9f64c13e055ba4b 100644
--- a/app/assets/stylesheets/themes/ui_gray.scss
+++ b/app/assets/stylesheets/themes/ui_gray.scss
@@ -1,33 +1,6 @@
 /**
- * This file represent some UI that can be changed
- * during web app restyle or theme select.
- *
- * Next items should be placed there
- * - link colors
- * - header restyles
- *
+ * Gray GitLab UI theme
  */
 .ui_gray {
-  /*
-   *  Application Header
-   *
-   */
-  header {
-    @extend .header-dark;
-    &.navbar-gitlab {
-      .navbar-inner {
-        background: #373737;
-        border-bottom: 1px solid #272727;
-        .app_logo, .navbar-toggle {
-          &:hover {
-            background-color: #272727;
-          }
-        }
-        .separator {
-          background: #272727;
-          border-left: 1px solid #474747;
-        }
-      }
-    }
-  }
+  @include dark-theme(#979797, #373737, #272727, #222222);
 }
diff --git a/app/assets/stylesheets/themes/ui_mars.scss b/app/assets/stylesheets/themes/ui_mars.scss
index 9af5adbf10ac0ce61cbc4a56bfa70ba5731e1171..4caf5843d9b048f4494eda646fc950ff91b7c981 100644
--- a/app/assets/stylesheets/themes/ui_mars.scss
+++ b/app/assets/stylesheets/themes/ui_mars.scss
@@ -1,39 +1,6 @@
 /**
- * This file represent some UI that can be changed
- * during web app restyle or theme select.
- *
- * Next items should be placed there
- * - link colors
- * - header restyles
- *
+ * Classic GitLab UI theme
  */
 .ui_mars {
-  /*
-   *  Application Header
-   *
-   */
-  header {
-    @extend .header-dark;
-    &.navbar-gitlab {
-      .navbar-inner {
-        background: #474D57;
-        border-bottom: 1px solid #373D47;
-        .app_logo, .navbar-toggle {
-          &:hover {
-            background-color: #373D47;
-          }
-        }
-        .separator {
-          background: #373D47;
-          border-left: 1px solid #575D67;
-        }
-        .nav > li > a {
-          color: #979DA7;
-        }
-        .search-input {
-          border-color: #979DA7;
-        }
-      }
-    }
-  }
+  @include dark-theme(#979DA7, #474D57, #373D47, #24272D);
 }
diff --git a/app/assets/stylesheets/themes/ui_modern.scss b/app/assets/stylesheets/themes/ui_modern.scss
index 308a03477dbff9380e5057fea89ef0087344716c..70449882317efef7cf129914ba4b3cbad9fa3909 100644
--- a/app/assets/stylesheets/themes/ui_modern.scss
+++ b/app/assets/stylesheets/themes/ui_modern.scss
@@ -1,43 +1,6 @@
 /**
- * This file represent some UI that can be changed
- * during web app restyle or theme select.
- *
- * Next items should be placed there
- * - link colors
- * - header restyles
- *
+ * Modern GitLab UI theme
  */
 .ui_modern {
-  /*
-   *  Application Header
-   *
-   */
-  header {
-    @extend .header-dark;
-    &.navbar-gitlab {
-      .navbar-inner {
-        background: #019875;
-        border-bottom: 1px solid #019875;
-        .app_logo, .navbar-toggle {
-          &:hover {
-            background-color: #018865;
-          }
-        }
-        .separator {
-          background: #018865;
-          border-left: 1px solid #11A885;
-        }
-        .nav > li > a {
-          color: #ADC;
-        }
-        .search-input {
-          border-color: #8ba;
-        }
-      }
-    }
-  }
-
-  .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus {
-    background: #019875;
-  }
+  @include dark-theme(#ADC, #019875, #018865, #017855);
 }
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9a5685877f8e2fa8835fd1a4f09cf4785211cf56
--- /dev/null
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -0,0 +1,44 @@
+class Admin::ApplicationSettingsController < Admin::ApplicationController
+  before_filter :set_application_setting
+
+  def show
+  end
+
+  def update
+    if @application_setting.update_attributes(application_setting_params)
+      redirect_to admin_application_settings_path,
+        notice: 'Application settings saved successfully'
+    else
+      render :show
+    end
+  end
+
+  private
+
+  def set_application_setting
+    @application_setting = ApplicationSetting.current
+  end
+
+  def application_setting_params
+    restricted_levels = params[:application_setting][:restricted_visibility_levels]
+    if restricted_levels.nil?
+      params[:application_setting][:restricted_visibility_levels] = []
+    else
+      restricted_levels.map! do |level|
+        level.to_i
+      end
+    end
+
+    params.require(:application_setting).permit(
+      :default_projects_limit,
+      :default_branch_protection,
+      :signup_enabled,
+      :signin_enabled,
+      :gravatar_enabled,
+      :twitter_sharing_enabled,
+      :sign_in_text,
+      :home_page_url,
+      restricted_visibility_levels: []
+    )
+  end
+end
diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..471d24934a017a5e802018a4eca7c759bd80e0f8
--- /dev/null
+++ b/app/controllers/admin/applications_controller.rb
@@ -0,0 +1,52 @@
+class Admin::ApplicationsController < Admin::ApplicationController
+  before_action :set_application, only: [:show, :edit, :update, :destroy]
+
+  def index
+    @applications = Doorkeeper::Application.where("owner_id IS NULL")
+  end
+
+  def show
+  end
+
+  def new
+    @application = Doorkeeper::Application.new
+  end
+
+  def edit
+  end
+
+  def create
+    @application = Doorkeeper::Application.new(application_params)
+
+    if @application.save
+      flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
+      redirect_to admin_application_url(@application)
+    else
+      render :new
+    end
+  end
+
+  def update
+    if @application.update(application_params)
+      redirect_to admin_application_path(@application), notice: 'Application was successfully updated.'
+    else
+      render :edit
+    end
+  end
+
+  def destroy
+    @application.destroy
+    redirect_to admin_applications_url, notice: 'Application was successfully destroyed.'
+  end
+
+  private
+
+  def set_application
+    @application = Doorkeeper::Application.where("owner_id IS NULL").find(params[:id])
+  end
+
+  # Only allow a trusted parameter "white list" through.
+  def application_params
+    params[:doorkeeper_application].permit(:name, :redirect_uri)
+  end
+end
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index be19139c9b1113c19bfad3b4a4b1584ceff2b145..c491e5c75501e259c300ae4586ff6464337b87e0 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -1,7 +1,7 @@
 class Admin::DashboardController < Admin::ApplicationController
   def index
-    @projects = Project.order("created_at DESC").limit(10)
-    @users = User.order("created_at DESC").limit(10)
-    @groups = Group.order("created_at DESC").limit(10)
+    @projects = Project.limit(10)
+    @users = User.limit(10)
+    @groups = Group.limit(10)
   end
 end
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index e6d0c9323c1fd4d5792526534cbf042ffeb1d3e2..9d9adaa467f16559ce65873769a54c341894f28e 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -1,15 +1,16 @@
 class Admin::GroupsController < Admin::ApplicationController
-  before_filter :group, only: [:edit, :show, :update, :destroy, :project_update, :project_teams_update]
+  before_filter :group, only: [:edit, :show, :update, :destroy, :project_update, :members_update]
 
   def index
-    @groups = Group.order('name ASC')
+    @groups = Group.all
+    @groups = @groups.sort(@sort = params[:sort])
     @groups = @groups.search(params[:name]) if params[:name].present?
-    @groups = @groups.page(params[:page]).per(20)
+    @groups = @groups.page(params[:page]).per(PER_PAGE)
   end
 
   def show
-    @members = @group.members.order("access_level DESC").page(params[:members_page]).per(30)
-    @projects = @group.projects.page(params[:projects_page]).per(30)
+    @members = @group.members.order("access_level DESC").page(params[:members_page]).per(PER_PAGE)
+    @projects = @group.projects.page(params[:projects_page]).per(PER_PAGE)
   end
 
   def new
@@ -21,7 +22,7 @@ class Admin::GroupsController < Admin::ApplicationController
 
   def create
     @group = Group.new(group_params)
-    @group.path = @group.name.dup.parameterize if @group.name
+    @group.name = @group.path.dup unless @group.name
 
     if @group.save
       @group.add_owner(current_user)
@@ -39,7 +40,7 @@ class Admin::GroupsController < Admin::ApplicationController
     end
   end
 
-  def project_teams_update
+  def members_update
     @group.add_users(params[:user_ids].split(','), params[:access_level])
 
     redirect_to [:admin, @group], notice: 'Users were successfully added.'
diff --git a/app/controllers/admin/keys_controller.rb b/app/controllers/admin/keys_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..21111bb44f5aa9cb5c3f3e0f8b7516a7e78272a7
--- /dev/null
+++ b/app/controllers/admin/keys_controller.rb
@@ -0,0 +1,34 @@
+class Admin::KeysController < Admin::ApplicationController
+  before_filter :user, only: [:show, :destroy]
+
+  def show
+    @key = user.keys.find(params[:id])
+
+    respond_to do |format|
+      format.html
+      format.js { render nothing: true }
+    end
+  end
+
+  def destroy
+    key = user.keys.find(params[:id])
+
+    respond_to do |format|
+      if key.destroy
+        format.html { redirect_to [:admin, user], notice: 'User key was successfully removed.' }
+      else
+        format.html { redirect_to [:admin, user], alert: 'Failed to remove user key.' }
+      end
+    end
+  end
+
+  protected
+
+  def user
+    @user ||= User.find_by!(username: params[:user_id])
+  end
+
+  def key_params
+    params.require(:user_id, :id)
+  end
+end
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index 7c2388e81be847b1ee1e85ea8c83cac040981fcd..5176a8399ae63b74ead7232cc94b6dca7d6df449 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -11,27 +11,30 @@ class Admin::ProjectsController < Admin::ApplicationController
     @projects = @projects.abandoned if params[:abandoned].present?
     @projects = @projects.search(params[:name]) if params[:name].present?
     @projects = @projects.sort(@sort = params[:sort])
-    @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
+    @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(PER_PAGE)
   end
 
   def show
     if @group
-      @group_members = @group.members.order("access_level DESC").page(params[:group_members_page]).per(30)
+      @group_members = @group.members.order("access_level DESC").page(params[:group_members_page]).per(PER_PAGE)
     end
 
-    @project_members = @project.project_members.page(params[:project_members_page]).per(30)
+    @project_members = @project.project_members.page(params[:project_members_page]).per(PER_PAGE)
   end
 
   def transfer
     ::Projects::TransferService.new(@project, current_user, params.dup).execute
 
-    redirect_to [:admin, @project.reload]
+    @project.reload
+    redirect_to admin_namespace_project_path(@project.namespace, @project)
   end
 
   protected
 
   def project
-    @project = Project.find_with_namespace(params[:id])
+    @project = Project.find_with_namespace(
+      [params[:namespace_id], '/', params[:id]].join('')
+    )
     @project || render_404
   end
 
diff --git a/app/controllers/admin/services_controller.rb b/app/controllers/admin/services_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..76a938c5fe4fd8587c4a75659946dad255edfe2b
--- /dev/null
+++ b/app/controllers/admin/services_controller.rb
@@ -0,0 +1,54 @@
+class Admin::ServicesController < Admin::ApplicationController
+  before_filter :service, only: [:edit, :update]
+
+  def index
+    @services = services_templates
+  end
+
+  def edit
+    unless service.present?
+      redirect_to admin_application_settings_services_path,
+        alert: "Service is unknown or it doesn't exist"
+    end
+  end
+
+  def update
+    if service.update_attributes(application_services_params[:service])
+      redirect_to admin_application_settings_services_path,
+        notice: 'Application settings saved successfully'
+    else
+      render :edit
+    end
+  end
+
+  private
+
+  def services_templates
+    templates = []
+
+    Service.available_services_names.each do |service_name|
+      service_template = service_name.concat("_service").camelize.constantize
+      templates << service_template.where(template: true).first_or_create
+    end
+
+    templates
+  end
+
+  def service
+    @service ||= Service.where(id: params[:id], template: true).first
+  end
+
+  def application_services_params
+    params.permit(:id,
+      service: [
+        :title, :token, :type, :active, :api_key, :subdomain,
+        :room, :recipients, :project_url, :webhook,
+        :user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
+        :build_key, :server, :teamcity_url, :build_type,
+        :description, :issues_url, :new_issue_url, :restrict_to_branch,
+        :send_from_committer_email, :disable_diffs,
+        :push_events, :tag_push_events, :note_events, :issues_events,
+        :merge_requests_events
+    ])
+  end
+end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index baad9095b70832695c6e2fce8e01ff6727032e77..693970e5349f820160e46a3064b680be5994907f 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -2,15 +2,16 @@ class Admin::UsersController < Admin::ApplicationController
   before_filter :user, only: [:show, :edit, :update, :destroy]
 
   def index
-    @users = User.filter(params[:filter])
+    @users = User.order_name_asc.filter(params[:filter])
     @users = @users.search(params[:name]) if params[:name].present?
     @users = @users.sort(@sort = params[:sort])
-    @users = @users.alphabetically.page(params[:page])
+    @users = @users.page(params[:page])
   end
 
   def show
     @personal_projects = user.personal_projects
     @joined_projects = user.projects.joined(@user)
+    @keys = user.keys
   end
 
   def new
@@ -23,7 +24,7 @@ class Admin::UsersController < Admin::ApplicationController
 
   def block
     if user.block
-      redirect_to :back, alert: "Successfully blocked"
+      redirect_to :back, notice: "Successfully blocked"
     else
       redirect_to :back, alert: "Error occurred. User was not blocked"
     end
@@ -31,7 +32,7 @@ class Admin::UsersController < Admin::ApplicationController
 
   def unblock
     if user.activate
-      redirect_to :back, alert: "Successfully unblocked"
+      redirect_to :back, notice: "Successfully unblocked"
     else
       redirect_to :back, alert: "Error occurred. User was not unblocked"
     end
@@ -101,6 +102,9 @@ class Admin::UsersController < Admin::ApplicationController
     email = user.emails.find(params[:email_id])
     email.destroy
 
+    user.set_notification_email
+    user.save if user.notification_email_changed?
+
     respond_to do |format|
       format.html { redirect_to :back, notice: "Successfully removed email." }
       format.js { render nothing: true }
@@ -117,8 +121,8 @@ class Admin::UsersController < Admin::ApplicationController
     params.require(:user).permit(
       :email, :remember_me, :bio, :name, :username,
       :skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, :force_random_password,
-      :extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key,
-      :projects_limit, :can_create_group, :admin
+      :extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key, :hide_no_password,
+      :projects_limit, :can_create_group, :admin, :key_id
     )
   end
 end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index f1e1bebe5ce548108e62173229d47e31e5bdce45..2809f90c0d54af6d715718cdaa47b3001ed67f4b 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,6 +1,11 @@
 require 'gon'
 
 class ApplicationController < ActionController::Base
+  include Gitlab::CurrentSettings
+  include GitlabRoutingHelper
+
+  PER_PAGE = 20
+
   before_filter :authenticate_user_from_token!
   before_filter :authenticate_user!
   before_filter :reject_blocked!
@@ -13,7 +18,8 @@ class ApplicationController < ActionController::Base
 
   protect_from_forgery with: :exception
 
-  helper_method :abilities, :can?
+  helper_method :abilities, :can?, :current_application_settings
+  helper_method :github_import_enabled?, :gitlab_import_enabled?, :bitbucket_import_enabled?
 
   rescue_from Encoding::CompatibilityError do |exception|
     log_exception(exception)
@@ -46,6 +52,17 @@ class ApplicationController < ActionController::Base
     end
   end
 
+  def authenticate_user!(*args)
+    # If user is not signed-in and tries to access root_path - redirect him to landing page
+    if current_application_settings.home_page_url.present?
+      if current_user.nil? && controller_name == 'dashboard' && action_name == 'show'
+        redirect_to current_application_settings.home_page_url and return
+      end
+    end
+
+    super(*args)
+  end
+
   def log_exception(exception)
     application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace
     application_trace.map!{ |t| "  #{t}\n" }
@@ -80,6 +97,7 @@ class ApplicationController < ActionController::Base
 
   def project
     unless @project
+      namespace = params[:namespace_id]
       id = params[:project_id] || params[:id]
 
       # Redirect from
@@ -91,7 +109,7 @@ class ApplicationController < ActionController::Base
         redirect_to request.original_url.gsub(/\.git\Z/, '') and return
       end
 
-      @project = Project.find_with_namespace(id)
+      @project = Project.find_with_namespace("#{namespace}/#{id}")
 
       if @project and can?(current_user, :read_project, @project)
         @project
@@ -108,7 +126,8 @@ class ApplicationController < ActionController::Base
 
   def repository
     @repository ||= project.repository
-  rescue Grit::NoSuchPathError
+  rescue Grit::NoSuchPathError(e)
+    log_exception(e)
     nil
   end
 
@@ -159,6 +178,18 @@ class ApplicationController < ActionController::Base
     response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
   end
 
+  def default_url_options
+    if !Rails.env.test?
+      port = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port?
+      { host: Gitlab.config.gitlab.host,
+        protocol: Gitlab.config.gitlab.protocol,
+        port: port,
+        script_name: Gitlab.config.gitlab.relative_url_root }
+    else
+      super
+    end
+  end
+
   def default_headers
     headers['X-Frame-Options'] = 'DENY'
     headers['X-XSS-Protection'] = '1; mode=block'
@@ -168,7 +199,7 @@ class ApplicationController < ActionController::Base
   end
 
   def add_gon_variables
-    gon.default_issues_tracker = Project.issues_tracker.default_value
+    gon.default_issues_tracker = Project.new.default_issue_tracker.to_param
     gon.api_version = API::API.version
     gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
     gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s
@@ -239,4 +270,75 @@ class ApplicationController < ActionController::Base
       redirect_to profile_path, notice: 'Please complete your profile with email address' and return
     end
   end
+
+  def set_filters_params
+    params[:sort] ||= 'created_desc'
+    params[:scope] = 'all' if params[:scope].blank?
+    params[:state] = 'opened' if params[:state].blank?
+
+    @filter_params = params.dup
+
+    if @project
+      @filter_params[:project_id] = @project.id
+    elsif @group
+      @filter_params[:group_id] = @group.id
+    else
+      # TODO: this filter ignore issues/mr created in public or
+      # internal repos where you are not a member. Enable this filter
+      # or improve current implementation to filter only issues you
+      # created or assigned or mentioned
+      #@filter_params[:authorized_only] = true
+    end
+
+    @filter_params
+  end
+
+  def set_filter_values(collection)
+    assignee_id = @filter_params[:assignee_id]
+    author_id = @filter_params[:author_id]
+    milestone_id = @filter_params[:milestone_id]
+
+    @sort = @filter_params[:sort]
+    @assignees = User.where(id: collection.pluck(:assignee_id))
+    @authors = User.where(id: collection.pluck(:author_id))
+    @milestones = Milestone.where(id: collection.pluck(:milestone_id))
+
+    if assignee_id.present? && !assignee_id.to_i.zero?
+      @assignee = @assignees.find_by(id: assignee_id)
+    end
+
+    if author_id.present? && !author_id.to_i.zero?
+      @author = @authors.find_by(id: author_id)
+    end
+
+    if milestone_id.present? && !milestone_id.to_i.zero?
+      @milestone = @milestones.find_by(id: milestone_id)
+    end
+  end
+
+  def get_issues_collection
+    set_filters_params
+    issues = IssuesFinder.new.execute(current_user, @filter_params)
+    set_filter_values(issues)
+    issues
+  end
+
+  def get_merge_requests_collection
+    set_filters_params
+    merge_requests = MergeRequestsFinder.new.execute(current_user, @filter_params)
+    set_filter_values(merge_requests)
+    merge_requests
+  end
+
+  def github_import_enabled?
+    OauthHelper.enabled_oauth_providers.include?(:github)
+  end
+
+  def gitlab_import_enabled?
+    OauthHelper.enabled_oauth_providers.include?(:gitlab)
+  end
+
+  def bitbucket_import_enabled?
+    OauthHelper.enabled_oauth_providers.include?(:bitbucket) && Gitlab::BitbucketImport.public_key.present?
+  end
 end
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..11af9895261f1a683df092e4f03d9dad02a6e0c5
--- /dev/null
+++ b/app/controllers/autocomplete_controller.rb
@@ -0,0 +1,30 @@
+class AutocompleteController < ApplicationController
+  def users
+    @users =
+      if params[:project_id].present?
+        project = Project.find(params[:project_id])
+
+        if can?(current_user, :read_project, project)
+          project.team.users
+        end
+      elsif params[:group_id]
+        group = Group.find(params[:group_id])
+
+        if can?(current_user, :read_group, group)
+          group.users
+        end
+      else
+        User.all
+      end
+
+    @users = @users.search(params[:search]) if params[:search].present?
+    @users = @users.active
+    @users = @users.page(params[:page]).per(PER_PAGE)
+    render json: @users, only: [:name, :username, :id], methods: [:avatar_url]
+  end
+
+  def user
+    @user = User.find(params[:id])
+    render json: @user, only: [:name, :username, :id], methods: [:avatar_url]
+  end
+end
diff --git a/app/controllers/dashboard/groups_controller.rb b/app/controllers/dashboard/groups_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ed14f4e1f3baa9689c8d000381dc67179560a7f3
--- /dev/null
+++ b/app/controllers/dashboard/groups_controller.rb
@@ -0,0 +1,5 @@
+class Dashboard::GroupsController < ApplicationController
+  def index
+    @group_members = current_user.group_members.page(params[:page]).per(PER_PAGE)
+  end
+end
diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cb51792df16f223fce050bcaf3ff170a62520cb6
--- /dev/null
+++ b/app/controllers/dashboard/milestones_controller.rb
@@ -0,0 +1,34 @@
+class Dashboard::MilestonesController < ApplicationController
+  before_filter :load_projects
+
+  def index
+    project_milestones = case params[:state]
+                         when 'all'; state
+                         when 'closed'; state('closed')
+                         else state('active')
+                         end
+    @dashboard_milestones = Milestones::GroupService.new(project_milestones).execute
+    @dashboard_milestones = Kaminari.paginate_array(@dashboard_milestones).page(params[:page]).per(PER_PAGE)
+  end
+
+  def show
+    project_milestones = Milestone.where(project_id: @projects).order("due_date ASC")
+    @dashboard_milestone = Milestones::GroupService.new(project_milestones).milestone(title)
+  end
+
+  private
+
+  def load_projects
+    @projects = current_user.authorized_projects.sorted_by_activity.non_archived
+  end
+
+  def title
+    params[:title]
+  end
+
+  def state(state = nil)
+    conditions = { project_id: @projects }
+    conditions.reverse_merge!(state: state) if state
+    Milestone.where(conditions).order("title ASC")
+  end
+end
diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..56e6fcc41ca1445c54150b4f9653968d5091c166
--- /dev/null
+++ b/app/controllers/dashboard/projects_controller.rb
@@ -0,0 +1,27 @@
+class Dashboard::ProjectsController < ApplicationController
+  before_filter :event_filter
+
+  def starred
+    @projects = current_user.starred_projects
+    @projects = @projects.includes(:namespace, :forked_from_project, :tags)
+    @projects = @projects.sort(@sort = params[:sort])
+    @groups = []
+
+    respond_to do |format|
+      format.html
+
+      format.json do
+        load_events
+        pager_json("events/_events", @events.count)
+      end
+    end
+  end
+
+  private
+
+  def load_events
+    @events = Event.in_projects(@projects.pluck(:id))
+    @events = @event_filter.apply_filter(@events).with_associations
+    @events = @events.limit(20).offset(params[:offset] || 0)
+  end
+end
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 5aff526d1b55fc112f2dd8c662a2b8ff9acbd223..9bd853ed5c70ef751c6cf40b6144ed3c77937e59 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -3,66 +3,35 @@ class DashboardController < ApplicationController
 
   before_filter :load_projects, except: [:projects]
   before_filter :event_filter, only: :show
-  before_filter :default_filter, only: [:issues, :merge_requests]
-
 
   def show
-    # Fetch only 30 projects.
-    # If user needs more - point to Dashboard#projects page
-    @projects_limit = 30
-
-    @groups = current_user.authorized_groups.sort_by(&:human_name)
-    @has_authorized_projects = @projects.count > 0
-    @projects_count = @projects.count
-    @projects = @projects.limit(@projects_limit)
-
-    @events = Event.in_projects(current_user.authorized_projects.pluck(:id))
-    @events = @event_filter.apply_filter(@events)
-    @events = @events.limit(20).offset(params[:offset] || 0)
-
+    @projects = @projects.includes(:namespace)
     @last_push = current_user.recent_push
 
-    @publicish_project_count = Project.publicish(current_user).count
-
     respond_to do |format|
       format.html
-      format.json { pager_json("events/_events", @events.count) }
-      format.atom { render layout: false }
-    end
-  end
-
-  def projects
-    @projects = case params[:scope]
-                when 'personal' then
-                  current_user.namespace.projects
-                when 'joined' then
-                  current_user.authorized_projects.joined(current_user)
-                when 'owned' then
-                  current_user.owned_projects
-                else
-                  current_user.authorized_projects
-                end
 
-    @projects = @projects.where(namespace_id: Group.find_by(name: params[:group])) if params[:group].present?
-    @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
-    @projects = @projects.includes(:namespace)
-    @projects = @projects.tagged_with(params[:tag]) if params[:tag].present?
-    @projects = @projects.sort(@sort = params[:sort])
-    @projects = @projects.page(params[:page]).per(30)
+      format.json do
+        load_events
+        pager_json("events/_events", @events.count)
+      end
 
-    @tags = current_user.authorized_projects.tags_on(:tags)
-    @groups = current_user.authorized_groups
+      format.atom do
+        load_events
+        render layout: false
+      end
+    end
   end
 
   def merge_requests
-    @merge_requests = MergeRequestsFinder.new.execute(current_user, params)
-    @merge_requests = @merge_requests.page(params[:page]).per(20)
+    @merge_requests = get_merge_requests_collection
+    @merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE)
     @merge_requests = @merge_requests.preload(:author, :target_project)
   end
 
   def issues
-    @issues = IssuesFinder.new.execute(current_user, params)
-    @issues = @issues.page(params[:page]).per(20)
+    @issues = get_issues_collection
+    @issues = @issues.page(params[:page]).per(PER_PAGE)
     @issues = @issues.preload(:author, :project)
 
     respond_to do |format|
@@ -77,9 +46,9 @@ class DashboardController < ApplicationController
     @projects = current_user.authorized_projects.sorted_by_activity.non_archived
   end
 
-  def default_filter
-    params[:scope] = 'assigned-to-me' if params[:scope].blank?
-    params[:state] = 'opened' if params[:state].blank?
-    params[:authorized_only] = true
+  def load_events
+    @events = Event.in_projects(current_user.authorized_projects.pluck(:id))
+    @events = @event_filter.apply_filter(@events).with_associations
+    @events = @events.limit(20).offset(params[:offset] || 0)
   end
 end
diff --git a/app/controllers/explore/groups_controller.rb b/app/controllers/explore/groups_controller.rb
index ada7031fea4318add194b9862790e63815e4f92c..c51a4a211a6210688350602240c8f6f5c5a744d1 100644
--- a/app/controllers/explore/groups_controller.rb
+++ b/app/controllers/explore/groups_controller.rb
@@ -8,6 +8,6 @@ class Explore::GroupsController < ApplicationController
     @groups = GroupsFinder.new.execute(current_user)
     @groups = @groups.search(params[:search]) if params[:search].present?
     @groups = @groups.sort(@sort = params[:sort])
-    @groups = @groups.page(params[:page]).per(20)
+    @groups = @groups.page(params[:page]).per(PER_PAGE)
   end
 end
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index d75fd8e72fa6b3b14b80aab5782f5790d849c7c1..b295f295bb10fbf0e1798a17af79500c4279f7ec 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -6,19 +6,22 @@ class Explore::ProjectsController < ApplicationController
 
   def index
     @projects = ProjectsFinder.new.execute(current_user)
+    @tags = @projects.tags_on(:tags)
+    @projects = @projects.tagged_with(params[:tag]) if params[:tag].present?
+    @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
     @projects = @projects.search(params[:search]) if params[:search].present?
     @projects = @projects.sort(@sort = params[:sort])
-    @projects = @projects.includes(:namespace).page(params[:page]).per(20)
+    @projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE)
   end
 
   def trending
     @trending_projects = TrendingProjectsFinder.new.execute(current_user)
-    @trending_projects = @trending_projects.page(params[:page]).per(10)
+    @trending_projects = @trending_projects.page(params[:page]).per(PER_PAGE)
   end
 
   def starred
     @starred_projects = ProjectsFinder.new.execute(current_user)
-    @starred_projects = @starred_projects.order('star_count DESC')
-    @starred_projects = @starred_projects.page(params[:page]).per(10)
+    @starred_projects = @starred_projects.reorder('star_count DESC')
+    @starred_projects = @starred_projects.page(params[:page]).per(PER_PAGE)
   end
 end
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
deleted file mode 100644
index 7937454810d9929279b9e84fcc86552d5aa882a3..0000000000000000000000000000000000000000
--- a/app/controllers/files_controller.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-class FilesController < ApplicationController
-  def download
-    note = Note.find(params[:id])
-    uploader = note.attachment
-
-    if uploader.file_storage?
-      if can?(current_user, :read_project, note.project)
-        send_file uploader.file.path, disposition: 'attachment'
-      else
-        not_found!
-      end
-    else
-      redirect_to uploader.url
-    end
-  end
-end
diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a73b8fa212a6c4b408e73ba87ae8e45c728ba840
--- /dev/null
+++ b/app/controllers/groups/application_controller.rb
@@ -0,0 +1,28 @@
+class Groups::ApplicationController < ApplicationController
+
+  private
+  
+  def authorize_read_group!
+    unless @group and can?(current_user, :read_group, @group)
+      if current_user.nil?
+        return authenticate_user!
+      else
+        return render_404
+      end
+    end
+  end
+  
+  def authorize_admin_group!
+    unless can?(current_user, :manage_group, group)
+      return render_404
+    end
+  end
+
+  def determine_layout
+    if current_user
+      'group'
+    else
+      'public_group'
+    end
+  end
+end
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index ca88d033878a04ac994a93e1570ebe1cb3caeff6..2df51c97a22ca805922977360c64f1da3ac4cdfb 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -1,15 +1,30 @@
-class Groups::GroupMembersController < ApplicationController
+class Groups::GroupMembersController < Groups::ApplicationController
+  skip_before_filter :authenticate_user!, only: [:index]
   before_filter :group
 
   # Authorize
-  before_filter :authorize_admin_group!
+  before_filter :authorize_read_group!
+  before_filter :authorize_admin_group!, except: [:index, :leave]
 
-  layout 'group'
+  layout :determine_layout
+
+  def index
+    @project = @group.projects.find(params[:project_id]) if params[:project_id]
+    @members = @group.group_members
+
+    if params[:search].present?
+      users = @group.users.search(params[:search]).to_a
+      @members = @members.where(user_id: users)
+    end
+
+    @members = @members.order('access_level DESC').page(params[:page]).per(50)
+    @group_member = GroupMember.new
+  end
 
   def create
     @group.add_users(params[:user_ids].split(','), params[:access_level])
 
-    redirect_to members_group_path(@group), notice: 'Users were successfully added.'
+    redirect_to group_group_members_path(@group), notice: 'Users were successfully added.'
   end
 
   def update
@@ -18,12 +33,12 @@ class Groups::GroupMembersController < ApplicationController
   end
 
   def destroy
-    @users_group = @group.group_members.find(params[:id])
+    @group_member = @group.group_members.find(params[:id])
 
-    if can?(current_user, :destroy, @users_group)  # May fail if last owner.
-      @users_group.destroy
+    if can?(current_user, :destroy_group_member, @group_member)  # May fail if last owner.
+      @group_member.destroy
       respond_to do |format|
-        format.html { redirect_to members_group_path(@group), notice: 'User was  successfully removed from group.' }
+        format.html { redirect_to group_group_members_path(@group), notice: 'User was  successfully removed from group.' }
         format.js { render nothing: true }
       end
     else
@@ -31,18 +46,23 @@ class Groups::GroupMembersController < ApplicationController
     end
   end
 
+  def leave
+    @group_member = @group.group_members.where(user_id: current_user.id).first
+    
+    if can?(current_user, :destroy_group_member, @group_member)
+      @group_member.destroy
+      redirect_to(dashboard_groups_path, info: "You left #{group.name} group.")
+    else
+      return render_403
+    end
+  end
+
   protected
 
   def group
     @group ||= Group.find_by(path: params[:group_id])
   end
 
-  def authorize_admin_group!
-    unless can?(current_user, :manage_group, group)
-      return render_404
-    end
-  end
-
   def member_params
     params.require(:group_member).permit(:access_level, :user_id)
   end
diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb
index 860d8e0392295bc62629058fb95b69bd2953ab7c..c46b8fff88ff1abd9acf64756955b71f2ebc5a12 100644
--- a/app/controllers/groups/milestones_controller.rb
+++ b/app/controllers/groups/milestones_controller.rb
@@ -4,13 +4,13 @@ class Groups::MilestonesController < ApplicationController
   before_filter :authorize_group_milestone!, only: :update
 
   def index
-    project_milestones = case params[:status]
-                         when 'all'; status
-                         when 'closed'; status('closed')
-                         else status('active')
+    project_milestones = case params[:state]
+                         when 'all'; state
+                         when 'closed'; state('closed')
+                         else state('active')
                          end
     @group_milestones = Milestones::GroupService.new(project_milestones).execute
-    @group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(30)
+    @group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(PER_PAGE)
   end
 
   def show
@@ -44,7 +44,7 @@ class Groups::MilestonesController < ApplicationController
     params[:title]
   end
 
-  def status(state = nil)
+  def state(state = nil)
     conditions = { project_id: group.projects }
     conditions.reverse_merge!(state: state) if state
     Milestone.where(conditions).order("title ASC")
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 36222758eb24611ef6f8facd34c989afcdc30ee3..7af3c077182228637d1691653336fcc6ea4f5caf 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -1,5 +1,5 @@
-class GroupsController < ApplicationController
-  skip_before_filter :authenticate_user!, only: [:show, :issues, :members, :merge_requests]
+class GroupsController < Groups::ApplicationController
+  skip_before_filter :authenticate_user!, only: [:show, :issues, :merge_requests]
   respond_to :html
   before_filter :group, except: [:new, :create]
 
@@ -10,20 +10,18 @@ class GroupsController < ApplicationController
 
   # Load group projects
   before_filter :load_projects, except: [:new, :create, :projects, :edit, :update]
-
-  before_filter :default_filter, only: [:issues, :merge_requests]
+  before_filter :event_filter, only: :show
+  before_filter :set_title, only: [:new, :create]
 
   layout :determine_layout
 
-  before_filter :set_title, only: [:new, :create]
-
   def new
     @group = Group.new
   end
 
   def create
     @group = Group.new(group_params)
-    @group.path = @group.name.dup.parameterize if @group.name
+    @group.name = @group.path.dup unless @group.name
 
     if @group.save
       @group.add_owner(current_user)
@@ -34,27 +32,33 @@ class GroupsController < ApplicationController
   end
 
   def show
-    @events = Event.in_projects(project_ids)
-    @events = event_filter.apply_filter(@events)
-    @events = @events.limit(20).offset(params[:offset] || 0)
     @last_push = current_user.recent_push if current_user
+    @projects = @projects.includes(:namespace)
 
     respond_to do |format|
       format.html
-      format.json { pager_json("events/_events", @events.count) }
-      format.atom { render layout: false }
+
+      format.json do
+        load_events
+        pager_json("events/_events", @events.count)
+      end
+
+      format.atom do
+        load_events
+        render layout: false
+      end
     end
   end
 
   def merge_requests
-    @merge_requests = MergeRequestsFinder.new.execute(current_user, params)
-    @merge_requests = @merge_requests.page(params[:page]).per(20)
+    @merge_requests = get_merge_requests_collection
+    @merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE)
     @merge_requests = @merge_requests.preload(:author, :target_project)
   end
 
   def issues
-    @issues = IssuesFinder.new.execute(current_user, params)
-    @issues = @issues.page(params[:page]).per(20)
+    @issues = get_issues_collection
+    @issues = @issues.page(params[:page]).per(PER_PAGE)
     @issues = @issues.preload(:author, :project)
 
     respond_to do |format|
@@ -63,19 +67,6 @@ class GroupsController < ApplicationController
     end
   end
 
-  def members
-    @project = group.projects.find(params[:project_id]) if params[:project_id]
-    @members = group.group_members
-
-    if params[:search].present?
-      users = group.users.search(params[:search]).to_a
-      @members = @members.where(user_id: users)
-    end
-
-    @members = @members.order('access_level DESC').page(params[:page]).per(50)
-    @users_group = GroupMember.new
-  end
-
   def edit
   end
 
@@ -128,12 +119,6 @@ class GroupsController < ApplicationController
     end
   end
 
-  def authorize_admin_group!
-    unless can?(current_user, :manage_group, group)
-      return render_404
-    end
-  end
-
   def set_title
     @title = 'New Group'
   end
@@ -148,19 +133,13 @@ class GroupsController < ApplicationController
     end
   end
 
-  def default_filter
-    if params[:scope].blank?
-      if current_user
-        params[:scope] = 'assigned-to-me'
-      else
-        params[:scope] = 'all'
-      end
-    end
-    params[:state] = 'opened' if params[:state].blank?
-    params[:group_id] = @group.id
-  end
-
   def group_params
     params.require(:group).permit(:name, :description, :path, :avatar)
   end
+
+  def load_events
+    @events = Event.in_projects(project_ids)
+    @events = event_filter.apply_filter(@events).with_associations
+    @events = @events.limit(20).offset(params[:offset] || 0)
+  end
 end
diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
index fc498559d6b25386467a85f08d8bc7711b2addd6..c4d620d87b15d2e84bdd1128976d4d2205c1f612 100644
--- a/app/controllers/help_controller.rb
+++ b/app/controllers/help_controller.rb
@@ -15,4 +15,7 @@ class HelpController < ApplicationController
 
   def shortcuts
   end
+
+  def ui
+  end
 end
diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..edb8bd4160b3cb1058dd42d085c3f27068c79907
--- /dev/null
+++ b/app/controllers/import/base_controller.rb
@@ -0,0 +1,19 @@
+class Import::BaseController < ApplicationController
+
+  private
+
+  def get_or_create_namespace
+    begin
+      namespace = Group.create!(name: @target_namespace, path: @target_namespace, owner: current_user)
+      namespace.add_owner(current_user)
+    rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid
+      namespace = Namespace.find_by_path_or_name(@target_namespace)
+      unless namespace.owner == current_user
+        @already_been_taken = true
+        return false
+      end
+    end
+
+    namespace
+  end
+end
diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..83ebc5fddca5139fbc9151033f4eae4f28429f3d
--- /dev/null
+++ b/app/controllers/import/bitbucket_controller.rb
@@ -0,0 +1,79 @@
+class Import::BitbucketController < Import::BaseController
+  before_filter :verify_bitbucket_import_enabled
+  before_filter :bitbucket_auth, except: :callback
+
+  rescue_from OAuth::Error, with: :bitbucket_unauthorized
+
+  def callback
+    request_token = session.delete(:oauth_request_token) 
+    raise "Session expired!" if request_token.nil?
+
+    request_token.symbolize_keys!
+    
+    access_token = client.get_token(request_token, params[:oauth_verifier], callback_import_bitbucket_url)
+
+    current_user.bitbucket_access_token = access_token.token
+    current_user.bitbucket_access_token_secret = access_token.secret
+
+    current_user.save
+    redirect_to status_import_bitbucket_url
+  end
+
+  def status
+    @repos = client.projects
+    
+    @already_added_projects = current_user.created_projects.where(import_type: "bitbucket")
+    already_added_projects_names = @already_added_projects.pluck(:import_source)
+
+    @repos.to_a.reject!{ |repo| already_added_projects_names.include? "#{repo["owner"]}/#{repo["slug"]}" }
+  end
+
+  def jobs
+    jobs = current_user.created_projects.where(import_type: "bitbucket").to_json(only: [:id, :import_status])
+    render json: jobs
+  end
+
+  def create
+    @repo_id = params[:repo_id] || ""
+    repo = client.project(@repo_id.gsub("___", "/"))
+    @target_namespace = params[:new_namespace].presence || repo["owner"]
+    @project_name = repo["slug"]
+    
+    namespace = get_or_create_namespace || (render and return)
+
+    unless Gitlab::BitbucketImport::KeyAdder.new(repo, current_user).execute
+      @access_denied = true
+      render
+      return
+    end
+
+    @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, current_user).execute
+  end
+
+  private
+
+  def client
+    @client ||= Gitlab::BitbucketImport::Client.new(current_user.bitbucket_access_token, current_user.bitbucket_access_token_secret)
+  end
+
+  def verify_bitbucket_import_enabled
+    not_found! unless bitbucket_import_enabled?
+  end
+
+  def bitbucket_auth
+    if current_user.bitbucket_access_token.blank?
+      go_to_bitbucket_for_permissions
+    end
+  end
+
+  def go_to_bitbucket_for_permissions
+    request_token = client.request_token(callback_import_bitbucket_url)
+    session[:oauth_request_token] = request_token
+
+    redirect_to client.authorize_url(request_token, callback_import_bitbucket_url)
+  end
+
+  def bitbucket_unauthorized
+    go_to_bitbucket_for_permissions
+  end
+end
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8650b6464dc86022a319a17a98fda0574685f6ff
--- /dev/null
+++ b/app/controllers/import/github_controller.rb
@@ -0,0 +1,65 @@
+class Import::GithubController < Import::BaseController
+  before_filter :verify_github_import_enabled
+  before_filter :github_auth, except: :callback
+
+  rescue_from Octokit::Unauthorized, with: :github_unauthorized
+
+  def callback
+    token = client.get_token(params[:code])
+    current_user.github_access_token = token
+    current_user.save
+    redirect_to status_import_github_url
+  end
+
+  def status
+    @repos = client.repos
+    client.orgs.each do |org|
+      @repos += client.org_repos(org.login)
+    end
+
+    @already_added_projects = current_user.created_projects.where(import_type: "github")
+    already_added_projects_names = @already_added_projects.pluck(:import_source)
+
+    @repos.reject!{ |repo| already_added_projects_names.include? repo.full_name }
+  end
+
+  def jobs
+    jobs = current_user.created_projects.where(import_type: "github").to_json(only: [:id, :import_status])
+    render json: jobs
+  end
+
+  def create
+    @repo_id = params[:repo_id].to_i
+    repo = client.repo(@repo_id)
+    @target_namespace = params[:new_namespace].presence || repo.owner.login
+    @project_name = repo.name
+    
+    namespace = get_or_create_namespace || (render and return)
+
+    @project = Gitlab::GithubImport::ProjectCreator.new(repo, namespace, current_user).execute
+  end
+
+  private
+
+  def client
+    @client ||= Gitlab::GithubImport::Client.new(current_user.github_access_token)
+  end
+
+  def verify_github_import_enabled
+    not_found! unless github_import_enabled?
+  end
+
+  def github_auth
+    if current_user.github_access_token.blank?
+      go_to_github_for_permissions
+    end
+  end
+
+  def go_to_github_for_permissions
+    redirect_to client.authorize_url(callback_import_github_url)
+  end
+
+  def github_unauthorized
+    go_to_github_for_permissions
+  end
+end
diff --git a/app/controllers/import/gitlab_controller.rb b/app/controllers/import/gitlab_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e979dad4b1188c8295757098aa30bc7a8a8ce772
--- /dev/null
+++ b/app/controllers/import/gitlab_controller.rb
@@ -0,0 +1,62 @@
+class Import::GitlabController < Import::BaseController
+  before_filter :verify_gitlab_import_enabled
+  before_filter :gitlab_auth, except: :callback
+
+  rescue_from OAuth2::Error, with: :gitlab_unauthorized
+
+  def callback
+    token = client.get_token(params[:code], callback_import_gitlab_url)
+    current_user.gitlab_access_token = token
+    current_user.save
+    redirect_to status_import_gitlab_url
+  end
+
+  def status
+    @repos = client.projects
+    
+    @already_added_projects = current_user.created_projects.where(import_type: "gitlab")
+    already_added_projects_names = @already_added_projects.pluck(:import_source)
+
+    @repos = @repos.to_a.reject{ |repo| already_added_projects_names.include? repo["path_with_namespace"] }
+  end
+
+  def jobs
+    jobs = current_user.created_projects.where(import_type: "gitlab").to_json(only: [:id, :import_status])
+    render json: jobs
+  end
+
+  def create
+    @repo_id = params[:repo_id].to_i
+    repo = client.project(@repo_id)
+    @target_namespace = params[:new_namespace].presence || repo["namespace"]["path"]
+    @project_name = repo["name"]
+    
+    namespace = get_or_create_namespace || (render and return)
+
+    @project = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, current_user).execute
+  end
+
+  private
+
+  def client
+    @client ||= Gitlab::GitlabImport::Client.new(current_user.gitlab_access_token)
+  end
+
+  def verify_gitlab_import_enabled
+    not_found! unless gitlab_import_enabled?
+  end
+
+  def gitlab_auth
+    if current_user.gitlab_access_token.blank?
+      go_to_gitlab_for_permissions
+    end
+  end
+
+  def go_to_gitlab_for_permissions
+    redirect_to client.authorize_url(callback_import_gitlab_url)
+  end
+
+  def gitlab_unauthorized
+    go_to_gitlab_for_permissions
+  end
+end
diff --git a/app/controllers/import/gitorious_controller.rb b/app/controllers/import/gitorious_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6067a87ee04dbc019e4b013956ffcc8d2bb33e8e
--- /dev/null
+++ b/app/controllers/import/gitorious_controller.rb
@@ -0,0 +1,43 @@
+class Import::GitoriousController < Import::BaseController
+
+  def new
+    redirect_to client.authorize_url(callback_import_gitorious_url)
+  end
+
+  def callback
+    session[:gitorious_repos] = params[:repos]
+    redirect_to status_import_gitorious_url
+  end
+
+  def status
+    @repos = client.repos
+
+    @already_added_projects = current_user.created_projects.where(import_type: "gitorious")
+    already_added_projects_names = @already_added_projects.pluck(:import_source)
+
+    @repos.reject! { |repo| already_added_projects_names.include? repo.full_name }
+  end
+
+  def jobs
+    jobs = current_user.created_projects.where(import_type: "gitorious").to_json(only: [:id, :import_status])
+    render json: jobs
+  end
+
+  def create
+    @repo_id = params[:repo_id]
+    repo = client.repo(@repo_id)
+    @target_namespace = params[:new_namespace].presence || repo.namespace
+    @project_name = repo.name
+
+    namespace = get_or_create_namespace || (render and return)
+
+    @project = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, current_user).execute
+  end
+
+  private
+
+  def client
+    @client ||= Gitlab::GitoriousImport::Client.new(session[:gitorious_repos])
+  end
+
+end
diff --git a/app/controllers/namespaces_controller.rb b/app/controllers/namespaces_controller.rb
index c59a2401cefa36351745da02591a50bfa845204e..b7a9d8c12912711862fe6a362b3e2a3eb2916b4d 100644
--- a/app/controllers/namespaces_controller.rb
+++ b/app/controllers/namespaces_controller.rb
@@ -15,4 +15,3 @@ class NamespacesController < ApplicationController
     end
   end
 end
-
diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..efa291d9397559f5e9c1eb1e3f0f388a51b4daa3
--- /dev/null
+++ b/app/controllers/oauth/applications_controller.rb
@@ -0,0 +1,39 @@
+class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
+  before_filter :authenticate_user!
+  layout "profile"
+
+  def index
+    head :forbidden and return
+  end
+
+  def create
+    @application = Doorkeeper::Application.new(application_params)
+
+    @application.owner = current_user
+    
+    if @application.save
+      flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
+      redirect_to oauth_application_url(@application)
+    else
+      render :new
+    end
+  end
+
+  def destroy
+    if @application.destroy
+      flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :destroy])
+    end
+
+    redirect_to applications_profile_url
+  end
+
+  private
+
+  def set_application
+    @application = current_user.oauth_applications.find(params[:id])
+  end
+
+  rescue_from ActiveRecord::RecordNotFound do |exception|
+    render "errors/not_found", layout: "errors", status: 404
+  end
+end
diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a57b4a60c24824950f14f8b2f74fe4d479c3b549
--- /dev/null
+++ b/app/controllers/oauth/authorizations_controller.rb
@@ -0,0 +1,57 @@
+class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
+  before_filter :authenticate_resource_owner!
+  layout "profile"
+
+  def new
+    if pre_auth.authorizable?
+      if skip_authorization? || matching_token?
+        auth = authorization.authorize
+        redirect_to auth.redirect_uri
+      else
+        render "doorkeeper/authorizations/new"
+      end
+    else
+      render "doorkeeper/authorizations/error"
+    end
+  end
+
+  # TODO: Handle raise invalid authorization
+  def create
+    redirect_or_render authorization.authorize
+  end
+
+  def destroy
+    redirect_or_render authorization.deny
+  end
+
+  private
+
+  def matching_token?
+    Doorkeeper::AccessToken.matching_token_for(pre_auth.client,
+                                               current_resource_owner.id,
+                                               pre_auth.scopes)
+  end
+
+  def redirect_or_render(auth)
+    if auth.redirectable?
+      redirect_to auth.redirect_uri
+    else
+      render json: auth.body, status: auth.status
+    end
+  end
+
+  def pre_auth
+    @pre_auth ||=
+      Doorkeeper::OAuth::PreAuthorization.new(Doorkeeper.configuration,
+                                              server.client_via_uid,
+                                              params)
+  end
+
+  def authorization
+    @authorization ||= strategy.request
+  end
+
+  def strategy
+    @strategy ||= server.authorization_request(pre_auth.response_type)
+  end
+end
diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0b27ce7da7291db743126bae189f107e948652d5
--- /dev/null
+++ b/app/controllers/oauth/authorized_applications_controller.rb
@@ -0,0 +1,8 @@
+class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicationsController
+  layout "profile"
+
+  def destroy
+    Doorkeeper::AccessToken.revoke_all_for(params[:id], current_resource_owner)
+    redirect_to applications_profile_url, notice: I18n.t(:notice, scope: [:doorkeeper, :flash, :authorized_applications, :destroy])
+  end
+end
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index bd4b310fcbfe0b7d2b94f48854197a8bab7b3dce..bb9d65c9ed6450acb0bc7b94b548bcfe3fa8f052 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -42,11 +42,9 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
 
   def handle_omniauth
     if current_user
-      # Change a logged-in user's authentication method:
-      current_user.extern_uid = oauth['uid']
-      current_user.provider = oauth['provider']
-      current_user.save
-      redirect_to profile_path
+      # Add new authentication method
+      current_user.identities.find_or_create_by(extern_uid: oauth['uid'], provider: oauth['provider'])
+      redirect_to profile_account_path, notice: 'Authentication method updated'
     else
       @user = Gitlab::OAuth::User.new(oauth)
       @user.save
@@ -67,8 +65,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
         redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return
       end
     end
-  rescue StandardError
-    flash[:notice] = "There's no such user!"
+  rescue Gitlab::OAuth::ForbiddenAction => e
+    flash[:notice] = e.message
     redirect_to new_user_session_path
   end
 
diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb
index 988ede3007bcde76b39f4754d9e94d412ef6d32d..dcbbe5baa4b2c1888a5d040ecde785ef332924a3 100644
--- a/app/controllers/passwords_controller.rb
+++ b/app/controllers/passwords_controller.rb
@@ -5,12 +5,12 @@ class PasswordsController < Devise::PasswordsController
     resource_found = resource_class.find_by_email(email)
     if resource_found && resource_found.ldap_user?
       flash[:alert] = "Cannot reset password for LDAP user."
-      respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name)) and return
+      respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name)) and return
     end
 
     self.resource = resource_class.send_reset_password_instructions(resource_params)
     if successfully_sent?(resource)
-      respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
+      respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name))
     else
       respond_with(resource)
     end
diff --git a/app/controllers/profiles/accounts_controller.rb b/app/controllers/profiles/accounts_controller.rb
index fe121691a10092034d86cf16ed1e6950d6a43607..9bd34fe22613ea5401ab2408887a3e277414ef47 100644
--- a/app/controllers/profiles/accounts_controller.rb
+++ b/app/controllers/profiles/accounts_controller.rb
@@ -4,4 +4,10 @@ class Profiles::AccountsController < ApplicationController
   def show
     @user = current_user
   end
+
+  def unlink
+    provider = params[:provider]
+    current_user.identities.find_by(provider: provider).destroy
+    redirect_to profile_account_path
+  end
 end
diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb
index f3f0e69b83a4ee516489662d6e45364e1f96d51b..4a65c978e5c36da4fc8a2cd05d5ab4355b240732 100644
--- a/app/controllers/profiles/emails_controller.rb
+++ b/app/controllers/profiles/emails_controller.rb
@@ -18,6 +18,9 @@ class Profiles::EmailsController < ApplicationController
     @email = current_user.emails.find(params[:id])
     @email.destroy
 
+    current_user.set_notification_email
+    current_user.save if current_user.notification_email_changed?
+
     respond_to do |format|
       format.html { redirect_to profile_emails_url }
       format.js { render nothing: true }
diff --git a/app/controllers/profiles/groups_controller.rb b/app/controllers/profiles/groups_controller.rb
deleted file mode 100644
index ce9dd50df67ebb525f0def5956e5ab1fa20f49ec..0000000000000000000000000000000000000000
--- a/app/controllers/profiles/groups_controller.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-class Profiles::GroupsController < ApplicationController
-  layout "profile"
-
-  def index
-    @user_groups = current_user.group_members.page(params[:page]).per(20)
-  end
-
-  def leave
-    @users_group = group.group_members.where(user_id: current_user.id).first
-    if can?(current_user, :destroy, @users_group)
-      @users_group.destroy
-      redirect_to(profile_groups_path, info: "You left #{group.name} group.")
-    else
-      return render_403
-    end
-  end
-
-  private
-
-  def group
-    @group ||= Group.find_by(path: params[:id])
-  end
-end
diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb
index 88414b13564c13623c41ef31dc0a246b0e2c489d..4e2bd0a9b4b92c9730f6ec9522a8e2f1e6f992b3 100644
--- a/app/controllers/profiles/keys_controller.rb
+++ b/app/controllers/profiles/keys_controller.rb
@@ -3,7 +3,7 @@ class Profiles::KeysController < ApplicationController
   skip_before_filter :authenticate_user!, only: [:get_keys]
 
   def index
-    @keys = current_user.keys.order('id DESC')
+    @keys = current_user.keys
   end
 
   def show
diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb
index 638d1f9789bed61dcd3a2abb93abe218f795f332..3fdcbbab61b531633827a36f336393e9d185f137 100644
--- a/app/controllers/profiles/notifications_controller.rb
+++ b/app/controllers/profiles/notifications_controller.rb
@@ -2,6 +2,7 @@ class Profiles::NotificationsController < ApplicationController
   layout 'profile'
 
   def show
+    @user = current_user
     @notification = current_user.notification
     @project_members = current_user.project_members
     @group_members = current_user.group_members
@@ -11,16 +12,33 @@ class Profiles::NotificationsController < ApplicationController
     type = params[:notification_type]
 
     @saved = if type == 'global'
-               current_user.notification_level = params[:notification_level]
-               current_user.save
+               current_user.update_attributes(user_params)
              elsif type == 'group'
-               users_group = current_user.group_members.find(params[:notification_id])
-               users_group.notification_level = params[:notification_level]
-               users_group.save
+               group_member = current_user.group_members.find(params[:notification_id])
+               group_member.notification_level = params[:notification_level]
+               group_member.save
              else
                project_member = current_user.project_members.find(params[:notification_id])
                project_member.notification_level = params[:notification_level]
                project_member.save
              end
+
+    respond_to do |format|
+      format.html do
+        if @saved
+          flash[:notice] = "Notification settings saved"
+        else
+          flash[:alert] = "Failed to save new settings"
+        end
+
+        redirect_to :back
+      end
+
+      format.js
+    end
+  end
+
+  def user_params
+    params.require(:user).permit(:notification_email, :notification_level)
   end
 end
diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb
index 1191ce47ebae5adf9b87279500168ae87e1cd3fb..0c614969a3fe8626cad43d97bece80f869dd2fb1 100644
--- a/app/controllers/profiles/passwords_controller.rb
+++ b/app/controllers/profiles/passwords_controller.rb
@@ -11,7 +11,7 @@ class Profiles::PasswordsController < ApplicationController
   end
 
   def create
-    unless @user.valid_password?(user_params[:current_password])
+    unless @user.password_automatically_set || @user.valid_password?(user_params[:current_password])
       redirect_to new_profile_password_path, alert: 'You must provide a valid current password'
       return
     end
@@ -21,7 +21,8 @@ class Profiles::PasswordsController < ApplicationController
 
     result = @user.update_attributes(
       password: new_password,
-      password_confirmation: new_password_confirmation
+      password_confirmation: new_password_confirmation,
+      password_automatically_set: false
     )
 
     if result
@@ -39,8 +40,9 @@ class Profiles::PasswordsController < ApplicationController
     password_attributes = user_params.select do |key, value|
       %w(password password_confirmation).include?(key.to_s)
     end
+    password_attributes[:password_automatically_set] = false
 
-    unless @user.valid_password?(user_params[:current_password])
+    unless @user.password_automatically_set || @user.valid_password?(user_params[:current_password])
       redirect_to edit_profile_password_path, alert: 'You must provide a valid current password'
       return
     end
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index e877f9b904946494885b625fc952a21f290694b5..9252e85e8ccb92d070eba2cf4ca1ba3a5e5c7caf 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -13,13 +13,20 @@ class ProfilesController < ApplicationController
   def design
   end
 
+  def applications
+    @applications = current_user.oauth_applications
+    @authorized_tokens = current_user.oauth_authorized_tokens
+    @authorized_apps = @authorized_tokens.map(&:application).uniq
+  end
+
   def update
     user_params.except!(:email) if @user.ldap_user?
 
     if @user.update_attributes(user_params)
       flash[:notice] = "Profile was successfully updated"
     else
-      flash[:alert] = "Failed to update profile"
+      messages = @user.errors.full_messages.uniq.join('. ')
+      flash[:alert] = "Failed to update profile. #{messages}"
     end
 
     respond_to do |format|
@@ -37,7 +44,7 @@ class ProfilesController < ApplicationController
   end
 
   def history
-    @events = current_user.recent_events.page(params[:page]).per(20)
+    @events = current_user.recent_events.page(params[:page]).per(PER_PAGE)
   end
 
   def update_username
@@ -62,7 +69,7 @@ class ProfilesController < ApplicationController
     params.require(:user).permit(
       :email, :password, :password_confirmation, :bio, :name, :username,
       :skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id,
-      :avatar, :hide_no_ssh_key,
+      :avatar, :hide_no_ssh_key, :hide_no_password, :location
     )
   end
 end
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 7e4580017dd7e6c26373a1b80186f7dd518a71b0..4719933394fca0ef749385e01a1a2bff8c435831 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -8,7 +8,8 @@ class Projects::ApplicationController < ApplicationController
     # for non-signed users
     if !current_user
       id = params[:project_id] || params[:id]
-      @project = Project.find_with_namespace(id)
+      project_with_namespace = "#{params[:namespace_id]}/#{id}"
+      @project = Project.find_with_namespace(project_with_namespace)
 
       return if @project && @project.public?
     end
@@ -26,7 +27,10 @@ class Projects::ApplicationController < ApplicationController
 
   def require_branch_head
     unless @repository.branch_names.include?(@ref)
-      redirect_to project_tree_path(@project, @ref), notice: "This action is not allowed unless you are on top of a branch"
+      redirect_to(
+        namespace_project_tree_path(@project.namespace, @project, @ref),
+        notice: "This action is not allowed unless you are on top of a branch"
+      )
     end
   end
 end
diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a482b90880da9fdf0e935a4d34d657777551732a
--- /dev/null
+++ b/app/controllers/projects/avatars_controller.rb
@@ -0,0 +1,29 @@
+class Projects::AvatarsController < Projects::ApplicationController
+  layout 'project'
+
+  before_filter :project
+
+  def show
+    @blob = @project.repository.blob_at_branch('master', @project.avatar_in_git)
+    if @blob
+      headers['X-Content-Type-Options'] = 'nosniff'
+      send_data(
+        @blob.data,
+        type: @blob.mime_type,
+        disposition: 'inline',
+        filename: @blob.name
+      )
+    else
+      not_found!
+    end
+  end
+
+  def destroy
+    @project.remove_avatar!
+
+    @project.save
+    @project.reset_events_cache
+
+    redirect_to edit_project_path(@project)
+  end
+end
diff --git a/app/controllers/projects/base_tree_controller.rb b/app/controllers/projects/base_tree_controller.rb
deleted file mode 100644
index a7b1b7b40e84dfd9ab45afb707ef4e5c30884e47..0000000000000000000000000000000000000000
--- a/app/controllers/projects/base_tree_controller.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class Projects::BaseTreeController < Projects::ApplicationController
-  include ExtractsPath
-
-  before_filter :authorize_download_code!
-  before_filter :require_non_empty_project
-end
-
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index 367d1295f342221307a069cf6f17e5978aa66df0..a87b8270a22eb37a365f285662897d6cb8885b84 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -2,12 +2,12 @@
 class Projects::BlameController < Projects::ApplicationController
   include ExtractsPath
 
-  # Authorize
-  before_filter :authorize_download_code!
   before_filter :require_non_empty_project
+  before_filter :assign_ref_vars
+  before_filter :authorize_download_code!
 
   def show
-    @blob = @repository.blob_at(@commit.id, @path)
-    @blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path)
+    @blame = Gitlab::Git::Blame.new(@repository, @commit.id, @path)
+    @blob = @blame.blob
   end
 end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 2412800c4931394a342c24b44b35bd02b60bb8e4..4b7eb4df298ee50c84d315a279dbd20a1c5b0c9b 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -1,23 +1,91 @@
 # Controller for viewing a file's blame
 class Projects::BlobController < Projects::ApplicationController
   include ExtractsPath
+  include ActionView::Helpers::SanitizeHelper
 
-  # Authorize
+  # Raised when given an invalid file path
+  class InvalidPathError < StandardError; end
+
+  before_filter :require_non_empty_project, except: [:new, :create]
   before_filter :authorize_download_code!
-  before_filter :require_non_empty_project
   before_filter :authorize_push_code!, only: [:destroy]
+  before_filter :assign_blob_vars
+  before_filter :commit, except: [:new, :create]
+  before_filter :blob, except: [:new, :create]
+  before_filter :from_merge_request, only: [:edit, :update]
+  before_filter :after_edit_path, only: [:edit, :update]
+  before_filter :require_branch_head, only: [:edit, :update]
+
+  def new
+    commit unless @repository.empty?
+  end
 
-  before_filter :blob
+  def create
+    file_path = File.join(@path, File.basename(params[:file_name]))
+    result = Files::CreateService.new(
+      @project,
+      current_user,
+      params.merge(new_branch: sanitized_new_branch_name),
+      @ref,
+      file_path
+    ).execute
+
+    if result[:status] == :success
+      flash[:notice] = "Your changes have been successfully committed"
+      ref = sanitized_new_branch_name.presence || @ref
+      redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(ref, file_path))
+    else
+      flash[:alert] = result[:message]
+      render :new
+    end
+  end
 
   def show
   end
 
+  def edit
+    @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
+  end
+
+  def update
+    result = Files::UpdateService.
+      new(
+        @project,
+        current_user,
+        params.merge(new_branch: sanitized_new_branch_name),
+        @ref,
+        @path
+      ).execute
+
+    if result[:status] == :success
+      flash[:notice] = "Your changes have been successfully committed"
+
+      if from_merge_request
+        from_merge_request.reload_code
+      end
+
+      redirect_to after_edit_path
+    else
+      flash[:alert] = result[:message]
+      render :edit
+    end
+  end
+
+  def preview
+    @content = params[:content]
+    diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
+    @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/))
+
+    render layout: false
+  end
+
   def destroy
     result = Files::DeleteService.new(@project, current_user, params, @ref, @path).execute
 
     if result[:status] == :success
       flash[:notice] = "Your changes have been successfully committed"
-      redirect_to project_tree_path(@project, @ref)
+      redirect_to namespace_project_tree_path(@project.namespace, @project,
+                                              @ref)
     else
       flash[:alert] = result[:message]
       render :show
@@ -46,10 +114,50 @@ class Projects::BlobController < Projects::ApplicationController
 
     if @blob
       @blob
-    elsif tree.entries.any?
-      redirect_to project_tree_path(@project, File.join(@ref, @path)) and return
     else
+      if tree = @repository.tree(@commit.id, @path)
+        if tree.entries.any?
+          redirect_to namespace_project_tree_path(@project.namespace, @project, File.join(@ref, @path)) and return
+        end
+      end
+
       return not_found!
     end
   end
+
+  def commit
+    @commit = @repository.commit(@ref)
+
+    return not_found! unless @commit
+  end
+
+  def assign_blob_vars
+    @id = params[:id]
+    @ref, @path = extract_ref(@id)
+
+
+  rescue InvalidPathError
+    not_found!
+  end
+
+  def after_edit_path
+    @after_edit_path ||=
+      if from_merge_request
+        diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) +
+          "#file-path-#{hexdigest(@path)}"
+      elsif sanitized_new_branch_name.present?
+        namespace_project_blob_path(@project.namespace, @project, File.join(sanitized_new_branch_name, @path))
+      else
+        namespace_project_blob_path(@project.namespace, @project, @id)
+      end
+  end
+
+  def from_merge_request
+    # If blob edit was initiated from merge request page
+    @from_merge_request ||= MergeRequest.find_by(id: params[:from_merge_request_id])
+  end
+
+  def sanitized_new_branch_name
+    @new_branch ||= sanitize(strip_tags(params[:new_branch]))
+  end
 end
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index cff1a907dc22be246f23e09b9cee0ed5d840bf65..f049e96e61df4fcee5ed91daf7f24c60aeb8a798 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -2,14 +2,13 @@ class Projects::BranchesController < Projects::ApplicationController
   include ActionView::Helpers::SanitizeHelper
   # Authorize
   before_filter :require_non_empty_project
-
   before_filter :authorize_download_code!
   before_filter :authorize_push_code!, only: [:create, :destroy]
 
   def index
     @sort = params[:sort] || 'name'
     @branches = @repository.branches_sorted_by(@sort)
-    @branches = Kaminari.paginate_array(@branches).page(params[:page]).per(30)
+    @branches = Kaminari.paginate_array(@branches).page(params[:page]).per(PER_PAGE)
   end
 
   def recent
@@ -24,7 +23,8 @@ class Projects::BranchesController < Projects::ApplicationController
 
     if result[:status] == :success
       @branch = result[:branch]
-      redirect_to project_tree_path(@project, @branch.name)
+      redirect_to namespace_project_tree_path(@project.namespace, @project,
+                                              @branch.name)
     else
       @error = result[:message]
       render action: 'new'
@@ -36,7 +36,10 @@ class Projects::BranchesController < Projects::ApplicationController
     @branch_name = params[:id]
 
     respond_to do |format|
-      format.html { redirect_to project_branches_path(@project) }
+      format.html do
+        redirect_to namespace_project_branches_path(@project.namespace,
+                                                    @project)
+      end
       format.js
     end
   end
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index dac858d8e16e8986980c66918236518031974744..87e39f1363a6acce991bf6101ca7c6fe998284a7 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -3,15 +3,14 @@
 # Not to be confused with CommitsController, plural.
 class Projects::CommitController < Projects::ApplicationController
   # Authorize
-  before_filter :authorize_download_code!
   before_filter :require_non_empty_project
+  before_filter :authorize_download_code!
   before_filter :commit
 
   def show
     return git_not_found! unless @commit
 
     @line_notes = @project.notes.for_commit_id(commit.id).inline
-    @branches = @project.repository.branch_names_contains(commit.id)
     @diffs = @commit.diffs
     @note = @project.build_commit_note(commit)
     @notes_count = @project.notes.for_commit_id(commit.id).count
@@ -30,6 +29,12 @@ class Projects::CommitController < Projects::ApplicationController
     end
   end
 
+  def branches
+    @branches = @project.repository.branch_names_contains(commit.id)
+    @tags = @project.repository.tag_names_contains(commit.id)
+    render layout: false
+  end
+
   def commit
     @commit ||= @project.repository.commit(params[:id])
   end
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index 9476b6c0284954281b16556a93a8465677689749..4b6ab43747625eb2dc91501b37bc7c51bd98e7e7 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -3,9 +3,9 @@ require "base64"
 class Projects::CommitsController < Projects::ApplicationController
   include ExtractsPath
 
-  # Authorize
-  before_filter :authorize_download_code!
   before_filter :require_non_empty_project
+  before_filter :assign_ref_vars
+  before_filter :authorize_download_code!
 
   def show
     @repo = @project.repository
@@ -13,7 +13,7 @@ class Projects::CommitsController < Projects::ApplicationController
 
     @commits = @repo.commits(@ref, @path, @limit, @offset)
     @note_counts = Note.where(commit_id: @commits.map(&:id)).
-        group(:commit_id).count
+      group(:commit_id).count
 
     respond_to do |format|
       format.html
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index ffb8c2e4af16b8f523928ebd03a73702b2652e77..146808fa5620c93b9bbb6c85949393ccbbfc51b0 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -1,7 +1,7 @@
 class Projects::CompareController < Projects::ApplicationController
   # Authorize
-  before_filter :authorize_download_code!
   before_filter :require_non_empty_project
+  before_filter :authorize_download_code!
 
   def index
   end
@@ -25,6 +25,7 @@ class Projects::CompareController < Projects::ApplicationController
   end
 
   def create
-    redirect_to project_compare_path(@project, params[:from], params[:to])
+    redirect_to namespace_project_compare_path(@project.namespace, @project,
+                                               params[:from], params[:to])
   end
 end
diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb
index 024b9520d30aaaff126e6c42796009dc31028255..679a5d76ec065131cca0e7ae7412b66dc4b6fe6c 100644
--- a/app/controllers/projects/deploy_keys_controller.rb
+++ b/app/controllers/projects/deploy_keys_controller.rb
@@ -25,7 +25,8 @@ class Projects::DeployKeysController < Projects::ApplicationController
     @key = DeployKey.new(deploy_key_params)
 
     if @key.valid? && @project.deploy_keys << @key
-      redirect_to project_deploy_keys_path(@project)
+      redirect_to namespace_project_deploy_keys_path(@project.namespace,
+                                                     @project)
     else
       render "new"
     end
@@ -36,7 +37,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
     @key.destroy
 
     respond_to do |format|
-      format.html { redirect_to project_deploy_keys_url }
+      format.html { redirect_to namespace_project_deploy_keys_path(@project.namespace, @project) }
       format.js { render nothing: true }
     end
   end
@@ -44,13 +45,15 @@ class Projects::DeployKeysController < Projects::ApplicationController
   def enable
     @project.deploy_keys << available_keys.find(params[:id])
 
-    redirect_to project_deploy_keys_path(@project)
+    redirect_to namespace_project_deploy_keys_path(@project.namespace,
+                                                   @project)
   end
 
   def disable
-    @project.deploy_keys_projects.where(deploy_key_id: params[:id]).last.destroy
+    @project.deploy_keys_projects.find_by(deploy_key_id: params[:id]).destroy
 
-    redirect_to project_deploy_keys_path(@project)
+    redirect_to namespace_project_deploy_keys_path(@project.namespace,
+                                                   @project)
   end
 
   protected
diff --git a/app/controllers/projects/edit_tree_controller.rb b/app/controllers/projects/edit_tree_controller.rb
deleted file mode 100644
index 65661c80410b66e22b578f1e78d6bfb64dea1ddb..0000000000000000000000000000000000000000
--- a/app/controllers/projects/edit_tree_controller.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-class Projects::EditTreeController < Projects::BaseTreeController
-  before_filter :require_branch_head
-  before_filter :blob
-  before_filter :authorize_push_code!
-  before_filter :from_merge_request
-  before_filter :after_edit_path
-
-  def show
-    @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
-  end
-
-  def update
-    result = Files::UpdateService.
-      new(@project, current_user, params, @ref, @path).execute
-
-    if result[:status] == :success
-      flash[:notice] = "Your changes have been successfully committed"
-
-      if from_merge_request
-        from_merge_request.reload_code
-      end
-
-      redirect_to after_edit_path
-    else
-      flash[:alert] = result[:message]
-      render :show
-    end
-  end
-
-  def preview
-    @content = params[:content]
-
-    diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3',
-                            include_diff_info: true)
-    @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/))
-
-    render layout: false
-  end
-
-  private
-
-  def blob
-    @blob ||= @repository.blob_at(@commit.id, @path)
-  end
-
-  def after_edit_path
-    @after_edit_path ||=
-      if from_merge_request
-        diffs_project_merge_request_path(from_merge_request.target_project, from_merge_request) +
-          "#file-path-#{hexdigest(@path)}"
-      else
-        project_blob_path(@project, @id)
-      end
-  end
-
-  def from_merge_request
-    # If blob edit was initiated from merge request page
-    @from_merge_request ||= MergeRequest.find_by(id: params[:from_merge_request_id])
-  end
-end
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..21a151a426e57fe3295f40061123ad63ee04f6a1
--- /dev/null
+++ b/app/controllers/projects/forks_controller.rb
@@ -0,0 +1,25 @@
+class Projects::ForksController < Projects::ApplicationController
+  # Authorize
+  before_filter :require_non_empty_project
+  before_filter :authorize_download_code!
+
+  def new
+    @namespaces = current_user.manageable_namespaces
+    @namespaces.delete(@project.namespace)
+  end
+
+  def create
+    namespace = Namespace.find(params[:namespace_key])
+    @forked_project = ::Projects::ForkService.new(project, current_user, namespace: namespace).execute
+
+    if @forked_project.saved? && @forked_project.forked?
+      redirect_to(
+        namespace_project_path(@forked_project.namespace, @forked_project),
+        notice: 'Project was successfully forked.'
+      )
+    else
+      @title = 'Fork project'
+      render :error
+    end
+  end
+end
diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb
index 4a318cb7d5681939ad2d9e7c3978c77c8098d041..6e54af356e0c96c8e1d60b9e62b0060baf6e4efc 100644
--- a/app/controllers/projects/graphs_controller.rb
+++ b/app/controllers/projects/graphs_controller.rb
@@ -1,7 +1,7 @@
 class Projects::GraphsController < Projects::ApplicationController
   # Authorize
-  before_filter :authorize_download_code!
   before_filter :require_non_empty_project
+  before_filter :authorize_download_code!
 
   def show
     respond_to do |format|
@@ -28,8 +28,8 @@ class Projects::GraphsController < Projects::ApplicationController
 
     @commits.each do |commit|
       @log << {
-        author_name: commit.author_name.force_encoding('UTF-8'),
-        author_email: commit.author_email.force_encoding('UTF-8'),
+        author_name: commit.author_name,
+        author_email: commit.author_email,
         date: commit.committed_date.strftime("%Y-%m-%d")
       }
     end
diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index cab8fd76e6c4f8b56096bcafba03c7f3ad6de633..ba95bb13e1fbae73408a512da0948705f61c073a 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -16,7 +16,7 @@ class Projects::HooksController < Projects::ApplicationController
     @hook.save
 
     if @hook.valid?
-      redirect_to project_hooks_path(@project)
+      redirect_to namespace_project_hooks_path(@project.namespace, @project)
     else
       @hooks = @project.hooks.select(&:persisted?)
       render :index
@@ -26,6 +26,7 @@ class Projects::HooksController < Projects::ApplicationController
   def test
     if !@project.empty_repo?
       status = TestHookService.new.execute(hook, current_user)
+
       if status
         flash[:notice] = 'Hook successfully executed.'
       else
@@ -42,7 +43,7 @@ class Projects::HooksController < Projects::ApplicationController
   def destroy
     hook.destroy
 
-    redirect_to project_hooks_path(@project)
+    redirect_to namespace_project_hooks_path(@project.namespace, @project)
   end
 
   private
diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b64491b4666b9a18cd30a24aaea42d99ed8c2893
--- /dev/null
+++ b/app/controllers/projects/imports_controller.rb
@@ -0,0 +1,51 @@
+class Projects::ImportsController < Projects::ApplicationController
+  # Authorize
+  before_filter :authorize_admin_project!
+  before_filter :require_no_repo
+  before_filter :redirect_if_progress, except: :show
+
+  def new
+  end
+
+  def create
+    @project.import_url = params[:project][:import_url]
+
+    if @project.save
+      @project.reload
+
+      if @project.import_failed?
+        @project.import_retry
+      else
+        @project.import_start
+      end
+    end
+
+    redirect_to namespace_project_import_path(@project.namespace, @project)
+  end
+
+  def show
+    unless @project.import_in_progress?
+      if @project.import_finished?
+        redirect_to(project_path(@project)) and return
+      else
+        redirect_to new_namespace_project_import_path(@project.namespace,
+                                                      @project) && return
+      end
+    end
+  end
+
+  private
+
+  def require_no_repo
+    if @project.repository_exists? && !@project.import_in_progress?
+      redirect_to(namespace_project_path(@project.namespace, @project)) and return
+    end
+  end
+
+  def redirect_if_progress
+    if @project.import_in_progress?
+      redirect_to namespace_project_import_path(@project.namespace, @project) &&
+        return
+    end
+  end
+end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index c6d526f05c5a1c5811a9843bed78692d93c0d09a..88302276b5ee59974886c60a40ea47d74cdbe770 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -1,6 +1,6 @@
 class Projects::IssuesController < Projects::ApplicationController
   before_filter :module_enabled
-  before_filter :issue, only: [:edit, :update, :show]
+  before_filter :issue, only: [:edit, :update, :show, :toggle_subscription]
 
   # Allow read any issue
   before_filter :authorize_read_issue!
@@ -18,17 +18,9 @@ class Projects::IssuesController < Projects::ApplicationController
 
   def index
     terms = params['issue_search']
-
-    @issues = issues_filtered
+    @issues = get_issues_collection
     @issues = @issues.full_search(terms) if terms.present?
-    @issues = @issues.page(params[:page]).per(20)
-
-    assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
-    @assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
-    @milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
-    sort_param = params[:sort] || 'newest'
-    @sort = sort_param.humanize unless sort_param.empty?
-    @assignees = User.where(id: @project.issues.pluck(:assignee_id)).active
+    @issues = @issues.page(params[:page]).per(PER_PAGE)
 
     respond_to do |format|
       format.html
@@ -68,7 +60,7 @@ class Projects::IssuesController < Projects::ApplicationController
     respond_to do |format|
       format.html do
         if @issue.valid?
-          redirect_to project_issue_path(@project, @issue)
+          redirect_to issue_path(@issue)
         else
           render :new
         end
@@ -86,7 +78,7 @@ class Projects::IssuesController < Projects::ApplicationController
       format.js
       format.html do
         if @issue.valid?
-          redirect_to [@project, @issue]
+          redirect_to issue_path(@issue)
         else
           render :edit
         end
@@ -101,10 +93,16 @@ class Projects::IssuesController < Projects::ApplicationController
   end
 
   def bulk_update
-    result = Issues::BulkUpdateService.new(project, current_user, params).execute
+    result = Issues::BulkUpdateService.new(project, current_user, bulk_update_params).execute
     redirect_to :back, notice: "#{result[:count]} issues updated"
   end
 
+  def toggle_subscription
+    @issue.toggle_subscription(current_user)
+    
+    render nothing: true
+  end
+
   protected
 
   def issue
@@ -127,12 +125,6 @@ class Projects::IssuesController < Projects::ApplicationController
     return render_404 unless @project.issues_enabled
   end
 
-  def issues_filtered
-    params[:scope] = 'all' if params[:scope].blank?
-    params[:state] = 'opened' if params[:state].blank?
-    @issues = IssuesFinder.new.execute(current_user, params.merge(project_id: @project.id))
-  end
-
   # Since iids are implemented only in 6.1
   # user may navigate to issue page using old global ids.
   #
@@ -142,7 +134,7 @@ class Projects::IssuesController < Projects::ApplicationController
     issue = @project.issues.find_by(id: params[:id])
 
     if issue
-      redirect_to project_issue_path(@project, issue)
+      redirect_to issue_path(issue)
       return
     else
       raise ActiveRecord::RecordNotFound.new
@@ -155,4 +147,13 @@ class Projects::IssuesController < Projects::ApplicationController
       :milestone_id, :state_event, :task_num, label_ids: []
     )
   end
+
+  def bulk_update_params
+    params.require(:update).permit(
+      :issues_ids,
+      :assignee_id,
+      :milestone_id,
+      :state_event
+    )
+  end
 end
diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb
index 6c7bde9c5d5544dac846842f48a3e5c26429379c..207a01ed3b0ef6c82669fc3055397af307d69394 100644
--- a/app/controllers/projects/labels_controller.rb
+++ b/app/controllers/projects/labels_controller.rb
@@ -7,7 +7,7 @@ class Projects::LabelsController < Projects::ApplicationController
   respond_to :js, :html
 
   def index
-    @labels = @project.labels.order_by_name.page(params[:page]).per(20)
+    @labels = @project.labels.page(params[:page]).per(PER_PAGE)
   end
 
   def new
@@ -18,7 +18,7 @@ class Projects::LabelsController < Projects::ApplicationController
     @label = @project.labels.create(label_params)
 
     if @label.valid?
-      redirect_to project_labels_path(@project)
+      redirect_to namespace_project_labels_path(@project.namespace, @project)
     else
       render 'new'
     end
@@ -29,7 +29,7 @@ class Projects::LabelsController < Projects::ApplicationController
 
   def update
     if @label.update_attributes(label_params)
-      redirect_to project_labels_path(@project)
+      redirect_to namespace_project_labels_path(@project.namespace, @project)
     else
       render 'edit'
     end
@@ -39,11 +39,12 @@ class Projects::LabelsController < Projects::ApplicationController
     Gitlab::IssuesLabels.generate(@project)
 
     if params[:redirect] == 'issues'
-      redirect_to project_issues_path(@project)
+      redirect_to namespace_project_issues_path(@project.namespace, @project)
     elsif params[:redirect] == 'merge_requests'
-      redirect_to project_merge_requests_path(@project)
+      redirect_to namespace_project_merge_requests_path(@project.namespace,
+                                                        @project)
     else
-      redirect_to project_labels_path(@project)
+      redirect_to namespace_project_labels_path(@project.namespace, @project)
     end
   end
 
@@ -51,7 +52,10 @@ class Projects::LabelsController < Projects::ApplicationController
     @label.destroy
 
     respond_to do |format|
-      format.html { redirect_to project_labels_path(@project), notice: 'Label was removed' }
+      format.html do
+        redirect_to(namespace_project_labels_path(@project.namespace, @project),
+                    notice: 'Label was removed')
+      end
       format.js
     end
   end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 20a733b10e131ff5d85f8e3ec93d6084573be326..47ce8467358b4c72804fe8ca71b79c7c28d84fac 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -2,7 +2,7 @@ require 'gitlab/satellite/satellite'
 
 class Projects::MergeRequestsController < Projects::ApplicationController
   before_filter :module_enabled
-  before_filter :merge_request, only: [:edit, :update, :show, :diffs, :automerge, :automerge_check, :ci_status]
+  before_filter :merge_request, only: [:edit, :update, :show, :diffs, :automerge, :automerge_check, :ci_status, :toggle_subscription]
   before_filter :closes_issues, only: [:edit, :update, :show, :diffs]
   before_filter :validates_merge_request, only: [:show, :diffs]
   before_filter :define_show_vars, only: [:show, :diffs]
@@ -17,26 +17,28 @@ class Projects::MergeRequestsController < Projects::ApplicationController
   before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort]
 
   def index
-    params[:sort] ||= 'newest'
-    params[:scope] = 'all' if params[:scope].blank?
-    params[:state] = 'opened' if params[:state].blank?
-
-    @merge_requests = MergeRequestsFinder.new.execute(current_user, params.merge(project_id: @project.id))
-    @merge_requests = @merge_requests.page(params[:page]).per(20)
-
-    @sort = params[:sort].humanize
-    assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
-    @assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
-    @milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
-    @assignees = User.where(id: @project.merge_requests.pluck(:assignee_id))
+    terms = params['issue_search']
+    @merge_requests = get_merge_requests_collection
+    @merge_requests = @merge_requests.full_search(terms) if terms.present?
+    @merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE)
+
+    respond_to do |format|
+      format.html
+      format.json do
+        render json: {
+          html: view_to_html_string("projects/merge_requests/_merge_requests")
+        }
+      end
+    end
   end
 
   def show
     @note_counts = Note.where(commit_id: @merge_request.commits.map(&:id)).
-        group(:commit_id).count
+      group(:commit_id).count
 
     respond_to do |format|
       format.html
+      format.json { render json: @merge_request }
       format.diff { render text: @merge_request.to_diff(current_user) }
       format.patch { render text: @merge_request.to_patch(current_user) }
     end
@@ -87,7 +89,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
     @merge_request = MergeRequests::CreateService.new(project, current_user, merge_request_params).execute
 
     if @merge_request.valid?
-      redirect_to project_merge_request_path(@merge_request.target_project, @merge_request), notice: 'Merge request was successfully created.'
+      redirect_to(merge_request_path(@merge_request))
     else
       @source_project = @merge_request.source_project
       @target_project = @merge_request.target_project
@@ -102,7 +104,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController
       respond_to do |format|
         format.js
         format.html do
-          redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully updated.'
+          redirect_to([@merge_request.target_project.namespace.becomes(Namespace),
+                       @merge_request.target_project, @merge_request])
+        end
+        format.json do
+          render json: {
+            saved: @merge_request.valid?,
+            assignee_avatar_url: @merge_request.assignee.try(:avatar_url)
+          }
         end
       end
     else
@@ -114,15 +123,15 @@ class Projects::MergeRequestsController < Projects::ApplicationController
     if @merge_request.unchecked?
       @merge_request.check_if_can_be_merged
     end
-    render json: {merge_status: @merge_request.merge_status_name}
+
+    render json: { merge_status: @merge_request.merge_status_name }
   end
 
   def automerge
     return access_denied! unless allowed_to_merge?
 
     if @merge_request.open? && @merge_request.can_be_merged?
-      @merge_request.should_remove_source_branch = params[:should_remove_source_branch]
-      @merge_request.automerge!(current_user, params[:commit_message])
+      AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params)
       @status = true
     else
       @status = false
@@ -151,10 +160,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
 
   def ci_status
     ci_service = @merge_request.source_project.ci_service
-    status = ci_service.commit_status(merge_request.last_commit.sha)
+    status = ci_service.commit_status(merge_request.last_commit.sha, merge_request.source_branch)
 
     if ci_service.respond_to?(:commit_coverage)
-      coverage = ci_service.commit_coverage(merge_request.last_commit.sha)
+      coverage = ci_service.commit_coverage(merge_request.last_commit.sha, merge_request.source_branch)
     end
 
     response = {
@@ -165,6 +174,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController
     render json: response
   end
 
+  def toggle_subscription
+    @merge_request.toggle_subscription(current_user)
+    
+    render nothing: true
+  end
+
   protected
 
   def selected_target_project
@@ -225,6 +240,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
     @allowed_to_merge = allowed_to_merge?
     @show_merge_controls = @merge_request.open? && @commits.any? && @allowed_to_merge
     @source_branch = @merge_request.source_project.repository.find_branch(@merge_request.source_branch).try(:name)
+
+    if @merge_request.locked_long_ago?
+      @merge_request.unlock_mr
+      @merge_request.close
+    end
   end
 
   def allowed_to_merge?
@@ -237,13 +257,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
   end
 
   def allowed_to_push_code?(project, branch)
-    action = if project.protected_branch?(branch)
-               :push_code_to_protected_branches
-             else
-               :push_code
-             end
-
-    can?(current_user, action, project)
+    ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(branch)
   end
 
   def merge_request_params
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index d338cdedfaf234fd50d6c1e67b08dc695bd09a58..b49b549547ab149278935b942996f79eeacebaca 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -11,14 +11,14 @@ class Projects::MilestonesController < Projects::ApplicationController
   respond_to :html
 
   def index
-    @milestones = case params[:f]
+    @milestones = case params[:state]
                   when 'all'; @project.milestones.order("state, due_date DESC")
                   when 'closed'; @project.milestones.closed.order("due_date DESC")
                   else @project.milestones.active.order("due_date ASC")
                   end
 
     @milestones = @milestones.includes(:project)
-    @milestones = @milestones.page(params[:page]).per(20)
+    @milestones = @milestones.page(params[:page]).per(PER_PAGE)
   end
 
   def new
@@ -40,7 +40,8 @@ class Projects::MilestonesController < Projects::ApplicationController
     @milestone = Milestones::CreateService.new(project, current_user, milestone_params).execute
 
     if @milestone.save
-      redirect_to project_milestone_path(@project, @milestone)
+      redirect_to namespace_project_milestone_path(@project.namespace,
+                                                   @project, @milestone)
     else
       render "new"
     end
@@ -53,7 +54,8 @@ class Projects::MilestonesController < Projects::ApplicationController
       format.js
       format.html do
         if @milestone.valid?
-          redirect_to [@project, @milestone]
+          redirect_to namespace_project_milestone_path(@project.namespace,
+                                                   @project, @milestone)
         else
           render :edit
         end
@@ -67,7 +69,7 @@ class Projects::MilestonesController < Projects::ApplicationController
     @milestone.destroy
 
     respond_to do |format|
-      format.html { redirect_to project_milestones_path }
+      format.html { redirect_to namespace_project_milestones_path }
       format.js { render nothing: true }
     end
   end
@@ -103,7 +105,9 @@ class Projects::MilestonesController < Projects::ApplicationController
   end
 
   def module_enabled
-    return render_404 unless @project.issues_enabled
+    unless @project.issues_enabled || @project.merge_requests_enabled
+      return render_404
+    end
   end
 
   def milestone_params
diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb
index ada1aed0df789656da87ea3ae2e9e7419d524b9c..83d1c1dacae6d5c4afa83ef10bdf520c95c76d21 100644
--- a/app/controllers/projects/network_controller.rb
+++ b/app/controllers/projects/network_controller.rb
@@ -2,9 +2,9 @@ class Projects::NetworkController < Projects::ApplicationController
   include ExtractsPath
   include ApplicationHelper
 
-  # Authorize
-  before_filter :authorize_download_code!
   before_filter :require_non_empty_project
+  before_filter :assign_ref_vars
+  before_filter :authorize_download_code!
 
   def show
     respond_to do |format|
diff --git a/app/controllers/projects/new_tree_controller.rb b/app/controllers/projects/new_tree_controller.rb
index ffba706b2f665223dae58078bf5e45bf381210e3..09c53bb3b1b8372020b640348a118412050de7bf 100644
--- a/app/controllers/projects/new_tree_controller.rb
+++ b/app/controllers/projects/new_tree_controller.rb
@@ -6,15 +6,67 @@ class Projects::NewTreeController < Projects::BaseTreeController
   end
 
   def update
-    file_path = File.join(@path, File.basename(params[:file_name]))
-    result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
-
-    if result[:status] == :success
-      flash[:notice] = "Your changes have been successfully committed"
-      redirect_to project_blob_path(@project, File.join(@ref, file_path))
-    else
-      flash[:alert] = result[:message]
-      render :show
+	flag = 0
+	#replace & upload 
+	if params[:file_upload] != nil
+		#get the name of the upload file
+		file_na = params[:file_upload].original_filename
+		file_path = nil
+		
+	    if file_na != nil
+			file_list = tree.entries.select(&:file?)
+			dir_list = tree.entries.select(&:dir?)
+			
+			#check whether current path is sub-repository
+			dir_list.each do |dir|		
+				if dir.name != nil
+					flag = 1
+				end
+			end
+			
+			#check whether current path is sub-repository
+			file_list.each do |file|	
+				if file.name != nil
+					flag = 1
+				end
+			end
+			
+			if @path.match(/(.*\/)*(.+)\z/) != nil && flag == 0	#replace existing file
+				flag = 2
+				params[:content] = params[:file_upload].read
+				params[:file_name] = @path	
+				file_path = @path
+				result = Files::UploadService.new(@project, current_user, params, @ref, @path).execute
+			end
+				
+			if flag == 1 || flag == 0	#upload new file	
+				flag = 3
+				file_list.each do |file|				
+					if file.name == file_na
+						flash[:alert] = file.name + " already exists!"
+						redirect_to project_blob_path(@project, File.join(@ref, @path))
+						return 
+					end
+				end
+				params[:content] = params[:file_upload].read
+				params[:file_name] = file_na	
+				file_path = File.join(@path, File.basename(params[:file_name]))
+				result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
+			end
+		end
+	end 
+	
+	if flag == 0
+		file_path = File.join(@path, File.basename(params[:file_name]))
+		result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
+	end
+	
+    	if result[:status] == :success
+		flash[:notice] = "Your changes have been successfully commited."		
+		redirect_to project_blob_path(@project, File.join(@ref, file_path))
+	else
+		flash[:alert] = result[:message]
+		render :show
     end
   end
 end
diff --git a/app/controllers/projects/new_tree_controller.rb.orig b/app/controllers/projects/new_tree_controller.rb.orig
new file mode 100644
index 0000000000000000000000000000000000000000..aae0502ab8d420341ff6a336dbe7ed1ee83019c6
--- /dev/null
+++ b/app/controllers/projects/new_tree_controller.rb.orig
@@ -0,0 +1,119 @@
+class Projects::NewTreeController < Projects::BaseTreeController
+  before_filter :require_branch_head
+  before_filter :authorize_push_code!
+
+  def show
+  end
+
+  def update
+<<<<<<< HEAD
+	flag = 0
+	#replace & upload 
+	if params[:file_upload] != nil
+		#get the name of the upload file
+		file_na = params[:file_upload].original_filename
+		file_path = nil
+=======
+	flag=0
+	#replace & upload 
+	if params[:file_upload] != nil
+		#get the name of the upload file
+		file_na=params[:file_upload].original_filename
+		file_path=nil
+>>>>>>> 7ac8341... Update new_tree_controller.rb
+		
+	    if file_na != nil
+			file_list = tree.entries.select(&:file?)
+			dir_list = tree.entries.select(&:dir?)
+			
+<<<<<<< HEAD
+			#check whether current path is sub-repository
+			dir_list.each do |dir|		
+				if dir.name != nil
+					flag = 1
+				end
+			end
+			
+			#check whether current path is sub-repository
+			file_list.each do |file|	
+				if file.name != nil
+					flag = 1
+				end
+			end
+			
+			if @path.match(/(.*\/)*(.+)\z/) != nil && flag == 0	#replace existing file
+				flag = 2
+				params[:content] = params[:file_upload].read
+				params[:file_name] = @path	
+				file_path = @path
+				result = Files::UploadService.new(@project, current_user, params, @ref, @path).execute
+			end
+				
+			if flag == 1 || flag == 0	#upload new file	
+				flag = 3
+=======
+			dir_list.each do |dir|		#check whether current path is sub-repository
+				if dir.name != nil
+					flag=1
+				end
+			end
+			
+			file_list.each do |file|	#check whether current path is sub-repository
+				if file.name != nil
+					flag=1
+				end
+			end
+			
+			if @path.match(/(.*\/)*(.+)\z/) != nil && flag==0	#replace existing file
+				flag=2
+				params[:content]=params[:file_upload].read
+				params[:file_name]=@path	
+				file_path=@path
+				result=Files::UploadService.new(@project, current_user, params, @ref, @path).execute
+			end
+				
+			if flag==1 || flag==0	#upload new file	
+				flag=3
+>>>>>>> 7ac8341... Update new_tree_controller.rb
+				file_list.each do |file|				
+					if file.name == file_na
+						flash[:alert] = file.name + " already exists!"
+						redirect_to project_blob_path(@project, File.join(@ref, @path))
+						return 
+					end
+				end
+<<<<<<< HEAD
+				params[:content] = params[:file_upload].read
+				params[:file_name] = file_na	
+=======
+				params[:content]=params[:file_upload].read
+				params[:file_name]=file_na	
+>>>>>>> 7ac8341... Update new_tree_controller.rb
+				file_path = File.join(@path, File.basename(params[:file_name]))
+				result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
+			end
+		end
+	end 
+	
+<<<<<<< HEAD
+	if flag == 0
+=======
+	if flag==0
+>>>>>>> 7ac8341... Update new_tree_controller.rb
+		file_path = File.join(@path, File.basename(params[:file_name]))
+		result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
+	end
+	
+<<<<<<< HEAD
+    	if result[:status] == :success
+=======
+    if result[:status] == :success
+>>>>>>> 7ac8341... Update new_tree_controller.rb
+		flash[:notice] = "Your changes have been successfully commited."		
+		redirect_to project_blob_path(@project, File.join(@ref, file_path))
+	else
+		flash[:alert] = result[:message]
+		render :show
+    end
+  end
+end
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index 7b08b79d236ef1a4061a3adf5409ba049ebb4fe5..868629a0bc4aee1f33e7e55cc154dda8efe4217c 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -3,10 +3,10 @@ class Projects::NotesController < Projects::ApplicationController
   before_filter :authorize_read_note!
   before_filter :authorize_write_note!, only: [:create]
   before_filter :authorize_admin_note!, only: [:update, :destroy]
+  before_filter :find_current_user_notes, except: [:destroy, :delete_attachment]
 
   def index
     current_fetched_at = Time.now.to_i
-    @notes = NotesFinder.new.execute(project, current_user, params)
 
     notes_json = { notes: [], last_fetched_at: current_fetched_at }
 
@@ -61,10 +61,6 @@ class Projects::NotesController < Projects::ApplicationController
     end
   end
 
-  def preview
-    render text: view_context.markdown(params[:note])
-  end
-
   private
 
   def note
@@ -120,4 +116,10 @@ class Projects::NotesController < Projects::ApplicationController
       :attachment, :line_code, :commit_id
     )
   end
+
+  private
+
+  def find_current_user_notes
+    @notes = NotesFinder.new.execute(project, current_user, params)
+  end
 end
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4ab15db01f7cec123564b3e43acc7b2bafaa98f6
--- /dev/null
+++ b/app/controllers/projects/project_members_controller.rb
@@ -0,0 +1,88 @@
+class Projects::ProjectMembersController < Projects::ApplicationController
+  # Authorize
+  before_filter :authorize_admin_project!, except: :leave
+
+  layout "project_settings"
+
+  def index
+    @project_members = @project.project_members
+
+    if params[:search].present?
+      users = @project.users.search(params[:search]).to_a
+      @project_members = @project_members.where(user_id: users)
+    end
+
+    @project_members = @project_members.order('access_level DESC')
+
+    @group = @project.group
+    if @group
+      @group_members = @group.group_members
+
+      if params[:search].present?
+        users = @group.users.search(params[:search]).to_a
+        @group_members = @group_members.where(user_id: users)
+      end
+      
+      @group_members = @group_members.order('access_level DESC').limit(20)
+    end
+
+    @project_member = @project.project_members.new
+  end
+
+  def new
+    @project_member = @project.project_members.new
+  end
+
+  def create
+    users = User.where(id: params[:user_ids].split(','))
+    @project.team << [users, params[:access_level]]
+
+    redirect_to namespace_project_project_members_path(@project.namespace, @project)
+  end
+
+  def update
+    @project_member = @project.project_members.find_by(user_id: member)
+    @project_member.update_attributes(member_params)
+  end
+
+  def destroy
+    @project_member = @project.project_members.find_by(user_id: member)
+    @project_member.destroy
+
+    respond_to do |format|
+      format.html do
+        redirect_to namespace_project_project_members_path(@project.namespace,
+                                                      @project)
+      end
+      format.js { render nothing: true }
+    end
+  end
+
+  def leave
+    @project.project_members.find_by(user_id: current_user).destroy
+
+    respond_to do |format|
+      format.html { redirect_to :back }
+      format.js { render nothing: true }
+    end
+  end
+
+  def apply_import
+    giver = Project.find(params[:source_project_id])
+    status = @project.team.import(giver)
+    notice = status ? "Successfully imported" : "Import failed"
+
+    redirect_to(namespace_project_project_members_path(project.namespace, project),
+                notice: notice)
+  end
+
+  protected
+
+  def member
+    @member ||= User.find_by(username: params[:id])
+  end
+
+  def member_params
+    params.require(:project_member).permit(:user_id, :access_level)
+  end
+end
diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb
index bd31b1d3c546df052e13deb31b9cea9c0f312da5..ac36ac6fcd3902470c175f6310132f53856f25dd 100644
--- a/app/controllers/projects/protected_branches_controller.rb
+++ b/app/controllers/projects/protected_branches_controller.rb
@@ -12,14 +12,33 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
 
   def create
     @project.protected_branches.create(protected_branch_params)
-    redirect_to project_protected_branches_path(@project)
+    redirect_to namespace_project_protected_branches_path(@project.namespace,
+                                                          @project)
+  end
+
+  def update
+    protected_branch = @project.protected_branches.find(params[:id])
+
+    if protected_branch &&
+       protected_branch.update_attributes(
+        developers_can_push: params[:developers_can_push]
+       )
+
+      respond_to do |format|
+        format.json { render json: protected_branch, status: :ok }
+      end
+    else
+      respond_to do |format|
+        format.json { render json: protected_branch.errors, status: :unprocessable_entity }
+      end
+    end
   end
 
   def destroy
     @project.protected_branches.find(params[:id]).destroy
 
     respond_to do |format|
-      format.html { redirect_to project_protected_branches_path }
+      format.html { redirect_to namespace_project_protected_branches_path }
       format.js { render nothing: true }
     end
   end
@@ -27,6 +46,6 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
   private
 
   def protected_branch_params
-    params.require(:protected_branch).permit(:name)
+    params.require(:protected_branch).permit(:name, :developers_can_push)
   end
 end
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index fdbc4c5a0984adb48193779ff3c56121e5a1ea75..b1a029ce69618c432c75ee6585d38c5242eb13d0 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -2,9 +2,9 @@
 class Projects::RawController < Projects::ApplicationController
   include ExtractsPath
 
-  # Authorize
-  before_filter :authorize_download_code!
   before_filter :require_non_empty_project
+  before_filter :assign_ref_vars
+  before_filter :authorize_download_code!
 
   def show
     @blob = @repository.blob_at(@commit.id, @path)
@@ -35,4 +35,3 @@ class Projects::RawController < Projects::ApplicationController
     end
   end
 end
-
diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb
index 5d9336bdc49b774782c307a8ab38f3d7886f5ce5..67acf45ab7f8d0429b22a7bbcd2fd774cfcce843 100644
--- a/app/controllers/projects/refs_controller.rb
+++ b/app/controllers/projects/refs_controller.rb
@@ -1,21 +1,23 @@
 class Projects::RefsController < Projects::ApplicationController
   include ExtractsPath
 
-  # Authorize
-  before_filter :authorize_download_code!
   before_filter :require_non_empty_project
+  before_filter :assign_ref_vars
+  before_filter :authorize_download_code!
 
   def switch
     respond_to do |format|
       format.html do
         new_path = if params[:destination] == "tree"
-                     project_tree_path(@project, (@id))
+                     namespace_project_tree_path(@project.namespace, @project,
+                                                 (@id))
                    elsif params[:destination] == "blob"
-                     project_blob_path(@project, (@id))
+                     namespace_project_blob_path(@project.namespace, @project,
+                                                 (@id))
                    elsif params[:destination] == "graph"
-                     project_network_path(@project, @id, @options)
+                     namespace_project_network_path(@project.namespace, @project, @id, @options)
                    else
-                     project_commits_path(@project, @id)
+                     namespace_project_commits_path(@project.namespace, @project, @id)
                    end
 
         redirect_to new_path
@@ -31,19 +33,19 @@ class Projects::RefsController < Projects::ApplicationController
 
   def logs_tree
     @offset = if params[:offset].present?
-             params[:offset].to_i
-           else
-             0
-           end
+                params[:offset].to_i
+              else
+                0
+              end
 
     @limit = 25
 
     @path = params[:path]
 
     contents = []
-    contents += tree.trees
-    contents += tree.blobs
-    contents += tree.submodules
+    contents.push(*tree.trees)
+    contents.push(*tree.blobs)
+    contents.push(*tree.submodules)
 
     @logs = contents[@offset, @limit].to_a.map do |content|
       file = @path ? File.join(@path, content.name) : content.name
diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb
index bcd14a1c847019f67405730a325c7c109557d6a1..cbb888b25e89e4b3ff1cfff41a07dcc608ab84ac 100644
--- a/app/controllers/projects/repositories_controller.rb
+++ b/app/controllers/projects/repositories_controller.rb
@@ -1,7 +1,14 @@
 class Projects::RepositoriesController < Projects::ApplicationController
   # Authorize
+  before_filter :require_non_empty_project, except: :create
   before_filter :authorize_download_code!
-  before_filter :require_non_empty_project
+  before_filter :authorize_admin_project!, only: :create
+
+  def create
+    @project.create_repository
+
+    redirect_to project_path(@project)
+  end
 
   def archive
     unless can?(current_user, :download_code, @project)
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index a5f30dcfd9d2a553a01323a65390ff74281be790..9a484c109baf9d449f5cbdf88ea9ec3240927eb0 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -9,7 +9,7 @@ class Projects::ServicesController < Projects::ApplicationController
 
   def index
     @project.build_missing_services
-    @services = @project.services.reload
+    @services = @project.services.visible.reload
   end
 
   def edit
@@ -17,18 +17,25 @@ class Projects::ServicesController < Projects::ApplicationController
 
   def update
     if @service.update_attributes(service_params)
-      redirect_to edit_project_service_path(@project, @service.to_param)
+      redirect_to(
+        edit_namespace_project_service_path(@project.namespace, @project,
+                                            @service.to_param, notice:
+                                            'Successfully updated.')
+      )
     else
       render 'edit'
     end
   end
 
   def test
-    data = GitPushService.new.sample_data(project, current_user)
-
-    @service.execute(data)
+    data = Gitlab::PushDataBuilder.build_sample(project, current_user)
+    if @service.execute(data)
+      message = { notice: 'We sent a request to the provided URL' }
+    else
+      message = { alert: 'We tried to send a request to the provided URL but an error occured' }
+    end
 
-    redirect_to :back
+    redirect_to :back, message
   end
 
   private
@@ -42,7 +49,11 @@ class Projects::ServicesController < Projects::ApplicationController
       :title, :token, :type, :active, :api_key, :subdomain,
       :room, :recipients, :project_url, :webhook,
       :user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
-      :build_key
+      :build_key, :server, :teamcity_url, :build_type,
+      :description, :issues_url, :new_issue_url, :restrict_to_branch, :channel,
+      :colorize_messages, :channels,
+      :push_events, :issues_events, :merge_requests_events, :tag_push_events,
+      :note_events, :send_from_committer_email, :disable_diffs, :external_wiki_url
     )
   end
 end
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index 9d5dd8a95cc044aa86ca2d0ce52353ae04cfe828..ed26840037360227877ddaa92fc275520f00ede8 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -28,25 +28,22 @@ class Projects::SnippetsController < Projects::ApplicationController
   end
 
   def create
-    @snippet = @project.snippets.build(snippet_params)
-    @snippet.author = current_user
-
-    if @snippet.save
-      redirect_to project_snippet_path(@project, @snippet)
-    else
-      respond_with(@snippet)
-    end
+    @snippet = CreateSnippetService.new(@project, current_user,
+                                        snippet_params).execute
+    respond_with(@snippet,
+                 location: namespace_project_snippet_path(@project.namespace,
+                                                          @project, @snippet))
   end
 
   def edit
   end
 
   def update
-    if @snippet.update_attributes(snippet_params)
-      redirect_to project_snippet_path(@project, @snippet)
-    else
-      respond_with(@snippet)
-    end
+    UpdateSnippetService.new(project, current_user, @snippet,
+                             snippet_params).execute
+    respond_with(@snippet,
+                 location: namespace_project_snippet_path(@project.namespace,
+                                                          @project, @snippet))
   end
 
   def show
@@ -60,7 +57,7 @@ class Projects::SnippetsController < Projects::ApplicationController
 
     @snippet.destroy
 
-    redirect_to project_snippets_path(@project)
+    redirect_to namespace_project_snippets_path(@project.namespace, @project)
   end
 
   def raw
@@ -68,7 +65,7 @@ class Projects::SnippetsController < Projects::ApplicationController
       @snippet.content,
       type: 'text/plain; charset=utf-8',
       disposition: 'inline',
-      filename: @snippet.file_name
+      filename: @snippet.sanitized_file_name
     )
   end
 
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index 162ddef0fec47239ad4c49a929e25f16ac1c4dd0..83f4937bce36838f944b786684e014cfff440f3e 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -7,15 +7,16 @@ class Projects::TagsController < Projects::ApplicationController
 
   def index
     sorted = VersionSorter.rsort(@repository.tag_names)
-    @tags = Kaminari.paginate_array(sorted).page(params[:page]).per(30)
+    @tags = Kaminari.paginate_array(sorted).page(params[:page]).per(PER_PAGE)
   end
 
   def create
     result = CreateTagService.new(@project, current_user).
       execute(params[:tag_name], params[:ref], params[:message])
+
     if result[:status] == :success
       @tag = result[:tag]
-      redirect_to project_tags_path(@project)
+      redirect_to namespace_project_tags_path(@project.namespace, @project)
     else
       @error = result[:message]
       render action: 'new'
@@ -23,14 +24,13 @@ class Projects::TagsController < Projects::ApplicationController
   end
 
   def destroy
-    tag = @repository.find_tag(params[:id])
-
-    if tag && @repository.rm_tag(tag.name)
-      Event.create_ref_event(@project, current_user, tag, 'rm', 'refs/tags')
-    end
+    DeleteTagService.new(project, current_user).execute(params[:id])
 
     respond_to do |format|
-      format.html { redirect_to project_tags_path }
+      format.html do
+        redirect_to namespace_project_tags_path(@project.namespace,
+                                                @project)
+      end
       format.js
     end
   end
diff --git a/app/controllers/projects/team_members_controller.rb b/app/controllers/projects/team_members_controller.rb
deleted file mode 100644
index 0791e6080fb4f6da4764afd1e3a40c904aca3f65..0000000000000000000000000000000000000000
--- a/app/controllers/projects/team_members_controller.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-class Projects::TeamMembersController < Projects::ApplicationController
-  # Authorize
-  before_filter :authorize_admin_project!, except: :leave
-
-  layout "project_settings"
-
-  def index
-    @group = @project.group
-    @project_members = @project.project_members.order('access_level DESC')
-  end
-
-  def new
-    @user_project_relation = @project.project_members.new
-  end
-
-  def create
-    users = User.where(id: params[:user_ids].split(','))
-
-    @project.team << [users, params[:access_level]]
-
-    if params[:redirect_to]
-      redirect_to params[:redirect_to]
-    else
-      redirect_to project_team_index_path(@project)
-    end
-  end
-
-  def update
-    @user_project_relation = @project.project_members.find_by(user_id: member)
-    @user_project_relation.update_attributes(member_params)
-
-    unless @user_project_relation.valid?
-      flash[:alert] = "User should have at least one role"
-    end
-    redirect_to project_team_index_path(@project)
-  end
-
-  def destroy
-    @user_project_relation = @project.project_members.find_by(user_id: member)
-    @user_project_relation.destroy
-
-    respond_to do |format|
-      format.html { redirect_to project_team_index_path(@project) }
-      format.js { render nothing: true }
-    end
-  end
-
-  def leave
-    @project.project_members.find_by(user_id: current_user).destroy
-
-    respond_to do |format|
-      format.html { redirect_to :back }
-      format.js { render nothing: true }
-    end
-  end
-
-  def apply_import
-    giver = Project.find(params[:source_project_id])
-    status = @project.team.import(giver)
-    notice = status ? "Successfully imported" : "Import failed"
-
-    redirect_to project_team_index_path(project), notice: notice
-  end
-
-  protected
-
-  def member
-    @member ||= User.find_by(username: params[:id])
-  end
-
-  def member_params
-    params.require(:project_member).permit(:user_id, :access_level)
-  end
-end
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index 4d033b368482ccda9a083686107e816fad732692..b23010bf59546dd664002c89c74789b466d10f3b 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -1,10 +1,18 @@
 # Controller for viewing a repository's file structure
-class Projects::TreeController < Projects::BaseTreeController
-  def show
+class Projects::TreeController < Projects::ApplicationController
+  include ExtractsPath
+
+  before_filter :require_non_empty_project, except: [:new, :create]
+  before_filter :assign_ref_vars
+  before_filter :authorize_download_code!
 
+  def show
     if tree.entries.empty?
       if @repository.blob_at(@commit.id, @path)
-        redirect_to project_blob_path(@project, File.join(@ref, @path)) and return
+        redirect_to(
+          namespace_project_blob_path(@project.namespace, @project,
+                                      File.join(@ref, @path))
+        ) and return
       else
         return not_found!
       end
diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9020e86c44e95903bd43214fa72951c5f9e2d9b2
--- /dev/null
+++ b/app/controllers/projects/uploads_controller.rb
@@ -0,0 +1,35 @@
+class Projects::UploadsController < Projects::ApplicationController
+  layout 'project'
+
+  before_filter :project
+
+  def create
+    link_to_file = ::Projects::UploadService.new(project, params[:file]).
+      execute
+
+    respond_to do |format|
+      if link_to_file
+        format.json do
+          render json: { link: link_to_file }
+        end
+      else
+        format.json do
+          render json: 'Invalid file.', status: :unprocessable_entity
+        end
+      end
+    end
+  end
+
+  def show
+    uploader = FileUploader.new(project, params[:secret])
+
+    return redirect_to uploader.url unless uploader.file_storage?
+
+    uploader.retrieve_from_store!(params[:filename])
+
+    return not_found! unless uploader.file.exists?
+
+    disposition = uploader.image? ? 'inline' : 'attachment'
+    send_file uploader.file.path, disposition: disposition
+  end
+end
diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb
index 0e03956e7382bf24bb402e38a4cd0e3b6b43aeb0..643167947b9f195f9a9b8393915619c2e3bd8345 100644
--- a/app/controllers/projects/wikis_controller.rb
+++ b/app/controllers/projects/wikis_controller.rb
@@ -7,7 +7,7 @@ class Projects::WikisController < Projects::ApplicationController
   before_filter :load_project_wiki
 
   def pages
-    @wiki_pages = Kaminari.paginate_array(@project_wiki.pages).page(params[:page]).per(30)
+    @wiki_pages = Kaminari.paginate_array(@project_wiki.pages).page(params[:page]).per(PER_PAGE)
   end
 
   def show
@@ -16,16 +16,16 @@ class Projects::WikisController < Projects::ApplicationController
     if @page
       render 'show'
     elsif file = @project_wiki.find_file(params[:id], params[:version_id])
-       if file.on_disk?
-         send_file file.on_disk_path, disposition: 'inline'
-       else
-         send_data(
-           file.raw_data,
-           type: file.mime_type,
-           disposition: 'inline',
-           filename: file.name
-         )
-       end
+      if file.on_disk?
+        send_file file.on_disk_path, disposition: 'inline'
+      else
+        send_data(
+          file.raw_data,
+          type: file.mime_type,
+          disposition: 'inline',
+          filename: file.name
+        )
+      end
     else
       return render('empty') unless can?(current_user, :write_wiki, @project)
       @page = WikiPage.new(@project_wiki)
@@ -45,7 +45,7 @@ class Projects::WikisController < Projects::ApplicationController
     return render('empty') unless can?(current_user, :write_wiki, @project)
 
     if @page.update(content, format, message)
-      redirect_to [@project, @page], notice: 'Wiki was successfully updated.'
+      redirect_to [@project.namespace.becomes(Namespace), @project, @page], notice: 'Wiki was successfully updated.'
     else
       render 'edit'
     end
@@ -55,7 +55,10 @@ class Projects::WikisController < Projects::ApplicationController
     @page = WikiPage.new(@project_wiki)
 
     if @page.create(wiki_params)
-      redirect_to project_wiki_path(@project, @page), notice: 'Wiki was successfully updated.'
+      redirect_to(
+        namespace_project_wiki_path(@project.namespace, @project, @page),
+        notice: 'Wiki was successfully updated.'
+      )
     else
       render action: "edit"
     end
@@ -65,7 +68,10 @@ class Projects::WikisController < Projects::ApplicationController
     @page = @project_wiki.find_page(params[:id])
 
     unless @page
-      redirect_to(project_wiki_path(@project, :home), notice: "Page not found")
+      redirect_to(
+        namespace_project_wiki_path(@project.namespace, @project, :home),
+        notice: "Page not found"
+      )
     end
   end
 
@@ -73,7 +79,10 @@ class Projects::WikisController < Projects::ApplicationController
     @page = @project_wiki.find_page(params[:id])
     @page.delete if @page
 
-    redirect_to project_wiki_path(@project, :home), notice: "Page was successfully deleted"
+    redirect_to(
+      namespace_project_wiki_path(@project.namespace, @project, :home),
+      notice: "Page was successfully deleted"
+    )
   end
 
   def git_access
@@ -88,7 +97,7 @@ class Projects::WikisController < Projects::ApplicationController
     @project_wiki.wiki
   rescue ProjectWiki::CouldNotCreateWikiError => ex
     flash[:notice] = "Could not create Wiki Repository at this time. Please try again later."
-    redirect_to @project
+    redirect_to project_path(@project)
     return false
   end
 
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index b5910c902e49fc87bb978a99eb47fe21fb3ea53c..0f28794b736e66a6c10b6f1f706beffeacb6bd9e 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,28 +1,34 @@
 class ProjectsController < ApplicationController
+  prepend_before_filter :render_go_import, only: [:show]
   skip_before_filter :authenticate_user!, only: [:show]
   before_filter :project, except: [:new, :create]
   before_filter :repository, except: [:new, :create]
 
   # Authorize
-  before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive, :retry_import]
+  before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive]
+  before_filter :set_title, only: [:new, :create]
+  before_filter :event_filter, only: :show
 
   layout 'navless', only: [:new, :create, :fork]
-  before_filter :set_title, only: [:new, :create]
 
   def new
     @project = Project.new
   end
 
   def edit
-    render 'edit', layout: "project_settings"
+    render 'edit', layout: 'project_settings'
   end
 
   def create
     @project = ::Projects::CreateService.new(current_user, project_params).execute
-    flash[:notice] = 'Project was successfully created.' if @project.saved?
 
-    respond_to do |format|
-      format.js
+    if @project.saved?
+      redirect_to(
+        project_path(@project),
+        notice: 'Project was successfully created.'
+      )
+    else
+      render 'new'
     end
   end
 
@@ -32,65 +38,59 @@ class ProjectsController < ApplicationController
     respond_to do |format|
       if status
         flash[:notice] = 'Project was successfully updated.'
-        format.html { redirect_to edit_project_path(@project), notice: 'Project was successfully updated.' }
+        format.html do
+          redirect_to(
+            edit_project_path(@project),
+            notice: 'Project was successfully updated.'
+          )
+        end
         format.js
       else
-        format.html { render "edit", layout: "project_settings" }
+        format.html { render 'edit', layout: 'project_settings' }
         format.js
       end
     end
   end
 
   def transfer
-    ::Projects::TransferService.new(project, current_user, project_params).execute
+    transfer_params = params.permit(:new_namespace_id)
+    ::Projects::TransferService.new(project, current_user, transfer_params).execute
+    if @project.errors[:namespace_id].present?
+      flash[:alert] = @project.errors[:namespace_id].first
+    end
   end
 
   def show
     if @project.import_in_progress?
-      redirect_to import_project_path(@project)
+      redirect_to namespace_project_import_path(@project.namespace, @project)
       return
     end
 
     limit = (params[:limit] || 20).to_i
-    @events = @project.events.recent
-    @events = event_filter.apply_filter(@events)
-    @events = @events.limit(limit).offset(params[:offset] || 0)
 
     @show_star = !(current_user && current_user.starred?(@project))
 
     respond_to do |format|
       format.html do
-        if @project.empty_repo?
-          render "projects/empty", layout: user_layout
+        if @project.repository_exists?
+          if @project.empty_repo?
+            render 'projects/empty', layout: user_layout
+          else
+            @last_push = current_user.recent_push(@project.id) if current_user
+            render :show, layout: user_layout
+          end
         else
-          @last_push = current_user.recent_push(@project.id) if current_user
-          render :show, layout: user_layout
+          render 'projects/no_repo', layout: user_layout
         end
       end
-      format.json { pager_json("events/_events", @events.count) }
-    end
-  end
-
-  def import
-    if @project.import_finished?
-      redirect_to @project
-      return
-    end
-  end
 
-  def retry_import
-    unless @project.import_failed?
-      redirect_to import_project_path(@project)
-    end
-
-    @project.import_url = project_params[:import_url]
-
-    if @project.save
-      @project.reload
-      @project.import_retry
+      format.json do
+        @events = @project.events.recent
+        @events = event_filter.apply_filter(@events).with_associations
+        @events = @events.limit(limit).offset(params[:offset] || 0)
+        pager_json('events/_events', @events.count)
+      end
     end
-
-    redirect_to import_project_path(@project)
   end
 
   def destroy
@@ -100,46 +100,32 @@ class ProjectsController < ApplicationController
 
     respond_to do |format|
       format.html do
-        flash[:alert] = "Project deleted."
+        flash[:alert] = 'Project deleted.'
 
-        if request.referer.include?("/admin")
-          redirect_to admin_projects_path
+        if request.referer.include?('/admin')
+          redirect_to admin_namespaces_projects_path
         else
-          redirect_to projects_dashboard_path
+          redirect_to dashboard_path
         end
       end
     end
   end
 
-  def fork
-    @forked_project = ::Projects::ForkService.new(project, current_user).execute
-
-    respond_to do |format|
-      format.html do
-        if @forked_project.saved? && @forked_project.forked?
-          redirect_to(@forked_project, notice: 'Project was successfully forked.')
-        else
-          @title = 'Fork project'
-          render "fork"
-        end
-      end
-      format.js
-    end
-  end
-
   def autocomplete_sources
     note_type = params['type']
     note_id = params['type_id']
-    participants = ::Projects::ParticipantsService.new(@project).execute(note_type, note_id)
+    autocomplete = ::Projects::AutocompleteService.new(@project)
+    participants = ::Projects::ParticipantsService.new(@project, current_user).execute(note_type, note_id)
+
     @suggestions = {
-      emojis: Emoji.names.map { |e| { name: e, path: view_context.image_url("emoji/#{e}.png") } },
-      issues: @project.issues.select([:iid, :title, :description]),
-      mergerequests: @project.merge_requests.select([:iid, :title, :description]),
+      emojis: autocomplete_emojis,
+      issues: autocomplete.issues,
+      mergerequests: autocomplete.merge_requests,
       members: participants
     }
 
     respond_to do |format|
-      format.json { render :json => @suggestions }
+      format.json { render json: @suggestions }
     end
   end
 
@@ -148,7 +134,7 @@ class ProjectsController < ApplicationController
     @project.archive!
 
     respond_to do |format|
-      format.html { redirect_to @project }
+      format.html { redirect_to project_path(@project) }
     end
   end
 
@@ -157,19 +143,7 @@ class ProjectsController < ApplicationController
     @project.unarchive!
 
     respond_to do |format|
-      format.html { redirect_to @project }
-    end
-  end
-
-  def upload_image
-    link_to_image = ::Projects::ImageService.new(repository, params, root_url).execute
-
-    respond_to do |format|
-      if link_to_image
-        format.json { render json: { link: link_to_image } }
-      else
-        format.json { render json: "Invalid file.", status: :unprocessable_entity }
-      end
+      format.html { redirect_to project_path(@project) }
     end
   end
 
@@ -179,30 +153,46 @@ class ProjectsController < ApplicationController
     render json: { star_count: @project.star_count }
   end
 
-  private
-
-  def upload_path
-    base_dir = FileUploader.generate_dir
-    File.join(repository.path_with_namespace, base_dir)
+  def markdown_preview
+    render text: view_context.markdown(params[:md_text])
   end
 
-  def accepted_images
-    %w(png jpg jpeg gif)
-  end
+  private
 
   def set_title
     @title = 'New Project'
   end
 
   def user_layout
-    current_user ? "projects" : "public_projects"
+    current_user ? 'projects' : 'public_projects'
   end
 
   def project_params
     params.require(:project).permit(
       :name, :path, :description, :issues_tracker, :tag_list,
       :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch,
-      :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id
+      :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar
     )
   end
+
+  def autocomplete_emojis
+    Rails.cache.fetch("autocomplete-emoji-#{Gemojione::VERSION}") do
+      Emoji.emojis.map do |name, emoji|
+        {
+          name: name,
+          path: view_context.image_url("emoji/#{emoji["unicode"]}.png")
+        }
+      end
+    end
+  end
+
+  def render_go_import
+    return unless params["go-get"] == "1"
+
+    @namespace = params[:namespace_id]
+    @id = params[:project_id] || params[:id]
+    @id = @id.gsub(/\.git\Z/, "")
+
+    render "go_import", layout: false
+  end
 end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 6d3214b70a8b1ffb74474b4d6a652745d357ba89..38d116a4ee3595bdedee46370726c7300dfa37d9 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -1,6 +1,10 @@
 class RegistrationsController < Devise::RegistrationsController
   before_filter :signup_enabled?
 
+  def new
+    redirect_to(new_user_session_path)
+  end
+
   def destroy
     current_user.destroy
 
@@ -15,18 +19,20 @@ class RegistrationsController < Devise::RegistrationsController
     super
   end
 
-  def after_sign_up_path_for(resource)
+  def after_sign_up_path_for(_resource)
     new_user_session_path
   end
 
-  def after_inactive_sign_up_path_for(resource)
+  def after_inactive_sign_up_path_for(_resource)
     new_user_session_path
   end
 
   private
 
   def signup_enabled?
-    redirect_to new_user_session_path unless Gitlab.config.gitlab.signup_enabled
+    unless current_application_settings.signup_enabled?
+      redirect_to(new_user_session_path)
+    end
   end
 
   def sign_up_params
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 55926a1ed229e9187b75206cf24cc6eefd06c937..a3284c82d3f1fcc1a60b62ca28e9b2577d53382a 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -2,34 +2,34 @@ class SearchController < ApplicationController
   include SearchHelper
 
   def show
+    return if params[:search].nil? || params[:search].blank?
     @project = Project.find_by(id: params[:project_id]) if params[:project_id].present?
     @group = Group.find_by(id: params[:group_id]) if params[:group_id].present?
     @scope = params[:scope]
     @show_snippets = params[:snippets].eql? 'true'
 
-    @search_results = if @project
-                        return access_denied! unless can?(current_user, :download_code, @project)
-
-                        unless %w(blobs notes issues merge_requests wiki_blobs).
-                                 include?(@scope)
-                          @scope = 'blobs'
-                        end
-
-                        Search::ProjectService.new(@project, current_user, params).execute
-                      elsif @show_snippets
-                        unless %w(snippet_blobs snippet_titles).include?(@scope)
-                          @scope = 'snippet_blobs'
-                        end
-
-                        Search::SnippetService.new(current_user, params).execute
-                      else
-                        unless %w(projects issues merge_requests).include?(@scope)
-                          @scope = 'projects'
-                        end
-
-                        Search::GlobalService.new(current_user, params).execute
-                      end
-
+    @search_results = 
+      if @project
+        return access_denied! unless can?(current_user, :download_code, @project)
+
+        unless %w(blobs notes issues merge_requests wiki_blobs).
+          include?(@scope)
+          @scope = 'blobs'
+        end
+
+        Search::ProjectService.new(@project, current_user, params).execute
+      elsif @show_snippets
+        unless %w(snippet_blobs snippet_titles).include?(@scope)
+          @scope = 'snippet_blobs'
+        end
+
+        Search::SnippetService.new(current_user, params).execute
+      else
+        unless %w(projects issues merge_requests).include?(@scope)
+          @scope = 'projects'
+        end
+        Search::GlobalService.new(current_user, params).execute
+      end
     @objects = @search_results.objects(@scope, params[:page])
   end
 
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 5ced98152a526e1e53bfddfb0c6dd810690add17..7b6982c50743b695c7507b6ea3faacae287531a3 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -1,16 +1,16 @@
 class SessionsController < Devise::SessionsController
-
   def new
-    redirect_path = if request.referer.present? && (params['redirect_to_referer'] == 'yes')
-                     referer_uri = URI(request.referer)
-                     if referer_uri.host == Gitlab.config.gitlab.host
-                       referer_uri.path
-                     else
-                       request.fullpath
-                     end
-                   else
-                     request.fullpath
-                   end
+    redirect_path =
+      if request.referer.present? && (params['redirect_to_referer'] == 'yes')
+        referer_uri = URI(request.referer)
+        if referer_uri.host == Gitlab.config.gitlab.host
+          referer_uri.path
+        else
+          request.fullpath
+        end
+      else
+        request.fullpath
+      end
 
     # Prevent a 'you are already signed in' message directly after signing:
     # we should never redirect to '/users/sign_in' after signing in successfully.
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index bf3312fedc8e8367134ba8e5b5f6c6576478965f..cd52556b20385f00049f92bc4770fd366d550dd2 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -16,7 +16,7 @@ class SnippetsController < ApplicationController
   layout :determine_layout
 
   def index
-    @snippets = SnippetsFinder.new.execute(current_user, filter: :all).page(params[:page]).per(20)
+    @snippets = SnippetsFinder.new.execute(current_user, filter: :all).page(params[:page]).per(PER_PAGE)
   end
 
   def user_index
@@ -27,8 +27,8 @@ class SnippetsController < ApplicationController
     @snippets = SnippetsFinder.new.execute(current_user, {
       filter: :by_user,
       user: @user,
-      scope: params[:scope]}).
-    page(params[:page]).per(20)
+      scope: params[:scope] }).
+    page(params[:page]).per(PER_PAGE)
 
     if @user == current_user
       render 'current_user_index'
@@ -42,25 +42,19 @@ class SnippetsController < ApplicationController
   end
 
   def create
-    @snippet = PersonalSnippet.new(snippet_params)
-    @snippet.author = current_user
+    @snippet = CreateSnippetService.new(nil, current_user,
+                                        snippet_params).execute
 
-    if @snippet.save
-      redirect_to snippet_path(@snippet)
-    else
-      respond_with @snippet
-    end
+    respond_with @snippet.becomes(Snippet)
   end
 
   def edit
   end
 
   def update
-    if @snippet.update_attributes(snippet_params)
-      redirect_to snippet_path(@snippet)
-    else
-      respond_with @snippet
-    end
+    UpdateSnippetService.new(nil, current_user, @snippet,
+                             snippet_params).execute
+    respond_with @snippet.becomes(Snippet)
   end
 
   def show
@@ -79,7 +73,7 @@ class SnippetsController < ApplicationController
       @snippet.content,
       type: 'text/plain; charset=utf-8',
       disposition: 'inline',
-      filename: @snippet.file_name
+      filename: @snippet.sanitized_file_name
     )
   end
 
@@ -106,6 +100,7 @@ class SnippetsController < ApplicationController
 
   def set_title
     @title = 'Snippets'
+    @title_url = snippets_path
   end
 
   def snippet_params
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c5f3da54ea23b63338585b4242fdac5f32463cd0
--- /dev/null
+++ b/app/controllers/uploads_controller.rb
@@ -0,0 +1,71 @@
+class UploadsController < ApplicationController
+  skip_before_filter :authenticate_user!
+  before_filter :find_model, :authorize_access!
+
+  def show
+    uploader = @model.send(upload_mount)
+
+    unless uploader.file_storage?
+      return redirect_to uploader.url
+    end
+
+    unless uploader.file && uploader.file.exists?
+      return not_found!
+    end
+
+    disposition = uploader.image? ? 'inline' : 'attachment'
+    send_file uploader.file.path, disposition: disposition
+  end
+
+  private
+
+  def find_model
+    unless upload_model && upload_mount
+      return not_found!
+    end
+
+    @model = upload_model.find(params[:id])
+  end
+
+  def authorize_access!
+    authorized = 
+      case @model
+      when Project
+        can?(current_user, :read_project, @model)
+      when Group
+        can?(current_user, :read_group, @model)
+      when Note
+        can?(current_user, :read_project, @model.project)
+      else
+        # No authentication required for user avatars.
+        true
+      end
+
+    return if authorized
+
+    if current_user
+      not_found!
+    else
+      authenticate_user!
+    end
+  end
+
+  def upload_model
+    upload_models = {
+      user: User,
+      project: Project,
+      note: Note,
+      group: Group
+    }
+
+    upload_models[params[:model].to_sym]
+  end
+
+  def upload_mount
+    upload_mounts = %w(avatar attachment file)
+
+    if upload_mounts.include?(params[:mounted_as])
+      params[:mounted_as]
+    end
+  end
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 0b442f5383a2ed8f9f0b4d48841d08cee15be404..679d6897ce97a38db06b7578387b431f6731c522 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1,28 +1,54 @@
 class UsersController < ApplicationController
-  skip_before_filter :authenticate_user!, only: [:show]
+  skip_before_filter :authenticate_user!
+  before_filter :set_user
   layout :determine_layout
 
   def show
-    @user = User.find_by_username!(params[:username])
-
-    unless current_user || @user.public_profile?
-      return authenticate_user!
-    end
-
-    # Projects user can view
-    authorized_projects_ids = ProjectsFinder.new.execute(current_user).pluck(:id)
+    @contributed_projects = contributed_projects.joined(@user).
+      reject(&:forked?)
 
     @projects = @user.personal_projects.
-      where(id: authorized_projects_ids)
+      where(id: authorized_projects_ids).includes(:namespace)
 
     # Collect only groups common for both users
     @groups = @user.groups & GroupsFinder.new.execute(current_user)
 
-    # Get user activity feed for projects common for both users
-    @events = @user.recent_events.
-      where(project_id: authorized_projects_ids).limit(20)
-
     @title = @user.name
+    @title_url = user_path(@user)
+
+    respond_to do |format|
+      format.html
+
+      format.atom do
+        load_events
+        render layout: false
+      end
+
+      format.json do
+        load_events
+        pager_json("events/_events", @events.count)
+      end
+    end
+  end
+
+  def calendar
+    calendar = contributions_calendar
+    @timestamps = calendar.timestamps
+    @starting_year = calendar.starting_year
+    @starting_month = calendar.starting_month
+
+    render 'calendar', layout: false
+  end
+
+  def calendar_activities
+    @calendar_date = Date.parse(params[:date]) rescue nil
+    @events = []
+
+    if @calendar_date
+      @events = contributions_calendar.events_by_date(@calendar_date)
+    end
+
+    render 'calendar_activities', layout: false
   end
 
   def determine_layout
@@ -32,4 +58,40 @@ class UsersController < ApplicationController
       'public_users'
     end
   end
+
+  private
+
+  def set_user
+    @user = User.find_by_username!(params[:username])
+
+    unless current_user || @user.public_profile?
+      return authenticate_user!
+    end
+  end
+
+  def authorized_projects_ids
+    # Projects user can view
+    @authorized_projects_ids ||=
+      ProjectsFinder.new.execute(current_user).pluck(:id)
+  end
+
+  def contributed_projects
+    @contributed_projects = Project.
+      where(id: authorized_projects_ids & @user.contributed_projects_ids).
+      includes(:namespace)
+  end
+
+  def contributions_calendar
+    @contributions_calendar ||= Gitlab::ContributionsCalendar.
+      new(contributed_projects.reject(&:forked?), @user)
+  end
+
+  def load_events
+    # Get user activity feed for projects common for both users
+    @events = @user.recent_events.
+      where(project_id: authorized_projects_ids).
+      with_associations
+
+    @events = @events.limit(20).offset(params[:offset] || 0)
+  end
 end
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index d05742405112f3d8e6a78233739c026a52d2858f..2c0702073d45009026784f6539da0db3f51d7542 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -19,6 +19,8 @@
 require_relative 'projects_finder'
 
 class IssuableFinder
+  NONE = '0'
+
   attr_accessor :current_user, :params
 
   def execute(current_user, params)
@@ -33,6 +35,7 @@ class IssuableFinder
     items = by_search(items)
     items = by_milestone(items)
     items = by_assignee(items)
+    items = by_author(items)
     items = by_label(items)
     items = sort(items)
   end
@@ -43,7 +46,7 @@ class IssuableFinder
     table_name = klass.table_name
 
     if project
-      if project.public? || (current_user && current_user.can?(:read_project, project))
+      if Ability.abilities.allowed?(current_user, :read_project, project)
         project.send(table_name)
       else
         []
@@ -111,7 +114,7 @@ class IssuableFinder
 
   def by_milestone(items)
     if params[:milestone_id].present?
-      items = items.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id]))
+      items = items.where(milestone_id: (params[:milestone_id] == NONE ? nil : params[:milestone_id]))
     end
 
     items
@@ -119,7 +122,15 @@ class IssuableFinder
 
   def by_assignee(items)
     if params[:assignee_id].present?
-      items = items.where(assignee_id: (params[:assignee_id] == '0' ? nil : params[:assignee_id]))
+      items = items.where(assignee_id: (params[:assignee_id] == NONE ? nil : params[:assignee_id]))
+    end
+
+    items
+  end
+
+  def by_author(items)
+    if params[:author_id].present?
+      items = items.where(author_id: (params[:author_id] == NONE ? nil : params[:author_id]))
     end
 
     items
diff --git a/app/finders/notes_finder.rb b/app/finders/notes_finder.rb
index bef82d7f0fdf23571e40242dbeaa274792eede58..ab252821b52133c5d2294d4f8ee4e530b3bcfafa 100644
--- a/app/finders/notes_finder.rb
+++ b/app/finders/notes_finder.rb
@@ -7,20 +7,21 @@ class NotesFinder
     # Default to 0 to remain compatible with old clients
     last_fetched_at = Time.at(params.fetch(:last_fetched_at, 0).to_i)
 
-    notes = case target_type
-    when "commit"
-      project.notes.for_commit_id(target_id).not_inline.fresh
-    when "issue"
-      project.issues.find(target_id).notes.inc_author.fresh
-    when "merge_request"
-      project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh
-    when "snippet", "project_snippet"
-      project.snippets.find(target_id).notes.fresh
-    else
-      raise 'invalid target_type'
-    end
+    notes =
+      case target_type
+      when "commit"
+        project.notes.for_commit_id(target_id).not_inline
+      when "issue"
+        project.issues.find(target_id).notes.inc_author
+      when "merge_request"
+        project.merge_requests.find(target_id).mr_and_commit_notes.inc_author
+      when "snippet", "project_snippet"
+        project.snippets.find(target_id).notes
+      else
+        raise 'invalid target_type'
+      end
 
     # Use overlapping intervals to avoid worrying about race conditions
-    notes.where('updated_at > ?', last_fetched_at - FETCH_OVERLAP)
+    notes.where('updated_at > ?', last_fetched_at - FETCH_OVERLAP).fresh
   end
 end
diff --git a/app/finders/snippets_finder.rb b/app/finders/snippets_finder.rb
index 4b0c69f2d2f91cf80c31a02e0bd685854eb72be3..07b5759443b2cf8346cc34f3858b3196bfa87d8b 100644
--- a/app/finders/snippets_finder.rb
+++ b/app/finders/snippets_finder.rb
@@ -40,7 +40,7 @@ class SnippetsFinder
       when 'are_public' then
         snippets.are_public
       else
-       snippets
+        snippets
       end
     else
       snippets.public_and_internal
diff --git a/app/finders/trending_projects_finder.rb b/app/finders/trending_projects_finder.rb
index 32d7968924ad9402504b9f9ebb9b88cd0bfe5b7a..a79bd47d9867de5379cd985b16cf3a0683e1fb74 100644
--- a/app/finders/trending_projects_finder.rb
+++ b/app/finders/trending_projects_finder.rb
@@ -8,7 +8,7 @@ class TrendingProjectsFinder
     # for period of time - ex. month
     projects.joins(:notes).where('notes.created_at > ?', start_date).
       select("projects.*, count(notes.id) as ncount").
-      group("projects.id").order("ncount DESC")
+      group("projects.id").reorder("ncount DESC")
   end
 
   private
diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb
index 96e5d43a369266aa97c06a29176a928e45162089..bb8d568380796f95c8039d39c983a90a5c5229af 100644
--- a/app/helpers/appearances_helper.rb
+++ b/app/helpers/appearances_helper.rb
@@ -14,4 +14,8 @@ module AppearancesHelper
   def brand_text
     nil
   end
+
+  def brand_header_logo
+    image_tag 'logo-white.png'
+  end
 end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 021bd0a494c74024ce617c368afad80456dd6e7b..3f3509bb18a1091000494de4c2099b6d274dfe7b 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -5,8 +5,9 @@ module ApplicationHelper
   COLOR_SCHEMES = {
     1 => 'white',
     2 => 'dark',
-    3 => 'solarized-dark',
-    4 => 'monokai',
+    3 => 'solarized-light',
+    4 => 'solarized-dark',
+    5 => 'monokai',
   }
   COLOR_SCHEMES.default = 'white'
 
@@ -49,12 +50,39 @@ module ApplicationHelper
     args.any? { |v| v.to_s.downcase == action_name }
   end
 
-  def group_icon(group_path)
-    group = Group.find_by(path: group_path)
-    if group && group.avatar.present?
-      group.avatar.url
-    else
-      image_path('no_group_avatar.png')
+  def project_icon(project_id, options = {})
+    project =
+      if project_id.is_a?(Project)
+        project = project_id
+      else
+        Project.find_with_namespace(project_id)
+      end
+
+    if project.avatar_url
+      image_tag project.avatar_url, options
+    else # generated icon
+      project_identicon(project, options)
+    end
+  end
+
+  def project_identicon(project, options = {})
+    allowed_colors = {
+      red: 'FFEBEE',
+      purple: 'F3E5F5',
+      indigo: 'E8EAF6',
+      blue: 'E3F2FD',
+      teal: 'E0F2F1',
+      orange: 'FBE9E7',
+      gray: 'EEEEEE'
+    }
+
+    options[:class] ||= ''
+    options[:class] << ' identicon'
+    bg_key = project.id % 7
+    style = "background-color: ##{ allowed_colors.values[bg_key] }; color: #555"
+
+    content_tag(:div, class: options[:class], style: style) do
+      project.name[0, 1].upcase
     end
   end
 
@@ -81,24 +109,24 @@ module ApplicationHelper
     if project.repo_exists?
       time_ago_with_tooltip(project.repository.commit.committed_date)
     else
-      "Never"
+      'Never'
     end
   rescue
-    "Never"
+    'Never'
   end
 
   def grouped_options_refs
     repository = @project.repository
 
     options = [
-      ["Branches", repository.branch_names],
-      ["Tags", VersionSorter.rsort(repository.tag_names)]
+      ['Branches', repository.branch_names],
+      ['Tags', VersionSorter.rsort(repository.tag_names)]
     ]
 
     # If reference is commit id - we should add it to branch/tag selectbox
     if(@ref && !options.flatten.include?(@ref) &&
        @ref =~ /^[0-9a-zA-Z]{6,52}$/)
-      options << ["Commit", [@ref]]
+      options << ['Commit', [@ref]]
     end
 
     grouped_options_for_select(options, @ref || @project.default_branch)
@@ -114,6 +142,10 @@ module ApplicationHelper
     Gitlab::Theme.css_class_by_id(current_user.try(:theme_id))
   end
 
+  def theme_type
+    Gitlab::Theme.type_css_class_by_id(current_user.try(:theme_id))
+  end
+
   def user_color_scheme_class
     COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user)
   end
@@ -142,21 +174,15 @@ module ApplicationHelper
     Digest::SHA1.hexdigest string
   end
 
-  def authbutton(provider, size = 64)
-    file_name = "#{provider.to_s.split('_').first}_#{size}.png"
-    image_tag(image_path("authbuttons/#{file_name}"), alt: "Sign in with #{provider.to_s.titleize}")
-  end
-
   def simple_sanitize(str)
     sanitize(str, tags: %w(a span))
   end
 
-
   def body_data_page
     path = controller.controller_path.split('/')
     namespace = path.first if path.second
 
-    [namespace, controller.controller_name, controller.action_name].compact.join(":")
+    [namespace, controller.controller_name, controller.action_name].compact.join(':')
   end
 
   # shortcut for gitlab config
@@ -171,13 +197,13 @@ module ApplicationHelper
 
   def search_placeholder
     if @project && @project.persisted?
-      "Search in this project"
+      'Search in this project'
     elsif @snippet || @snippets || @show_snippets
       'Search snippets'
     elsif @group && @group.persisted?
-      "Search in this group"
+      'Search in this group'
     else
-      "Search"
+      'Search'
     end
   end
 
@@ -185,24 +211,10 @@ module ApplicationHelper
     BroadcastMessage.current
   end
 
-  def highlight_js(&block)
-    string = capture(&block)
-
-    content_tag :div, class: "highlighted-data #{user_color_scheme_class}" do
-      content_tag :div, class: 'highlight' do
-        content_tag :pre do
-          content_tag :code do
-            string.html_safe
-          end
-        end
-      end
-    end
-  end
-
   def time_ago_with_tooltip(date, placement = 'top', html_class = 'time_ago')
     capture_haml do
       haml_tag :time, date.to_s,
-        class: html_class, datetime: date.getutc.iso8601, title: date.stamp("Aug 21, 2011 9:23pm"),
+        class: html_class, datetime: date.getutc.iso8601, title: date.stamp('Aug 21, 2011 9:23pm'),
         data: { toggle: 'tooltip', placement: placement }
 
       haml_tag :script, "$('." + html_class + "').timeago().tooltip()"
@@ -224,15 +236,6 @@ module ApplicationHelper
     Gitlab::MarkdownHelper.gitlab_markdown?(filename)
   end
 
-  def spinner(text = nil, visible = false)
-    css_class = "loading"
-    css_class << " hide" unless visible
-
-    content_tag :div, class: css_class do
-      content_tag(:i, nil, class: 'fa fa-spinner fa-spin') + text
-    end
-  end
-
   def link_to(name = nil, options = nil, html_options = nil, &block)
     begin
       uri = URI(options)
@@ -243,17 +246,17 @@ module ApplicationHelper
       absolute_uri = nil
     end
 
-    # Add "nofollow" only to external links
+    # Add 'nofollow' only to external links
     if host && host != Gitlab.config.gitlab.host && absolute_uri
       if html_options
         if html_options[:rel]
-          html_options[:rel] << " nofollow"
+          html_options[:rel] << ' nofollow'
         else
-          html_options.merge!(rel: "nofollow")
+          html_options.merge!(rel: 'nofollow')
         end
       else
         html_options = Hash.new
-        html_options[:rel] = "nofollow"
+        html_options[:rel] = 'nofollow'
       end
     end
 
@@ -271,4 +274,50 @@ module ApplicationHelper
   def promo_url
     'https://' + promo_host
   end
+
+  def page_filter_path(options = {})
+    without = options.delete(:without)
+
+    exist_opts = {
+      state: params[:state],
+      scope: params[:scope],
+      label_name: params[:label_name],
+      milestone_id: params[:milestone_id],
+      assignee_id: params[:assignee_id],
+      author_id: params[:author_id],
+      sort: params[:sort],
+    }
+
+    options = exist_opts.merge(options)
+
+    if without.present?
+      without.each do |key|
+        options.delete(key)
+      end
+    end
+
+    path = request.path
+    path << "?#{options.to_param}"
+    path
+  end
+
+  def outdated_browser?
+    browser.ie? && browser.version.to_i < 10
+  end
+
+  def path_to_key(key, admin = false)
+    if admin
+      admin_user_key_path(@user, key)
+    else
+      profile_key_path(key)
+    end
+  end
+
+  def nav_sidebar_class
+    if nav_menu_collapsed?
+      "page-sidebar-collapsed"
+    else
+      "page-sidebar-expanded"
+    end
+  end
 end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..241d6075c9f686d5b519cd265a7e342ee2eb30dd
--- /dev/null
+++ b/app/helpers/application_settings_helper.rb
@@ -0,0 +1,38 @@
+module ApplicationSettingsHelper
+  def gravatar_enabled?
+    current_application_settings.gravatar_enabled?
+  end
+
+  def twitter_sharing_enabled?
+    current_application_settings.twitter_sharing_enabled?
+  end
+
+  def signup_enabled?
+    current_application_settings.signup_enabled?
+  end
+
+  def signin_enabled?
+    current_application_settings.signin_enabled?
+  end
+
+  def extra_sign_in_text
+    current_application_settings.sign_in_text
+  end
+
+  # Return a group of checkboxes that use Bootstrap's button plugin for a
+  # toggle button effect.
+  def restricted_level_checkboxes(help_block_id)
+    Gitlab::VisibilityLevel.options.map do |name, level|
+      checked = restricted_visibility_levels(true).include?(level)
+      css_class = 'btn btn-primary'
+      css_class += ' active' if checked
+      checkbox_name = 'application_setting[restricted_visibility_levels][]'
+
+      label_tag(checkbox_name, class: css_class) do
+        check_box_tag(checkbox_name, level, checked,
+                      autocomplete: 'off',
+                      'aria-describedby' => help_block_id) + name
+      end
+    end
+  end
+end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 11fbf1baae75dc860576ea4dbc10d37810540464..4ea838ca44731fef9fc818a8665a41f90a9eaf70 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -1,18 +1,72 @@
 module BlobHelper
-  def highlightjs_class(blob_name)
-    if blob_name.include?('.')
-      ext = blob_name.split('.').last
-      return 'language-' + ext
-    else
-      if no_highlight_files.include?(blob_name.downcase)
-        'no-highlight'
-      else
-        blob_name.downcase
-      end
+  def highlight(blob_name, blob_content, nowrap = false)
+    formatter = Rugments::Formatters::HTML.new(
+      nowrap: nowrap,
+      cssclass: 'code highlight',
+      lineanchors: true,
+      lineanchorsid: 'LC'
+    )
+
+    begin
+      lexer = Rugments::Lexer.guess(filename: blob_name, source: blob_content)
+    rescue Rugments::Lexer::AmbiguousGuess
+      lexer = Rugments::Lexers::PlainText
     end
+
+    formatter.format(lexer.lex(blob_content)).html_safe
   end
 
   def no_highlight_files
-    %w(credits changelog copying copyright license authors)
+    %w(credits changelog news copying copyright license authors)
+  end
+
+  def edit_blob_link(project, ref, path, options = {})
+    blob =
+      begin
+        project.repository.blob_at(ref, path)
+      rescue
+        nil
+      end
+
+    if blob && blob.text?
+      text = 'Edit'
+      after = options[:after] || ''
+      from_mr = options[:from_merge_request_id]
+      link_opts = {}
+      link_opts[:from_merge_request_id] = from_mr if from_mr
+      cls = 'btn btn-small'
+      if allowed_tree_edit?(project, ref)
+        link_to(text,
+                namespace_project_edit_blob_path(project.namespace, project,
+                                                 tree_join(ref, path),
+                                                 link_opts),
+                class: cls
+               )
+      else
+        content_tag :span, text, class: cls + ' disabled'
+      end + after.html_safe
+    else
+      ''
+    end
+  end
+
+  def leave_edit_message
+    "Leave edit mode?\nAll unsaved changes will be lost."
+  end
+
+  def editing_preview_title(filename)
+    if Gitlab::MarkdownHelper.previewable?(filename)
+      'Preview'
+    else
+      'Preview changes'
+    end
+  end
+
+  # Return an image icon depending on the file mode and extension
+  #
+  # mode - File unix mode
+  # mode - File name
+  def blob_icon(mode, name)
+    icon("#{file_type_icon_class('file', mode, name)} fw")
   end
 end
diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb
index 2ec2cc961578c88d850cbf210114788c41c39f9a..d6eaa7d57bcafcbf6496187e66cf58ea5252bb3d 100644
--- a/app/helpers/branches_helper.rb
+++ b/app/helpers/branches_helper.rb
@@ -11,12 +11,7 @@ module BranchesHelper
 
   def can_push_branch?(project, branch_name)
     return false unless project.repository.branch_names.include?(branch_name)
-    action = if project.protected_branch?(branch_name)
-               :push_code_to_protected_branches
-             else
-               :push_code
-             end
-
-    current_user.can?(action, project)
+    
+    ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(branch_name)
   end
 end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 36adeadd8a5d7af0175ac28d89d3198e8944f22a..5aae697e2f0a1102c32ce39fbad9d96ecd3c8445 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -37,16 +37,26 @@ module CommitsHelper
 
     # Add the root project link and the arrow icon
     crumbs = content_tag(:li) do
-      link_to(@project.path, project_commits_path(@project, @ref))
+      link_to(
+        @project.path,
+        namespace_project_commits_path(@project.namespace, @project, @ref)
+      )
     end
 
     if @path
       parts = @path.split('/')
 
       parts.each_with_index do |part, i|
-        crumbs += content_tag(:li) do
+        crumbs << content_tag(:li) do
           # The text is just the individual part, but the link needs all the parts before it
-          link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/')))
+          link_to(
+            part,
+            namespace_project_commits_path(
+              @project.namespace,
+              @project,
+              tree_join(@ref, parts[0..i].join('/'))
+            )
+          )
         end
       end
     end
@@ -62,18 +72,55 @@ module CommitsHelper
 
   # Returns the sorted alphabetically links to branches, separated by a comma
   def commit_branches_links(project, branches)
-    branches.sort.map { |branch| link_to(branch, project_tree_path(project, branch)) }.join(", ").html_safe
+    branches.sort.map do |branch|
+      link_to(
+        namespace_project_tree_path(project.namespace, project, branch)
+      ) do
+        content_tag :span, class: 'label label-gray' do
+          icon('code-fork') + ' ' + branch
+        end
+      end
+    end.join(" ").html_safe
+  end
+
+  # Returns the sorted links to tags, separated by a comma
+  def commit_tags_links(project, tags)
+    sorted = VersionSorter.rsort(tags)
+    sorted.map do |tag|
+      link_to(
+        namespace_project_commits_path(project.namespace, project,
+                                       project.repository.find_tag(tag).name)
+      ) do
+        content_tag :span, class: 'label label-gray' do
+          icon('tag') + ' ' + tag
+        end
+      end
+    end.join(" ").html_safe
   end
 
   def link_to_browse_code(project, commit)
     if current_controller?(:projects, :commits)
       if @repo.blob_at(commit.id, @path)
-        return link_to "Browse File »", project_blob_path(project, tree_join(commit.id, @path)), class: "pull-right"
+        return link_to(
+          "Browse File »",
+          namespace_project_blob_path(project.namespace, project,
+                                      tree_join(commit.id, @path)),
+          class: "pull-right"
+        )
       elsif @path.present?
-        return link_to "Browse Dir »", project_tree_path(project, tree_join(commit.id, @path)), class: "pull-right"
+        return link_to(
+          "Browse Dir »",
+          namespace_project_tree_path(project.namespace, project,
+                                      tree_join(commit.id, @path)),
+          class: "pull-right"
+        )
       end
     end
-    link_to "Browse Code »", project_tree_path(project, commit), class: "pull-right"
+    link_to(
+      "Browse Code »",
+      namespace_project_tree_path(project.namespace, project, commit),
+      class: "pull-right"
+    )
   end
 
   protected
@@ -94,12 +141,13 @@ module CommitsHelper
     person_name = user.nil? ? source_name : user.name
     person_email = user.nil? ? source_email : user.email
 
-    text = if options[:avatar]
-            avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
-            %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>}
-          else
-            person_name
-          end
+    text =
+      if options[:avatar]
+        avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
+        %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>}
+      else
+        person_name
+      end
 
     options = {
       class: "commit-#{options[:source]}-link has_tooltip",
@@ -114,8 +162,11 @@ module CommitsHelper
   end
 
   def view_file_btn(commit_sha, diff, project)
-    link_to project_blob_path(project, tree_join(commit_sha, diff.new_path)),
-            class: 'btn btn-small view-file js-view-file' do
+    link_to(
+      namespace_project_blob_path(project.namespace, project,
+                                  tree_join(commit_sha, diff.new_path)),
+      class: 'btn btn-small view-file js-view-file'
+    ) do
       raw('View file @') + content_tag(:span, commit_sha[0..6],
                                        class: 'commit-short-id')
     end
diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb
index 5ff19b8829381a9e0e0c363def1cd73d8886f9b2..01847c6b807c1e7049d2e1f808a81185c9894de8 100644
--- a/app/helpers/compare_helper.rb
+++ b/app/helpers/compare_helper.rb
@@ -1,7 +1,7 @@
 module CompareHelper
   def compare_to_mr_button?
     @project.merge_requests_enabled &&
-      params[:from].present? && 
+      params[:from].present? &&
       params[:to].present? &&
       @repository.branch_names.include?(params[:from]) &&
       @repository.branch_names.include?(params[:to]) &&
@@ -10,6 +10,13 @@ module CompareHelper
   end
 
   def compare_mr_path
-    new_project_merge_request_path(@project, merge_request: {source_branch: params[:to], target_branch: params[:from]})
+    new_namespace_project_merge_request_path(
+      @project.namespace,
+      @project,
+      merge_request: {
+        source_branch: params[:to],
+        target_branch: params[:from]
+      }
+    )
   end
 end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index acc0eeb76b36ab83bba42fb6c35888b5ce6d596f..c25b54eadc693650412f1e2280e009de6748f659 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -1,67 +1,9 @@
 module DashboardHelper
-  def filter_path(entity, options={})
-    exist_opts = {
-      state: params[:state],
-      scope: params[:scope],
-      project_id: params[:project_id],
-    }
-
-    options = exist_opts.merge(options)
-
-    path = request.path
-    path << "?#{options.to_param}"
-    path
-  end
-
-  def entities_per_project(project, entity)
-    case entity.to_sym
-    when :issue then @issues.where(project_id: project.id)
-    when :merge_request then @merge_requests.where(target_project_id: project.id)
-    else
-      []
-    end.count
-  end
-
-  def projects_dashboard_filter_path(options={})
-    exist_opts = {
-      sort: params[:sort],
-      scope: params[:scope],
-      group: params[:group],
-    }
-
-    options = exist_opts.merge(options)
-
-    path = request.path
-    path << "?#{options.to_param}"
-    path
+  def assigned_issues_dashboard_path
+    issues_dashboard_path(assignee_id: current_user.id)
   end
 
-  def assigned_entities_count(current_user, entity, scope = nil)
-    items = current_user.send('assigned_' + entity.pluralize)
-    get_count(items, scope)
-  end
-
-  def authored_entities_count(current_user, entity, scope = nil)
-    items = current_user.send(entity.pluralize)
-    get_count(items, scope)
-  end
-
-  def authorized_entities_count(current_user, entity, scope = nil)
-    items = entity.classify.constantize
-    get_count(items, scope, true, current_user)
-  end
-
-  protected
-
-  def get_count(items, scope, get_authorized = false, current_user = nil)
-    items = items.opened
-    if scope.kind_of?(Group)
-      items = items.of_group(scope)
-    elsif scope.kind_of?(Project)
-      items = items.of_projects(scope)
-    elsif get_authorized
-      items = items.of_projects(current_user.authorized_projects)
-    end
-    items.count
+  def assigned_mrs_dashboard_path
+    merge_requests_dashboard_path(assignee_id: current_user.id)
   end
 end
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index cb50d89cba8c79815ae1c21a7939021f2534f572..b56f21c7a18b0c6492ca17558a3e892d18fda726 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -117,4 +117,41 @@ module DiffHelper
 
     [comments_left, comments_right]
   end
+
+  def inline_diff_btn
+    params_copy = params.dup
+    params_copy[:view] = 'inline'
+    # Always use HTML to handle case where JSON diff rendered this button
+    params_copy.delete(:format)
+
+    link_to url_for(params_copy), id: "commit-diff-viewtype", class: (params[:view] != 'parallel' ? 'btn btn-sm active' : 'btn btn-sm') do
+      'Inline'
+    end
+  end
+
+  def parallel_diff_btn
+    params_copy = params.dup
+    params_copy[:view] = 'parallel'
+    # Always use HTML to handle case where JSON diff rendered this button
+    params_copy.delete(:format)
+
+    link_to url_for(params_copy), id: "commit-diff-viewtype", class: (params[:view] == 'parallel' ? 'btn active btn-sm' : 'btn btn-sm') do
+      'Side-by-side'
+    end
+  end
+
+  def submodule_link(blob, ref)
+    tree, commit = submodule_links(blob, ref)
+    commit_id = if commit.nil?
+                  blob.id[0..10]
+                else
+                  link_to "#{blob.id[0..10]}", commit
+                end
+
+    [
+      content_tag(:span, link_to(truncate(blob.name, length: 40), tree)),
+      '@',
+      content_tag(:span, commit_id, class: 'monospace'),
+    ].join(' ').html_safe
+  end
 end
diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb
index 24d67c21d6bbc1be68fe8618d2a9764a5d326cfa..08476f8516e8265af3ef0f1c374b732de0301863 100644
--- a/app/helpers/emails_helper.rb
+++ b/app/helpers/emails_helper.rb
@@ -1,3 +1,6 @@
+require 'html/pipeline'
+require 'html/pipeline/gitlab'
+
 module EmailsHelper
 
   # Google Actions
@@ -29,4 +32,36 @@ module EmailsHelper
       end
     end
   end
+
+  def add_email_highlight_css
+    Rugments::Themes::Github.render(scope: '.highlight')
+  end
+
+  def color_email_diff(diffcontent)
+    formatter = Rugments::Formatters::HTML.new(cssclass: 'highlight')
+    lexer = Rugments::Lexers::Diff.new
+    raw formatter.format(lexer.lex(diffcontent))
+  end
+
+  def replace_image_links_with_base64(text, project)
+    # Used pipelines in GitLab:
+    # GitlabEmailImageFilter - replaces images that have been uploaded as attachments with inline images in emails.
+    #
+    # see https://gitlab.com/gitlab-org/html-pipeline-gitlab for more filters
+    filters = [
+      HTML::Pipeline::Gitlab::GitlabEmailImageFilter
+    ]
+
+    context = {
+      base_url: File.join(Gitlab.config.gitlab.url, project.path_with_namespace, 'uploads'),
+      upload_path: File.join(Rails.root, 'public', 'uploads', project.path_with_namespace),
+    }
+
+    pipeline = HTML::Pipeline::Gitlab.new(filters).pipeline
+
+    result = pipeline.call(text, context)
+    text = result[:output].to_html(save_with: 0)
+
+    text.html_safe
+  end
 end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 71f97fbb8c8f3d5fdfa6c23c854a21d8bbb42180..c9fd0f0362b9fb473d5934a76dd5e72f6dec8323 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -10,83 +10,104 @@ module EventsHelper
   end
 
   def event_action_name(event)
-    target = if event.target_type
-               event.target_type.titleize.downcase
-             else
-               'project'
-             end
+    target =  if event.target_type
+                if event.note?
+                  event.note_target_type
+                else
+                  event.target_type.titleize.downcase
+                end
+              else
+                'project'
+              end
 
     [event.action_name, target].join(" ")
   end
 
   def event_filter_link(key, tooltip)
     key = key.to_s
-    inactive = if @event_filter.active? key
-                 nil
-               else
-                 'inactive'
-               end
-
-    content_tag :div, class: "filter_icon #{inactive}" 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]
+    active = if @event_filter.active? key
+               'active'
+             end
+
+    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' => 'Filter by ' + tooltip.downcase do
+        icon(icon_for_event[key]) + content_tag(:span, ' ' + tooltip)
       end
     end
   end
 
   def icon_for_event
     {
-      EventFilter.push     => 'fa fa-upload',
-      EventFilter.merged   => 'fa fa-check-square-o',
-      EventFilter.comments => 'fa fa-comments',
-      EventFilter.team     => 'fa fa-user',
+      EventFilter.push     => 'upload',
+      EventFilter.merged   => 'check-square-o',
+      EventFilter.comments => 'comments',
+      EventFilter.team     => 'user',
     }
   end
 
   def event_feed_title(event)
-    if event.issue?
-      "#{event.author_name} #{event.action_name} issue ##{event.target_iid}: #{event.issue_title} at #{event.project_name}"
-    elsif event.merge_request?
-      "#{event.author_name} #{event.action_name} MR ##{event.target_iid}: #{event.merge_request_title} at #{event.project_name}"
-    elsif event.push?
-      "#{event.author_name} #{event.push_action_name} #{event.ref_type} #{event.ref_name} at #{event.project_name}"
-    elsif event.membership_changed?
-      "#{event.author_name} #{event.action_name} #{event.project_name}"
-    elsif event.note? && event.note_commit?
-      "#{event.author_name} commented on #{event.note_target_type} #{event.note_short_commit_id} at #{event.project_name}"
-    elsif event.note?
-      "#{event.author_name} commented on #{event.note_target_type} ##{truncate event.note_target_iid} at #{event.project_name}"
-    else
-      ""
+    words = []
+    words << event.author_name
+    words << event_action_name(event)
+
+    if event.push?
+      words << event.ref_type
+      words << event.ref_name
+      words << "at"
+    elsif event.commented?
+      if event.note_commit?
+        words << event.note_short_commit_id
+      else
+        words << "##{truncate event.note_target_iid}"
+      end
+      words << "at"
+    elsif event.target
+      words << "##{event.target_iid}:" 
+      words << event.target.title if event.target.respond_to?(:title)
+      words << "at"
     end
+
+    words << event.project_name
+
+    words.join(" ")
   end
 
   def event_feed_url(event)
     if event.issue?
-      project_issue_url(event.project, event.issue)
+      namespace_project_issue_url(event.project.namespace, event.project,
+                                  event.issue)
     elsif event.merge_request?
-      project_merge_request_url(event.project, event.merge_request)
+      namespace_project_merge_request_url(event.project.namespace,
+                                          event.project, event.merge_request)
     elsif event.note? && event.note_commit?
-      project_commit_url(event.project, event.note_target)
+      namespace_project_commit_url(event.project.namespace, event.project,
+                                   event.note_target)
     elsif event.note?
       if event.note_target
         if event.note_commit?
-          project_commit_path(event.project, event.note_commit_id, anchor: dom_id(event.target))
+          namespace_project_commit_path(event.project.namespace, event.project,
+                                        event.note_commit_id,
+                                        anchor: dom_id(event.target))
         elsif event.note_project_snippet?
-          project_snippet_path(event.project, event.note_target)
+          namespace_project_snippet_path(event.project.namespace,
+                                         event.project, event.note_target)
         else
           event_note_target_path(event)
         end
       end
     elsif event.push?
-      if event.push_with_commits?
+      if event.push_with_commits? && event.md_ref?
         if event.commits_count > 1
-          project_compare_url(event.project, from: event.commit_from, to: event.commit_to)
+          namespace_project_compare_url(event.project.namespace, event.project,
+                                        from: event.commit_from, to:
+                                        event.commit_to)
         else
-          project_commit_url(event.project, id: event.commit_to)
+          namespace_project_commit_url(event.project.namespace, event.project,
+                                       id: event.commit_to)
         end
       else
-        project_commits_url(event.project, event.ref_name)
+        namespace_project_commits_url(event.project.namespace, event.project,
+                                      event.ref_name)
       end
     end
   end
@@ -98,8 +119,6 @@ module EventsHelper
       render "events/event_push", event: event
     elsif event.merge_request?
       render "events/event_merge_request", merge_request: event.merge_request
-    elsif event.push?
-      render "events/event_push", event: event
     elsif event.note?
       render "events/event_note", note: event.note
     end
@@ -107,20 +126,30 @@ module EventsHelper
 
   def event_note_target_path(event)
     if event.note? && event.note_commit?
-      project_commit_path(event.project, event.note_target)
+      namespace_project_commit_path(event.project.namespace, event.project,
+                                    event.note_target)
     else
-      polymorphic_path([event.project, event.note_target], anchor: dom_id(event.target))
+      polymorphic_path([event.project.namespace.becomes(Namespace),
+                        event.project, event.note_target],
+                       anchor: dom_id(event.target))
     end
   end
 
   def event_note_title_html(event)
     if event.note_target
       if event.note_commit?
-        link_to project_commit_path(event.project, event.note_commit_id, anchor: dom_id(event.target)), class: "commit_short_id" do
+        link_to(
+          namespace_project_commit_path(event.project.namespace, event.project,
+                                        event.note_commit_id,
+                                        anchor: dom_id(event.target)),
+          class: "commit_short_id"
+        ) do
           "#{event.note_target_type} #{event.note_short_commit_id}"
         end
       elsif event.note_project_snippet?
-        link_to(project_snippet_path(event.project, event.note_target)) do
+        link_to(namespace_project_snippet_path(event.project.namespace,
+                                               event.project,
+                                               event.note_target)) do
           "#{event.note_target_type} ##{truncate event.note_target_id}"
         end
       else
@@ -137,7 +166,7 @@ module EventsHelper
 
   def event_note(text)
     text = first_line_in_markdown(text, 150)
-    sanitize(text, tags: %w(a img b pre code p))
+    sanitize(text, tags: %w(a img b pre code p span))
   end
 
   def event_commit_title(message)
@@ -145,4 +174,26 @@ module EventsHelper
   rescue
     "--broken encoding"
   end
+
+  def event_to_atom(xml, event)
+    if event.proper?
+      xml.entry do
+        event_link = event_feed_url(event)
+        event_title = event_feed_title(event)
+        event_summary = event_feed_summary(event)
+
+        xml.id      "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
+        xml.link    href: event_link
+        xml.title   truncate(event_title, length: 80)
+        xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
+        xml.media   :thumbnail, width: "40", height: "40", url: avatar_icon(event.author_email)
+        xml.author do |author|
+          xml.name event.author_name
+          xml.email event.author_email
+        end
+
+        xml.summary(type: "xhtml") { |x| x << event_summary unless event_summary.nil? }
+      end
+    end
+  end
 end
diff --git a/app/helpers/explore_helper.rb b/app/helpers/explore_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7616fe6bad8b9ccda5b3f2406fe25b6817a86c8b
--- /dev/null
+++ b/app/helpers/explore_helper.rb
@@ -0,0 +1,17 @@
+module ExploreHelper
+  def explore_projects_filter_path(options={})
+    exist_opts = {
+      sort: params[:sort],
+      scope: params[:scope],
+      group: params[:group],
+      tag: params[:tag],
+      visibility_level: params[:visibility_level],
+    }
+
+    options = exist_opts.merge(options)
+
+    path = request.path
+    path << "?#{options.to_param}"
+    path
+  end
+end
diff --git a/app/helpers/external_wiki_helper.rb b/app/helpers/external_wiki_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..838b85afdfe573e1d605c784fe47b35731aa9894
--- /dev/null
+++ b/app/helpers/external_wiki_helper.rb
@@ -0,0 +1,11 @@
+module ExternalWikiHelper
+  def get_project_wiki_path(project)
+    external_wiki_service = project.services.
+      select { |service| service.to_param == 'external_wiki' }.first
+    if external_wiki_service.present? && external_wiki_service.active?
+      external_wiki_service.properties['external_wiki_url']
+    else
+      namespace_project_wiki_path(project.namespace, project, :home)
+    end
+  end
+end
diff --git a/app/helpers/git_helper.rb b/app/helpers/git_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..096849552336c2495ab4d2f9fbe08c547f4737e0
--- /dev/null
+++ b/app/helpers/git_helper.rb
@@ -0,0 +1,5 @@
+module GitHelper
+  def strip_gpg_signature(text)
+    text.gsub(/-----BEGIN PGP SIGNATURE-----(.*)-----END PGP SIGNATURE-----/m, "")
+  end
+end
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index 7d3cb7498291708b04b841e0bc33a63636e137e0..7ca3f058636919d8142c97e6632a066ec672e735 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -29,11 +29,12 @@ module GitlabMarkdownHelper
   end
 
   def markdown(text, options={})
-    unless (@markdown and options == @options)
+    unless @markdown && options == @options
       @options = options
-      gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self, {
+      gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self,
+                                                          user_color_scheme_class,
+                                                          {
                             # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-
-                            filter_html: true,
                             with_toc_data: true,
                             safe_links_only: true
                           }.merge(options))
@@ -110,7 +111,7 @@ module GitlabMarkdownHelper
   end
 
   def link_to_ignore?(link)
-    if link =~ /\#\w+/
+    if link =~ /\A\#\w+/
       # ignore anchors like <a href="#my-header">
       true
     else
@@ -119,13 +120,14 @@ module GitlabMarkdownHelper
   end
 
   def ignored_protocols
-    ["http://","https://", "ftp://", "mailto:"]
+    ["http://","https://", "ftp://", "mailto:", "smb://"]
   end
 
-  def rebuild_path(path)
-    path.gsub!(/(#.*)/, "")
+  def rebuild_path(file_path)
+    file_path = file_path.dup
+    file_path.gsub!(/(#.*)/, "")
     id = $1 || ""
-    file_path = relative_file_path(path)
+    file_path = relative_file_path(file_path)
     file_path = sanitize_slashes(file_path)
 
     [
@@ -179,7 +181,7 @@ module GitlabMarkdownHelper
 
   def file_exists?(path)
     return false if path.nil?
-    return @repository.blob_at(current_sha, path).present? || @repository.tree(current_sha, path).entries.any?
+    @repository.blob_at(current_sha, path).present? || @repository.tree(current_sha, path).entries.any?
   end
 
   # Check if the path is pointing to a directory(tree) or a file(blob)
@@ -187,7 +189,7 @@ module GitlabMarkdownHelper
   def local_path(path)
     return "tree" if @repository.tree(current_sha, path).entries.any?
     return "raw" if @repository.blob_at(current_sha, path).image?
-    return "blob"
+    "blob"
   end
 
   def current_sha
@@ -254,4 +256,16 @@ module GitlabMarkdownHelper
       truncated
     end
   end
+
+  def cross_project_reference(project, entity)
+    path = project.path_with_namespace
+
+    if entity.kind_of?(Issue)
+      [path, entity.iid].join('#')
+    elsif entity.kind_of?(MergeRequest)
+      [path, entity.iid].join('!')
+    else
+      raise 'Not supported type'
+    end
+  end
 end
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3386fac8657c0f3e5f85aace844e40b3122d5c08
--- /dev/null
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -0,0 +1,51 @@
+# Shorter routing method for project and project items
+# Since update to rails 4.1.9 we are now allowed to use `/` in project routing
+# so we use nested routing for project resources which include project and
+# project namespace. To avoid writing long methods every time we define shortcuts for
+# some of routing.
+#
+# For example instead of this:
+#
+#   namespace_project_merge_request_path(merge_request.project.namespace, merge_request.projects, merge_request)
+#
+# We can simply use shortcut:
+#
+#   merge_request_path(merge_request)
+#
+module GitlabRoutingHelper
+  def project_path(project, *args)
+    namespace_project_path(project.namespace, project, *args)
+  end
+
+  def edit_project_path(project, *args)
+    edit_namespace_project_path(project.namespace, project, *args)
+  end
+
+  def issue_path(entity, *args)
+    namespace_project_issue_path(entity.project.namespace, entity.project, entity, *args)
+  end
+
+  def merge_request_path(entity, *args)
+    namespace_project_merge_request_path(entity.project.namespace, entity.project, entity, *args)
+  end
+
+  def project_url(project, *args)
+    namespace_project_url(project.namespace, project, *args)
+  end
+
+  def edit_project_url(project, *args)
+    edit_namespace_project_url(project.namespace, project, *args)
+  end
+
+  def issue_url(entity, *args)
+    namespace_project_issue_url(entity.project.namespace, entity.project, entity, *args)
+  end
+
+  def merge_request_url(entity, *args)
+    namespace_project_merge_request_url(entity.project.namespace, entity.project, entity, *args)
+  end
+
+  def project_snippet_url(entity, *args)
+    namespace_project_snippet_url(entity.project.namespace, entity.project, entity, *args)
+  end
+end
diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb
index 7cb1b6f8d1aca34e64a96bc870ca06777d2706bf..e1dda20de858708c6da9be66f40dce1149653bd0 100644
--- a/app/helpers/graph_helper.rb
+++ b/app/helpers/graph_helper.rb
@@ -1,10 +1,10 @@
 module GraphHelper
   def get_refs(repo, commit)
     refs = ""
-    refs += commit.ref_names(repo).join(" ")
+    refs << commit.ref_names(repo).join(' ')
 
     # append note count
-    refs += "[#{@graph.notes[commit.id]}]" if @graph.notes[commit.id] > 0
+    refs << "[#{@graph.notes[commit.id]}]" if @graph.notes[commit.id] > 0
 
     refs
   end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 0dc53dedeb7bab58f27ac275c0579cb2e3e9cdaa..2d0d0b494f677972e72601fa3a73bf4d22c4d199 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -6,7 +6,7 @@ module GroupsHelper
   def leave_group_message(group)
     "Are you sure you want to leave \"#{group}\" group?"
   end
-  
+
   def should_user_see_group_roles?(user, group)
     if user
       user.is_admin? || group.members.exists?(user_id: user.id)
@@ -33,15 +33,23 @@ module GroupsHelper
     title
   end
 
-  def group_filter_path(entity, options={})
-    exist_opts = {
-      status: params[:status]
-    }
+  def group_settings_page?
+    if current_controller?('groups')
+      current_action?('edit') || current_action?('projects')
+    else
+      false
+    end
+  end
 
-    options = exist_opts.merge(options)
+  def group_icon(group)
+    if group.is_a?(String)
+      group = Group.find_by(path: group)
+    end
 
-    path = request.path
-    path << "?#{options.to_param}"
-    path
+    if group && group.avatar.present?
+      group.avatar.url
+    else
+      image_path('no_group_avatar.png')
+    end
   end
 end
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
index aaa8f8d0077565d14b5ccdf3d18db1c7cfcf675e..187e21832f0f30da19d7c1bfb0d2d96e7c8ede3d 100644
--- a/app/helpers/icons_helper.rb
+++ b/app/helpers/icons_helper.rb
@@ -1,21 +1,83 @@
 module IconsHelper
+  # Creates an icon tag given icon name(s) and possible icon modifiers.
+  #
+  # Right now this method simply delegates directly to `fa_icon` from the
+  # font-awesome-rails gem, but should we ever use a different icon pack in the
+  # future we won't have to change hundreds of method calls.
+  def icon(names, options = {})
+    fa_icon(names, options)
+  end
+
+  def spinner(text = nil, visible = false)
+    css_class = 'loading'
+    css_class << ' hide' unless visible
+
+    content_tag :div, class: css_class do
+      icon('spinner spin') + text
+    end
+  end
+
   def boolean_to_icon(value)
     if value.to_s == "true"
-      content_tag :i, nil, class: 'fa fa-circle cgreen'
+      icon('circle', class: 'cgreen')
     else
-      content_tag :i, nil, class: 'fa fa-power-off clgray'
+      icon('power-off', class: 'clgray')
     end
   end
 
   def public_icon
-    content_tag :i, nil, class: 'fa fa-globe'
+    icon('globe')
   end
 
   def internal_icon
-    content_tag :i, nil, class: 'fa fa-shield'
+    icon('shield')
   end
 
   def private_icon
-    content_tag :i, nil, class: 'fa fa-lock'
+    icon('lock')
+  end
+
+  def file_type_icon_class(type, mode, name)
+    if type == 'folder'
+      icon_class = 'folder'
+    elsif mode == 0120000
+      icon_class = 'share'
+    else
+      # Guess which icon to choose based on file extension.
+      # If you think a file extension is missing, feel free to add it on PR
+
+      case File.extname(name).downcase
+      when '.pdf'
+        icon_class = 'file-pdf-o'
+      when '.jpg', '.jpeg', '.jif', '.jfif',
+          '.jp2', '.jpx', '.j2k', '.j2c',
+          '.png', '.gif', '.tif', '.tiff',
+          '.svg', '.ico', '.bmp'
+        icon_class = 'file-image-o'
+      when '.zip', '.zipx', '.tar', '.gz', '.bz', '.bzip',
+          '.xz', '.rar', '.7z'
+        icon_class = 'file-archive-o'
+      when '.mp3', '.wma', '.ogg', '.oga', '.wav', '.flac', '.aac'
+        icon_class = 'file-audio-o'
+      when '.mp4', '.m4p', '.m4v',
+          '.mpg', '.mp2', '.mpeg', '.mpe', '.mpv',
+          '.mpg', '.mpeg', '.m2v',
+          '.avi', '.mkv', '.flv', '.ogv', '.mov',
+          '.3gp', '.3g2'
+        icon_class = 'file-video-o'
+      when '.doc', '.dot', '.docx', '.docm', '.dotx', '.dotm', '.docb'
+        icon_class = 'file-word-o'
+      when '.xls', '.xlt', '.xlm', '.xlsx', '.xlsm', '.xltx', '.xltm',
+          '.xlsb', '.xla', '.xlam', '.xll', '.xlw'
+        icon_class = 'file-excel-o'
+      when '.ppt', '.pot', '.pps', '.pptx', '.pptm', '.potx', '.potm',
+          '.ppam', '.ppsx', '.ppsm', '.sldx', '.sldm'
+        icon_class = 'file-powerpoint-o'
+      else
+        icon_class = 'file-text-o'
+      end
+    end
+
+    icon_class
   end
 end
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index d513e0ba58ef9a8ca5bdd3a203582fdaffa17092..a4bd4d30215ea025e69946b7b5d93928d40e890b 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -16,45 +16,25 @@ module IssuesHelper
   def url_for_project_issues(project = @project)
     return '' if project.nil?
 
-    if project.used_default_issues_tracker? || !external_issues_tracker_enabled?
-      project_issues_path(project)
-    else
-      url = Gitlab.config.issues_tracker[project.issues_tracker]['project_url']
-      url.gsub(':project_id', project.id.to_s).
-          gsub(':issues_tracker_id', project.issues_tracker_id.to_s)
-    end
+    project.issues_tracker.project_url
   end
 
   def url_for_new_issue(project = @project)
     return '' if project.nil?
 
-    if project.used_default_issues_tracker? || !external_issues_tracker_enabled?
-      url = new_project_issue_path project_id: project
-    else
-      issues_tracker = Gitlab.config.issues_tracker[project.issues_tracker]
-      url = issues_tracker['new_issue_url']
-      url.gsub(':project_id', project.id.to_s).
-          gsub(':issues_tracker_id', project.issues_tracker_id.to_s)
-    end
+    project.issues_tracker.new_issue_url
   end
 
   def url_for_issue(issue_iid, project = @project)
     return '' if project.nil?
 
-    if project.used_default_issues_tracker? || !external_issues_tracker_enabled?
-      url = project_issue_url project_id: project, id: issue_iid
-    else
-      url = Gitlab.config.issues_tracker[project.issues_tracker]['issues_url']
-      url.gsub(':id', issue_iid.to_s).
-          gsub(':project_id', project.id.to_s).
-          gsub(':issues_tracker_id', project.issues_tracker_id.to_s)
-    end
+    project.issues_tracker.issue_url(issue_iid)
   end
 
   def title_for_issue(issue_iid, project = @project)
     return '' if project.nil?
 
-    if project.used_default_issues_tracker?
+    if project.default_issues_tracker?
       issue = project.issues.where(iid: issue_iid).first
       return issue.title if issue
     end
@@ -67,36 +47,22 @@ module IssuesHelper
     ts = "#{time_ago_with_tooltip(issue.created_at, 'bottom', 'note_created_ago')}"
     if issue.updated_at != issue.created_at
       ts << capture_haml do
-        haml_tag :small do
-          haml_concat " (Edited #{time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_edited_ago')})"
+        haml_tag :span do
+          haml_concat '&middot;'
+          haml_concat icon('edit', title: 'edited')
+          haml_concat time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_edited_ago')
         end
       end
     end
     ts.html_safe
   end
 
-  # Checks if issues_tracker setting exists in gitlab.yml
-  def external_issues_tracker_enabled?
-    Gitlab.config.issues_tracker && Gitlab.config.issues_tracker.values.any?
-  end
-
   def bulk_update_milestone_options
-    options_for_select(['None (backlog)']) +
+    options_for_select([['None (backlog)', -1]]) +
         options_from_collection_for_select(project_active_milestones, 'id',
                                            'title', params[:milestone_id])
   end
 
-  def bulk_update_assignee_options(project = @project)
-    options_for_select(['None (unassigned)']) +
-        options_from_collection_for_select(project.team.members, 'id',
-                                           'name', params[:assignee_id])
-  end
-
-  def assignee_options(object, project = @project)
-    options_from_collection_for_select(project.team.members.sort_by(&:name),
-                                       'id', 'name', object.assignee_id)
-  end
-
   def milestone_options(object)
     options_from_collection_for_select(object.project.milestones.active,
                                        'id', 'title', object.milestone_id)
@@ -113,4 +79,21 @@ module IssuesHelper
       'issue-box-open'
     end
   end
+
+  def issue_to_atom(xml, issue)
+    xml.entry do
+      xml.id      namespace_project_issue_url(issue.project.namespace,
+                                              issue.project, issue)
+      xml.link    href: namespace_project_issue_url(issue.project.namespace,
+                                                    issue.project, issue)
+      xml.title   truncate(issue.title, length: 80)
+      xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
+      xml.media   :thumbnail, width: "40", height: "40", url: avatar_icon(issue.author_email)
+      xml.author do |author|
+        xml.name issue.author_name
+        xml.email issue.author_email
+      end
+      xml.summary issue.title
+    end
+  end
 end
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 19d688c4bb89e29769b9a93add88ad9dba24eaec..32ef2e7ca8416c7ea3cacb1961370d0bc4092c29 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -7,21 +7,34 @@ module LabelsHelper
     label_color = label.color || Label::DEFAULT_COLOR
     text_color = text_color_for_bg(label_color)
 
-    content_tag :span, class: 'label color-label', style: "background:#{label_color};color:#{text_color}" do
+    content_tag :span, class: 'label color-label', style: "background-color:#{label_color};color:#{text_color}" do
       label.name
     end
   end
 
   def suggested_colors
     [
-      '#D9534F',
-      '#F0AD4E',
+      '#0033CC',
       '#428BCA',
+      '#44AD8E',
+      '#A8D695',
       '#5CB85C',
+      '#69D100',
+      '#004E00',
       '#34495E',
       '#7F8C8D',
+      '#A295D6',
+      '#5843AD',
       '#8E44AD',
-      '#FFECDB'
+      '#FFECDB',
+      '#AD4363',
+      '#D10069',
+      '#CC0033',
+      '#FF0000',
+      '#D9534F',
+      '#D1D100',
+      '#F0AD4E',
+      '#AD8D43'
     ]
   end
 
@@ -34,4 +47,8 @@ module LabelsHelper
       "#FFF"
     end
   end
+
+  def project_labels_options(project)
+    options_from_collection_for_select(project.labels, 'name', 'name', params[:label_name])
+  end
 end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index fe6fd5832fc0c4d041f617b86801f8c1d4cb7793..54462fd00e3c81687b01226183af68fd5a6acd64 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -1,25 +1,29 @@
 module MergeRequestsHelper
   def new_mr_path_from_push_event(event)
     target_project = event.project.forked_from_project || event.project
-    new_project_merge_request_path(
+    new_namespace_project_merge_request_path(
+      event.project.namespace,
       event.project,
       new_mr_from_push_event(event, target_project)
     )
   end
 
   def new_mr_path_for_fork_from_push_event(event)
-    new_project_merge_request_path(
+    new_namespace_project_merge_request_path(
+      event.project.namespace,
       event.project,
       new_mr_from_push_event(event, event.project.forked_from_project)
     )
   end
 
   def new_mr_from_push_event(event, target_project)
-    return :merge_request => {
-      source_project_id: event.project.id,
-      target_project_id: target_project.id,
-      source_branch: event.branch_name,
-      target_branch: target_project.repository.root_ref
+    {
+      merge_request: {
+        source_project_id: event.project.id,
+        target_project_id: target_project.id,
+        source_branch: event.branch_name,
+        target_branch: target_project.repository.root_ref
+      }
     }
   end
 
@@ -31,7 +35,7 @@ module MergeRequestsHelper
   end
 
   def ci_build_details_path(merge_request)
-    merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha)
+    merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha, merge_request.source_branch)
   end
 
   def merge_path_description(merge_request, separator)
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..282bdf744d2c74119903873abef25835a55134cf
--- /dev/null
+++ b/app/helpers/milestones_helper.rb
@@ -0,0 +1,33 @@
+module MilestonesHelper
+  def milestones_filter_path(opts = {})
+    if @project
+      namespace_project_milestones_path(@project.namespace, @project, opts)
+    elsif @group
+      group_milestones_path(@group, opts)
+    else
+      dashboard_milestones_path(opts)
+    end
+  end
+
+  def milestone_progress_bar(milestone)
+    options = {
+      class: 'progress-bar progress-bar-success',
+      style: "width: #{milestone.percent_complete}%;"
+    }
+
+    content_tag :div, class: 'progress' do
+      content_tag :div, nil, options
+    end
+  end
+
+  def projects_milestones_options
+    milestones =
+      if @project
+        @project.milestones
+      else
+        Milestone.where(project_id: @projects)
+      end.active
+
+    options_from_collection_for_select(milestones, 'id', 'title', params[:milestone_id])
+  end
+end
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index bf25dce23015aed324b1e95719ae5d43b77e62d9..b3132a1f3ba1e43e289a196793503182a2b5e07e 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -25,4 +25,12 @@ module NamespacesHelper
 
     hidden_field_tag(id, value, class: css_class)
   end
+
+  def namespace_icon(namespace, size = 40)
+    if namespace.kind_of?(Group)
+      group_icon(namespace)
+    else
+      avatar_icon(namespace.owner.email, size)
+    end
+  end
 end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2b03269800ec0091bf806d84aec751a30b12e044
--- /dev/null
+++ b/app/helpers/nav_helper.rb
@@ -0,0 +1,5 @@
+module NavHelper
+  def nav_menu_collapsed?
+    cookies[:collapsed_nav] == 'true'
+  end
+end
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index 901052edec6932d54e5f338718e74ba6a428aa4d..ab44fa6ee4300aecda8bc3a2cb5d80b67bac0615 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -1,17 +1,21 @@
 module NotesHelper
-   # Helps to distinguish e.g. commit notes in mr notes list
+  # Helps to distinguish e.g. commit notes in mr notes list
   def note_for_main_target?(note)
     (@noteable.class.name == note.noteable_type && !note.for_diff_line?)
   end
 
-  def note_target_fields
-    hidden_field_tag(:target_type, @target_type) +
-    hidden_field_tag(:target_id, @target_id)
+  def note_target_fields(note)
+    hidden_field_tag(:target_type, note.noteable.class.name.underscore) +
+    hidden_field_tag(:target_id, note.noteable.id)
   end
 
   def link_to_commit_diff_line_note(note)
     if note.for_commit_diff_line?
-      link_to "#{note.diff_file_name}:L#{note.diff_new_line}", project_commit_path(@project, note.noteable, anchor: note.line_code)
+      link_to(
+        "#{note.diff_file_name}:L#{note.diff_new_line}",
+        namespace_project_commit_path(@project.namespace, @project,
+                                      note.noteable, anchor: note.line_code)
+      )
     end
   end
 
@@ -20,8 +24,10 @@ module NotesHelper
     ts = "#{time_ago_with_tooltip(note.created_at, 'bottom', 'note_created_ago')}"
     if note.updated_at != note.created_at
       ts << capture_haml do
-        haml_tag :small do
-          haml_concat " (Edited #{time_ago_with_tooltip(note.updated_at, 'bottom', 'note_edited_ago')})"
+        haml_tag :span do
+          haml_concat '&middot;'
+          haml_concat icon('edit', title: 'edited')
+          haml_concat time_ago_with_tooltip(note.updated_at, 'bottom', 'note_edited_ago')
         end
       end
     end
@@ -52,8 +58,11 @@ module NotesHelper
       discussion_id: discussion_id
     }
 
-    button_tag '', class: 'btn add-diff-note js-add-diff-note-button',
-               data: data, title: 'Add a comment to this line'
+    button_tag(class: 'btn add-diff-note js-add-diff-note-button',
+               data: data,
+               title: 'Add a comment to this line') do
+      icon('comment-o')
+    end
   end
 
   def link_to_reply_diff(note)
@@ -69,7 +78,7 @@ module NotesHelper
 
     button_tag class: 'btn reply-btn js-discussion-reply-button',
                data: data, title: 'Add a reply' do
-      link_text = content_tag(:i, nil, class: 'fa fa-comment')
+      link_text = icon('comment')
       link_text << ' Reply'
     end
   end
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index bad380e98a8e5a95e27943726466bdf4e9ef0e35..f771fe761efc19e9adb674845c2a2b3fe7edbf1e 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -1,13 +1,13 @@
 module NotificationsHelper
   def notification_icon(notification)
     if notification.disabled?
-      content_tag :i, nil, class: 'fa fa-volume-off ns-mute'
+      icon('volume-off', class: 'ns-mute')
     elsif notification.participating?
-      content_tag :i, nil, class: 'fa fa-volume-down ns-part'
+      icon('volume-down', class: 'ns-part')
     elsif notification.watch?
-      content_tag :i, nil, class: 'fa fa-volume-up ns-watch'
+      icon('volume-up', class: 'ns-watch')
     else
-      content_tag :i, nil, class: 'fa fa-circle-o ns-default'
+      icon('circle-o', class: 'ns-default')
     end
   end
 end
diff --git a/app/helpers/oauth_helper.rb b/app/helpers/oauth_helper.rb
index 7024483b8b3ad0bbba7066b107782ac32f82b3e8..997b91de07764368c19d530942160685d8fb7dd0 100644
--- a/app/helpers/oauth_helper.rb
+++ b/app/helpers/oauth_helper.rb
@@ -4,7 +4,7 @@ module OauthHelper
   end
 
   def default_providers
-    [:twitter, :github, :google_oauth2, :ldap]
+    [:twitter, :github, :gitlab, :bitbucket, :google_oauth2, :ldap]
   end
 
   def enabled_oauth_providers
@@ -13,7 +13,22 @@ module OauthHelper
 
   def enabled_social_providers
     enabled_oauth_providers.select do |name|
-      [:twitter, :github, :google_oauth2].include?(name.to_sym)
+      [:twitter, :gitlab, :github, :bitbucket, :google_oauth2].include?(name.to_sym)
     end
   end
+
+  def additional_providers
+    enabled_oauth_providers.reject{|provider| provider.to_s.starts_with?('ldap')}
+  end
+
+  def oauth_image_tag(provider, size = 64)
+    file_name = "#{provider.to_s.split('_').first}_#{size}.png"
+    image_tag(image_path("authbuttons/#{file_name}"), alt: "Sign in with #{provider.to_s.titleize}")
+  end
+
+  def oauth_active?(provider)
+    current_user.identities.exists?(provider: provider.to_s)
+  end
+
+  extend self
 end
diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb
index 0b3755583053c7b3c2aa780f36e9c7bebaaa5a70..780c7cd51332193bb526402232fd36ad26d6cb7c 100644
--- a/app/helpers/profile_helper.rb
+++ b/app/helpers/profile_helper.rb
@@ -1,19 +1,13 @@
 module ProfileHelper
-  def oauth_active_class(provider)
-    if current_user.provider == provider.to_s
-      'active'
-    end
-  end
-
   def show_profile_username_tab?
     current_user.can_change_username?
   end
 
   def show_profile_social_tab?
-    enabled_social_providers.any? && !current_user.ldap_user?
+    enabled_social_providers.any?
   end
 
   def show_profile_remove_tab?
-    gitlab_config.signup_enabled && !current_user.ldap_user?
+    signup_enabled?
   end
 end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index fb5470d98e57c2caf34382619fbdd6716a0a5ee3..e3734023be3142c25e1ce000cfce04cef937ffc5 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -4,7 +4,7 @@ module ProjectsHelper
   end
 
   def link_to_project(project)
-    link_to project do
+    link_to [project.namespace.becomes(Namespace), project] do
       title = content_tag(:span, project.name, class: 'project-name')
 
       if project.namespace
@@ -42,12 +42,20 @@ module ProjectsHelper
   def project_title(project)
     if project.group
       content_tag :span do
-        link_to(simple_sanitize(project.group.name), group_path(project.group)) + ' / ' + link_to(simple_sanitize(project.name), project_path(project))
+        link_to(
+          simple_sanitize(project.group.name), group_path(project.group)
+        ) + ' / ' +
+          link_to(simple_sanitize(project.name),
+                  project_path(project))
       end
     else
       owner = project.namespace.owner
       content_tag :span do
-        link_to(simple_sanitize(owner.name), user_path(owner)) + ' / ' + link_to(simple_sanitize(project.name), project_path(project))
+        link_to(
+          simple_sanitize(owner.name), user_path(owner)
+        ) + ' / ' +
+          link_to(simple_sanitize(project.name),
+                  project_path(project))
       end
     end
   end
@@ -68,76 +76,22 @@ module ProjectsHelper
     project_nav_tabs.include? name
   end
 
-  def selected_label?(label_name)
-    params[:label_name].to_s.split(',').include?(label_name)
-  end
-
-  def labels_filter_path(label_name)
-    label_name =
-      if selected_label?(label_name)
-        params[:label_name].split(',').reject { |l| l == label_name }.join(',')
-      elsif params[:label_name].present?
-        "#{params[:label_name]},#{label_name}"
-      else
-        label_name
-      end
-
-    project_filter_path(label_name: label_name)
-  end
-
-  def label_filter_class(label_name)
-    if selected_label?(label_name)
-      'label-filter-item active'
-    else
-      'label-filter-item light'
-    end
-  end
-
-  def project_filter_path(options={})
-    exist_opts = {
-      state: params[:state],
-      scope: params[:scope],
-      label_name: params[:label_name],
-      milestone_id: params[:milestone_id],
-      assignee_id: params[:assignee_id],
-      sort: params[:sort],
-    }
-
-    options = exist_opts.merge(options)
-
-    path = request.path
-    path << "?#{options.to_param}"
-    path
-  end
-
   def project_active_milestones
     @project.milestones.active.order("due_date, title ASC")
   end
 
-  def project_issues_trackers(current_tracker = nil)
-    values = Project.issues_tracker.values.map do |tracker_key|
-      if tracker_key.to_sym == :gitlab
-        ['GitLab', tracker_key]
+  def link_to_toggle_star(title, starred)
+    cls = 'star-btn btn btn-sm btn-default'
+
+    toggle_text =
+      if starred
+        ' Unstar'
       else
-        [Gitlab.config.issues_tracker[tracker_key]['title'] || tracker_key, tracker_key]
+        ' Star'
       end
-    end
-
-    options_for_select(values, current_tracker)
-  end
-
-  def link_to_toggle_star(title, starred, signed_in)
-    cls = 'star-btn'
-    cls += ' disabled' unless signed_in
 
     toggle_html = content_tag('span', class: 'toggle') do
-      toggle_text = if starred
-                      ' Unstar'
-                    else
-                      ' Star'
-                    end
-
-      content_tag('i', ' ', class: 'fa fa-star') + toggle_text
+      icon('star') + toggle_text
     end
 
     count_html = content_tag('span', class: 'count') do
@@ -149,23 +103,28 @@ module ProjectsHelper
       class: cls,
       method: :post,
       remote: true,
-      data: {type: 'json'}
+      data: { type: 'json' }
     }
 
+    path = toggle_star_namespace_project_path(@project.namespace, @project)
 
     content_tag 'span', class: starred ? 'turn-on' : 'turn-off' do
-      link_to toggle_star_project_path(@project), link_opts do
+      link_to(path, link_opts) do
         toggle_html + ' ' + count_html
       end
     end
   end
 
   def link_to_toggle_fork
-    out = content_tag(:i, '', class: 'fa fa-code-fork')
-    out << ' Fork'
-    out << content_tag(:span, class: 'count') do
+    html = content_tag('span') do
+      icon('code-fork') + ' Fork'
+    end
+
+    count_html = content_tag(:span, class: 'count') do
       @project.forks_count.to_s
     end
+
+    html + count_html
   end
 
   private
@@ -189,6 +148,10 @@ module ProjectsHelper
       nav_tabs << feature if project.send :"#{feature}_enabled"
     end
 
+    if project.issues_enabled || project.merge_requests_enabled
+      nav_tabs << [:milestones, :labels]
+    end
+
     nav_tabs.flatten
   end
 
@@ -229,7 +192,13 @@ module ProjectsHelper
                 "Issues - " + title
               end
             elsif current_controller?(:blob)
-              "#{@project.path}\/#{@blob.path} at #{@ref} - " + title
+              if current_action?(:new) || current_action?(:create)
+                "New file at #{@ref}"
+              elsif current_action?(:show)
+                "#{@blob.path} at #{@ref}"
+              elsif @blob
+                "Edit file #{@blob.path} at #{@ref}"
+              end
             elsif current_controller?(:commits)
               "Commits at #{@ref} - " + title
             elsif current_controller?(:merge_requests)
@@ -269,14 +238,80 @@ module ProjectsHelper
   end
 
   def contribution_guide_url(project)
-    if project && project.repository.contribution_guide
-      project_blob_path(project, tree_join(project.default_branch, project.repository.contribution_guide.name))
+    if project && contribution_guide = project.repository.contribution_guide
+      namespace_project_blob_path(
+        project.namespace,
+        project,
+        tree_join(project.default_branch,
+                  contribution_guide.name)
+      )
+    end
+  end
+
+  def changelog_url(project)
+    if project && changelog = project.repository.changelog
+      namespace_project_blob_path(
+        project.namespace,
+        project,
+        tree_join(project.default_branch,
+                  changelog.name)
+      )
+    end
+  end
+
+  def license_url(project)
+    if project && license = project.repository.license
+      namespace_project_blob_path(
+        project.namespace,
+        project,
+        tree_join(project.default_branch,
+                  license.name)
+      )
+    end
+  end
+
+  def version_url(project)
+    if project && version = project.repository.version
+      namespace_project_blob_path(
+        project.namespace,
+        project,
+        tree_join(project.default_branch,
+                  version.name)
+      )
     end
   end
 
   def hidden_pass_url(original_url)
     result = URI(original_url)
-    result.password = '*****' if result.password.present?
+    result.password = '*****' unless result.password.nil?
     result
+  rescue
+    original_url
+  end
+
+  def project_wiki_path_with_version(proj, page, version, is_newest)
+    url_params = is_newest ? {} : { version_id: version }
+    namespace_project_wiki_path(proj.namespace, proj, page, url_params)
+  end
+
+  def project_status_css_class(status)
+    case status
+    when "started"
+      "active"
+    when "failed"
+      "danger"
+    when "finished"
+      "success"
+    end
+  end
+
+  def service_field_value(type, value)
+    return value unless type == 'password'
+
+    if value.present?
+      "***********"
+    else
+      nil
+    end
   end
 end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 65b9408cfa1e45b51fd922805fa3a5c5a1bef2c7..c31a556ff7b3d83a0ab6663713eb0d21b98b3893 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -23,9 +23,9 @@ module SearchHelper
   # Autocomplete results for various settings pages
   def default_autocomplete
     [
-      { label: "My Profile settings", url: profile_path },
-      { label: "My SSH Keys",         url: profile_keys_path },
-      { label: "My Dashboard",        url: root_path },
+      { label: "Profile settings", url: profile_path },
+      { label: "SSH Keys",         url: profile_keys_path },
+      { label: "Dashboard",        url: root_path },
       { label: "Admin Section",       url: admin_root_path },
     ]
   end
@@ -52,16 +52,16 @@ module SearchHelper
       ref    = @ref || @project.repository.root_ref
 
       [
-        { label: "#{prefix} - Files",          url: project_tree_path(@project, ref) },
-        { label: "#{prefix} - Commits",        url: project_commits_path(@project, ref) },
-        { label: "#{prefix} - Network",        url: project_network_path(@project, ref) },
-        { label: "#{prefix} - Graph",          url: project_graph_path(@project, ref) },
-        { label: "#{prefix} - Issues",         url: project_issues_path(@project) },
-        { label: "#{prefix} - Merge Requests", url: project_merge_requests_path(@project) },
-        { label: "#{prefix} - Milestones",     url: project_milestones_path(@project) },
-        { label: "#{prefix} - Snippets",       url: project_snippets_path(@project) },
-        { label: "#{prefix} - Team",           url: project_team_index_path(@project) },
-        { label: "#{prefix} - Wiki",           url: project_wikis_path(@project) },
+        { label: "#{prefix} - Files",          url: namespace_project_tree_path(@project.namespace, @project, ref) },
+        { label: "#{prefix} - Commits",        url: namespace_project_commits_path(@project.namespace, @project, ref) },
+        { label: "#{prefix} - Network",        url: namespace_project_network_path(@project.namespace, @project, ref) },
+        { label: "#{prefix} - Graph",          url: namespace_project_graph_path(@project.namespace, @project, ref) },
+        { label: "#{prefix} - Issues",         url: namespace_project_issues_path(@project.namespace, @project) },
+        { label: "#{prefix} - Merge Requests", url: namespace_project_merge_requests_path(@project.namespace, @project) },
+        { label: "#{prefix} - Milestones",     url: namespace_project_milestones_path(@project.namespace, @project) },
+        { label: "#{prefix} - Snippets",       url: namespace_project_snippets_path(@project.namespace, @project) },
+        { label: "#{prefix} - Members",        url: namespace_project_project_members_path(@project.namespace, @project) },
+        { label: "#{prefix} - Wiki",           url: namespace_project_wikis_path(@project.namespace, @project) },
       ]
     else
       []
@@ -84,7 +84,7 @@ module SearchHelper
       sorted_by_stars.non_archived.limit(limit).map do |p|
       {
         label: "project: #{search_result_sanitize(p.name_with_namespace)}",
-        url: project_path(p)
+        url: namespace_project_path(p.namespace, p)
       }
     end
   end
diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb
index ab24367c45521eccacd14ef5a34b310c277c3d21..457cd3fa46b697d4f83bf36d1ca00646b60f6c05 100644
--- a/app/helpers/selects_helper.rb
+++ b/app/helpers/selects_helper.rb
@@ -4,17 +4,35 @@ module SelectsHelper
     css_class << "multiselect " if opts[:multiple]
     css_class << (opts[:class] || '')
     value = opts[:selected] || ''
+    placeholder = opts[:placeholder] || 'Search for a user'
 
-    hidden_field_tag(id, value, class: css_class)
+    null_user = opts[:null_user] || false
+    any_user = opts[:any_user] || false
+
+    html = {
+      class: css_class,
+      'data-placeholder' => placeholder,
+      'data-null-user' => null_user,
+      'data-any-user' => any_user,
+    }
+
+    unless opts[:scope] == :all
+      if @project
+        html['data-project-id'] = @project.id
+      elsif @group
+        html['data-group-id'] = @group.id
+      end
+    end
+
+    hidden_field_tag(id, value, html)
   end
 
-  def project_users_select_tag(id, opts = {})
-    css_class = "ajax-project-users-select "
+  def groups_select_tag(id, opts = {})
+    css_class = "ajax-groups-select "
     css_class << "multiselect " if opts[:multiple]
     css_class << (opts[:class] || '')
     value = opts[:selected] || ''
-    placeholder = opts[:placeholder] || 'Select user'
-    project_id = opts[:project_id] || @project.id
-    hidden_field_tag(id, value, class: css_class, 'data-placeholder' => placeholder, 'data-project-id' => project_id)
+
+    hidden_field_tag(id, value, class: css_class)
   end
 end
diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb
index b0abc2cae339eb71b2a699a4394fe8492bf44ccc..906cb12cd48f911c0e1fde91be1a577315c682e7 100644
--- a/app/helpers/snippets_helper.rb
+++ b/app/helpers/snippets_helper.rb
@@ -11,7 +11,8 @@ module SnippetsHelper
 
   def reliable_snippet_path(snippet)
     if snippet.project_id?
-      project_snippet_path(snippet.project, snippet)
+      namespace_project_snippet_path(snippet.project.namespace,
+                                     snippet.project, snippet)
     else
       snippet_path(snippet)
     end
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..bb12d43f3972c040a4b8e21df990e71768f68c5e
--- /dev/null
+++ b/app/helpers/sorting_helper.rb
@@ -0,0 +1,96 @@
+module SortingHelper
+  def sort_options_hash
+    {
+      sort_value_name => sort_title_name,
+      sort_value_recently_updated => sort_title_recently_updated,
+      sort_value_oldest_updated => sort_title_oldest_updated,
+      sort_value_recently_created => sort_title_recently_created,
+      sort_value_oldest_created => sort_title_oldest_created,
+      sort_value_milestone_soon => sort_title_milestone_soon,
+      sort_value_milestone_later => sort_title_milestone_later,
+      sort_value_largest_repo => sort_title_largest_repo,
+      sort_value_recently_signin => sort_title_recently_signin,
+      sort_value_oldest_signin => sort_title_oldest_signin,
+    }
+  end
+
+  def sort_title_oldest_updated
+    'Oldest updated'
+  end
+
+  def sort_title_recently_updated
+    'Recently updated'
+  end
+
+  def sort_title_oldest_created
+    'Oldest created'
+  end
+
+  def sort_title_recently_created
+    'Recently created'
+  end
+
+  def sort_title_milestone_soon
+    'Milestone due soon'
+  end
+
+  def sort_title_milestone_later
+    'Milestone due later'
+  end
+
+  def sort_title_name
+    'Name'
+  end
+
+  def sort_title_largest_repo
+    'Largest repository'
+  end
+
+  def sort_title_recently_signin
+    'Recent sign in'
+  end
+
+  def sort_title_oldest_signin
+    'Oldest sign in'
+  end
+
+  def sort_value_oldest_updated
+    'updated_asc'
+  end
+
+  def sort_value_recently_updated
+    'updated_desc'
+  end
+
+  def sort_value_oldest_created
+    'created_asc'
+  end
+
+  def sort_value_recently_created
+    'created_desc'
+  end
+
+  def sort_value_milestone_soon
+    'milestone_due_asc'
+  end
+
+  def sort_value_milestone_later
+    'milestone_due_desc'
+  end
+
+  def sort_value_name
+    'name_asc'
+  end
+
+  def sort_value_largest_repo
+    'repository_size_desc'
+  end
+
+  def sort_value_recently_signin
+    'recent_sign_in'
+  end
+
+  def sort_value_oldest_signin
+    'oldest_sign_in'
+  end
+end
diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb
index 09e5c08e621cbd7883e54acb732a36904bb9d092..241462e5e4c2ba5abd2789767c5aee4153c0d4a9 100644
--- a/app/helpers/submodule_helper.rb
+++ b/app/helpers/submodule_helper.rb
@@ -2,22 +2,25 @@ module SubmoduleHelper
   include Gitlab::ShellAdapter
 
   # links to files listing for submodule if submodule is a project on this server
-  def submodule_links(submodule_item)
-    url = @repository.submodule_url_for(@ref, submodule_item.path)
+  def submodule_links(submodule_item, ref = nil)
+    url = @repository.submodule_url_for(ref, submodule_item.path)
 
-    return url, nil unless url =~ /([^\/:]+\/[^\/]+\.git)\Z/
+    return url, nil unless url =~ /([^\/:]+)\/([^\/]+\.git)\Z/
 
-    project = $1
+    namespace = $1
+    project = $2
     project.chomp!('.git')
 
-    if self_url?(url, project)
-      return project_path(project), project_tree_path(project, submodule_item.id)
+    if self_url?(url, namespace, project)
+      return namespace_project_path(namespace, project),
+        namespace_project_tree_path(namespace, project,
+                                    submodule_item.id)
     elsif relative_self_url?(url)
       relative_self_links(url, submodule_item.id)
     elsif github_dot_com_url?(url)
-      standard_links('github.com', project, submodule_item.id)
+      standard_links('github.com', namespace, project, submodule_item.id)
     elsif gitlab_dot_com_url?(url)
-      standard_links('gitlab.com', project, submodule_item.id)
+      standard_links('gitlab.com', namespace, project, submodule_item.id)
     else
       return url, nil
     end
@@ -33,9 +36,10 @@ module SubmoduleHelper
     url =~ /gitlab\.com[\/:][^\/]+\/[^\/]+\Z/
   end
 
-  def self_url?(url, project)
-    return true if url == [ Gitlab.config.gitlab.url, '/', project, '.git' ].join('')
-    url == gitlab_shell.url_to_repo(project)
+  def self_url?(url, namespace, project)
+    return true if url == [ Gitlab.config.gitlab.url, '/', namespace, '/',
+                            project, '.git' ].join('')
+    url == gitlab_shell.url_to_repo([namespace, '/', project].join(''))
   end
 
   def relative_self_url?(url)
@@ -43,9 +47,9 @@ module SubmoduleHelper
     url =~ /^((\.\/)?(\.\.\/))(?!(\.\.)|(.*\/)).*\.git\Z/ || url =~ /^((\.\/)?(\.\.\/){2})(?!(\.\.))([^\/]*)\/(?!(\.\.)|(.*\/)).*\.git\Z/
   end
 
-  def standard_links(host, project, commit)
-    base = [ 'https://', host, '/', project ].join('')
-    return base, [ base, '/tree/', commit ].join('')
+  def standard_links(host, namespace, project, commit)
+    base = [ 'https://', host, '/', namespace, '/', project ].join('')
+    [base, [ base, '/tree/', commit ].join('')]
   end
 
   def relative_self_links(url, commit)
@@ -54,6 +58,10 @@ module SubmoduleHelper
     else
       base = [ @project.group.path, '/', url[/([^\/]*)\.git/, 1] ].join('')
     end
-    return project_path(base), project_tree_path(base, commit)
+
+    [
+      namespace_project_path(base.namespace, base),
+      namespace_project_tree_path(base.namespace, base, commit)
+    ]
   end
 end
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index bc43e07856841d0d858b7ea0c1e5602585c409e1..a1d263d9d3a92369fa5083e4d33290923b21ac94 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -28,6 +28,10 @@ module TabHelper
   #   nav_link(controller: [:tree, :refs]) { "Hello" }
   #   # => '<li class="active">Hello</li>'
   #
+  #   # Several paths
+  #   nav_link(path: ['tree#show', 'profile#show']) { "Hello" }
+  #   # => '<li class="active">Hello</li>'
+  #
   #   # Shorthand path
   #   nav_link(path: 'tree#show') { "Hello" }
   #   # => '<li class="active">Hello</li>'
@@ -38,25 +42,7 @@ module TabHelper
   #
   # Returns a list item element String
   def nav_link(options = {}, &block)
-    if path = options.delete(:path)
-      if path.respond_to?(:each)
-        c = path.map { |p| p.split('#').first }
-        a = path.map { |p| p.split('#').last }
-      else
-        c, a, _ = path.split('#')
-      end
-    else
-      c = options.delete(:controller)
-      a = options.delete(:action)
-    end
-
-    if c && a
-      # When given both options, make sure BOTH are active
-      klass = current_controller?(*c) && current_action?(*a) ? 'active' : ''
-    else
-      # Otherwise check EITHER option
-      klass = current_controller?(*c) || current_action?(*a) ? 'active' : ''
-    end
+    klass = active_nav_link?(options) ? 'active' : ''
 
     # Add our custom class into the html_options, which may or may not exist
     # and which may or may not already have a :class key
@@ -72,18 +58,47 @@ module TabHelper
     end
   end
 
+  def active_nav_link?(options)
+    if path = options.delete(:path)
+      unless path.respond_to?(:each)
+        path = [path]
+      end
+
+      path.any? do |single_path|
+        current_path?(single_path)
+      end
+    else
+      c = options.delete(:controller)
+      a = options.delete(:action)
+
+      if c && a
+        # When given both options, make sure BOTH are true
+        current_controller?(*c) && current_action?(*a)
+      else
+        # Otherwise check EITHER option
+        current_controller?(*c) || current_action?(*a)
+      end
+    end
+  end
+
+  def current_path?(path)
+    c, a, _ = path.split('#')
+    current_controller?(c) && current_action?(a)
+  end
+
   def project_tab_class
     return "active" if current_page?(controller: "/projects", action: :edit, id: @project)
 
-    if ['services', 'hooks', 'deploy_keys', 'team_members', 'protected_branches'].include? controller.controller_name
-     "active"
+    if ['services', 'hooks', 'deploy_keys', 'project_members', 'protected_branches'].include? controller.controller_name
+      "active"
     end
   end
 
   def branches_tab_class
     if current_controller?(:protected_branches) ||
       current_controller?(:branches) ||
-      current_page?(project_repository_path(@project))
+      current_page?(namespace_project_repository_path(@project.namespace,
+                                                      @project))
       'active'
     end
   end
diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb
index ef89bb32c6d4fb82418dbe853bcb736a20510e77..fb85544df2d7a9da130de651631bf962562cfd6a 100644
--- a/app/helpers/tags_helper.rb
+++ b/app/helpers/tags_helper.rb
@@ -6,7 +6,7 @@ module TagsHelper
   def tag_list(project)
     html = ''
     project.tag_list.each do |tag|
-      html += link_to tag, tag_path(tag)
+      html << link_to(tag, tag_path(tag))
     end
 
     html.html_safe
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 8e2094983231c4c9bd2b2ac0fc6eb4e6c1e7cc3e..6dd9b6f017cc909f3f125ec31b7b97dc12db0944 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -10,13 +10,16 @@ module TreeHelper
     tree = ""
 
     # Render folders if we have any
-    tree += render partial: 'projects/tree/tree_item', collection: folders, locals: {type: 'folder'} if folders.present?
+    tree << render(partial: 'projects/tree/tree_item', collection: folders,
+                   locals: { type: 'folder' }) if folders.present?
 
     # Render files if we have any
-    tree += render partial: 'projects/tree/blob_item', collection: files, locals: {type: 'file'} if files.present?
+    tree << render(partial: 'projects/tree/blob_item', collection: files,
+                   locals: { type: 'file' }) if files.present?
 
     # Render submodules if we have any
-    tree += render partial: 'projects/tree/submodule_item', collection: submodules if submodules.present?
+    tree << render(partial: 'projects/tree/submodule_item',
+                   collection: submodules) if submodules.present?
 
     tree.html_safe
   end
@@ -31,17 +34,13 @@ module TreeHelper
     end
   end
 
-  # Return an image icon depending on the file type
+  # Return an image icon depending on the file type and mode
   #
   # type - String type of the tree item; either 'folder' or 'file'
-  def tree_icon(type)
-    icon_class = if type == 'folder'
-                   'fa fa-folder'
-                 else
-                   'fa fa-file-o'
-                 end
-
-    content_tag :i, nil, class: icon_class
+  # mode - File unix mode
+  # name - File name
+  def tree_icon(type, mode, name)
+    icon("#{file_type_icon_class(type, mode, name)} fw")
   end
 
   def tree_hex_class(content)
@@ -53,14 +52,12 @@ module TreeHelper
     File.join(*args)
   end
 
-  def allowed_tree_edit?
-    return false unless @repository.branch_names.include?(@ref)
+  def allowed_tree_edit?(project = nil, ref = nil)
+    project ||= @project
+    ref ||= @ref
+    return false unless project.repository.branch_names.include?(ref)
 
-    if @project.protected_branch? @ref
-      can?(current_user, :push_code_to_protected_branches, @project)
-    else
-      can?(current_user, :push_code, @project)
-    end
+    ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(ref)
   end
 
   def tree_breadcrumbs(tree, max_links = 2)
@@ -80,20 +77,18 @@ module TreeHelper
     end
   end
 
-  def up_dir_path(tree)
+  def up_dir_path
     file = File.join(@path, "..")
     tree_join(@ref, file)
   end
 
-  def leave_edit_message
-    "Leave edit mode?\nAll unsaved changes will be lost."
-  end
-
-  def editing_preview_title(filename)
-    if Gitlab::MarkdownHelper.previewable?(filename)
-      'Preview'
+  # returns the relative path of the first subdir that doesn't have only one directory descendant
+  def flatten_tree(tree)
+    subtree = Gitlab::Git::Tree.where(@repository, @commit.id, tree.path)
+    if subtree.count == 1 && subtree.first.dir?
+      return tree_join(tree.name, flatten_tree(subtree.first))
     else
-      'Diff'
+      return tree.name
     end
   end
 end
diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb
index deb9c8b4d49f5479ca5b1dbef3638295cbff54ae..0d573e72a80aa93807d869b1436b5fdd070eda13 100644
--- a/app/helpers/visibility_level_helper.rb
+++ b/app/helpers/visibility_level_helper.rb
@@ -60,7 +60,8 @@ module VisibilityLevelHelper
     Project.visibility_levels.key(level)
   end
 
-  def restricted_visibility_levels
-    current_user.is_admin? ? [] : gitlab_config.restricted_visibility_levels
+  def restricted_visibility_levels(show_all = false)
+    return [] if current_user.is_admin? && !show_all
+    current_application_settings.restricted_visibility_levels || []
   end
 end
diff --git a/app/mailers/emails/groups.rb b/app/mailers/emails/groups.rb
index 8c09389985e2f54219c6fb76931a12fcecbdacdd..26f43bf955e8b7d2ea559547f6c9cea5d72fa663 100644
--- a/app/mailers/emails/groups.rb
+++ b/app/mailers/emails/groups.rb
@@ -1,10 +1,10 @@
 module Emails
   module Groups
-    def group_access_granted_email(user_group_id)
-      @membership = GroupMember.find(user_group_id)
-      @group = @membership.group
+    def group_access_granted_email(group_member_id)
+      @group_member = GroupMember.find(group_member_id)
+      @group = @group_member.group
       @target_url = group_url(@group)
-      mail(to: @membership.user.email,
+      mail(to: @group_member.user.email,
            subject: subject("Access to group was granted"))
     end
   end
diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb
index e53462359635e2eafb5da97a65ab764bd1f0146f..687bac3aa31a009de8219bf58624626bee70c60b 100644
--- a/app/mailers/emails/issues.rb
+++ b/app/mailers/emails/issues.rb
@@ -3,7 +3,7 @@ module Emails
     def new_issue_email(recipient_id, issue_id)
       @issue = Issue.find(issue_id)
       @project = @issue.project
-      @target_url = project_issue_url(@project, @issue)
+      @target_url = namespace_project_issue_url(@project.namespace, @project, @issue)
       mail_new_thread(@issue,
                       from: sender(@issue.author_id),
                       to: recipient(recipient_id),
@@ -14,7 +14,7 @@ module Emails
       @issue = Issue.find(issue_id)
       @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
       @project = @issue.project
-      @target_url = project_issue_url(@project, @issue)
+      @target_url = namespace_project_issue_url(@project.namespace, @project, @issue)
       mail_answer_thread(@issue,
                          from: sender(updated_by_user_id),
                          to: recipient(recipient_id),
@@ -25,7 +25,7 @@ module Emails
       @issue = Issue.find issue_id
       @project = @issue.project
       @updated_by = User.find updated_by_user_id
-      @target_url = project_issue_url(@project, @issue)
+      @target_url = namespace_project_issue_url(@project.namespace, @project, @issue)
       mail_answer_thread(@issue,
                          from: sender(updated_by_user_id),
                          to: recipient(recipient_id),
@@ -37,7 +37,7 @@ module Emails
       @issue_status = status
       @project = @issue.project
       @updated_by = User.find updated_by_user_id
-      @target_url = project_issue_url(@project, @issue)
+      @target_url = namespace_project_issue_url(@project.namespace, @project, @issue)
       mail_answer_thread(@issue,
                          from: sender(updated_by_user_id),
                          to: recipient(recipient_id),
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index 9ecdac87d722cddd3c271be681f0e9f1fb673a6a..512a8f7ea6be5034077a1944b066415c61a66b0d 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -3,7 +3,9 @@ module Emails
     def new_merge_request_email(recipient_id, merge_request_id)
       @merge_request = MergeRequest.find(merge_request_id)
       @project = @merge_request.project
-      @target_url = project_merge_request_url(@project, @merge_request)
+      @target_url = namespace_project_merge_request_url(@project.namespace,
+                                                        @project,
+                                                        @merge_request)
       mail_new_thread(@merge_request,
                       from: sender(@merge_request.author_id),
                       to: recipient(recipient_id),
@@ -14,7 +16,9 @@ module Emails
       @merge_request = MergeRequest.find(merge_request_id)
       @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
       @project = @merge_request.project
-      @target_url = project_merge_request_url(@project, @merge_request)
+      @target_url = namespace_project_merge_request_url(@project.namespace,
+                                                        @project,
+                                                        @merge_request)
       mail_answer_thread(@merge_request,
                          from: sender(updated_by_user_id),
                          to: recipient(recipient_id),
@@ -25,7 +29,9 @@ module Emails
       @merge_request = MergeRequest.find(merge_request_id)
       @updated_by = User.find updated_by_user_id
       @project = @merge_request.project
-      @target_url = project_merge_request_url(@project, @merge_request)
+      @target_url = namespace_project_merge_request_url(@project.namespace,
+                                                        @project,
+                                                        @merge_request)
       mail_answer_thread(@merge_request,
                          from: sender(updated_by_user_id),
                          to: recipient(recipient_id),
@@ -35,7 +41,9 @@ module Emails
     def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
       @merge_request = MergeRequest.find(merge_request_id)
       @project = @merge_request.project
-      @target_url = project_merge_request_url(@project, @merge_request)
+      @target_url = namespace_project_merge_request_url(@project.namespace,
+                                                        @project,
+                                                        @merge_request)
       mail_answer_thread(@merge_request,
                          from: sender(updated_by_user_id),
                          to: recipient(recipient_id),
@@ -47,7 +55,9 @@ module Emails
       @mr_status = status
       @project = @merge_request.project
       @updated_by = User.find updated_by_user_id
-      @target_url = project_merge_request_url(@project, @merge_request)
+      @target_url = namespace_project_merge_request_url(@project.namespace,
+                                                        @project,
+                                                        @merge_request)
       set_reference("merge_request_#{merge_request_id}")
       mail_answer_thread(@merge_request,
                          from: sender(updated_by_user_id),
@@ -56,7 +66,7 @@ module Emails
     end
   end
 
-  # Over rides default behavour to show source/target
+  # Over rides default behaviour to show source/target
   # Formats arguments into a String suitable for use as an email subject
   #
   # extra - Extra Strings to be inserted into the subject
diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb
index ef9af726a6cbe68d98c3d161a774dc3e3508744c..ff251209e01e2d6c4f82c61167080f183e378c7c 100644
--- a/app/mailers/emails/notes.rb
+++ b/app/mailers/emails/notes.rb
@@ -4,7 +4,9 @@ module Emails
       @note = Note.find(note_id)
       @commit = @note.noteable
       @project = @note.project
-      @target_url = project_commit_url(@project, @commit, anchor: "note_#{@note.id}")
+      @target_url = namespace_project_commit_url(@project.namespace, @project,
+                                                 @commit, anchor:
+                                                 "note_#{@note.id}")
       mail_answer_thread(@commit,
                          from: sender(@note.author_id),
                          to: recipient(recipient_id),
@@ -15,7 +17,9 @@ module Emails
       @note = Note.find(note_id)
       @issue = @note.noteable
       @project = @note.project
-      @target_url = project_issue_url(@project, @issue, anchor: "note_#{@note.id}")
+      @target_url = namespace_project_issue_url(@project.namespace, @project,
+                                                @issue, anchor:
+                                                "note_#{@note.id}")
       mail_answer_thread(@issue,
                          from: sender(@note.author_id),
                          to: recipient(recipient_id),
@@ -26,7 +30,10 @@ module Emails
       @note = Note.find(note_id)
       @merge_request = @note.noteable
       @project = @note.project
-      @target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{@note.id}")
+      @target_url = namespace_project_merge_request_url(@project.namespace,
+                                                        @project,
+                                                        @merge_request, anchor:
+                                                        "note_#{@note.id}")
       mail_answer_thread(@merge_request,
                          from: sender(@note.author_id),
                          to: recipient(recipient_id),
diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb
index f8a7d133d1d1861cf7bd43745b7e5b410188efc6..ab5b076535213e38a5a5e07b2f788116d2c6e86f 100644
--- a/app/mailers/emails/profile.rb
+++ b/app/mailers/emails/profile.rb
@@ -1,24 +1,23 @@
 module Emails
   module Profile
-    def new_user_email(user_id, password, token = nil)
+    def new_user_email(user_id, token = nil)
       @user = User.find(user_id)
-      @password = password
       @target_url = user_url(@user)
       @token = token
-      mail(to: @user.email, subject: subject("Account was created for you"))
+      mail(to: @user.notification_email, subject: subject("Account was created for you"))
     end
 
     def new_email_email(email_id)
       @email = Email.find(email_id)
       @user = @email.user
-      mail(to: @user.email, subject: subject("Email was added to your account"))
+      mail(to: @user.notification_email, subject: subject("Email was added to your account"))
     end
 
     def new_ssh_key_email(key_id)
       @key = Key.find(key_id)
       @user = @key.user
       @target_url = user_url(@user)
-      mail(to: @user.email, subject: subject("SSH key was added to your account"))
+      mail(to: @user.notification_email, subject: subject("SSH key was added to your account"))
     end
   end
 end
diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb
index d6edfd7059ff46f66bbad1a493554c100d6e0b31..3cd812825e2546912a049ced0f7d82f97bdae038 100644
--- a/app/mailers/emails/projects.rb
+++ b/app/mailers/emails/projects.rb
@@ -3,7 +3,7 @@ module Emails
     def project_access_granted_email(user_project_id)
       @project_member = ProjectMember.find user_project_id
       @project = @project_member.project
-      @target_url = project_url(@project)
+      @target_url = namespace_project_url(@project.namespace, @project)
       mail(to: @project_member.user.email,
            subject: subject("Access to project was granted"))
     end
@@ -11,29 +11,81 @@ module Emails
     def project_was_moved_email(project_id, user_id)
       @user = User.find user_id
       @project = Project.find project_id
-      @target_url = project_url(@project)
-      mail(to: @user.email,
+      @target_url = namespace_project_url(@project.namespace, @project)
+      mail(to: @user.notification_email,
            subject: subject("Project was moved"))
     end
 
-    def repository_push_email(project_id, recipient, author_id, branch, compare)
+    def repository_push_email(project_id, recipient,  author_id: nil, 
+                                                      ref: nil, 
+                                                      action: nil, 
+                                                      compare: nil, 
+                                                      reverse_compare: false, 
+                                                      send_from_committer_email: false, 
+                                                      disable_diffs: false)
+      unless author_id && ref && action
+        raise ArgumentError, "missing keywords: author_id, ref, action"
+      end
+
       @project = Project.find(project_id)
       @author  = User.find(author_id)
+      @reverse_compare = reverse_compare
       @compare = compare
-      @commits = Commit.decorate(compare.commits)
-      @diffs   = compare.diffs
-      @branch  = branch
-      if @commits.length > 1
-        @target_url = project_compare_url(@project, from: @commits.first, to: @commits.last)
-        @subject = "#{@commits.length} new commits pushed to repository"
+      @ref_name  = Gitlab::Git.ref_name(ref)
+      @ref_type  = Gitlab::Git.tag_ref?(ref) ? "tag" : "branch"
+      @action  = action
+      @disable_diffs = disable_diffs
+
+      if @compare
+        @commits = Commit.decorate(compare.commits)
+        @diffs   = compare.diffs
+      end
+
+      @action_name = 
+        case action
+        when :create
+          "pushed new"
+        when :delete
+          "deleted"
+        else
+          "pushed to"
+        end
+
+      @subject = "[#{@project.path_with_namespace}]"
+      @subject << "[#{@ref_name}]" if action == :push
+      @subject << " "
+
+      if action == :push
+        if @commits.length > 1
+          @target_url = namespace_project_compare_url(@project.namespace,
+                                                      @project,
+                                                      from: Commit.new(@compare.base),
+                                                      to:   Commit.new(@compare.head))
+          @subject << "Deleted " if @reverse_compare
+          @subject << "#{@commits.length} commits: #{@commits.first.title}"
+        else
+          @target_url = namespace_project_commit_url(@project.namespace,
+                                                     @project, @commits.first)
+
+          @subject << "Deleted 1 commit: " if @reverse_compare
+          @subject << @commits.first.title
+        end
       else
-        @target_url = project_commit_url(@project, @commits.first)
-        @subject = @commits.first.title
+        unless action == :delete
+          @target_url = namespace_project_tree_url(@project.namespace,
+                                                   @project, @ref_name)
+        end
+
+        subject_action = @action_name.dup
+        subject_action[0] = subject_action[0].capitalize
+        @subject << "#{subject_action} #{@ref_type} #{@ref_name}"
       end
 
-      mail(from: sender(author_id),
+      @disable_footer = true
+
+      mail(from: sender(author_id, send_from_committer_email),
            to: recipient,
-           subject: subject(@subject))
+           subject: @subject)
     end
   end
 end
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 0ee198366271611ccbe42effb04c118a0372a0b7..8fcdd3bc8534ac254f19aea28c492a904f1c962f 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -26,21 +26,49 @@ class Notify < ActionMailer::Base
     delay_for(2.seconds)
   end
 
+  def test_email(recipient_email, subject, body)
+    mail(to: recipient_email,
+         subject: subject,
+         body: body.html_safe,
+         content_type: 'text/html'
+    )
+  end
+
+  # Splits "gitlab.corp.company.com" up into "gitlab.corp.company.com",
+  # "corp.company.com" and "company.com".
+  # Respects set tld length so "company.co.uk" won't match "somethingelse.uk"
+  def self.allowed_email_domains
+    domain_parts = Gitlab.config.gitlab.host.split(".")
+    allowed_domains = []
+    begin
+      allowed_domains << domain_parts.join(".")
+      domain_parts.shift
+    end while domain_parts.length > ActionDispatch::Http::URL.tld_length
+
+    allowed_domains
+  end
+
   private
 
   # The default email address to send emails from
   def default_sender_address
     address = Mail::Address.new(Gitlab.config.gitlab.email_from)
-    address.display_name = "GitLab"
+    address.display_name = Gitlab.config.gitlab.email_display_name
     address
   end
 
   # Return an email address that displays the name of the sender.
   # Only the displayed name changes; the actual email address is always the same.
-  def sender(sender_id)
+  def sender(sender_id, send_from_user_email = false)
     if sender = User.find(sender_id)
       address = default_sender_address
       address.display_name = sender.name
+
+      sender_domain = sender.email.split("@").last
+      if send_from_user_email && self.class.allowed_email_domains.include?(sender_domain)
+        address.address = sender.email
+      end
+
       address.format
     end
   end
@@ -52,7 +80,7 @@ class Notify < ActionMailer::Base
   # Returns a String containing the User's email address.
   def recipient(recipient_id)
     if recipient = User.find(recipient_id)
-      recipient.email
+      recipient.notification_email
     end
   end
 
@@ -103,6 +131,7 @@ class Notify < ActionMailer::Base
   # See: mail_answer_thread
   def mail_new_thread(model, headers = {}, &block)
     headers['Message-ID'] = message_id(model)
+    headers['X-GitLab-Project'] = "#{@project.name} | " if @project
     mail(headers, &block)
   end
 
@@ -117,8 +146,9 @@ class Notify < ActionMailer::Base
   def mail_answer_thread(model, headers = {}, &block)
     headers['In-Reply-To'] = message_id(model)
     headers['References'] = message_id(model)
+    headers['X-GitLab-Project'] = "#{@project.name} | " if @project
 
-    if (headers[:subject])
+    if headers[:subject]
       headers[:subject].prepend('Re: ')
     end
 
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 97a72bf3635b17ae61d5fab57284c9fd632c7762..d2b39f667f2b6d77faa001e0d053c60a44fe32e2 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -14,7 +14,7 @@ class Ability
       when "MergeRequest" then merge_request_abilities(user, subject)
       when "Group" then group_abilities(user, subject)
       when "Namespace" then namespace_abilities(user, subject)
-      when "GroupMember" then users_group_abilities(user, subject)
+      when "GroupMember" then group_member_abilities(user, subject)
       else []
       end.concat(global_abilities(user))
     end
@@ -37,7 +37,7 @@ class Ability
           :read_issue,
           :read_milestone,
           :read_project_snippet,
-          :read_team_member,
+          :read_project_member,
           :read_merge_request,
           :read_note,
           :download_code
@@ -73,28 +73,28 @@ class Ability
 
         # Rules based on role in project
         if team.master?(user)
-          rules += project_master_rules
+          rules.push(*project_master_rules)
 
         elsif team.developer?(user)
-          rules += project_dev_rules
+          rules.push(*project_dev_rules)
 
         elsif team.reporter?(user)
-          rules += project_report_rules
+          rules.push(*project_report_rules)
 
         elsif team.guest?(user)
-          rules += project_guest_rules
+          rules.push(*project_guest_rules)
         end
 
         if project.public? || project.internal?
-          rules += public_project_rules
+          rules.push(*public_project_rules)
         end
 
         if project.owner == user || user.admin?
-          rules += project_admin_rules
+          rules.push(*project_admin_rules)
         end
 
         if project.group && project.group.has_owner?(user)
-          rules += project_admin_rules
+          rules.push(*project_admin_rules)
         end
 
         if project.archived?
@@ -119,7 +119,7 @@ class Ability
         :read_issue,
         :read_milestone,
         :read_project_snippet,
-        :read_team_member,
+        :read_project_member,
         :read_merge_request,
         :read_note,
         :write_project,
@@ -166,7 +166,7 @@ class Ability
         :admin_issue,
         :admin_milestone,
         :admin_project_snippet,
-        :admin_team_member,
+        :admin_project_member,
         :admin_merge_request,
         :admin_note,
         :admin_wiki,
@@ -193,17 +193,17 @@ class Ability
 
       # Only group masters and group owners can create new projects in group
       if group.has_master?(user) || group.has_owner?(user) || user.admin?
-        rules += [
+        rules.push(*[
           :create_projects,
-        ]
+        ])
       end
 
       # Only group owner and administrators can manage group
       if group.has_owner?(user) || user.admin?
-        rules += [
+        rules.push(*[
           :manage_group,
           :manage_namespace
-        ]
+        ])
       end
 
       rules.flatten
@@ -214,10 +214,10 @@ class Ability
 
       # Only namespace owner and administrators can manage it
       if namespace.owner == user || user.admin?
-        rules += [
+        rules.push(*[
           :create_projects,
           :manage_namespace
-        ]
+        ])
       end
 
       rules.flatten
@@ -225,13 +225,15 @@ class Ability
 
     [:issue, :note, :project_snippet, :personal_snippet, :merge_request].each do |name|
       define_method "#{name}_abilities" do |user, subject|
-        if subject.author == user
-          [
+        if subject.author == user || user.is_admin?
+          rules = [
             :"read_#{name}",
             :"write_#{name}",
             :"modify_#{name}",
             :"admin_#{name}"
           ]
+          rules.push(:change_visibility_level) if subject.is_a?(Snippet)
+          rules
         elsif subject.respond_to?(:assignee) && subject.assignee == user
           [
             :"read_#{name}",
@@ -248,17 +250,17 @@ class Ability
       end
     end
 
-    def users_group_abilities(user, subject)
+    def group_member_abilities(user, subject)
       rules = []
       target_user = subject.user
       group = subject.group
       can_manage = group_abilities(user, group).include?(:manage_group)
       if can_manage && (user != target_user)
-        rules << :modify
-        rules << :destroy
+        rules << :modify_group_member
+        rules << :destroy_group_member
       end
       if !group.last_owner?(user) && (can_manage || (user == target_user))
-        rules << :destroy
+        rules << :destroy_group_member
       end
       rules
     end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1c87db613ae49f2db2cf68c2ff97034a7a5a1269
--- /dev/null
+++ b/app/models/application_setting.rb
@@ -0,0 +1,59 @@
+# == Schema Information
+#
+# Table name: application_settings
+#
+#  id                           :integer        not null, primary key
+#  default_projects_limit       :integer
+#  default_branch_protection    :integer
+#  signup_enabled               :boolean
+#  signin_enabled               :boolean
+#  gravatar_enabled             :boolean
+#  twitter_sharing_enabled      :boolean
+#  sign_in_text                 :text
+#  created_at                   :datetime
+#  updated_at                   :datetime
+#  home_page_url                :string(255)
+#  default_branch_protection    :integer          default(2)
+#  twitter_sharing_enabled      :boolean          default(TRUE)
+#  restricted_visibility_levels :text
+#
+
+class ApplicationSetting < ActiveRecord::Base
+  serialize :restricted_visibility_levels
+
+  validates :home_page_url,
+    allow_blank: true,
+    format: { with: URI::regexp(%w(http https)), message: "should be a valid url" },
+    if: :home_page_url_column_exist
+
+  validates_each :restricted_visibility_levels do |record, attr, value|
+    unless value.nil?
+      value.each do |level|
+        unless Gitlab::VisibilityLevel.options.has_value?(level)
+          record.errors.add(attr, "'#{level}' is not a valid visibility level")
+        end
+      end
+    end
+  end
+
+  def self.current
+    ApplicationSetting.last
+  end
+
+  def self.create_from_defaults
+    create(
+      default_projects_limit: Settings.gitlab['default_projects_limit'],
+      default_branch_protection: Settings.gitlab['default_branch_protection'],
+      signup_enabled: Settings.gitlab['signup_enabled'],
+      signin_enabled: Settings.gitlab['signin_enabled'],
+      twitter_sharing_enabled: Settings.gitlab['twitter_sharing_enabled'],
+      gravatar_enabled: Settings.gravatar['enabled'],
+      sign_in_text: Settings.extra['sign_in_text'],
+      restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels']
+    )
+  end
+
+  def home_page_url_column_exist
+    ActiveRecord::Base.connection.column_exists?(:application_settings, :home_page_url)
+  end
+end
diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb
index 4d0c04bcc3d6dddf757a80f20ec6a17956dc64bb..05f5e9796959d577298a87dd0bc366f24d686865 100644
--- a/app/models/broadcast_message.rb
+++ b/app/models/broadcast_message.rb
@@ -14,6 +14,8 @@
 #
 
 class BroadcastMessage < ActiveRecord::Base
+  include Sortable
+
   validates :message, presence: true
   validates :starts_at, presence: true
   validates :ends_at, presence: true
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 212229649fc403aca0037aedc4dd87f59701edb0..e0461809e1007fa3608e375302697291c8955488 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -10,12 +10,12 @@ class Commit
   # Used to prevent 500 error on huge commits by suppressing diff
   #
   # User can force display of diff above this size
-  DIFF_SAFE_FILES  = 100
-  DIFF_SAFE_LINES  = 5000
+  DIFF_SAFE_FILES  = 100 unless defined?(DIFF_SAFE_FILES)
+  DIFF_SAFE_LINES  = 5000 unless defined?(DIFF_SAFE_LINES)
 
   # Commits above this size will not be rendered in HTML
-  DIFF_HARD_LIMIT_FILES = 1000
-  DIFF_HARD_LIMIT_LINES = 50000
+  DIFF_HARD_LIMIT_FILES = 1000 unless defined?(DIFF_HARD_LIMIT_FILES)
+  DIFF_HARD_LIMIT_LINES = 50000 unless defined?(DIFF_HARD_LIMIT_LINES)
 
   class << self
     def decorate(commits)
@@ -75,11 +75,11 @@ class Commit
 
     return no_commit_message if title.blank?
 
-    title_end = title.index(/\n/)
+    title_end = title.index("\n")
     if (!title_end && title.length > 100) || (title_end && title_end > 100)
       title[0..79] << "&hellip;".html_safe
     else
-      title.split(/\n/, 2).first
+      title.split("\n", 2).first
     end
   end
 
@@ -87,12 +87,13 @@ class Commit
   #
   # cut off, ellipses (`&hellp;`) are prepended to the commit message.
   def description
-    title_end = safe_message.index(/\n/)
-    @description ||= if (!title_end && safe_message.length > 100) || (title_end && title_end > 100)
-                    "&hellip;".html_safe << safe_message[80..-1]
-                  else
-                    safe_message.split(/\n/, 2)[1].try(:chomp)
-                  end
+    title_end = safe_message.index("\n")
+    @description ||=
+      if (!title_end && safe_message.length > 100) || (title_end && title_end > 100)
+        "&hellip;".html_safe << safe_message[80..-1]
+      else
+        safe_message.split("\n", 2)[1].try(:chomp)
+      end
   end
 
   def description?
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index f49708fd6eb36db6c3c10f983f725b821aac054d..88ac83744df446d5d6c915b61491e9a540769ca1 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -15,6 +15,7 @@ module Issuable
     has_many :notes, as: :noteable, dependent: :destroy
     has_many :label_links, as: :target, dependent: :destroy
     has_many :labels, through: :label_links
+    has_many :subscriptions, dependent: :destroy, as: :subscribable
 
     validates :author, presence: true
     validates :title, presence: true, length: { within: 0..255 }
@@ -29,6 +30,8 @@ module Issuable
     scope :only_opened, -> { with_state(:opened) }
     scope :only_reopened, -> { with_state(:reopened) }
     scope :closed, -> { with_state(:closed) }
+    scope :order_milestone_due_desc, -> { joins(:milestone).reorder('milestones.due_date DESC, milestones.id DESC') }
+    scope :order_milestone_due_asc, -> { joins(:milestone).reorder('milestones.due_date ASC, milestones.id ASC') }
 
     delegate :name,
              :email,
@@ -55,13 +58,10 @@ module Issuable
 
     def sort(method)
       case method.to_s
-      when 'newest' then reorder("#{table_name}.created_at DESC")
-      when 'oldest' then reorder("#{table_name}.created_at ASC")
-      when 'recently_updated' then reorder("#{table_name}.updated_at DESC")
-      when 'last_updated' then reorder("#{table_name}.updated_at ASC")
-      when 'milestone_due_soon' then joins(:milestone).reorder("milestones.due_date ASC")
-      when 'milestone_due_later' then joins(:milestone).reorder("milestones.due_date DESC")
-      else reorder("#{table_name}.created_at DESC")
+      when 'milestone_due_asc' then order_milestone_due_asc
+      when 'milestone_due_desc' then order_milestone_due_desc
+      else
+        order_by(method)
       end
     end
   end
@@ -88,7 +88,7 @@ module Issuable
 
   # Return the number of -1 comments (downvotes)
   def downvotes
-    notes.select(&:downvote?).size
+    filter_superceded_votes(notes.select(&:downvote?), notes).size
   end
 
   def downvotes_in_percent
@@ -101,7 +101,7 @@ module Issuable
 
   # Return the number of +1 comments (upvotes)
   def upvotes
-    notes.select(&:upvote?).size
+    filter_superceded_votes(notes.select(&:upvote?), notes).size
   end
 
   def upvotes_in_percent
@@ -124,13 +124,31 @@ module Issuable
     users << assignee if is_assigned?
     mentions = []
     mentions << self.mentioned_users
+
     notes.each do |note|
       users << note.author
       mentions << note.mentioned_users
     end
+
     users.concat(mentions.reduce([], :|)).uniq
   end
 
+  def subscribed?(user)
+    subscription = subscriptions.find_by_user_id(user.id)
+
+    if subscription
+      return subscription.subscribed
+    end
+
+    participants.include?(user)
+  end
+
+  def toggle_subscription(user)
+    subscriptions.
+      find_or_initialize_by(user_id: user.id).
+      update(subscribed: !subscribed?(user))
+  end
+
   def to_hook_data(user)
     {
       object_kind: self.class.name.underscore,
@@ -149,9 +167,23 @@ module Issuable
 
   def add_labels_by_names(label_names)
     label_names.each do |label_name|
-      label = project.labels.create_with(
-        color: Label::DEFAULT_COLOR).find_or_create_by(title: label_name.strip)
+      label = project.labels.create_with(color: Label::DEFAULT_COLOR).
+        find_or_create_by(title: label_name.strip)
       self.labels << label
     end
   end
+
+  private
+
+  def filter_superceded_votes(votes, notes)
+    filteredvotes = [] + votes
+
+    votes.each do |vote|
+      if vote.superceded?(notes)
+        filteredvotes.delete(vote)
+      end
+    end
+
+    filteredvotes
+  end
 end
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index 6c1aa99668a43c433a4a4ab2024731e624761658..74900d4675d788675f11069320eac5ed190be1e7 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -50,10 +50,13 @@ module Mentionable
     matches.each do |match|
       identifier = match.delete "@"
       if identifier == "all"
-        users += project.team.members.flatten
-      else
-        id = User.find_by(username: identifier).try(:id)
-        users << User.find(id) unless id.blank?
+        users.push(*project.team.members.flatten)
+      elsif namespace = Namespace.find_by(path: identifier)
+        if namespace.type == "Group"
+          users.push(*namespace.users)
+        else
+          users << namespace.owner
+        end
       end
     end
     users.uniq
@@ -64,9 +67,10 @@ module Mentionable
     return [] if text.blank?
     ext = Gitlab::ReferenceExtractor.new
     ext.analyze(text, p)
-    (ext.issues_for +
-     ext.merge_requests_for +
-     ext.commits_for).uniq - [local_reference]
+
+    (ext.issues_for(p)  +
+     ext.merge_requests_for(p) +
+     ext.commits_for(p)).uniq - [local_reference]
   end
 
   # Create a cross-reference Note for each GFM reference to another Mentionable found in +mentionable_text+.
@@ -95,5 +99,4 @@ module Mentionable
     preexisting = references(p, original)
     create_cross_references!(p, a, preexisting)
   end
-
 end
diff --git a/app/models/concerns/sortable.rb b/app/models/concerns/sortable.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0ad2654867d767ca1e18955ab773d81ce59a23f3
--- /dev/null
+++ b/app/models/concerns/sortable.rb
@@ -0,0 +1,35 @@
+# == Sortable concern
+#
+# Set default scope for ordering objects
+#
+module Sortable
+  extend ActiveSupport::Concern
+
+  included do
+    # By default all models should be ordered
+    # by created_at field starting from newest
+    default_scope { order(created_at: :desc, id: :desc) }
+
+    scope :order_created_desc, -> { reorder(created_at: :desc, id: :desc) }
+    scope :order_created_asc, -> { reorder(created_at: :asc, id: :asc) }
+    scope :order_updated_desc, -> { reorder(updated_at: :desc, id: :desc) }
+    scope :order_updated_asc, -> { reorder(updated_at: :asc, id: :asc) }
+    scope :order_name_asc, -> { reorder(name: :asc) }
+    scope :order_name_desc, -> { reorder(name: :desc) }
+  end
+
+  module ClassMethods
+    def order_by(method)
+      case method.to_s
+      when 'name_asc' then order_name_asc
+      when 'name_desc' then order_name_desc
+      when 'updated_asc' then order_updated_asc
+      when 'updated_desc' then order_updated_desc
+      when 'created_asc' then order_created_asc
+      when 'created_desc' then order_created_desc
+      else
+        all
+      end
+    end
+  end
+end
diff --git a/app/models/concerns/taskable.rb b/app/models/concerns/taskable.rb
index 410e8dc820b7c2790e63c911f413ec5d3de677b4..bbb3b301a9f5a1392ed6a97cdb9946de79c3258e 100644
--- a/app/models/concerns/taskable.rb
+++ b/app/models/concerns/taskable.rb
@@ -5,7 +5,7 @@
 # Used by MergeRequest and Issue
 module Taskable
   TASK_PATTERN_MD = /^(?<bullet> *[*-] *)\[(?<checked>[ xX])\]/.freeze
-  TASK_PATTERN_HTML = /^<li>\[(?<checked>[ xX])\]/.freeze
+  TASK_PATTERN_HTML = /^<li>(?<p_tag>\s*<p>)?\[(?<checked>[ xX])\]/.freeze
 
   # Change the state of a task list item for this Taskable.  Edit the object's
   # description by finding the nth task item and changing its checkbox
diff --git a/app/models/deploy_keys_project.rb b/app/models/deploy_keys_project.rb
index f23d8205ddcb64d9d41653607bb456a3caa3a941..7e88903b9af9b0cc2ea186c5fa5364964bbe6323 100644
--- a/app/models/deploy_keys_project.rb
+++ b/app/models/deploy_keys_project.rb
@@ -16,4 +16,12 @@ class DeployKeysProject < ActiveRecord::Base
   validates :deploy_key_id, presence: true
   validates :deploy_key_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
   validates :project_id, presence: true
+
+  after_destroy :destroy_orphaned_deploy_key
+
+  private
+
+  def destroy_orphaned_deploy_key
+    self.deploy_key.destroy if self.deploy_key.deploy_keys_projects.length == 0
+  end
 end
diff --git a/app/models/email.rb b/app/models/email.rb
index 57f476bd519124244d92de88f3192b66bf4e2e58..556b0e9586e72d8f23c99feaae8e53e17cfbc710 100644
--- a/app/models/email.rb
+++ b/app/models/email.rb
@@ -10,6 +10,8 @@
 #
 
 class Email < ActiveRecord::Base
+  include Sortable
+
   belongs_to :user
 
   validates :user_id, presence: true
diff --git a/app/models/event.rb b/app/models/event.rb
index 65b4c2edfee043d343707218f95b2e9993805850..57f6d5cd4e036eb670164f6c5b44ffcf53072153 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -15,6 +15,7 @@
 #
 
 class Event < ActiveRecord::Base
+  include Sortable
   default_scope { where.not(author_id: nil) }
 
   CREATED   = 1
@@ -46,36 +47,20 @@ class Event < ActiveRecord::Base
   scope :recent, -> { order("created_at DESC") }
   scope :code_push, -> { where(action: PUSHED) }
   scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent }
+  scope :with_associations, -> { includes(project: :namespace) }
 
   class << self
-    def create_ref_event(project, user, ref, action = 'add', prefix = 'refs/heads')
-      commit = project.repository.commit(ref.target)
-
-      if action.to_s == 'add'
-        before = '00000000'
-        after = commit.id
-      else
-        before = commit.id
-        after = '00000000'
-      end
-
-      Event.create(
-        project: project,
-        action: Event::PUSHED,
-        data: {
-          ref: "#{prefix}/#{ref.name}",
-          before: before,
-          after: after
-        },
-        author_id: user.id
-      )
-    end
-
     def reset_event_cache_for(target)
       Event.where(target_id: target.id, target_type: target.class.to_s).
         order('id DESC').limit(100).
         update_all(updated_at: Time.now)
     end
+
+    def contributions
+      where("action = ? OR (target_type in (?) AND action in (?))",
+            Event::PUSHED, ["MergeRequest", "Issue"],
+            [Event::CREATED, Event::CLOSED, Event::MERGED])
+    end
   end
 
   def proper?
@@ -83,6 +68,8 @@ class Event < ActiveRecord::Base
       true
     elsif membership_changed?
       true
+    elsif created_project?
+      true
     else
       (issue? || merge_request? || note? || milestone?) && target
     end
@@ -97,25 +84,51 @@ class Event < ActiveRecord::Base
   end
 
   def target_title
-    if target && target.respond_to?(:title)
-      target.title
-    end
+    target.title if target && target.respond_to?(:title)
+  end
+
+  def created?
+    action == CREATED
   end
 
   def push?
-    action == self.class::PUSHED && valid_push?
+    action == PUSHED && valid_push?
   end
 
   def merged?
-    action == self.class::MERGED
+    action == MERGED
   end
 
   def closed?
-    action == self.class::CLOSED
+    action == CLOSED
   end
 
   def reopened?
-    action == self.class::REOPENED
+    action == REOPENED
+  end
+
+  def joined?
+    action == JOINED
+  end
+
+  def left?
+    action == LEFT
+  end
+
+  def commented?
+    action == COMMENTED
+  end
+
+  def membership_changed?
+    joined? || left?
+  end
+
+  def created_project?
+    created? && !target
+  end
+
+  def created_target?
+    created? && target
   end
 
   def milestone?
@@ -134,32 +147,32 @@ class Event < ActiveRecord::Base
     target_type == "MergeRequest"
   end
 
-  def joined?
-    action == JOINED
-  end
-
-  def left?
-    action == LEFT
-  end
-
-  def membership_changed?
-    joined? || left?
+  def milestone
+    target if milestone?
   end
 
   def issue
-    target if target_type == "Issue"
+    target if issue?
   end
 
   def merge_request
-    target if target_type == "MergeRequest"
+    target if merge_request?
   end
 
   def note
-    target if target_type == "Note"
+    target if note?
   end
 
   def action_name
-    if closed?
+    if push?
+      if new_ref?
+        "pushed new"
+      elsif rm_ref?
+        "deleted"
+      else
+        "pushed to"
+      end
+    elsif closed?
       "closed"
     elsif merged?
       "accepted"
@@ -167,6 +180,10 @@ class Event < ActiveRecord::Base
       'joined'
     elsif left?
       'left'
+    elsif commented?
+      "commented on"
+    elsif created_project?
+      "created"
     else
       "opened"
     end
@@ -174,24 +191,24 @@ class Event < ActiveRecord::Base
 
   def valid_push?
     data[:ref] && ref_name.present?
-  rescue => ex
+  rescue
     false
   end
 
   def tag?
-    data[:ref]["refs/tags"]
+    Gitlab::Git.tag_ref?(data[:ref])
   end
 
   def branch?
-    data[:ref]["refs/heads"]
+    Gitlab::Git.branch_ref?(data[:ref])
   end
 
   def new_ref?
-    commit_from =~ /^00000/
+    Gitlab::Git.blank_ref?(commit_from)
   end
 
   def rm_ref?
-    commit_to =~ /^00000/
+    Gitlab::Git.blank_ref?(commit_to)
   end
 
   def md_ref?
@@ -215,11 +232,11 @@ class Event < ActiveRecord::Base
   end
 
   def branch_name
-    @branch_name ||= data[:ref].gsub("refs/heads/", "")
+    @branch_name ||= Gitlab::Git.ref_name(data[:ref])
   end
 
   def tag_name
-    @tag_name ||= data[:ref].gsub("refs/tags/", "")
+    @tag_name ||= Gitlab::Git.ref_name(data[:ref])
   end
 
   # Max 20 commits from push DESC
@@ -235,18 +252,8 @@ class Event < ActiveRecord::Base
     tag? ? "tag" : "branch"
   end
 
-  def push_action_name
-    if new_ref?
-      "pushed new"
-    elsif rm_ref?
-      "deleted"
-    else
-      "pushed to"
-    end
-  end
-
   def push_with_commits?
-    md_ref? && commits.any? && commit_from && commit_to
+    !commits.empty? && commit_from && commit_to
   end
 
   def last_push_to_non_root?
diff --git a/app/models/external_issue.rb b/app/models/external_issue.rb
new file mode 100644
index 0000000000000000000000000000000000000000..50efcb32f1b9f93c41dd20e858a9405e97e4543a
--- /dev/null
+++ b/app/models/external_issue.rb
@@ -0,0 +1,25 @@
+class ExternalIssue
+  def initialize(issue_identifier, project)
+    @issue_identifier, @project = issue_identifier, project
+  end
+
+  def to_s
+    @issue_identifier.to_s
+  end
+
+  def id
+    @issue_identifier.to_s
+  end
+
+  def iid
+    @issue_identifier.to_s
+  end
+
+  def ==(other)
+    other.is_a?(self.class) && (to_s == other.to_s)
+  end
+
+  def project
+    @project
+  end
+end
diff --git a/app/models/group.rb b/app/models/group.rb
index b8ed3b8ac73bffb61499d65098da8dc6c4ddaa31..da9621a2a1a20e5b545268ef9595c3a60fcc7190 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -21,9 +21,22 @@ class Group < Namespace
   has_many :users, through: :group_members
 
   validate :avatar_type, if: ->(user) { user.avatar_changed? }
-  validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
+  validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
 
-  mount_uploader :avatar, AttachmentUploader
+  mount_uploader :avatar, AvatarUploader
+
+  after_create :post_create_hook
+  after_destroy :post_destroy_hook
+
+  class << self
+    def search(query)
+      where("LOWER(namespaces.name) LIKE :query or LOWER(namespaces.path) LIKE :query", query: "%#{query.downcase}%")
+    end
+
+    def sort(method)
+      order_by(method)
+    end
+  end
 
   def human_name
     name
@@ -74,19 +87,15 @@ class Group < Namespace
     projects.public_only.any?
   end
 
-  class << self
-    def search(query)
-      where("LOWER(namespaces.name) LIKE :query", query: "%#{query.downcase}%")
-    end
+  def post_create_hook
+    system_hook_service.execute_hooks_for(self, :create)
+  end
 
-    def sort(method)
-      case method.to_s
-      when "newest" then reorder("namespaces.created_at DESC")
-      when "oldest" then reorder("namespaces.created_at ASC")
-      when "recently_updated" then reorder("namespaces.updated_at DESC")
-      when "last_updated" then reorder("namespaces.updated_at ASC")
-      else reorder("namespaces.path, namespaces.name ASC")
-      end
-    end
+  def post_destroy_hook
+    system_hook_service.execute_hooks_for(self, :destroy)
+  end
+
+  def system_hook_service
+    SystemHooksService.new
   end
 end
diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb
index 33915313789ae60e7a83cc1d2b785aa65e2ee4ba..7e4f16ebf167ee51bf45bd4cecc10d470fb980cc 100644
--- a/app/models/group_milestone.rb
+++ b/app/models/group_milestone.rb
@@ -66,15 +66,15 @@ class GroupMilestone
   end
 
   def issues
-    @group_issues ||= milestones.map { |milestone| milestone.issues }.flatten.group_by(&:state)
+    @group_issues ||= milestones.map(&:issues).flatten.group_by(&:state)
   end
 
   def merge_requests
-    @group_merge_requests ||= milestones.map { |milestone| milestone.merge_requests }.flatten.group_by(&:state)
+    @group_merge_requests ||= milestones.map(&:merge_requests).flatten.group_by(&:state)
   end
 
   def participants
-    milestones.map { |milestone| milestone.participants.uniq }.reject(&:empty?).flatten
+    @group_participants ||= milestones.map(&:participants).flatten.compact.uniq
   end
 
   def opened_issues
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index 23fa01e0b70f9a89c66af543b30a18c4d9cc3121..defef7216f2c6f1f92450cb965ee958269e70150 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -16,6 +16,7 @@
 #
 
 class WebHook < ActiveRecord::Base
+  include Sortable
   include HTTParty
 
   default_value_for :push_events, true
@@ -32,7 +33,10 @@ class WebHook < ActiveRecord::Base
   def execute(data)
     parsed_url = URI.parse(url)
     if parsed_url.userinfo.blank?
-      WebHook.post(url, body: data.to_json, headers: { "Content-Type" => "application/json" }, verify: false)
+      WebHook.post(url,
+                   body: data.to_json,
+                   headers: { "Content-Type" => "application/json" },
+                   verify: false)
     else
       post_url = url.gsub("#{parsed_url.userinfo}@", "")
       auth = {
@@ -41,10 +45,13 @@ class WebHook < ActiveRecord::Base
       }
       WebHook.post(post_url,
                    body: data.to_json,
-                   headers: {"Content-Type" => "application/json"},
+                   headers: { "Content-Type" => "application/json" },
                    verify: false,
                    basic_auth: auth)
     end
+  rescue SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e
+    logger.error("WebHook Error => #{e}")
+    false
   end
 
   def async_execute(data)
diff --git a/app/models/identity.rb b/app/models/identity.rb
new file mode 100644
index 0000000000000000000000000000000000000000..440fcd0d052070f46dfb4a6ebba73d67e3322f51
--- /dev/null
+++ b/app/models/identity.rb
@@ -0,0 +1,18 @@
+# == Schema Information
+#
+# Table name: identities
+#
+#  id         :integer          not null, primary key
+#  extern_uid :string(255)
+#  provider   :string(255)
+#  user_id    :integer
+#  created_at :datetime
+#  updated_at :datetime
+#
+
+class Identity < ActiveRecord::Base
+  include Sortable
+  belongs_to :user
+
+  validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider }
+end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 8a9e969248c14d753c196422a59f1c7f09cb9456..6e1020513875aba4f1af2d3e21f8a9d37d25850e 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -24,6 +24,7 @@ class Issue < ActiveRecord::Base
   include Issuable
   include InternalId
   include Taskable
+  include Sortable
 
   ActsAsTaggableOn.strict_case_match = true
 
@@ -31,7 +32,6 @@ class Issue < ActiveRecord::Base
   validates :project, presence: true
 
   scope :of_group, ->(group) { where(project_id: group.project_ids) }
-  scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) }
   scope :cared, ->(user) { where(assignee_id: user) }
   scope :open_for, ->(user) { opened.assigned_to(user) }
 
diff --git a/app/models/key.rb b/app/models/key.rb
index 095c73d8baf8a325135f13fd2f49bfa2abecddb0..e2e59296eedda139bfa1023660af63f6769399ae 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -15,11 +15,12 @@
 require 'digest/md5'
 
 class Key < ActiveRecord::Base
+  include Sortable
   include Gitlab::Popen
 
   belongs_to :user
 
-  before_validation :strip_white_space, :generate_fingerpint
+  before_validation :strip_white_space, :generate_fingerprint
 
   validates :title, presence: true, length: { within: 0..255 }
   validates :key, presence: true, length: { within: 0..5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ }, uniqueness: true
@@ -76,7 +77,7 @@ class Key < ActiveRecord::Base
 
   private
 
-  def generate_fingerpint
+  def generate_fingerprint
     self.fingerprint = nil
     return unless key.present?
 
@@ -89,7 +90,7 @@ class Key < ActiveRecord::Base
     end
 
     if cmd_status.zero?
-      cmd_output.gsub /([\d\h]{2}:)+[\d\h]{2}/ do |match|
+      cmd_output.gsub /(\h{2}:)+\h{2}/ do |match|
         self.fingerprint = match
       end
     end
diff --git a/app/models/label.rb b/app/models/label.rb
index 2b2b02e0645d3af641d1d63cbcb3ef864f66088c..9d7099c5652db38d914eae00a3e5823a37813f28 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -28,7 +28,7 @@ class Label < ActiveRecord::Base
             format: { with: /\A[^&\?,&]+\z/ },
             uniqueness: { scope: :project_id }
 
-  scope :order_by_name, -> { reorder("labels.title ASC") }
+  default_scope { order(title: :asc) }
 
   alias_attribute :name, :title
 
diff --git a/app/models/member.rb b/app/models/member.rb
index 671ef466baaec1f955cbb0b753abc1b5318ed50a..fe3d2f40e87b773c47662f44f1ffe9d15ff25e06 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -14,6 +14,7 @@
 #
 
 class Member < ActiveRecord::Base
+  include Sortable
   include Notifiable
   include Gitlab::Access
 
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index b7f296b13fb7ea174528fc6b929fb79c82465522..28d0b4483b440fe832797f345fa9e6857a780700 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -27,8 +27,9 @@ class GroupMember < Member
   scope :with_group, ->(group) { where(source_id: group.id) }
   scope :with_user, ->(user) { where(user_id: user.id) }
 
-  after_create :notify_create
+  after_create :post_create_hook
   after_update :notify_update
+  after_destroy :post_destroy_hook
 
   def self.access_level_roles
     Gitlab::Access.options_with_owner
@@ -42,8 +43,9 @@ class GroupMember < Member
     access_level
   end
 
-  def notify_create
+  def post_create_hook
     notification_service.new_group_member(self)
+    system_hook_service.execute_hooks_for(self, :create)
   end
 
   def notify_update
@@ -52,6 +54,14 @@ class GroupMember < Member
     end
   end
 
+  def post_destroy_hook
+    system_hook_service.execute_hooks_for(self, :destroy)
+  end
+
+  def system_hook_service
+    SystemHooksService.new
+  end
+
   def notification_service
     NotificationService.new
   end
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 30c09f768d7069c8b4fc0091e19fb791028a1b79..6b13e0ff30ba251fe1953a462a8989e6952a3d92 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -114,30 +114,27 @@ class ProjectMember < Member
   end
 
   def post_create_hook
-    Event.create(
-      project_id: self.project.id,
-      action: Event::JOINED,
-      author_id: self.user.id
-    )
-
-    notification_service.new_team_member(self) unless owner?
+    unless owner?
+      event_service.join_project(self.project, self.user)
+      notification_service.new_project_member(self)
+    end
+    
     system_hook_service.execute_hooks_for(self, :create)
   end
 
   def post_update_hook
-    notification_service.update_team_member(self) if self.access_level_changed?
+    notification_service.update_project_member(self) if self.access_level_changed?
   end
 
   def post_destroy_hook
-    Event.create(
-      project_id: self.project.id,
-      action: Event::LEFT,
-      author_id: self.user.id
-    )
-
+    event_service.leave_project(self.project, self.user)
     system_hook_service.execute_hooks_for(self, :destroy)
   end
 
+  def event_service
+    EventCreateService.new
+  end
+
   def notification_service
     NotificationService.new
   end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 7c525b02f4848dcf2f5c07d5f34abe5f1d29299e..5634f9a686e082a88114bb8284827d9965d6675e 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -18,6 +18,7 @@
 #  iid               :integer
 #  description       :text
 #  position          :integer          default(0)
+#  locked_at         :datetime
 #
 
 require Rails.root.join("app/models/commit")
@@ -27,6 +28,7 @@ class MergeRequest < ActiveRecord::Base
   include Issuable
   include Taskable
   include InternalId
+  include Sortable
 
   belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project"
   belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project"
@@ -70,6 +72,16 @@ class MergeRequest < ActiveRecord::Base
       transition locked: :reopened
     end
 
+    after_transition any => :locked do |merge_request, transition|
+      merge_request.locked_at = Time.now
+      merge_request.save
+    end
+
+    after_transition locked: (any - :locked) do |merge_request, transition|
+      merge_request.locked_at = nil
+      merge_request.save
+    end
+
     state :opened
     state :reopened
     state :closed
@@ -83,16 +95,25 @@ class MergeRequest < ActiveRecord::Base
     end
 
     event :mark_as_mergeable do
-      transition unchecked: :can_be_merged
+      transition [:unchecked, :cannot_be_merged] => :can_be_merged
     end
 
     event :mark_as_unmergeable do
-      transition unchecked: :cannot_be_merged
+      transition [:unchecked, :can_be_merged] => :cannot_be_merged
     end
 
     state :unchecked
     state :can_be_merged
     state :cannot_be_merged
+
+    around_transition do |merge_request, transition, block|
+      merge_request.record_timestamps = false
+      begin
+        block.call
+      ensure
+        merge_request.record_timestamps = true
+      end
+    end
   end
 
   validates :source_project, presence: true, unless: :allow_broken
@@ -103,7 +124,6 @@ class MergeRequest < ActiveRecord::Base
   validate :validate_fork
 
   scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)", group_project_ids: group.project_ids) }
-  scope :of_user_team, ->(team) { where("(source_project_id in (:team_project_ids) OR target_project_id in (:team_project_ids) AND assignee_id in (:team_member_ids))", team_project_ids: team.project_ids, team_member_ids: team.member_ids) }
   scope :merged, -> { with_state(:merged) }
   scope :by_branch, ->(branch_name) { where("(source_branch LIKE :branch) OR (target_branch LIKE :branch)", branch: branch_name) }
   scope :cared, ->(user) { where('assignee_id = :user OR author_id = :user', user: user.id) }
@@ -179,7 +199,9 @@ class MergeRequest < ActiveRecord::Base
   end
 
   def automerge!(current_user, commit_message = nil)
-    MergeRequests::AutoMergeService.new.execute(self, current_user, commit_message)
+    MergeRequests::AutoMergeService.
+      new(target_project, current_user).
+      execute(self, commit_message)
   end
 
   def open?
@@ -238,7 +260,8 @@ class MergeRequest < ActiveRecord::Base
   def closes_issues
     if target_branch == project.default_branch
       issues = commits.flat_map { |c| c.closes_issues(project) }
-      issues += Gitlab::ClosingIssueExtractor.closed_by_message_in_project(description, project)
+      issues.push(*Gitlab::ClosingIssueExtractor.
+                  closed_by_message_in_project(description, project))
       issues.uniq.sort_by(&:id)
     else
       []
@@ -318,7 +341,7 @@ class MergeRequest < ActiveRecord::Base
   end
 
   # Return array of possible target branches
-  # dependes on target project of MR
+  # depends on target project of MR
   def target_branches
     if target_project.nil?
       []
@@ -328,7 +351,7 @@ class MergeRequest < ActiveRecord::Base
   end
 
   # Return array of possible source branches
-  # dependes on source project of MR
+  # depends on source project of MR
   def source_branches
     if source_project.nil?
       []
@@ -336,4 +359,8 @@ class MergeRequest < ActiveRecord::Base
       source_project.repository.branch_names
     end
   end
+
+  def locked_long_ago?
+    locked_at && locked_at < (Time.now - 1.day)
+  end
 end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index a71122d5e0784e48e5116f67ed056d2b51e0890c..acac1ca4cf7ca2e3ccabbf70e754f6402d730e19 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -14,6 +14,8 @@
 require Rails.root.join("app/models/commit")
 
 class MergeRequestDiff < ActiveRecord::Base
+  include Sortable
+
   # Prevent store of diff
   # if commits amount more then 200
   COMMITS_SAFE_SIZE = 200
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 8fd3e56d2eec13f55f18c0bf42243b68507c5cbf..9bbb2bafb981c1398adf5cedf65e091145b0e40f 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -15,6 +15,7 @@
 
 class Milestone < ActiveRecord::Base
   include InternalId
+  include Sortable
 
   belongs_to :project
   has_many :issues
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index c0c6de0ee7dcab9b90011a99cf4f70521d919e4c..35280889a8663344d4a7f40d8261179751d75bea 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -14,21 +14,27 @@
 #
 
 class Namespace < ActiveRecord::Base
+  include Sortable
   include Gitlab::ShellAdapter
 
   has_many :projects, dependent: :destroy
   belongs_to :owner, class_name: "User"
 
   validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
-  validates :name, presence: true, uniqueness: true,
-            length: { within: 0..255 },
-            format: { with: Gitlab::Regex.name_regex,
-                      message: Gitlab::Regex.name_regex_message }
+  validates :name,
+    presence: true, uniqueness: true,
+    length: { within: 0..255 },
+    format: { with: Gitlab::Regex.name_regex,
+              message: Gitlab::Regex.name_regex_message }
+
   validates :description, length: { within: 0..255 }
-  validates :path, uniqueness: { case_sensitive: false }, presence: true, length: { within: 1..255 },
-            exclusion: { in: Gitlab::Blacklist.path },
-            format: { with: Gitlab::Regex.path_regex,
-                      message: Gitlab::Regex.path_regex_message }
+  validates :path,
+    uniqueness: { case_sensitive: false },
+    presence: true,
+    length: { within: 1..255 },
+    exclusion: { in: Gitlab::Blacklist.path },
+    format: { with: Gitlab::Regex.path_regex,
+              message: Gitlab::Regex.path_regex_message }
 
   delegate :name, to: :owner, allow_nil: true, prefix: true
 
@@ -38,6 +44,15 @@ class Namespace < ActiveRecord::Base
 
   scope :root, -> { where('type IS NULL') }
 
+  def self.by_path(path)
+    where('lower(path) = :value', value: path.downcase).first
+  end
+
+  # Case insensetive search for namespace by path or name
+  def self.find_by_path_or_name(path)
+    find_by("lower(path) = :path OR lower(name) = :path", path: path.downcase)
+  end
+
   def self.search(query)
     where("name LIKE :query OR path LIKE :query", query: "%#{query}%")
   end
@@ -90,4 +105,8 @@ class Namespace < ActiveRecord::Base
   def kind
     type == 'Group' ? 'group' : 'user'
   end
+
+  def find_fork_of(project)
+    projects.joins(:forked_project_link).where('forked_project_links.forked_from_project_id = ?', project.id).first
+  end
 end
diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb
index 43979b5e8071b619a2176abb0e7ced0d3ad74c4c..f4e90125373dba51119c47fc2c822798e22400d5 100644
--- a/app/models/network/graph.rb
+++ b/app/models/network/graph.rb
@@ -84,7 +84,7 @@ module Network
             skip += self.class.max_count
           end
         else
-          # Cant't find the target commit in the repo.
+          # Can't find the target commit in the repo.
           offset = 0
         end
       end
@@ -226,7 +226,7 @@ module Network
 
       reserved = []
       for day in time_range
-        reserved += @reserved[day]
+        reserved.push(*@reserved[day])
       end
       reserved.uniq!
 
diff --git a/app/models/note.rb b/app/models/note.rb
index 5bf645bbd1d9e140d3fb3cf2ffbfca3389702aeb..e86160e7cd9ebdb0897d2df1b62bf0f1577df980 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -48,8 +48,9 @@ class Note < ActiveRecord::Base
   scope :inline, ->{ where("line_code IS NOT NULL") }
   scope :not_inline, ->{ where(line_code: [nil, '']) }
   scope :system, ->{ where(system: true) }
+  scope :user, ->{ where(system: false) }
   scope :common, ->{ where(noteable_type: ["", nil]) }
-  scope :fresh, ->{ order("created_at ASC, id ASC") }
+  scope :fresh, ->{ order(created_at: :asc, id: :asc) }
   scope :inc_author_project, ->{ includes(:project, :author) }
   scope :inc_author, ->{ includes(:author) }
 
@@ -59,7 +60,7 @@ class Note < ActiveRecord::Base
 
   class << self
     def create_status_change_note(noteable, project, author, status, source)
-      body = "_Status changed to #{status}#{' by ' + source.gfm_reference if source}_"
+      body = "Status changed to #{status}#{' by ' + source.gfm_reference if source}"
 
       create(
         noteable: noteable,
@@ -95,9 +96,9 @@ class Note < ActiveRecord::Base
 
     def create_milestone_change_note(noteable, project, author, milestone)
       body = if milestone.nil?
-               '_Milestone removed_'
+               'Milestone removed'
              else
-               "_Milestone changed to #{milestone.title}_"
+               "Milestone changed to #{milestone.title}"
              end
 
       create(
@@ -110,7 +111,7 @@ class Note < ActiveRecord::Base
     end
 
     def create_assignee_change_note(noteable, project, author, assignee)
-      body = assignee.nil? ? '_Assignee removed_' : "_Reassigned to @#{assignee.username}_"
+      body = assignee.nil? ? 'Assignee removed' : "Reassigned to @#{assignee.username}"
 
       create({
         noteable: noteable,
@@ -121,18 +122,75 @@ class Note < ActiveRecord::Base
       })
     end
 
-    def create_new_commits_note(noteable, project, author, commits)
-      commits_text = ActionController::Base.helpers.pluralize(commits.size, 'new commit')
+    def create_labels_change_note(noteable, project, author, added_labels, removed_labels)
+      labels_count = added_labels.count + removed_labels.count
+      added_labels = added_labels.map{ |label| "~#{label.id}" }.join(' ')
+      removed_labels = removed_labels.map{ |label| "~#{label.id}" }.join(' ')
+      message = ''
+
+      if added_labels.present?
+        message << "added #{added_labels}"
+      end
+
+      if added_labels.present? && removed_labels.present?
+        message << ' and '
+      end
+
+      if removed_labels.present?
+        message << "removed #{removed_labels}"
+      end
+
+      message << ' ' << 'label'.pluralize(labels_count)
+      body = "#{message.capitalize}"
+
+      create(
+        noteable: noteable,
+        project: project,
+        author: author,
+        note: body,
+        system: true
+      )
+    end
+
+    def create_new_commits_note(merge_request, project, author, new_commits, existing_commits = [], oldrev = nil)
+      total_count = new_commits.length + existing_commits.length
+      commits_text = ActionController::Base.helpers.pluralize(total_count, 'commit')
       body = "Added #{commits_text}:\n\n"
 
-      commits.each do |commit|
+      if existing_commits.length > 0
+        commit_ids =
+          if existing_commits.length == 1
+            existing_commits.first.short_id
+          else
+            if oldrev
+              "#{Commit.truncate_sha(oldrev)}...#{existing_commits.last.short_id}"
+            else
+              "#{existing_commits.first.short_id}..#{existing_commits.last.short_id}"
+            end
+          end
+
+        commits_text = ActionController::Base.helpers.pluralize(existing_commits.length, 'commit')
+
+        branch =
+          if merge_request.for_fork?
+            "#{merge_request.target_project_namespace}:#{merge_request.target_branch}"
+          else
+            merge_request.target_branch
+          end
+
+        message = "* #{commit_ids} - #{commits_text} from branch `#{branch}`"
+        body << message
+        body << "\n"
+      end
+
+      new_commits.each do |commit|
         message = "* #{commit.short_id} - #{commit.title}"
         body << message
         body << "\n"
       end
 
       create(
-        noteable: noteable,
+        noteable: merge_request,
         project: project,
         author: author,
         note: body,
@@ -183,7 +241,7 @@ class Note < ActiveRecord::Base
                 where(noteable_id: noteable.id)
               end
 
-      notes.where('note like ?', cross_reference_note_content(gfm_reference)).
+      notes.where('note like ?', cross_reference_note_pattern(gfm_reference)).
         system.any?
     end
 
@@ -192,13 +250,18 @@ class Note < ActiveRecord::Base
     end
 
     def cross_reference_note_prefix
-      '_mentioned in '
+      'mentioned in '
     end
 
     private
 
     def cross_reference_note_content(gfm_reference)
-      cross_reference_note_prefix + "#{gfm_reference}_"
+      cross_reference_note_prefix + "#{gfm_reference}"
+    end
+
+    def cross_reference_note_pattern(gfm_reference)
+      # Older cross reference notes contained underscores for emphasis
+      "%" + cross_reference_note_content(gfm_reference) + "%"
     end
 
     # Prepend the mentioner's namespaced project path to the GFM reference for
@@ -278,6 +341,10 @@ class Note < ActiveRecord::Base
     end
   end
 
+  def hook_attrs
+    attributes
+  end
+
   def set_diff
     # First lets find notes with same diff
     # before iterating over all mr diffs
@@ -296,6 +363,7 @@ class Note < ActiveRecord::Base
   # If not - its outdated diff
   def active?
     return true unless self.diff
+    return false unless noteable
 
     noteable.diffs.each do |mr_diff|
       next unless mr_diff.new_path == self.diff.new_path
@@ -378,19 +446,19 @@ class Note < ActiveRecord::Base
     prev_lines = []
 
     diff_lines.each do |line|
-      if generate_line_code(line) != self.line_code
-        if line.type == "match"
-          prev_lines.clear
-          prev_match_line = line
-        else
-          prev_lines.push(line)
-          prev_lines.shift if prev_lines.length >= max_number_of_lines
-        end
+      if line.type == "match"
+        prev_lines.clear
+        prev_match_line = line
       else
         prev_lines << line
-        return prev_lines
+        
+        break if generate_line_code(line) == self.line_code
+
+        prev_lines.shift if prev_lines.length >= max_number_of_lines
       end
     end
+
+    prev_lines
   end
 
   def diff_lines
@@ -435,6 +503,10 @@ class Note < ActiveRecord::Base
     for_merge_request? && for_diff_line?
   end
 
+  def for_project_snippet?
+    noteable_type == "Snippet"
+  end
+
   # override to return commits, which are not active record
   def noteable
     if for_commit?
@@ -458,6 +530,26 @@ class Note < ActiveRecord::Base
                 )
   end
 
+  def superceded?(notes)
+    return false unless vote?
+
+    notes.each do |note|
+      next if note == self
+
+      if note.vote? &&
+        self[:author_id] == note[:author_id] &&
+        self[:created_at] <= note[:created_at]
+        return true
+      end
+    end
+
+    false
+  end
+
+  def vote?
+    upvote? || downvote?
+  end
+
   def votable?
     for_issue? || (for_merge_request? && !for_diff_line?)
   end
@@ -479,7 +571,7 @@ class Note < ActiveRecord::Base
   end
 
   # FIXME: Hack for polymorphic associations with STI
-  #        For more information wisit http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations
+  #        For more information visit http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations
   def noteable_type=(sType)
     super(sType.to_s.classify.constantize.base_class.to_s)
   end
@@ -502,6 +594,6 @@ class Note < ActiveRecord::Base
   end
 
   def editable?
-    !system
+    !read_attribute(:system)
   end
 end
diff --git a/app/models/notification.rb b/app/models/notification.rb
index b0f8ed6a4ecdaa2856a12d2c67d964c4c7a8568f..1395274173d4d18609167b6b9f6ed12abc133076 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -6,12 +6,13 @@ class Notification
   N_PARTICIPATING = 1
   N_WATCH = 2
   N_GLOBAL = 3
+  N_MENTION = 4
 
   attr_accessor :target
 
   class << self
     def notification_levels
-      [N_DISABLED, N_PARTICIPATING, N_WATCH]
+      [N_DISABLED, N_PARTICIPATING, N_WATCH, N_MENTION]
     end
 
     def options_with_labels
@@ -19,12 +20,13 @@ class Notification
         disabled: N_DISABLED,
         participating: N_PARTICIPATING,
         watch: N_WATCH,
+        mention: N_MENTION,
         global: N_GLOBAL
       }
     end
 
     def project_notification_levels
-      [N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL]
+      [N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL, N_MENTION]
     end
   end
 
@@ -48,6 +50,10 @@ class Notification
     target.notification_level == N_GLOBAL
   end
 
+  def mention?
+    target.notification_level == N_MENTION
+  end
+
   def level
     target.notification_level
   end
diff --git a/app/models/project.rb b/app/models/project.rb
index d2576bb85d0ee8a303d1360f0e13e353bab6afa6..c50b8a12621cb95e9a9cf7f380a5be5b62f0d0d4 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -24,12 +24,21 @@
 #  import_status          :string(255)
 #  repository_size        :float            default(0.0)
 #  star_count             :integer          default(0), not null
+#  import_type            :string(255)
+#  import_source          :string(255)
+#  avatar                 :string(255)
 #
 
+require 'carrierwave/orm/activerecord'
+require 'file_size_validator'
+
 class Project < ActiveRecord::Base
+  include Sortable
   include Gitlab::ShellAdapter
   include Gitlab::VisibilityLevel
   include Gitlab::ConfigHelper
+  include Rails.application.routes.url_helpers
+
   extend Gitlab::ConfigHelper
   extend Enumerize
 
@@ -41,14 +50,20 @@ class Project < ActiveRecord::Base
   default_value_for :wall_enabled, false
   default_value_for :snippets_enabled, gitlab_config_features.snippets
 
+  # set last_activity_at to the same as created_at
+  after_create :set_last_activity_at
+  def set_last_activity_at
+    update_column(:last_activity_at, self.created_at)
+  end
+
   ActsAsTaggableOn.strict_case_match = true
   acts_as_taggable_on :tags
 
   attr_accessor :new_default_branch
 
   # Relations
-  belongs_to :creator,      foreign_key: "creator_id", class_name: "User"
-  belongs_to :group, -> { where(type: Group) }, foreign_key: "namespace_id"
+  belongs_to :creator, foreign_key: 'creator_id', class_name: 'User'
+  belongs_to :group, -> { where(type: Group) }, foreign_key: 'namespace_id'
   belongs_to :namespace
 
   has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id'
@@ -58,29 +73,39 @@ class Project < ActiveRecord::Base
   has_one :gitlab_ci_service, dependent: :destroy
   has_one :campfire_service, dependent: :destroy
   has_one :emails_on_push_service, dependent: :destroy
+  has_one :irker_service, dependent: :destroy
   has_one :pivotaltracker_service, dependent: :destroy
   has_one :hipchat_service, dependent: :destroy
   has_one :flowdock_service, dependent: :destroy
   has_one :assembla_service, dependent: :destroy
+  has_one :asana_service, dependent: :destroy
   has_one :gemnasium_service, dependent: :destroy
   has_one :slack_service, dependent: :destroy
   has_one :buildbox_service, dependent: :destroy
   has_one :bamboo_service, dependent: :destroy
+  has_one :teamcity_service, dependent: :destroy
   has_one :pushover_service, dependent: :destroy
+  has_one :jira_service, dependent: :destroy
+  has_one :redmine_service, dependent: :destroy
+  has_one :custom_issue_tracker_service, dependent: :destroy
+  has_one :gitlab_issue_tracker_service, dependent: :destroy
+  has_one :external_wiki_service, dependent: :destroy
+
   has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
+
   has_one :forked_from_project, through: :forked_project_link
   # Merge Requests for target project should be removed with it
-  has_many :merge_requests,     dependent: :destroy, foreign_key: "target_project_id"
+  has_many :merge_requests,     dependent: :destroy, foreign_key: 'target_project_id'
   # Merge requests from source project should be kept when source project was removed
-  has_many :fork_merge_requests, foreign_key: "source_project_id", class_name: MergeRequest
-  has_many :issues, -> { order 'issues.state DESC, issues.created_at DESC' }, dependent: :destroy
+  has_many :fork_merge_requests, foreign_key: 'source_project_id', class_name: MergeRequest
+  has_many :issues,             dependent: :destroy
   has_many :labels,             dependent: :destroy
   has_many :services,           dependent: :destroy
   has_many :events,             dependent: :destroy
   has_many :milestones,         dependent: :destroy
   has_many :notes,              dependent: :destroy
-  has_many :snippets,           dependent: :destroy, class_name: "ProjectSnippet"
-  has_many :hooks,              dependent: :destroy, class_name: "ProjectHook"
+  has_many :snippets,           dependent: :destroy, class_name: 'ProjectSnippet'
+  has_many :hooks,              dependent: :destroy, class_name: 'ProjectHook'
   has_many :protected_branches, dependent: :destroy
   has_many :project_members, dependent: :destroy, as: :source, class_name: 'ProjectMember'
   has_many :users, through: :project_members
@@ -95,67 +120,71 @@ class Project < ActiveRecord::Base
   # Validations
   validates :creator, presence: true, on: :create
   validates :description, length: { maximum: 2000 }, allow_blank: true
-  validates :name, presence: true, length: { within: 0..255 },
-            format: { with: Gitlab::Regex.project_name_regex,
-                      message: Gitlab::Regex.project_regex_message }
-  validates :path, presence: true, length: { within: 0..255 },
-            exclusion: { in: Gitlab::Blacklist.path },
-            format: { with: Gitlab::Regex.path_regex,
-                      message: Gitlab::Regex.path_regex_message }
+  validates :name,
+    presence: true,
+    length: { within: 0..255 },
+    format: { with: Gitlab::Regex.project_name_regex,
+              message: Gitlab::Regex.project_regex_message }
+  validates :path,
+    presence: true,
+    length: { within: 0..255 },
+    format: { with: Gitlab::Regex.path_regex,
+              message: Gitlab::Regex.path_regex_message }
   validates :issues_enabled, :merge_requests_enabled,
             :wiki_enabled, inclusion: { in: [true, false] }
-  validates :visibility_level,
-    exclusion: { in: gitlab_config.restricted_visibility_levels },
-    if: -> { gitlab_config.restricted_visibility_levels.any? }
   validates :issues_tracker_id, length: { maximum: 255 }, allow_blank: true
   validates :namespace, presence: true
   validates_uniqueness_of :name, scope: :namespace_id
   validates_uniqueness_of :path, scope: :namespace_id
   validates :import_url,
-    format: { with: URI::regexp(%w(git http https)), message: "should be a valid url" },
+    format: { with: URI::regexp(%w(ssh git http https)), message: 'should be a valid url' },
     if: :import?
   validates :star_count, numericality: { greater_than_or_equal_to: 0 }
   validate :check_limit, on: :create
+  validate :avatar_type,
+    if: ->(project) { project.avatar && project.avatar_changed? }
+  validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
+
+  mount_uploader :avatar, AvatarUploader
 
   # Scopes
-  scope :without_user, ->(user)  { where("projects.id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) }
-  scope :without_team, ->(team) { team.projects.present? ? where("projects.id NOT IN (:ids)", ids: team.projects.map(&:id)) : scoped  }
-  scope :not_in_group, ->(group) { where("projects.id NOT IN (:ids)", ids: group.project_ids ) }
-  scope :in_team, ->(team) { where("projects.id IN (:ids)", ids: team.projects.map(&:id)) }
+  scope :sorted_by_activity, -> { reorder(last_activity_at: :desc) }
+  scope :sorted_by_stars, -> { reorder('projects.star_count DESC') }
+  scope :sorted_by_names, -> { joins(:namespace).reorder('namespaces.name ASC, projects.name ASC') }
+
+  scope :without_user, ->(user)  { where('projects.id NOT IN (:ids)', ids: user.authorized_projects.map(&:id) ) }
+  scope :without_team, ->(team) { team.projects.present? ? where('projects.id NOT IN (:ids)', ids: team.projects.map(&:id)) : scoped  }
+  scope :not_in_group, ->(group) { where('projects.id NOT IN (:ids)', ids: group.project_ids ) }
   scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
   scope :in_group_namespace, -> { joins(:group) }
-  scope :sorted_by_activity, -> { reorder("projects.last_activity_at DESC") }
-  scope :sorted_by_stars, -> { reorder("projects.star_count DESC") }
   scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
-  scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
+  scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) }
   scope :public_only, -> { where(visibility_level: Project::PUBLIC) }
   scope :public_and_internal_only, -> { where(visibility_level: Project.public_and_internal_levels) }
   scope :non_archived, -> { where(archived: false) }
 
-  enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab
-
   state_machine :import_status, initial: :none do
     event :import_start do
-      transition :none => :started
+      transition [:none, :finished] => :started
     end
 
     event :import_finish do
-      transition :started => :finished
+      transition started: :finished
     end
 
     event :import_fail do
-      transition :started => :failed
+      transition started: :failed
     end
 
     event :import_retry do
-      transition :failed => :started
+      transition failed: :started
     end
 
     state :started
     state :finished
     state :failed
 
-    after_transition any => :started, :do => :add_import_job
+    after_transition any => :started, do: :add_import_job
   end
 
   class << self
@@ -169,7 +198,7 @@ class Project < ActiveRecord::Base
 
     def publicish(user)
       visibility_levels = [Project::PUBLIC]
-      visibility_levels += [Project::INTERNAL] if user
+      visibility_levels << Project::INTERNAL if user
       where(visibility_level: visibility_levels)
     end
 
@@ -178,21 +207,26 @@ class Project < ActiveRecord::Base
     end
 
     def active
-      joins(:issues, :notes, :merge_requests).order("issues.created_at, notes.created_at, merge_requests.created_at DESC")
+      joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC')
     end
 
     def search(query)
-      joins(:namespace).where("projects.archived = ?", false).where("projects.name LIKE :query OR projects.path LIKE :query OR namespaces.name LIKE :query OR projects.description LIKE :query", query: "%#{query}%")
+      joins(:namespace).where('projects.archived = ?', false).
+        where('LOWER(projects.name) LIKE :query OR
+              LOWER(projects.path) LIKE :query OR
+              LOWER(namespaces.name) LIKE :query OR
+              LOWER(projects.description) LIKE :query',
+              query: "%#{query.try(:downcase)}%")
     end
 
     def search_by_title(query)
-      where("projects.archived = ?", false).where("LOWER(projects.name) LIKE :query", query: "%#{query.downcase}%")
+      where('projects.archived = ?', false).where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%")
     end
 
     def find_with_namespace(id)
-      return nil unless id.include?("/")
+      return nil unless id.include?('/')
 
-      id = id.split("/")
+      id = id.split('/')
       namespace = Namespace.find_by(path: id.first)
       return nil unless namespace
 
@@ -204,13 +238,10 @@ class Project < ActiveRecord::Base
     end
 
     def sort(method)
-      case method.to_s
-      when 'newest' then reorder('projects.created_at DESC')
-      when 'oldest' then reorder('projects.created_at ASC')
-      when 'recently_updated' then reorder('projects.updated_at DESC')
-      when 'last_updated' then reorder('projects.updated_at ASC')
-      when 'largest_repository' then reorder('projects.repository_size DESC')
-      else reorder("namespaces.path, projects.name ASC")
+      if method == 'repository_size_desc'
+        reorder(repository_size: :desc, id: :desc)
+      else
+        order_by(method)
       end
     end
   end
@@ -260,19 +291,19 @@ class Project < ActiveRecord::Base
   end
 
   def to_param
-    namespace.path + "/" + path
+    path
   end
 
   def web_url
-    [gitlab_config.url, path_with_namespace].join("/")
+    [gitlab_config.url, path_with_namespace].join('/')
   end
 
   def web_url_without_protocol
-    web_url.split("://")[1]
+    web_url.split('://')[1]
   end
 
   def build_commit_note(commit)
-    notes.new(commit_id: commit.id, noteable_type: "Commit")
+    notes.new(commit_id: commit.id, noteable_type: 'Commit')
   end
 
   def last_activity
@@ -288,33 +319,68 @@ class Project < ActiveRecord::Base
   end
 
   def issue_exists?(issue_id)
-    if used_default_issues_tracker?
+    if default_issues_tracker?
       self.issues.where(iid: issue_id).first.present?
     else
       true
     end
   end
 
-  def used_default_issues_tracker?
-    self.issues_tracker == Project.issues_tracker.default_value
+  def default_issue_tracker
+    gitlab_issue_tracker_service || create_gitlab_issue_tracker_service
+  end
+
+  def issues_tracker
+    if external_issue_tracker
+      external_issue_tracker
+    else
+      default_issue_tracker
+    end
+  end
+
+  def default_issues_tracker?
+    if external_issue_tracker
+      false
+    else
+      true
+    end
+  end
+
+  def external_issues_trackers
+    services.select(&:issue_tracker?).reject(&:default?)
+  end
+
+  def external_issue_tracker
+    @external_issues_tracker ||= external_issues_trackers.select(&:activated?).first
   end
 
   def can_have_issues_tracker_id?
-    self.issues_enabled && !self.used_default_issues_tracker?
+    self.issues_enabled && !self.default_issues_tracker?
   end
 
   def build_missing_services
-    available_services_names.each do |service_name|
-      service = services.find { |service| service.to_param == service_name }
+    services_templates = Service.where(template: true)
+
+    Service.available_services_names.each do |service_name|
+      service = find_service(services, service_name)
 
       # If service is available but missing in db
-      # we should create an instance. Ex `create_gitlab_ci_service`
-      service = self.send :"create_#{service_name}_service" if service.nil?
+      if service.nil?
+        # We should check if template for the service exists
+        template = find_service(services_templates, service_name)
+
+        if template.nil?
+          # If no template, we should create an instance. Ex `create_gitlab_ci_service`
+          service = self.send :"create_#{service_name}_service"
+        else
+          Service.create_from_template(self.id, template)
+        end
+      end
     end
   end
 
-  def available_services_names
-    %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack pushover buildbox bamboo)
+  def find_service(list, name)
+    list.find { |service| service.to_param == name }
   end
 
   def gitlab_ci?
@@ -329,6 +395,27 @@ class Project < ActiveRecord::Base
     @ci_service ||= ci_services.select(&:activated?).first
   end
 
+  def avatar_type
+    unless self.avatar.image?
+      self.errors.add :avatar, 'only images allowed'
+    end
+  end
+
+  def avatar_in_git
+    @avatar_file ||= 'logo.png' if repository.blob_at_branch('master', 'logo.png')
+    @avatar_file ||= 'logo.jpg' if repository.blob_at_branch('master', 'logo.jpg')
+    @avatar_file ||= 'logo.gif' if repository.blob_at_branch('master', 'logo.gif')
+    @avatar_file
+  end
+
+  def avatar_url
+    if avatar.present?
+      [gitlab_config.url, avatar.url].join
+    elsif avatar_in_git
+      [gitlab_config.url, namespace_project_avatar_path(namespace, self)].join
+    end
+  end
+
   # For compatibility with old code
   def code
     path
@@ -355,20 +442,20 @@ class Project < ActiveRecord::Base
     end
   end
 
-  def team_member_by_name_or_email(name = nil, email = nil)
-    user = users.where("name like ? or email like ?", name, email).first
+  def project_member_by_name_or_email(name = nil, email = nil)
+    user = users.where('name like ? or email like ?', name, email).first
     project_members.where(user: user) if user
   end
 
   # Get Team Member record by user id
-  def team_member_by_id(user_id)
+  def project_member_by_id(user_id)
     project_members.find_by(user_id: user_id)
   end
 
   def name_with_namespace
     @name_with_namespace ||= begin
                                if namespace
-                                 namespace.human_name + " / " + name
+                                 namespace.human_name + ' / ' + name
                                else
                                  name
                                end
@@ -389,15 +476,10 @@ class Project < ActiveRecord::Base
     end
   end
 
-  def execute_services(data)
-    services.each do |service|
-
-      # Call service hook only if it is active
-      begin
-        service.execute(data) if service.active
-      rescue => e
-        logger.error(e)
-      end
+  def execute_services(data, hooks_scope = :push_hooks)
+    # Call only service hooks that are active for this scope
+    services.send(hooks_scope).each do |service|
+      service.async_execute(data)
     end
   end
 
@@ -409,7 +491,7 @@ class Project < ActiveRecord::Base
   def valid_repo?
     repository.exists?
   rescue
-    errors.add(:path, "Invalid repository path")
+    errors.add(:path, 'Invalid repository path')
     false
   end
 
@@ -468,7 +550,7 @@ class Project < ActiveRecord::Base
   end
 
   def http_url_to_repo
-    [gitlab_config.url, "/", path_with_namespace, ".git"].join('')
+    [gitlab_config.url, '/', path_with_namespace, '.git'].join('')
   end
 
   # Check if current branch name is marked as protected in the system
@@ -476,6 +558,10 @@ class Project < ActiveRecord::Base
     protected_branches_names.include?(branch_name)
   end
 
+  def developers_can_push_to_protected_branch?(branch_name)
+    protected_branches.any? { |pb| pb.name == branch_name && pb.developers_can_push }
+  end
+
   def forked?
     !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
   end
@@ -527,6 +613,7 @@ class Project < ActiveRecord::Base
   # Since we do cache @event we need to reset cache in special cases:
   # * when project was moved
   # * when project was renamed
+  # * when the project avatar changes
   # Events cache stored like  events/23-20130109142513.
   # The cache key includes updated_at timestamp.
   # Thus it will automatically generate a new fragment
@@ -586,4 +673,25 @@ class Project < ActiveRecord::Base
   def origin_merge_requests
     merge_requests.where(source_project_id: self.id)
   end
+
+  def create_repository
+    if gitlab_shell.add_repository(path_with_namespace)
+      true
+    else
+      errors.add(:base, 'Failed to create repository')
+      false
+    end
+  end
+
+  def repository_exists?
+    !!repository.exists?
+  end
+
+  def create_wiki
+    ProjectWiki.new(self, self.owner).wiki
+    true
+  rescue ProjectWiki::CouldNotCreateWikiError => ex
+    errors.add(:base, 'Failed create wiki')
+    false
+  end
 end
diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e6e16058d41bd7223dadb698513a5f7c57bd8b17
--- /dev/null
+++ b/app/models/project_services/asana_service.rb
@@ -0,0 +1,127 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
+#
+require 'asana'
+
+class AsanaService < Service
+  prop_accessor :api_key, :restrict_to_branch
+  validates :api_key, presence: true, if: :activated?
+
+  def title
+    'Asana'
+  end
+
+  def description
+    'Asana - Teamwork without email'
+  end
+
+  def help
+    'This service adds commit messages as comments to Asana tasks.
+Once enabled, commit messages are checked for Asana task URLs
+(for example, `https://app.asana.com/0/123456/987654`) or task IDs
+starting with # (for example, `#987654`). Every task ID found will
+get the commit comment added to it.
+
+You can also close a task with a message containing: `fix #123456`.
+
+You can find your Api Keys here:
+http://developer.asana.com/documentation/#api_keys'
+  end
+
+  def to_param
+    'asana'
+  end
+
+  def fields
+    [
+      {
+        type: 'text',
+        name: 'api_key',
+        placeholder: 'User API token. User must have access to task,
+all comments will be attributed to this user.'
+      },
+      {
+        type: 'text',
+        name: 'restrict_to_branch',
+        placeholder: 'Comma-separated list of branches which will be
+automatically inspected. Leave blank to include all branches.'
+      }
+    ]
+  end
+
+  def supported_events
+    %w(push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
+    Asana.configure do |client|
+      client.api_key = api_key
+    end
+
+    user = data[:user_name]
+    branch = Gitlab::Git.ref_name(data[:ref])
+
+    branch_restriction = restrict_to_branch.to_s
+
+    # check the branch restriction is poplulated and branch is not included
+    if branch_restriction.length > 0 && branch_restriction.index(branch).nil?
+      return
+    end
+
+    project_name = project.name_with_namespace
+    push_msg = user + ' pushed to branch ' + branch + ' of ' + project_name
+
+    data[:commits].each do |commit|
+      check_commit(' ( ' + commit[:url] + ' ): ' + commit[:message], push_msg)
+    end
+  end
+
+  def check_commit(message, push_msg)
+    task_list = []
+    close_list = []
+
+    message.split("\n").each do |line|
+      # look for a task ID or a full Asana url
+      task_list.concat(line.scan(/#(\d+)/))
+      task_list.concat(line.scan(/https:\/\/app\.asana\.com\/\d+\/\d+\/(\d+)/))
+      # look for a word starting with 'fix' followed by a task ID
+      close_list.concat(line.scan(/(fix\w*)\W*#(\d+)/i))
+    end
+
+    # post commit to every taskid found
+    task_list.each do |taskid|
+      task = Asana::Task.find(taskid[0])
+
+      if task
+        task.create_story(text: push_msg + ' ' + message)
+      end
+    end
+
+    # close all tasks that had 'fix(ed/es/ing) #:id' in them
+    close_list.each do |taskid|
+      task = Asana::Task.find(taskid.last)
+
+      if task
+        task.modify(completed: true)
+      end
+    end
+  end
+end
diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb
index 0b90a14f39c9abab2cd0318371776143eb05e11b..fb7e0c0fb0d1580c5b36217e6f5f44b9e7f3b289 100644
--- a/app/models/project_services/assembla_service.rb
+++ b/app/models/project_services/assembla_service.rb
@@ -2,14 +2,20 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
 #
 
 class AssemblaService < Service
@@ -37,8 +43,14 @@ class AssemblaService < Service
     ]
   end
 
-  def execute(push)
+  def supported_events
+    %w(push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
     url = "https://atlas.assembla.com/spaces/#{subdomain}/github_tool?secret_key=#{token}"
-    AssemblaService.post(url, body: { payload: push }.to_json, headers: { 'Content-Type' => 'application/json' })
+    AssemblaService.post(url, body: { payload: data }.to_json, headers: { 'Content-Type' => 'application/json' })
   end
 end
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index b9eec9ab21e9a9f28028b43cfb32ba4962b7597c..f968afe9fa8db4de6127aa79ef9df535d92f452b 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -1,15 +1,41 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
+#
+
 class BambooService < CiService
   include HTTParty
 
   prop_accessor :bamboo_url, :build_key, :username, :password
 
-  validates :bamboo_url, presence: true,
-            format: { with: URI::regexp }, if: :activated?
+  validates :bamboo_url,
+    presence: true,
+    format: { with: URI::regexp },
+    if: :activated?
   validates :build_key, presence: true, if: :activated?
-  validates :username, presence: true,
-            if: ->(service) { service.password? }, if: :activated?
-  validates :password, presence: true,
-            if: ->(service) { service.username? }, if: :activated?
+  validates :username,
+    presence: true,
+    if: ->(service) { service.password? },
+    if: :activated?
+  validates :password,
+    presence: true,
+    if: ->(service) { service.username? },
+    if: :activated?
 
   attr_accessor :response
 
@@ -48,6 +74,10 @@ class BambooService < CiService
     ]
   end
 
+  def supported_events
+    %w(push)
+  end
+  
   def build_info(sha)
     url = URI.parse("#{bamboo_url}/rest/api/latest/result?label=#{sha}")
 
@@ -63,7 +93,7 @@ class BambooService < CiService
     end
   end
 
-  def build_page(sha)
+  def build_page(sha, ref)
     build_info(sha) if @response.nil? || !@response.code
 
     if @response.code != 200 || @response['results']['results']['size'] == '0'
@@ -76,7 +106,7 @@ class BambooService < CiService
     end
   end
 
-  def commit_status(sha)
+  def commit_status(sha, ref)
     build_info(sha) if @response.nil? || !@response.code
     return :error unless @response.code == 200 || @response.code == 404
 
@@ -97,7 +127,9 @@ class BambooService < CiService
     end
   end
 
-  def execute(_data)
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
     # Bamboo requires a GET and does not take any data.
     self.class.get("#{bamboo_url}/updateAndBuild.action?buildKey=#{build_key}",
                    verify: false)
diff --git a/app/models/project_services/buildbox_service.rb b/app/models/project_services/buildbox_service.rb
index 0ab67b79fe4fd85ebda1693d001a1f55ed3ef205..3a381ff11b8fd82ef8a5fb9a3375df37d57c780b 100644
--- a/app/models/project_services/buildbox_service.rb
+++ b/app/models/project_services/buildbox_service.rb
@@ -2,19 +2,29 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
 #
 
 require "addressable/uri"
 
+# Buildbox renamed to Buildkite, but for backwards compatability with the STI
+# of Services, the class name is kept as "Buildbox"
 class BuildboxService < CiService
+  ENDPOINT = "https://buildkite.com"
+
   prop_accessor :project_url, :token
 
   validates :project_url, presence: true, if: :activated?
@@ -23,7 +33,7 @@ class BuildboxService < CiService
   after_save :compose_service_hook, if: :activated?
 
   def webhook_url
-    "#{buildbox_endpoint('webhook')}/deliver/#{webhook_token}"
+    "#{buildkite_endpoint('webhook')}/deliver/#{webhook_token}"
   end
 
   def compose_service_hook
@@ -32,11 +42,17 @@ class BuildboxService < CiService
     hook.save
   end
 
+  def supported_events
+    %w(push)
+  end
+
   def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
     service_hook.execute(data)
   end
 
-  def commit_status(sha)
+  def commit_status(sha, ref)
     response = HTTParty.get(commit_status_path(sha), verify: false)
 
     if response.code == 200 && response['status']
@@ -47,10 +63,10 @@ class BuildboxService < CiService
   end
 
   def commit_status_path(sha)
-    "#{buildbox_endpoint('gitlab')}/status/#{status_token}.json?commit=#{sha}"
+    "#{buildkite_endpoint('gitlab')}/status/#{status_token}.json?commit=#{sha}"
   end
 
-  def build_page(sha)
+  def build_page(sha, ref)
     "#{project_url}/builds?commit=#{sha}"
   end
 
@@ -59,11 +75,11 @@ class BuildboxService < CiService
   end
 
   def status_img_path
-    "#{buildbox_endpoint('badge')}/#{status_token}.svg"
+    "#{buildkite_endpoint('badge')}/#{status_token}.svg"
   end
 
   def title
-    'Buildbox'
+    'Buildkite'
   end
 
   def description
@@ -71,18 +87,18 @@ class BuildboxService < CiService
   end
 
   def to_param
-    'buildbox'
+    'buildkite'
   end
 
   def fields
     [
       { type: 'text',
         name: 'token',
-        placeholder: 'Buildbox project GitLab token' },
+        placeholder: 'Buildkite project GitLab token' },
 
       { type: 'text',
         name: 'project_url',
-        placeholder: 'https://buildbox.io/example/project' }
+        placeholder: "#{ENDPOINT}/example/project" }
     ]
   end
 
@@ -104,11 +120,9 @@ class BuildboxService < CiService
     end
   end
 
-  def buildbox_endpoint(subdomain = nil)
-    endpoint = 'https://buildbox.io'
-
+  def buildkite_endpoint(subdomain = nil)
     if subdomain.present?
-      uri = Addressable::URI.parse(endpoint)
+      uri = Addressable::URI.parse(ENDPOINT)
       new_endpoint = "#{uri.scheme || 'http'}://#{subdomain}.#{uri.host}"
 
       if uri.port.present?
@@ -117,7 +131,7 @@ class BuildboxService < CiService
         new_endpoint
       end
     else
-      endpoint
+      ENDPOINT
     end
   end
 end
diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb
index 0736ddab99bfa29c943d0674f06b70f3252063c1..e591afdda6448e1502bb075b2a90a15cec9cb119 100644
--- a/app/models/project_services/campfire_service.rb
+++ b/app/models/project_services/campfire_service.rb
@@ -2,14 +2,20 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
 #
 
 class CampfireService < Service
@@ -36,11 +42,17 @@ class CampfireService < Service
     ]
   end
 
-  def execute(push_data)
+  def supported_events
+    %w(push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
     room = gate.find_room_by_name(self.room)
     return true unless room
 
-    message = build_message(push_data)
+    message = build_message(data)
 
     room.speak(message)
   end
@@ -52,7 +64,7 @@ class CampfireService < Service
   end
 
   def build_message(push)
-    ref = push[:ref].gsub("refs/heads/", "")
+    ref = Gitlab::Git.ref_name(push[:ref])
     before = push[:before]
     after = push[:after]
 
@@ -60,9 +72,9 @@ class CampfireService < Service
     message << "[#{project.name_with_namespace}] "
     message << "#{push[:user_name]} "
 
-    if before =~ /000000/
+    if Gitlab::Git.blank_ref?(before)
       message << "pushed new branch #{ref} \n"
-    elsif after =~ /000000/
+    elsif Gitlab::Git.blank_ref?(after)
       message << "removed branch #{ref} \n"
     else
       message << "pushed #{push[:total_commits_count]} commits to #{ref}. "
diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb
index b1d5e49ede3557cc4b8b7fa6f6abcebbcab9568d..1a36e439245c1d7ef3cba67f84e2d666074431da 100644
--- a/app/models/project_services/ci_service.rb
+++ b/app/models/project_services/ci_service.rb
@@ -2,14 +2,19 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
 #
 
 # Base class for CI services
@@ -20,12 +25,16 @@ class CiService < Service
     :ci
   end
 
+  def supported_events
+    %w(push)
+  end
+
   # Return complete url to build page
   #
   # Ex.
   #   http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
   #
-  def build_page(sha)
+  def build_page(sha, ref)
     # implement inside child
   end
 
@@ -42,7 +51,7 @@ class CiService < Service
   #   # => 'running'
   #
   #
-  def commit_status(sha)
+  def commit_status(sha, ref)
     # implement inside child
   end
 end
diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8d25f6278709b42cd768127beab4af769f416669
--- /dev/null
+++ b/app/models/project_services/custom_issue_tracker_service.rb
@@ -0,0 +1,57 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+class CustomIssueTrackerService < IssueTrackerService
+
+  prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
+
+  def title
+    if self.properties && self.properties['title'].present?
+      self.properties['title']
+    else
+      'Custom Issue Tracker'
+    end
+  end
+
+  def description
+    if self.properties && self.properties['description'].present?
+      self.properties['description']
+    else
+      'Custom issue tracker'
+    end
+  end
+
+  def to_param
+    'custom_issue_tracker'
+  end
+
+  def fields
+    [
+      { type: 'text', name: 'title', placeholder: title },
+      { type: 'text', name: 'description', placeholder: description },
+      { type: 'text', name: 'project_url', placeholder: 'Project url' },
+      { type: 'text', name: 'issues_url', placeholder: 'Issue url' },
+      { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' }
+    ]
+  end
+
+  def initialize_properties
+    self.properties = {} if properties.nil?
+  end
+end
diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb
index b9071b982955fd6b96867e17c44c5f26c998ae38..6f6e5950aab3575b00cc53f9030e4946003dd46b 100644
--- a/app/models/project_services/emails_on_push_service.rb
+++ b/app/models/project_services/emails_on_push_service.rb
@@ -2,17 +2,24 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
 #
 
 class EmailsOnPushService < Service
+  prop_accessor :send_from_committer_email
+  prop_accessor :disable_diffs
   prop_accessor :recipients
   validates :recipients, presence: true, if: :activated?
 
@@ -28,12 +35,37 @@ class EmailsOnPushService < Service
     'emails_on_push'
   end
 
+  def supported_events
+    %w(push tag_push)
+  end
+
   def execute(push_data)
-    EmailsOnPushWorker.perform_async(project_id, recipients, push_data)
+    return unless supported_events.include?(push_data[:object_kind])
+
+    EmailsOnPushWorker.perform_async(
+      project_id, 
+      recipients, 
+      push_data, 
+      send_from_committer_email:  send_from_committer_email?, 
+      disable_diffs:              disable_diffs?
+    )
+  end
+
+  def send_from_committer_email?
+    self.send_from_committer_email == "1"
+  end
+
+  def disable_diffs?
+    self.disable_diffs == "1"
   end
 
   def fields
+    domains = Notify.allowed_email_domains.map { |domain| "user@#{domain}" }.join(", ")
     [
+      { type: 'checkbox', name: 'send_from_committer_email', title: "Send from committer",
+        help: "Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. #{domains})." },
+      { type: 'checkbox', name: 'disable_diffs', title: "Disable code diffs",
+        help: "Don't include possibly sensitive code diffs in notification body." },
       { type: 'textarea', name: 'recipients', placeholder: 'Emails separated by whitespace' },
     ]
   end
diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e521186798c70029063d40fac807d0fcf1549688
--- /dev/null
+++ b/app/models/project_services/external_wiki_service.rb
@@ -0,0 +1,48 @@
+# == 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 ExternalWikiService < Service
+  include HTTParty
+
+  prop_accessor :external_wiki_url
+  validates :external_wiki_url,
+            presence: true,
+            format: { with: URI::regexp },
+            if: :activated?
+
+  def title
+    'External Wiki'
+  end
+
+  def description
+    'Replaces the link to the internal wiki with a link to an external wiki.'
+  end
+
+  def to_param
+    'external_wiki'
+  end
+
+  def fields
+    [
+      { type: 'text', name: 'external_wiki_url', placeholder: 'The URL of the external Wiki' },
+    ]
+  end
+
+  def execute(_data)
+    @response = HTTParty.get(properties['external_wiki_url'], verify: true) rescue nil
+    if @response !=200
+      nil
+    end
+  end
+end
diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb
index 86705f5dabd19c4be5835237d83ae82a923512fd..99e361dd6ed18361d59ae4fb5b54fe76f0ae32e3 100644
--- a/app/models/project_services/flowdock_service.rb
+++ b/app/models/project_services/flowdock_service.rb
@@ -2,14 +2,19 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
 #
 
 require "flowdock-git-hook"
@@ -36,11 +41,17 @@ class FlowdockService < Service
     ]
   end
 
-  def execute(push_data)
+  def supported_events
+    %w(push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
     Flowdock::Git.post(
-      push_data[:ref],
-      push_data[:before],
-      push_data[:after],
+      data[:ref],
+      data[:before],
+      data[:after],
       token: token,
       repo: project.repository.path_to_repo,
       repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}",
diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb
index 18fdd204ecd6a901349dba79005f1d34a5d8a288..4e75bdfc953eec9ee220cf00e505b07292f44dc9 100644
--- a/app/models/project_services/gemnasium_service.rb
+++ b/app/models/project_services/gemnasium_service.rb
@@ -2,14 +2,19 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
 #
 
 require "gemnasium/gitlab_service"
@@ -37,11 +42,17 @@ class GemnasiumService < Service
     ]
   end
 
-  def execute(push_data)
+  def supported_events
+    %w(push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
     Gemnasium::GitlabService.execute(
-      ref: push_data[:ref],
-      before: push_data[:before],
-      after: push_data[:after],
+      ref: data[:ref],
+      before: data[:before],
+      after: data[:after],
       token: token,
       api_key: api_key,
       repo: project.repository.path_to_repo
diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb
index fadebf968bc7fe4f058ad82f7d1a30acf32ebac9..edaeeffc22842cbc7f63c8861f1fdba2318e53eb 100644
--- a/app/models/project_services/gitlab_ci_service.rb
+++ b/app/models/project_services/gitlab_ci_service.rb
@@ -2,14 +2,19 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
 #
 
 class GitlabCiService < CiService
@@ -17,8 +22,6 @@ class GitlabCiService < CiService
   validates :project_url, presence: true, if: :activated?
   validates :token, presence: true, if: :activated?
 
-  delegate :execute, to: :service_hook, prefix: nil
-
   after_save :compose_service_hook, if: :activated?
 
   def compose_service_hook
@@ -27,17 +30,27 @@ class GitlabCiService < CiService
     hook.save
   end
 
-  def commit_status_path(sha)
-    project_url + "/commits/#{sha}/status.json?token=#{token}"
+  def supported_events
+    %w(push tag_push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
+    service_hook.execute(data)
+  end
+
+  def commit_status_path(sha, ref)
+    project_url + "/refs/#{ref}/commits/#{sha}/status.json?token=#{token}"
   end
 
-  def get_ci_build(sha)
+  def get_ci_build(sha, ref)
     @ci_builds ||= {}
-    @ci_builds[sha] ||= HTTParty.get(commit_status_path(sha), verify: false)
+    @ci_builds[sha] ||= HTTParty.get(commit_status_path(sha, ref), verify: false)
   end
 
-  def commit_status(sha)
-    response = get_ci_build(sha)
+  def commit_status(sha, ref)
+    response = get_ci_build(sha, ref)
 
     if response.code == 200 and response["status"]
       response["status"]
@@ -46,16 +59,16 @@ class GitlabCiService < CiService
     end
   end
 
-  def commit_coverage(sha)
-    response = get_ci_build(sha)
+  def commit_coverage(sha, ref)
+    response = get_ci_build(sha, ref)
 
     if response.code == 200 and response["coverage"]
       response["coverage"]
     end
   end
 
-  def build_page(sha)
-    project_url + "/commits/#{sha}"
+  def build_page(sha, ref)
+    project_url + "/refs/#{ref}/commits/#{sha}"
   end
 
   def builds_path
@@ -81,7 +94,7 @@ class GitlabCiService < CiService
   def fields
     [
       { type: 'text', name: 'token', placeholder: 'GitLab CI project specific token' },
-      { type: 'text', name: 'project_url', placeholder: 'http://ci.gitlabhq.com/projects/3'}
+      { type: 'text', name: 'project_url', placeholder: 'http://ci.gitlabhq.com/projects/3' }
     ]
   end
 end
diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..84346350a6c9e7879bc85cdd3dbdf8b7c6acfe29
--- /dev/null
+++ b/app/models/project_services/gitlab_issue_tracker_service.rb
@@ -0,0 +1,51 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
+#
+
+class GitlabIssueTrackerService < IssueTrackerService
+  include Rails.application.routes.url_helpers
+  prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
+
+
+  def default?
+    true
+  end
+
+  def to_param
+    'gitlab'
+  end
+
+  def project_url
+    "#{gitlab_url}#{namespace_project_issues_path(project.namespace, project)}"
+  end
+
+  def new_issue_url
+    "#{gitlab_url}#{new_namespace_project_issue_path(namespace_id: project.namespace, project_id: project)}"
+  end
+
+  def issue_url(iid)
+    "#{gitlab_url}#{namespace_project_issue_path(namespace_id: project.namespace, project_id: project, id: iid)}"
+  end
+
+  private
+
+  def gitlab_url
+    Gitlab.config.gitlab.relative_url_root.chomp("/") if Gitlab.config.gitlab.relative_url_root
+  end
+end
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
index 4078938cdbb87fbe1cc9d412680c76dfd8a23f12..d264a56ebdf496582c6861139b1eb8a789195a1f 100644
--- a/app/models/project_services/hipchat_service.rb
+++ b/app/models/project_services/hipchat_service.rb
@@ -2,24 +2,29 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
 #
 
 class HipchatService < Service
   MAX_COMMITS = 3
 
-  prop_accessor :token, :room
+  prop_accessor :token, :room, :server
   validates :token, presence: true, if: :activated?
 
   def title
-    'Hipchat'
+    'HipChat'
   end
 
   def description
@@ -32,37 +37,64 @@ class HipchatService < Service
 
   def fields
     [
-      { type: 'text', name: 'token',     placeholder: '' },
-      { type: 'text', name: 'room',      placeholder: '' }
+      { type: 'text', name: 'token',     placeholder: 'Room token' },
+      { type: 'text', name: 'room',      placeholder: 'Room name or ID' },
+      { type: 'text', name: 'server',
+        placeholder: 'Leave blank for default. https://hipchat.example.com' }
     ]
   end
 
-  def execute(push_data)
-    gate[room].send('GitLab', create_message(push_data))
+  def supported_events
+    %w(push issue merge_request note tag_push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
+    gate[room].send('GitLab', create_message(data))
   end
 
   private
 
   def gate
-    @gate ||= HipChat::Client.new(token)
+    options = { api_version: 'v2' }
+    options[:server_url] = server unless server.blank?
+    @gate ||= HipChat::Client.new(token, options)
+  end
+
+  def create_message(data)
+    object_kind = data[:object_kind]
+
+    message = \
+      case object_kind
+      when "push", "tag_push"
+        create_push_message(data)
+      when "issue"
+        create_issue_message(data) unless is_update?(data)
+      when "merge_request"
+        create_merge_request_message(data) unless is_update?(data)
+      when "note"
+        create_note_message(data)
+      end
   end
 
-  def create_message(push)
-    ref = push[:ref].gsub("refs/heads/", "")
+  def create_push_message(push)
+    ref_type = Gitlab::Git.tag_ref?(push[:ref]) ? 'tag' : 'branch'
+    ref = Gitlab::Git.ref_name(push[:ref])
+
     before = push[:before]
     after = push[:after]
 
     message = ""
     message << "#{push[:user_name]} "
-    if before =~ /000000/
-      message << "pushed new branch <a href=\""\
-                 "#{project.web_url}/commits/#{URI.escape(ref)}\">#{ref}</a>"\
-                 " to <a href=\"#{project.web_url}\">"\
-                 "#{project.name_with_namespace.gsub!(/\s/, "")}</a>\n"
-    elsif after =~ /000000/
-      message << "removed branch #{ref} from <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> \n"
+    if Gitlab::Git.blank_ref?(before)
+      message << "pushed new #{ref_type} <a href=\""\
+                 "#{project_url}/commits/#{URI.escape(ref)}\">#{ref}</a>"\
+                 " to #{project_link}\n"
+    elsif Gitlab::Git.blank_ref?(after)
+      message << "removed #{ref_type} <b>#{ref}</b> from <a href=\"#{project.web_url}\">#{project_name}</a> \n"
     else
-      message << "pushed to branch <a href=\""\
+      message << "pushed to #{ref_type} <a href=\""\
                   "#{project.web_url}/commits/#{URI.escape(ref)}\">#{ref}</a> "
       message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> "
       message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)"
@@ -78,4 +110,129 @@ class HipchatService < Service
 
     message
   end
+
+  def format_body(body)
+    if body
+      body = body.truncate(200, separator: ' ', omission: '...')
+    end
+
+    "<pre>#{body}</pre>"
+  end
+
+  def create_issue_message(data)
+    user_name = data[:user][:name]
+
+    obj_attr = data[:object_attributes]
+    obj_attr = HashWithIndifferentAccess.new(obj_attr)
+    title = obj_attr[:title]
+    state = obj_attr[:state]
+    issue_iid = obj_attr[:iid]
+    issue_url = obj_attr[:url]
+    description = obj_attr[:description]
+
+    issue_link = "<a href=\"#{issue_url}\">issue ##{issue_iid}</a>"
+    message = "#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>"
+
+    if description
+      description = format_body(description)
+      message << description
+    end
+
+    message
+  end
+
+  def create_merge_request_message(data)
+    user_name = data[:user][:name]
+
+    obj_attr = data[:object_attributes]
+    obj_attr = HashWithIndifferentAccess.new(obj_attr)
+    merge_request_id = obj_attr[:iid]
+    source_branch = obj_attr[:source_branch]
+    target_branch = obj_attr[:target_branch]
+    state = obj_attr[:state]
+    description = obj_attr[:description]
+    title = obj_attr[:title]
+
+    merge_request_url = "#{project_url}/merge_requests/#{merge_request_id}"
+    merge_request_link = "<a href=\"#{merge_request_url}\">merge request ##{merge_request_id}</a>"
+    message = "#{user_name} #{state} #{merge_request_link} in " \
+      "#{project_link}: <b>#{title}</b>"
+
+    if description
+      description = format_body(description)
+      message << description
+    end
+
+    message
+  end
+
+  def format_title(title)
+    "<b>" + title.lines.first.chomp + "</b>"
+  end
+
+  def create_note_message(data)
+    data = HashWithIndifferentAccess.new(data)
+    user_name = data[:user][:name]
+
+    repo_attr = HashWithIndifferentAccess.new(data[:repository])
+
+    obj_attr = HashWithIndifferentAccess.new(data[:object_attributes])
+    note = obj_attr[:note]
+    note_url = obj_attr[:url]
+    noteable_type = obj_attr[:noteable_type]
+
+    case noteable_type
+    when "Commit"
+      commit_attr = HashWithIndifferentAccess.new(data[:commit])
+      subject_desc = commit_attr[:id]
+      subject_desc = Commit.truncate_sha(subject_desc)
+      subject_type = "commit"
+      title = format_title(commit_attr[:message])
+    when "Issue"
+      subj_attr = HashWithIndifferentAccess.new(data[:issue])
+      subject_id = subj_attr[:iid]
+      subject_desc = "##{subject_id}"
+      subject_type = "issue"
+      title = format_title(subj_attr[:title])
+    when "MergeRequest"
+      subj_attr = HashWithIndifferentAccess.new(data[:merge_request])
+      subject_id = subj_attr[:iid]
+      subject_desc = "##{subject_id}"
+      subject_type = "merge request"
+      title = format_title(subj_attr[:title])
+    when "Snippet"
+      subj_attr = HashWithIndifferentAccess.new(data[:snippet])
+      subject_id = subj_attr[:id]
+      subject_desc = "##{subject_id}"
+      subject_type = "snippet"
+      title = format_title(subj_attr[:title])
+    end
+
+    subject_html = "<a href=\"#{note_url}\">#{subject_type} #{subject_desc}</a>"
+    message = "#{user_name} commented on #{subject_html} in #{project_link}: "
+    message << title
+
+    if note
+      note = format_body(note)
+      message << note
+    end
+
+    message
+  end
+
+  def project_name
+    project.name_with_namespace.gsub(/\s/, '')
+  end
+
+  def project_url
+    project.web_url
+  end
+
+  def project_link
+    "<a href=\"#{project_url}\">#{project_name}</a>"
+  end
+
+  def is_update?(data)
+    data[:object_attributes][:action] == 'update'
+  end
 end
diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2bddb7b881cfd7f33dfa775d272d2d524f45603a
--- /dev/null
+++ b/app/models/project_services/irker_service.rb
@@ -0,0 +1,163 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'uri'
+
+class IrkerService < Service
+  prop_accessor :colorize_messages, :recipients, :channels
+  validates :recipients, presence: true, if: :activated?
+  validate :check_recipients_count, if: :activated?
+
+  before_validation :get_channels
+  after_initialize :initialize_settings
+
+  # Writer for RSpec tests
+  attr_writer :settings
+
+  def initialize_settings
+    # See the documentation (doc/project_services/irker.md) for possible values
+    # here
+    @settings ||= {
+      server_ip: 'localhost',
+      server_port: 6659,
+      max_channels: 3,
+      default_irc_uri: nil
+    }
+  end
+
+  def title
+    'Irker (IRC gateway)'
+  end
+
+  def description
+    'Send IRC messages, on update, to a list of recipients through an Irker '\
+    'gateway.'
+  end
+
+  def help
+    msg = 'Recipients have to be specified with a full URI: '\
+    'irc[s]://irc.network.net[:port]/#channel. Special cases: if you want '\
+    'the channel to be a nickname instead, append ",isnick" to the channel '\
+    'name; if the channel is protected by a secret password, append '\
+    '"?key=secretpassword" to the URI.'
+
+    unless @settings[:default_irc].nil?
+      msg += ' Note that a default IRC URI is provided by this service\'s '\
+      "administrator: #{default_irc}. You can thus just give a channel name."
+    end
+    msg
+  end
+
+  def to_param
+    'irker'
+  end
+
+  def supported_events
+    %w(push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
+    IrkerWorker.perform_async(project_id, channels,
+                              colorize_messages, data, @settings)
+  end
+
+  def fields
+    [
+      { type: 'textarea', name: 'recipients',
+        placeholder: 'Recipients/channels separated by whitespaces' },
+      { type: 'checkbox', name: 'colorize_messages' },
+    ]
+  end
+
+  private
+
+  def check_recipients_count
+    return true if recipients.nil? || recipients.empty?
+
+    if recipients.split(/\s+/).count > max_chans
+      errors.add(:recipients, "are limited to #{max_chans}")
+    end
+  end
+
+  def max_chans
+    @settings[:max_channels]
+  end
+
+  def get_channels
+    return true unless :activated?
+    return true if recipients.nil? || recipients.empty?
+
+    map_recipients
+
+    errors.add(:recipients, 'are all invalid') if channels.empty?
+    true
+  end
+
+  def map_recipients
+    self.channels = recipients.split(/\s+/).map do |recipient|
+      format_channel default_irc_uri, recipient
+    end
+    channels.reject! &:nil?
+  end
+
+  def default_irc_uri
+    default_irc = @settings[:default_irc_uri]
+    if !(default_irc.nil? || default_irc[-1] == '/')
+      default_irc += '/'
+    end
+    default_irc
+  end
+
+  def format_channel(default_irc, recipient)
+    cnt = 0
+    url = nil
+
+    # Try to parse the chan as a full URI
+    begin
+      uri = URI.parse(recipient)
+      raise URI::InvalidURIError if uri.scheme.nil? && cnt == 0
+    rescue URI::InvalidURIError
+      unless default_irc.nil?
+        cnt += 1
+        recipient = "#{default_irc}#{recipient}"
+        retry if cnt == 1
+      end
+    else
+      url = consider_uri uri
+    end
+    url
+  end
+
+  def consider_uri(uri)
+    # Authorize both irc://domain.com/#chan and irc://domain.com/chan
+    if uri.is_a?(URI) && uri.scheme[/^ircs?$/] && !uri.path.nil?
+      # Do not authorize irc://domain.com/
+      if uri.fragment.nil? && uri.path.length > 1
+        uri.to_s
+      else
+        # Authorize irc://domain.com/smthg#chan
+        # The irker daemon will deal with it by concatenating smthg and
+        # chan, thus sending messages on #smthgchan
+        uri.to_s
+      end
+    end
+  end
+end
diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8e90c44d10361925a1615e51b6b1c4c2abc6d882
--- /dev/null
+++ b/app/models/project_services/issue_tracker_service.rb
@@ -0,0 +1,113 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
+#
+
+class IssueTrackerService < Service
+
+  validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated?
+
+  def category
+    :issue_tracker
+  end
+
+  def default?
+    false
+  end
+
+  def issue_url(iid)
+    self.issues_url.gsub(':id', iid.to_s)
+  end
+
+  def fields
+    [
+      { type: 'text', name: 'description', placeholder: description },
+      { type: 'text', name: 'project_url', placeholder: 'Project url' },
+      { type: 'text', name: 'issues_url', placeholder: 'Issue url' },
+      { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' }
+    ]
+  end
+
+  def initialize_properties
+    if properties.nil?
+      if enabled_in_gitlab_config
+        self.properties = {
+          title: issues_tracker['title'],
+          project_url: add_issues_tracker_id(issues_tracker['project_url']),
+          issues_url: add_issues_tracker_id(issues_tracker['issues_url']),
+          new_issue_url: add_issues_tracker_id(issues_tracker['new_issue_url'])
+        }
+      else
+        self.properties = {}
+      end
+    end
+  end
+
+  def supported_events
+    %w(push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
+    message = "#{self.type} was unable to reach #{self.project_url}. Check the url and try again."
+    result = false
+
+    begin
+      url = URI.parse(self.project_url)
+
+      if url.host && url.port
+        http = Net::HTTP.start(url.host, url.port, { open_timeout: 5, read_timeout: 5 })
+        response = http.head("/")
+
+        if response
+          message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}"
+          result = true
+        end
+      end
+    rescue Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED => error
+      message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}"
+    end
+    Rails.logger.info(message)
+    result
+  end
+
+  private
+
+  def enabled_in_gitlab_config
+    Gitlab.config.issues_tracker &&
+    Gitlab.config.issues_tracker.values.any? &&
+    issues_tracker
+  end
+
+  def issues_tracker
+    Gitlab.config.issues_tracker[to_param]
+  end
+
+  def add_issues_tracker_id(url)
+    if self.project
+      id = self.project.issues_tracker_id
+
+      if id
+        url = url.gsub(":issues_tracker_id", id)
+      end
+    end
+
+    url
+  end
+end
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fcd9dc2f33674ccd1fbd781434c542e1dc3cc298
--- /dev/null
+++ b/app/models/project_services/jira_service.rb
@@ -0,0 +1,58 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
+#
+
+class JiraService < IssueTrackerService
+  include Rails.application.routes.url_helpers
+
+  prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
+
+  def help
+    issue_tracker_link =  help_page_path("integration", "external-issue-tracker")
+
+    line1 = "Setting `project_url`, `issues_url` and `new_issue_url` will "\
+    "allow a user to easily navigate to the Jira issue tracker. "\
+    "See the [integration doc](#{issue_tracker_link}) for details."
+
+    line2 = 'Support for referencing commits and automatic closing of Jira issues directly ' \
+    'from GitLab is [available in GitLab EE.](http://doc.gitlab.com/ee/integration/jira.html)'
+
+    [line1, line2].join("\n\n")
+  end
+
+  def title
+    if self.properties && self.properties['title'].present?
+      self.properties['title']
+    else
+      'JIRA'
+    end
+  end
+
+  def description
+    if self.properties && self.properties['description'].present?
+      self.properties['description']
+    else
+      'Jira issue tracker'
+    end
+  end
+
+  def to_param
+    'jira'
+  end
+end
diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb
index 09e114f9cca2fa139b9922da74195a362bdb4e74..ade9ee97873999daa81fba4880cd736b9d6319aa 100644
--- a/app/models/project_services/pivotaltracker_service.rb
+++ b/app/models/project_services/pivotaltracker_service.rb
@@ -2,14 +2,20 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
 #
 
 class PivotaltrackerService < Service
@@ -36,9 +42,15 @@ class PivotaltrackerService < Service
     ]
   end
 
-  def execute(push)
+  def supported_events
+    %w(push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
     url = 'https://www.pivotaltracker.com/services/v5/source_commits'
-    push[:commits].each do |commit|
+    data[:commits].each do |commit|
       message = {
         'source_commit' => {
           'commit_id' => commit[:id],
diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb
index f247fde776262e14db640e82eeae796de439d554..53edf522e9a729a5827911c85c04a8b049ad3d29 100644
--- a/app/models/project_services/pushover_service.rb
+++ b/app/models/project_services/pushover_service.rb
@@ -2,14 +2,20 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
 #
 
 class PushoverService < Service
@@ -75,21 +81,27 @@ class PushoverService < Service
     ]
   end
 
-  def execute(push_data)
-    ref = push_data[:ref].gsub('refs/heads/', '')
-    before = push_data[:before]
-    after = push_data[:after]
+  def supported_events
+    %w(push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
+    ref = Gitlab::Git.ref_name(data[:ref])
+    before = data[:before]
+    after = data[:after]
 
-    if before =~ /000000/
-      message = "#{push_data[:user_name]} pushed new branch \"#{ref}\"."
-    elsif after =~ /000000/
-      message = "#{push_data[:user_name]} deleted branch \"#{ref}\"."
+    if Gitlab::Git.blank_ref?(before)
+      message = "#{data[:user_name]} pushed new branch \"#{ref}\"."
+    elsif Gitlab::Git.blank_ref?(after)
+      message = "#{data[:user_name]} deleted branch \"#{ref}\"."
     else
-      message = "#{push_data[:user_name]} push to branch \"#{ref}\"."
+      message = "#{data[:user_name]} push to branch \"#{ref}\"."
     end
 
-    if push_data[:total_commits_count] > 0
-      message << "\nTotal commits count: #{push_data[:total_commits_count]}"
+    if data[:total_commits_count] > 0
+      message << "\nTotal commits count: #{data[:total_commits_count]}"
     end
 
     pushover_data = {
@@ -99,7 +111,7 @@ class PushoverService < Service
       priority: priority,
       title: "#{project.name_with_namespace}",
       message: message,
-      url: push_data[:repository][:homepage],
+      url: data[:repository][:homepage],
       url_title: "See project #{project.name_with_namespace}"
     }
 
diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dd9ba97ee1fac487d66f5315955002abef9da6d9
--- /dev/null
+++ b/app/models/project_services/redmine_service.rb
@@ -0,0 +1,44 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
+#
+
+class RedmineService < IssueTrackerService
+
+  prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
+
+  def title
+    if self.properties && self.properties['title'].present?
+      self.properties['title']
+    else
+      'Redmine'
+    end
+  end
+
+  def description
+    if self.properties && self.properties['description'].present?
+      self.properties['description']
+    else
+      'Redmine issue tracker'
+    end
+  end
+
+  def to_param
+    'redmine'
+  end
+end
diff --git a/app/models/project_services/slack_message.rb b/app/models/project_services/slack_message.rb
deleted file mode 100644
index 28204e5ea60e6f2694296a9004df287449a459e1..0000000000000000000000000000000000000000
--- a/app/models/project_services/slack_message.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-require 'slack-notifier'
-
-class SlackMessage
-  def initialize(params)
-    @after = params.fetch(:after)
-    @before = params.fetch(:before)
-    @commits = params.fetch(:commits, [])
-    @project_name = params.fetch(:project_name)
-    @project_url = params.fetch(:project_url)
-    @ref = params.fetch(:ref).gsub('refs/heads/', '')
-    @username = params.fetch(:user_name)
-  end
-
-  def pretext
-    format(message)
-  end
-
-  def attachments
-    return [] if new_branch? || removed_branch?
-
-    commit_message_attachments
-  end
-
-  private
-
-  attr_reader :after
-  attr_reader :before
-  attr_reader :commits
-  attr_reader :project_name
-  attr_reader :project_url
-  attr_reader :ref
-  attr_reader :username
-
-  def message
-    if new_branch?
-      new_branch_message
-    elsif removed_branch?
-      removed_branch_message
-    else
-      push_message
-    end
-  end
-
-  def format(string)
-    Slack::Notifier::LinkFormatter.format(string)
-  end
-
-  def new_branch_message
-    "#{username} pushed new branch #{branch_link} to #{project_link}"
-  end
-
-  def removed_branch_message
-    "#{username} removed branch #{ref} from #{project_link}"
-  end
-
-  def push_message
-    "#{username} pushed to branch #{branch_link} of #{project_link} (#{compare_link})"
-  end
-
-  def commit_messages
-    commits.each_with_object('') do |commit, str|
-      str << compose_commit_message(commit)
-    end.chomp
-  end
-
-  def commit_message_attachments
-    [{ text: format(commit_messages), color: attachment_color }]
-  end
-
-  def compose_commit_message(commit)
-    author = commit.fetch(:author).fetch(:name)
-    id = commit.fetch(:id)[0..8]
-    message = commit.fetch(:message)
-    url = commit.fetch(:url)
-
-    "[#{id}](#{url}): #{message} - #{author}\n"
-  end
-
-  def new_branch?
-    before =~ /000000/
-  end
-
-  def removed_branch?
-    after =~ /000000/
-  end
-
-  def branch_url
-    "#{project_url}/commits/#{ref}"
-  end
-
-  def compare_url
-    "#{project_url}/compare/#{before}...#{after}"
-  end
-
-  def branch_link
-    "[#{ref}](#{branch_url})"
-  end
-
-  def project_link
-    "[#{project_name}](#{project_url})"
-  end
-
-  def compare_link
-    "[Compare changes](#{compare_url})"
-  end
-
-  def attachment_color
-    '#345'
-  end
-end
diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb
index 963f5440b6f87fef112f7bb7cf5ad7ce2b1740bf..36d9874edd32d3b8d8a3f22c377458817858b935 100644
--- a/app/models/project_services/slack_service.rb
+++ b/app/models/project_services/slack_service.rb
@@ -2,18 +2,24 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
 #
 
 class SlackService < Service
-  prop_accessor :webhook
+  prop_accessor :webhook, :username, :channel
   validates :webhook, presence: true, if: :activated?
 
   def title
@@ -30,20 +36,52 @@ class SlackService < Service
 
   def fields
     [
-      { type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' }
+      { type: 'text', name: 'webhook',
+        placeholder: 'https://hooks.slack.com/services/...' },
+      { type: 'text', name: 'username', placeholder: 'username' },
+      { type: 'text', name: 'channel', placeholder: '#channel' }
     ]
   end
 
-  def execute(push_data)
+  def supported_events
+    %w(push issue merge_request note tag_push)
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
     return unless webhook.present?
 
-    message = SlackMessage.new(push_data.merge(
+    object_kind = data[:object_kind]
+
+    data = data.merge(
       project_url: project_url,
       project_name: project_name
-    ))
+    )
+
+    # WebHook events often have an 'update' event that follows a 'open' or
+    # 'close' action. Ignore update events for now to prevent duplicate
+    # messages from arriving.
+
+    message = \
+      case object_kind
+      when "push", "tag_push"
+        PushMessage.new(data)
+      when "issue"
+        IssueMessage.new(data) unless is_update?(data)
+      when "merge_request"
+        MergeMessage.new(data) unless is_update?(data)
+      when "note"
+        NoteMessage.new(data)
+      end
 
-    notifier = Slack::Notifier.new(webhook)
-    notifier.ping(message.pretext, attachments: message.attachments)
+    opt = {}
+    opt[:channel] = channel if channel
+    opt[:username] = username if username
+
+    if message
+      notifier = Slack::Notifier.new(webhook, opt)
+      notifier.ping(message.pretext, attachments: message.attachments)
+    end
   end
 
   private
@@ -55,4 +93,13 @@ class SlackService < Service
   def project_url
     project.web_url
   end
+
+  def is_update?(data)
+    data[:object_attributes][:action] == 'update'
+  end
 end
+
+require "slack_service/issue_message"
+require "slack_service/push_message"
+require "slack_service/merge_message"
+require "slack_service/note_message"
diff --git a/app/models/project_services/slack_service/base_message.rb b/app/models/project_services/slack_service/base_message.rb
new file mode 100644
index 0000000000000000000000000000000000000000..aa00d6061a118473758411a0b7581836ff9db291
--- /dev/null
+++ b/app/models/project_services/slack_service/base_message.rb
@@ -0,0 +1,31 @@
+require 'slack-notifier'
+
+class SlackService
+  class BaseMessage
+    def initialize(params)
+      raise NotImplementedError
+    end
+
+    def pretext
+      format(message)
+    end
+
+    def attachments
+      raise NotImplementedError
+    end
+
+    private
+
+    def message
+      raise NotImplementedError
+    end
+
+    def format(string)
+      Slack::Notifier::LinkFormatter.format(string)
+    end
+
+    def attachment_color
+      '#345'
+    end
+  end
+end
diff --git a/app/models/project_services/slack_service/issue_message.rb b/app/models/project_services/slack_service/issue_message.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5af24a80609352547ab9b5b29549f6cd463a3a07
--- /dev/null
+++ b/app/models/project_services/slack_service/issue_message.rb
@@ -0,0 +1,56 @@
+class SlackService
+  class IssueMessage < BaseMessage
+    attr_reader :user_name
+    attr_reader :title
+    attr_reader :project_name
+    attr_reader :project_url
+    attr_reader :issue_iid
+    attr_reader :issue_url
+    attr_reader :action
+    attr_reader :state
+    attr_reader :description
+
+    def initialize(params)
+      @user_name = params[:user][:name]
+      @project_name = params[:project_name]
+      @project_url = params[:project_url]
+
+      obj_attr = params[:object_attributes]
+      obj_attr = HashWithIndifferentAccess.new(obj_attr)
+      @title = obj_attr[:title]
+      @issue_iid = obj_attr[:iid]
+      @issue_url = obj_attr[:url]
+      @action = obj_attr[:action]
+      @state = obj_attr[:state]
+      @description = obj_attr[:description]
+    end
+
+    def attachments
+      return [] unless opened_issue?
+
+      description_message
+    end
+
+    private
+
+    def message
+      "#{user_name} #{state} #{issue_link} in #{project_link}: *#{title}*"
+    end
+
+    def opened_issue?
+      action == "open"
+    end
+
+    def description_message
+      [{ text: format(description), color: attachment_color }]
+    end
+
+    def project_link
+      "[#{project_name}](#{project_url})"
+    end
+
+    def issue_link
+      "[issue ##{issue_iid}](#{issue_url})"
+    end
+  end
+end
diff --git a/app/models/project_services/slack_service/merge_message.rb b/app/models/project_services/slack_service/merge_message.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e792c258f7394a5e6e1c12dd222c75cd93d39620
--- /dev/null
+++ b/app/models/project_services/slack_service/merge_message.rb
@@ -0,0 +1,60 @@
+class SlackService
+  class MergeMessage < BaseMessage
+    attr_reader :user_name
+    attr_reader :project_name
+    attr_reader :project_url
+    attr_reader :merge_request_id
+    attr_reader :source_branch
+    attr_reader :target_branch
+    attr_reader :state
+    attr_reader :title
+
+    def initialize(params)
+      @user_name = params[:user][:name]
+      @project_name = params[:project_name]
+      @project_url = params[:project_url]
+
+      obj_attr = params[:object_attributes]
+      obj_attr = HashWithIndifferentAccess.new(obj_attr)
+      @merge_request_id = obj_attr[:iid]
+      @source_branch = obj_attr[:source_branch]
+      @target_branch = obj_attr[:target_branch]
+      @state = obj_attr[:state]
+      @title = format_title(obj_attr[:title])
+    end
+
+    def pretext
+      format(message)
+    end
+
+    def attachments
+      []
+    end
+
+    private
+
+    def format_title(title)
+      '*' + title.lines.first.chomp + '*'
+    end
+
+    def message
+      merge_request_message
+    end
+
+    def project_link
+      "[#{project_name}](#{project_url})"
+    end
+
+    def merge_request_message
+      "#{user_name} #{state} #{merge_request_link} in #{project_link}: #{title}"
+    end
+
+    def merge_request_link
+      "[merge request ##{merge_request_id}](#{merge_request_url})"
+    end
+
+    def merge_request_url
+      "#{project_url}/merge_requests/#{merge_request_id}"
+    end
+  end
+end
diff --git a/app/models/project_services/slack_service/note_message.rb b/app/models/project_services/slack_service/note_message.rb
new file mode 100644
index 0000000000000000000000000000000000000000..074478b292da5ef73cd6cd7860bf0893404d1cfa
--- /dev/null
+++ b/app/models/project_services/slack_service/note_message.rb
@@ -0,0 +1,82 @@
+class SlackService
+  class NoteMessage < BaseMessage
+    attr_reader :message
+    attr_reader :user_name
+    attr_reader :project_name
+    attr_reader :project_link
+    attr_reader :note
+    attr_reader :note_url
+    attr_reader :title
+
+    def initialize(params)
+      params = HashWithIndifferentAccess.new(params)
+      @user_name = params[:user][:name]
+      @project_name = params[:project_name]
+      @project_url = params[:project_url]
+
+      obj_attr = params[:object_attributes]
+      obj_attr = HashWithIndifferentAccess.new(obj_attr)
+      @note = obj_attr[:note]
+      @note_url = obj_attr[:url]
+      noteable_type = obj_attr[:noteable_type]
+
+      case noteable_type
+      when "Commit"
+        create_commit_note(HashWithIndifferentAccess.new(params[:commit]))
+      when "Issue"
+        create_issue_note(HashWithIndifferentAccess.new(params[:issue]))
+      when "MergeRequest"
+        create_merge_note(HashWithIndifferentAccess.new(params[:merge_request]))
+      when "Snippet"
+        create_snippet_note(HashWithIndifferentAccess.new(params[:snippet]))
+      end
+    end
+
+    def attachments
+      description_message
+    end
+
+    private
+
+    def format_title(title)
+      title.lines.first.chomp
+    end
+
+    def create_commit_note(commit)
+      commit_sha = commit[:id]
+      commit_sha = Commit.truncate_sha(commit_sha)
+      commit_link = "[commit #{commit_sha}](#{@note_url})"
+      title = format_title(commit[:message])
+      @message = "#{@user_name} commented on #{commit_link} in #{project_link}: *#{title}*"
+    end
+
+    def create_issue_note(issue)
+      issue_iid = issue[:iid]
+      note_link = "[issue ##{issue_iid}](#{@note_url})"
+      title = format_title(issue[:title])
+      @message = "#{@user_name} commented on #{note_link} in #{project_link}: *#{title}*"
+    end
+
+    def create_merge_note(merge_request)
+      merge_request_id = merge_request[:iid]
+      merge_request_link = "[merge request ##{merge_request_id}](#{@note_url})"
+      title = format_title(merge_request[:title])
+      @message = "#{@user_name} commented on #{merge_request_link} in #{project_link}: *#{title}*"
+    end
+
+    def create_snippet_note(snippet)
+      snippet_id = snippet[:id]
+      snippet_link = "[snippet ##{snippet_id}](#{@note_url})"
+      title = format_title(snippet[:title])
+      @message = "#{@user_name} commented on #{snippet_link} in #{project_link}: *#{title}*"
+    end
+
+    def description_message
+      [{ text: format(@note), color: attachment_color }]
+    end
+
+    def project_link
+      "[#{@project_name}](#{@project_url})"
+    end
+  end
+end
diff --git a/app/models/project_services/slack_service/push_message.rb b/app/models/project_services/slack_service/push_message.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b26f3e9ddce9f392d6cc06e9446fb03a49fa1de3
--- /dev/null
+++ b/app/models/project_services/slack_service/push_message.rb
@@ -0,0 +1,110 @@
+class SlackService
+  class PushMessage < BaseMessage
+    attr_reader :after
+    attr_reader :before
+    attr_reader :commits
+    attr_reader :project_name
+    attr_reader :project_url
+    attr_reader :ref
+    attr_reader :ref_type
+    attr_reader :user_name
+
+    def initialize(params)
+      @after = params[:after]
+      @before = params[:before]
+      @commits = params.fetch(:commits, [])
+      @project_name = params[:project_name]
+      @project_url = params[:project_url]
+      @ref_type = Gitlab::Git.tag_ref?(params[:ref]) ? 'tag' : 'branch'
+      @ref = Gitlab::Git.ref_name(params[:ref])
+      @user_name = params[:user_name]
+    end
+
+    def pretext
+      format(message)
+    end
+
+    def attachments
+      return [] if new_branch? || removed_branch?
+
+      commit_message_attachments
+    end
+
+    private
+
+    def message
+      if new_branch?
+        new_branch_message
+      elsif removed_branch?
+        removed_branch_message
+      else
+        push_message
+      end
+    end
+
+    def format(string)
+      Slack::Notifier::LinkFormatter.format(string)
+    end
+
+    def new_branch_message
+      "#{user_name} pushed new #{ref_type} #{branch_link} to #{project_link}"
+    end
+
+    def removed_branch_message
+      "#{user_name} removed #{ref_type} #{ref} from #{project_link}"
+    end
+
+    def push_message
+      "#{user_name} pushed to #{ref_type} #{branch_link} of #{project_link} (#{compare_link})"
+    end
+
+    def commit_messages
+      commits.map { |commit| compose_commit_message(commit) }.join("\n")
+    end
+
+    def commit_message_attachments
+      [{ text: format(commit_messages), color: attachment_color }]
+    end
+
+    def compose_commit_message(commit)
+      author = commit[:author][:name]
+      id = Commit.truncate_sha(commit[:id])
+      message = commit[:message]
+      url = commit[:url]
+
+      "[#{id}](#{url}): #{message} - #{author}"
+    end
+
+    def new_branch?
+      Gitlab::Git.blank_ref?(before)
+    end
+
+    def removed_branch?
+      Gitlab::Git.blank_ref?(after)
+    end
+
+    def branch_url
+      "#{project_url}/commits/#{ref}"
+    end
+
+    def compare_url
+      "#{project_url}/compare/#{before}...#{after}"
+    end
+
+    def branch_link
+      "[#{ref}](#{branch_url})"
+    end
+
+    def project_link
+      "[#{project_name}](#{project_url})"
+    end
+
+    def compare_link
+      "[Compare changes](#{compare_url})"
+    end
+
+    def attachment_color
+      '#345'
+    end
+  end
+end
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c26bc551352c3f2136c111795dcbe158635f2aed
--- /dev/null
+++ b/app/models/project_services/teamcity_service.rb
@@ -0,0 +1,145 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#  note_events           :boolean          default(TRUE), not null
+#
+
+class TeamcityService < CiService
+  include HTTParty
+
+  prop_accessor :teamcity_url, :build_type, :username, :password
+
+  validates :teamcity_url,
+    presence: true,
+    format: { with: URI::regexp }, if: :activated?
+  validates :build_type, presence: true, if: :activated?
+  validates :username,
+    presence: true,
+    if: ->(service) { service.password? }, if: :activated?
+  validates :password,
+    presence: true,
+    if: ->(service) { service.username? }, if: :activated?
+
+  attr_accessor :response
+
+  after_save :compose_service_hook, if: :activated?
+
+  def compose_service_hook
+    hook = service_hook || build_service_hook
+    hook.save
+  end
+
+  def title
+    'JetBrains TeamCity CI'
+  end
+
+  def description
+    'A continuous integration and build server'
+  end
+
+  def help
+    'The build configuration in Teamcity must use the build format '\
+    'number %build.vcs.number% '\
+    'you will also want to configure monitoring of all branches so merge '\
+    'requests build, that setting is in the vsc root advanced settings.'
+  end
+
+  def to_param
+    'teamcity'
+  end
+
+  def supported_events
+    %w(push)
+  end
+
+  def fields
+    [
+      { type: 'text', name: 'teamcity_url',
+        placeholder: 'TeamCity root URL like https://teamcity.example.com' },
+      { type: 'text', name: 'build_type',
+        placeholder: 'Build configuration ID' },
+      { type: 'text', name: 'username',
+        placeholder: 'A user with permissions to trigger a manual build' },
+      { type: 'password', name: 'password' },
+    ]
+  end
+
+  def build_info(sha)
+    url = URI.parse("#{teamcity_url}/httpAuth/app/rest/builds/"\
+                    "branch:unspecified:any,number:#{sha}")
+    auth = {
+      username: username,
+      password: password,
+    }
+    @response = HTTParty.get("#{url}", verify: false, basic_auth: auth)
+  end
+
+  def build_page(sha, ref)
+    build_info(sha) if @response.nil? || !@response.code
+
+    if @response.code != 200
+      # If actual build link can't be determined,
+      # send user to build summary page.
+      "#{teamcity_url}/viewLog.html?buildTypeId=#{build_type}"
+    else
+      # If actual build link is available, go to build result page.
+      built_id = @response['build']['id']
+      "#{teamcity_url}/viewLog.html?buildId=#{built_id}"\
+      "&buildTypeId=#{build_type}"
+    end
+  end
+
+  def commit_status(sha, ref)
+    build_info(sha) if @response.nil? || !@response.code
+    return :error unless @response.code == 200 || @response.code == 404
+
+    status = if @response.code == 404
+               'Pending'
+             else
+               @response['build']['status']
+             end
+
+    if status.include?('SUCCESS')
+      'success'
+    elsif status.include?('FAILURE')
+      'failed'
+    elsif status.include?('Pending')
+      'pending'
+    else
+      :error
+    end
+  end
+
+  def execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
+    auth = {
+      username: username,
+      password: password,
+    }
+
+    branch = Gitlab::Git.ref_name(data[:ref])
+
+    self.class.post("#{teamcity_url}/httpAuth/app/rest/buildQueue",
+                    body: "<build branchName=\"#{branch}\">"\
+                          "<buildType id=\"#{build_type}\"/>"\
+                          '</build>',
+                    headers: { 'Content-type' => 'application/xml' },
+                    basic_auth: auth
+        )
+  end
+end
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 657ee23ae23a19ef1b4103900bf619032d467a9f..d4a07caf9efdbeaace3fd12d5f049df7b7fa90c9 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -31,16 +31,16 @@ class ProjectTeam
     user
   end
 
-  def find_tm(user_id)
-    tm = project.project_members.find_by(user_id: user_id)
+  def find_member(user_id)
+    member = project.project_members.find_by(user_id: user_id)
 
     # If user is not in project members
     # we should check for group membership
-    if group && !tm
-      tm = group.group_members.find_by(user_id: user_id)
+    if group && !member
+      member = group.group_members.find_by(user_id: user_id)
     end
 
-    tm
+    member
   end
 
   def add_user(user, access)
@@ -91,24 +91,24 @@ class ProjectTeam
   def import(source_project)
     target_project = project
 
-    source_team = source_project.project_members.to_a
+    source_members = source_project.project_members.to_a
     target_user_ids = target_project.project_members.pluck(:user_id)
 
-    source_team.reject! do |tm|
+    source_members.reject! do |member|
       # Skip if user already present in team
-      target_user_ids.include?(tm.user_id)
+      target_user_ids.include?(member.user_id)
     end
 
-    source_team.map! do |tm|
-      new_tm = tm.dup
-      new_tm.id = nil
-      new_tm.source = target_project
-      new_tm
+    source_members.map! do |member|
+      new_member = member.dup
+      new_member.id = nil
+      new_member.source = target_project
+      new_member
     end
 
     ProjectMember.transaction do
-      source_team.each do |tm|
-        tm.save
+      source_members.each do |member|
+        member.save
       end
     end
 
@@ -118,26 +118,26 @@ class ProjectTeam
   end
 
   def guest?(user)
-    max_tm_access(user.id) == Gitlab::Access::GUEST
+    max_member_access(user.id) == Gitlab::Access::GUEST
   end
 
   def reporter?(user)
-    max_tm_access(user.id) == Gitlab::Access::REPORTER
+    max_member_access(user.id) == Gitlab::Access::REPORTER
   end
 
   def developer?(user)
-    max_tm_access(user.id) == Gitlab::Access::DEVELOPER
+    max_member_access(user.id) == Gitlab::Access::DEVELOPER
   end
 
   def master?(user)
-    max_tm_access(user.id) == Gitlab::Access::MASTER
+    max_member_access(user.id) == Gitlab::Access::MASTER
   end
 
   def member?(user_id)
-    !!find_tm(user_id)
+    !!find_member(user_id)
   end
 
-  def max_tm_access(user_id)
+  def max_member_access(user_id)
     access = []
     access << project.project_members.find_by(user_id: user_id).try(:access_field)
 
@@ -160,7 +160,7 @@ class ProjectTeam
     end
 
     user_ids = project_members.pluck(:user_id)
-    user_ids += group_members.pluck(:user_id) if group
+    user_ids.push(*group_members.pluck(:user_id)) if group
 
     User.where(id: user_ids)
   end
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 770a26ed8947bcbbadadb67480d3c3a5f6dc373b..772c868d9cd0088307f7bab85d8166878a528a1c 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -5,7 +5,7 @@ class ProjectWiki
     'Markdown' => :markdown,
     'RDoc'     => :rdoc,
     'AsciiDoc' => :asciidoc
-  }
+  } unless defined?(MARKUPS)
 
   class CouldNotCreateWikiError < StandardError; end
 
@@ -104,7 +104,7 @@ class ProjectWiki
   def page_title_and_dir(title)
     title_array =  title.split("/")
     title = title_array.pop
-    [title.gsub(/\.[^.]*$/, ""), title_array.join("/")]
+    [title, title_array.join("/")]
   end
 
   def search_files(query)
@@ -136,7 +136,7 @@ class ProjectWiki
   def commit_details(action, message = nil, title = nil)
     commit_message = message || default_message(action, title)
 
-    {email: @user.email, name: @user.name, message: commit_message}
+    { email: @user.email, name: @user.name, message: commit_message }
   end
 
   def default_message(action, title)
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 1b06dd775230f0e34b05faa90c2223531fda97c1..97207ba12726c4cd6179f6e623d5a447ff0de39f 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -2,11 +2,12 @@
 #
 # Table name: protected_branches
 #
-#  id         :integer          not null, primary key
-#  project_id :integer          not null
-#  name       :string(255)      not null
-#  created_at :datetime
-#  updated_at :datetime
+#  id                  :integer          not null, primary key
+#  project_id          :integer          not null
+#  name                :string(255)      not null
+#  created_at          :datetime
+#  updated_at          :datetime
+#  developers_can_push :boolean          default(FALSE), not null
 #
 
 class ProtectedBranch < ActiveRecord::Base
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 93994123a90505cce29bc36a22d10d5906d65767..77765cae1a0b1902d74c28595ebd9fc55183dd5c 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -30,7 +30,7 @@ class Repository
     commit = Gitlab::Git::Commit.find(raw_repository, id)
     commit = Commit.new(commit) if commit
     commit
-  rescue Rugged::OdbError => ex
+  rescue Rugged::OdbError
     nil
   end
 
@@ -61,25 +61,29 @@ class Repository
   end
 
   def add_branch(branch_name, ref)
-    Rails.cache.delete(cache_key(:branch_names))
+    cache.expire(:branch_names)
+    @branches = nil
 
     gitlab_shell.add_branch(path_with_namespace, branch_name, ref)
   end
 
   def add_tag(tag_name, ref, message = nil)
-    Rails.cache.delete(cache_key(:tag_names))
+    cache.expire(:tag_names)
+    @tags = nil
 
     gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message)
   end
 
   def rm_branch(branch_name)
-    Rails.cache.delete(cache_key(:branch_names))
+    cache.expire(:branch_names)
+    @branches = nil
 
     gitlab_shell.rm_branch(path_with_namespace, branch_name)
   end
 
   def rm_tag(tag_name)
-    Rails.cache.delete(cache_key(:tag_names))
+    cache.expire(:tag_names)
+    @tags = nil
 
     gitlab_shell.rm_tag(path_with_namespace, tag_name)
   end
@@ -97,19 +101,15 @@ class Repository
   end
 
   def branch_names
-    Rails.cache.fetch(cache_key(:branch_names)) do
-      raw_repository.branch_names
-    end
+    cache.fetch(:branch_names) { raw_repository.branch_names }
   end
 
   def tag_names
-    Rails.cache.fetch(cache_key(:tag_names)) do
-      raw_repository.tag_names
-    end
+    cache.fetch(:tag_names) { raw_repository.tag_names }
   end
 
   def commit_count
-    Rails.cache.fetch(cache_key(:commit_count)) do
+    cache.fetch(:commit_count) do
       begin
         raw_repository.commit_count(self.root_ref)
       rescue
@@ -121,45 +121,45 @@ class Repository
   # Return repo size in megabytes
   # Cached in redis
   def size
-    Rails.cache.fetch(cache_key(:size)) do
-      raw_repository.size
-    end
+    cache.fetch(:size) { raw_repository.size }
   end
 
   def expire_cache
-    Rails.cache.delete(cache_key(:size))
-    Rails.cache.delete(cache_key(:branch_names))
-    Rails.cache.delete(cache_key(:tag_names))
-    Rails.cache.delete(cache_key(:commit_count))
-    Rails.cache.delete(cache_key(:graph_log))
-    Rails.cache.delete(cache_key(:readme))
-    Rails.cache.delete(cache_key(:version))
-    Rails.cache.delete(cache_key(:contribution_guide))
+    %i(size branch_names tag_names commit_count graph_log
+       readme version contribution_guide changelog license).each do |key|
+      cache.expire(key)
+    end
   end
 
   def graph_log
-    Rails.cache.fetch(cache_key(:graph_log)) do
+    cache.fetch(:graph_log) do
       commits = raw_repository.log(limit: 6000, skip_merges: true,
                                    ref: root_ref)
+
       commits.map do |rugged_commit|
         commit = Gitlab::Git::Commit.new(rugged_commit)
 
         {
-          author_name: commit.author_name.force_encoding('UTF-8'),
-          author_email: commit.author_email.force_encoding('UTF-8'),
+          author_name: commit.author_name,
+          author_email: commit.author_email,
           additions: commit.stats.additions,
-          deletions: commit.stats.deletions
+          deletions: commit.stats.deletions,
         }
       end
     end
   end
 
-  def cache_key(type)
-    "#{type}:#{path_with_namespace}"
+  def lookup_cache
+    @lookup_cache ||= {}
   end
 
   def method_missing(m, *args, &block)
-    raw_repository.send(m, *args, &block)
+    if m == :lookup && !block_given?
+      lookup_cache[m] ||= {}
+      lookup_cache[m][args.join(":")] ||= raw_repository.send(m, *args, &block)
+    else
+      raw_repository.send(m, *args, &block)
+    end
   end
 
   def respond_to?(method)
@@ -177,13 +177,11 @@ class Repository
   end
 
   def readme
-    Rails.cache.fetch(cache_key(:readme)) do
-      tree(:head).readme
-    end
+    cache.fetch(:readme) { tree(:head).readme }
   end
 
   def version
-    Rails.cache.fetch(cache_key(:version)) do
+    cache.fetch(:version) do
       tree(:head).blobs.find do |file|
         file.name.downcase == 'version'
       end
@@ -191,18 +189,44 @@ class Repository
   end
 
   def contribution_guide
-    Rails.cache.fetch(cache_key(:contribution_guide)) do
-      tree(:head).contribution_guide
+    cache.fetch(:contribution_guide) do
+      tree(:head).blobs.find do |file|
+        file.contributing?
+      end
+    end
+  end
+
+  def changelog
+    cache.fetch(:changelog) do
+      tree(:head).blobs.find do |file|
+        file.name =~ /^(changelog|history)/i
+      end
+    end
+  end
+
+  def license
+    cache.fetch(:license) do
+      tree(:head).blobs.find do |file|
+        file.name =~ /^license/i
+      end
     end
   end
 
   def head_commit
-    commit(self.root_ref)
+    @head_commit ||= commit(self.root_ref)
+  end
+
+  def head_tree
+    @head_tree ||= Tree.new(self, head_commit.sha, nil)
   end
 
   def tree(sha = :head, path = nil)
     if sha == :head
-      sha = head_commit.sha
+      if path.nil?
+        return head_tree
+      else
+        sha = head_commit.sha
+      end
     end
 
     Tree.new(self, sha, path)
@@ -235,7 +259,7 @@ class Repository
   end
 
   def last_commit_for_path(sha, path)
-    args = %W(git rev-list --max-count 1 #{sha} -- #{path})
+    args = %W(git rev-list --max-count=1 #{sha} -- #{path})
     sha = Gitlab::Popen.popen(args, path_to_repo).first.strip
     commit(sha)
   end
@@ -312,4 +336,39 @@ class Repository
       []
     end
   end
+
+  def tag_names_contains(sha)
+    args = %W(git tag --contains #{sha})
+    names = Gitlab::Popen.popen(args, path_to_repo).first
+
+    if names.respond_to?(:split)
+      names = names.split("\n").map(&:strip)
+
+      names.each do |name|
+        name.slice! '* '
+      end
+
+      names
+    else
+      []
+    end
+  end
+
+  def branches
+    @branches ||= raw_repository.branches
+  end
+
+  def tags
+    @tags ||= raw_repository.tags
+  end
+
+  def root_ref
+    @root_ref ||= raw_repository.root_ref
+  end
+
+  private
+
+  def cache
+    @cache ||= RepositoryCache.new(path_with_namespace)
+  end
 end
diff --git a/app/models/service.rb b/app/models/service.rb
index c489c1e96e1b0d8d9e1c6c8943711ed82442257c..f54ad19666bb976cc4e74a7a0308c8b789a0e44c 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -2,34 +2,57 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
 #
 
 # To add new service you should build a class inherited from Service
 # and implement a set of methods
 class Service < ActiveRecord::Base
+  include Sortable
   serialize :properties, JSON
 
   default_value_for :active, false
+  default_value_for :push_events, true
+  default_value_for :issues_events, true
+  default_value_for :merge_requests_events, true
+  default_value_for :tag_push_events, true
+  default_value_for :note_events, true
 
   after_initialize :initialize_properties
 
   belongs_to :project
   has_one :service_hook
 
-  validates :project_id, presence: true
+  validates :project_id, presence: true, unless: Proc.new { |service| service.template? }
+
+  scope :visible, -> { where.not(type: 'GitlabIssueTrackerService') }
+
+  scope :push_hooks, -> { where(push_events: true, active: true) }
+  scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) }
+  scope :issue_hooks, -> { where(issues_events: true, active: true) }
+  scope :merge_request_hooks, -> { where(merge_requests_events: true, active: true) }
+  scope :note_hooks, -> { where(note_events: true, active: true) }
 
   def activated?
     active
   end
 
+  def template?
+    template
+  end
+
   def category
     :common
   end
@@ -59,6 +82,10 @@ class Service < ActiveRecord::Base
     []
   end
 
+  def supported_events
+    %w(push tag_push issue merge_request)
+  end
+
   def execute
     # implement inside child
   end
@@ -82,4 +109,45 @@ class Service < ActiveRecord::Base
       }
     end
   end
+
+  def async_execute(data)
+    return unless supported_events.include?(data[:object_kind])
+
+    Sidekiq::Client.enqueue(ProjectServiceWorker, id, data)
+  end
+
+  def issue_tracker?
+    self.category == :issue_tracker
+  end
+
+  def self.available_services_names
+    %w(
+      gitlab_ci
+      campfire
+      hipchat
+      pivotaltracker
+      flowdock
+      assembla
+      asana
+      emails_on_push
+      gemnasium
+      slack
+      pushover
+      buildbox
+      bamboo
+      teamcity
+      jira
+      redmine
+      custom_issue_tracker
+      irker
+      external_wiki
+    )
+  end
+
+  def self.create_from_template(project_id, template)
+    service = template.dup
+    service.template = false
+    service.project_id = project_id
+    service if service.save
+  end
 end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index a47fbca3260c31ed9e8b56a307069c57cab4aed2..3fb2ec1d66cc655c29a784dbe386f827c62f16d0 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -16,6 +16,7 @@
 #
 
 class Snippet < ActiveRecord::Base
+  include Sortable
   include Linguist::BlobHelper
   include Gitlab::VisibilityLevel
 
@@ -29,7 +30,11 @@ class Snippet < ActiveRecord::Base
 
   validates :author, presence: true
   validates :title, presence: true, length: { within: 0..255 }
-  validates :file_name, presence: true, length: { within: 0..255 }
+  validates :file_name,
+    presence: true,
+    length: { within: 0..255 },
+    format: { with: Gitlab::Regex.path_regex,
+              message: Gitlab::Regex.path_regex_message }
   validates :content, presence: true
   validates :visibility_level, inclusion: { in: Gitlab::VisibilityLevel.values }
 
@@ -54,6 +59,10 @@ class Snippet < ActiveRecord::Base
     content
   end
 
+  def hook_attrs
+    attributes
+  end
+
   def size
     0
   end
@@ -62,6 +71,10 @@ class Snippet < ActiveRecord::Base
     file_name
   end
 
+  def sanitized_file_name
+    file_name.gsub(/[^a-zA-Z0-9_\-\.]+/, '')
+  end
+
   def mode
     nil
   end
@@ -72,7 +85,7 @@ class Snippet < ActiveRecord::Base
 
   def visibility_level_field
     visibility_level
-  end 
+  end
 
   class << self
     def search(query)
diff --git a/app/models/subscription.rb b/app/models/subscription.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dd75d3ab8ba39d8fa66c1e2d22f5c61dc39194e8
--- /dev/null
+++ b/app/models/subscription.rb
@@ -0,0 +1,21 @@
+# == Schema Information
+#
+# Table name: subscriptions
+#
+#  id                :integer          not null, primary key
+#  user_id           :integer
+#  subscribable_id   :integer
+#  subscribable_type :string(255)
+#  subscribed        :boolean
+#  created_at        :datetime
+#  updated_at        :datetime
+#
+
+class Subscription < ActiveRecord::Base
+  belongs_to :user
+  belongs_to :subscribable, polymorphic: true
+
+  validates :user_id, 
+            uniqueness: { scope: [:subscribable_id, :subscribable_type] },
+            presence: true
+end
diff --git a/app/models/tree.rb b/app/models/tree.rb
index 4f5d81f0a5e27d41e30f929f5177b578941d00f8..f279e896cda38bb176eaad6d62599352d87114f4 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -1,38 +1,38 @@
 class Tree
   include Gitlab::MarkdownHelper
 
-  attr_accessor :entries, :readme, :contribution_guide
+  attr_accessor :repository, :sha, :path, :entries
 
   def initialize(repository, sha, path = '/')
     path = '/' if path.blank?
-    git_repo = repository.raw_repository
-    @entries = Gitlab::Git::Tree.where(git_repo, sha, path)
-
-    available_readmes = @entries.select(&:readme?)
-
-    if available_readmes.count > 0
-      # If there is more than 1 readme in tree, find readme which is supported
-      # by markup renderer.
-      if available_readmes.length > 1
-        supported_readmes = available_readmes.select do |readme|
-          previewable?(readme.name)
-        end
-
-        # Take the first supported readme, or the first available readme, if we
-        # don't support any of them
-        readme_tree = supported_readmes.first || available_readmes.first
-      else
-        readme_tree = available_readmes.first
-      end
-
-      readme_path = path == '/' ? readme_tree.name : File.join(path, readme_tree.name)
-      @readme = Gitlab::Git::Blob.find(git_repo, sha, readme_path)
-    end
+    
+    @repository = repository
+    @sha = sha
+    @path = path
+
+    git_repo = @repository.raw_repository
+    @entries = Gitlab::Git::Tree.where(git_repo, @sha, @path)
+  end
+
+  def readme
+    return @readme if defined?(@readme)
 
-    if contribution_tree = @entries.find(&:contributing?)
-      contribution_path = path == '/' ? contribution_tree.name : File.join(path, contribution_tree.name)
-      @contribution_guide = Gitlab::Git::Blob.find(git_repo, sha, contribution_path)
+    available_readmes = blobs.select(&:readme?)
+
+    if available_readmes.count == 0
+      return @readme = nil 
     end
+
+    # Take the first previewable readme, or the first available readme, if we
+    # can't preview any of them
+    readme_tree = available_readmes.find do |readme|
+      previewable?(readme.name)
+    end || available_readmes.first
+
+    readme_path = path == '/' ? readme_tree.name : File.join(path, readme_tree.name)
+
+    git_repo = repository.raw_repository
+    @readme = Gitlab::Git::Blob.find(git_repo, sha, readme_path)
   end
 
   def trees
diff --git a/app/models/user.rb b/app/models/user.rb
index d400edc0df5ff40b152db816b2e2f8e7f8e3a353..979150b4d6850ca6a52ecb283639c41133d693a1 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -2,63 +2,70 @@
 #
 # Table name: users
 #
-#  id                       :integer          not null, primary key
-#  email                    :string(255)      default(""), not null
-#  encrypted_password       :string(255)      default(""), not null
-#  reset_password_token     :string(255)
-#  reset_password_sent_at   :datetime
-#  remember_created_at      :datetime
-#  sign_in_count            :integer          default(0)
-#  current_sign_in_at       :datetime
-#  last_sign_in_at          :datetime
-#  current_sign_in_ip       :string(255)
-#  last_sign_in_ip          :string(255)
-#  created_at               :datetime
-#  updated_at               :datetime
-#  name                     :string(255)
-#  admin                    :boolean          default(FALSE), not null
-#  projects_limit           :integer          default(10)
-#  skype                    :string(255)      default(""), not null
-#  linkedin                 :string(255)      default(""), not null
-#  twitter                  :string(255)      default(""), not null
-#  authentication_token     :string(255)
-#  theme_id                 :integer          default(1), not null
-#  bio                      :string(255)
-#  failed_attempts          :integer          default(0)
-#  locked_at                :datetime
-#  extern_uid               :string(255)
-#  provider                 :string(255)
-#  username                 :string(255)
-#  can_create_group         :boolean          default(TRUE), not null
-#  can_create_team          :boolean          default(TRUE), not null
-#  state                    :string(255)
-#  color_scheme_id          :integer          default(1), not null
-#  notification_level       :integer          default(1), not null
-#  password_expires_at      :datetime
-#  created_by_id            :integer
-#  last_credential_check_at :datetime
-#  avatar                   :string(255)
-#  confirmation_token       :string(255)
-#  confirmed_at             :datetime
-#  confirmation_sent_at     :datetime
-#  unconfirmed_email        :string(255)
-#  hide_no_ssh_key          :boolean          default(FALSE)
-#  website_url              :string(255)      default(""), not null
+#  id                            :integer          not null, primary key
+#  email                         :string(255)      default(""), not null
+#  encrypted_password            :string(255)      default(""), not null
+#  reset_password_token          :string(255)
+#  reset_password_sent_at        :datetime
+#  remember_created_at           :datetime
+#  sign_in_count                 :integer          default(0)
+#  current_sign_in_at            :datetime
+#  last_sign_in_at               :datetime
+#  current_sign_in_ip            :string(255)
+#  last_sign_in_ip               :string(255)
+#  created_at                    :datetime
+#  updated_at                    :datetime
+#  name                          :string(255)
+#  admin                         :boolean          default(FALSE), not null
+#  projects_limit                :integer          default(10)
+#  skype                         :string(255)      default(""), not null
+#  linkedin                      :string(255)      default(""), not null
+#  twitter                       :string(255)      default(""), not null
+#  authentication_token          :string(255)
+#  theme_id                      :integer          default(1), not null
+#  bio                           :string(255)
+#  failed_attempts               :integer          default(0)
+#  locked_at                     :datetime
+#  username                      :string(255)
+#  can_create_group              :boolean          default(TRUE), not null
+#  can_create_team               :boolean          default(TRUE), not null
+#  state                         :string(255)
+#  color_scheme_id               :integer          default(1), not null
+#  notification_level            :integer          default(1), not null
+#  password_expires_at           :datetime
+#  created_by_id                 :integer
+#  last_credential_check_at      :datetime
+#  avatar                        :string(255)
+#  confirmation_token            :string(255)
+#  confirmed_at                  :datetime
+#  confirmation_sent_at          :datetime
+#  unconfirmed_email             :string(255)
+#  hide_no_ssh_key               :boolean          default(FALSE)
+#  website_url                   :string(255)      default(""), not null
+#  github_access_token           :string(255)
+#  gitlab_access_token           :string(255)
+#  notification_email            :string(255)
+#  hide_no_password              :boolean          default(FALSE)
+#  password_automatically_set    :boolean          default(FALSE)
+#  bitbucket_access_token        :string(255)
+#  bitbucket_access_token_secret :string(255)
 #
 
 require 'carrierwave/orm/activerecord'
 require 'file_size_validator'
 
 class User < ActiveRecord::Base
+  include Sortable
   include Gitlab::ConfigHelper
-  extend Gitlab::ConfigHelper
   include TokenAuthenticatable
+  extend Gitlab::ConfigHelper
+  include Gitlab::CurrentSettings
 
   default_value_for :admin, false
   default_value_for :can_create_group, gitlab_config.default_can_create_group
   default_value_for :can_create_team, false
   default_value_for :hide_no_ssh_key, false
-  default_value_for :projects_limit, gitlab_config.default_projects_limit
+  default_value_for :hide_no_password, false
   default_value_for :theme_id, gitlab_config.default_theme
 
   devise :database_authenticatable, :lockable, :async,
@@ -79,6 +86,7 @@ class User < ActiveRecord::Base
   # Profile
   has_many :keys, dependent: :destroy
   has_many :emails, dependent: :destroy
+  has_many :identities, dependent: :destroy
 
   # Groups
   has_many :members, dependent: :destroy
@@ -102,35 +110,42 @@ class User < ActiveRecord::Base
   has_many :notes,                    dependent: :destroy, foreign_key: :author_id
   has_many :merge_requests,           dependent: :destroy, foreign_key: :author_id
   has_many :events,                   dependent: :destroy, foreign_key: :author_id,   class_name: "Event"
+  has_many :subscriptions,            dependent: :destroy
   has_many :recent_events, -> { order "id DESC" }, foreign_key: :author_id,   class_name: "Event"
   has_many :assigned_issues,          dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue"
   has_many :assigned_merge_requests,  dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest"
+  has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy
 
 
   #
   # Validations
   #
   validates :name, presence: true
-  validates :email, presence: true, email: {strict_mode: true}, uniqueness: true
+  validates :email, presence: true, email: { strict_mode: true }, uniqueness: true
+  validates :notification_email, presence: true, email: { strict_mode: true }
   validates :bio, length: { maximum: 255 }, allow_blank: true
-  validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider}
-  validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0}
-  validates :username, presence: true, uniqueness: { case_sensitive: false },
-            exclusion: { in: Gitlab::Blacklist.path },
-            format: { with: Gitlab::Regex.username_regex,
-                      message: Gitlab::Regex.username_regex_message }
+  validates :projects_limit, presence: true, numericality: { greater_than_or_equal_to: 0 }
+  validates :username,
+    presence: true,
+    uniqueness: { case_sensitive: false },
+    exclusion: { in: Gitlab::Blacklist.path },
+    format: { with: Gitlab::Regex.username_regex,
+              message: Gitlab::Regex.username_regex_message }
 
   validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true
   validate :namespace_uniq, if: ->(user) { user.username_changed? }
   validate :avatar_type, if: ->(user) { user.avatar_changed? }
   validate :unique_email, if: ->(user) { user.email_changed? }
-  validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
+  validate :owns_notification_email, if: ->(user) { user.notification_email_changed? }
+  validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
 
   before_validation :generate_password, on: :create
   before_validation :sanitize_attrs
+  before_validation :set_notification_email, if: ->(user) { user.email_changed? }
 
   before_save :ensure_authentication_token
   after_save :ensure_namespace_correct
+  after_initialize :set_projects_limit
   after_create :post_create_hook
   after_destroy :post_destroy_hook
 
@@ -140,24 +155,6 @@ class User < ActiveRecord::Base
   delegate :path, to: :namespace, allow_nil: true, prefix: true
 
   state_machine :state, initial: :active do
-    after_transition any => :blocked do |user, transition|
-      # Remove user from all projects and
-      user.project_members.find_each do |membership|
-        # skip owned resources
-        next if membership.project.owner == user
-
-        return false unless membership.destroy
-      end
-
-      # Remove user from all groups
-      user.group_members.find_each do |membership|
-        # skip owned resources
-        next if membership.group.last_owner?(user)
-
-        return false unless membership.destroy
-      end
-    end
-
     event :block do
       transition active: :blocked
     end
@@ -167,19 +164,14 @@ class User < ActiveRecord::Base
     end
   end
 
-  mount_uploader :avatar, AttachmentUploader
+  mount_uploader :avatar, AvatarUploader
 
   # Scopes
   scope :admins, -> { where(admin:  true) }
   scope :blocked, -> { with_state(:blocked) }
   scope :active, -> { with_state(:active) }
-  scope :alphabetically, -> { order('name ASC') }
-  scope :in_team, ->(team){ where(id: team.member_ids) }
-  scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
   scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all }
   scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members)') }
-  scope :ldap, -> { where('provider LIKE ?', 'ldap%') }
-  scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active  }
 
   #
   # Class methods
@@ -197,11 +189,10 @@ class User < ActiveRecord::Base
 
     def sort(method)
       case method.to_s
-      when 'recent_sign_in' then reorder('users.last_sign_in_at DESC')
-      when 'oldest_sign_in' then reorder('users.last_sign_in_at ASC')
-      when 'recently_created' then reorder('users.created_at DESC')
-      when 'late_created' then reorder('users.created_at ASC')
-      else reorder("users.name ASC")
+      when 'recent_sign_in' then reorder(last_sign_in_at: :desc)
+      when 'oldest_sign_in' then reorder(last_sign_in_at: :asc)
+      else
+        order_by(method)
       end
     end
 
@@ -238,6 +229,22 @@ class User < ActiveRecord::Base
     def build_user(attrs = {})
       User.new(attrs)
     end
+
+    def clean_username(username)
+      username.gsub!(/@.*\z/,             "")
+      username.gsub!(/\.git\z/,           "")
+      username.gsub!(/\A-/,               "")
+      username.gsub!(/[^a-zA-Z0-9_\-\.]/, "")
+
+      counter = 0
+      base = username
+      while User.by_login(username).present? || Namespace.by_path(username).present?
+        counter += 1
+        username = "#{base}#{counter}"
+      end
+
+      username
+    end
   end
 
   #
@@ -269,7 +276,8 @@ class User < ActiveRecord::Base
 
   def namespace_uniq
     namespace_name = self.username
-    if Namespace.find_by(path: namespace_name)
+    existing_namespace = Namespace.by_path(namespace_name)
+    if existing_namespace && existing_namespace != self.namespace
       self.errors.add :username, "already exists"
     end
   end
@@ -284,11 +292,15 @@ class User < ActiveRecord::Base
     self.errors.add(:email, 'has already been taken') if Email.exists?(email: self.email)
   end
 
+  def owns_notification_email
+    self.errors.add(:notification_email, "is not an email you own") unless self.all_emails.include?(self.notification_email)
+  end
+
   # Groups user has access to
   def authorized_groups
     @authorized_groups ||= begin
                              group_ids = (groups.pluck(:id) + authorized_projects.pluck(:namespace_id))
-                             Group.where(id: group_ids).order('namespaces.name ASC')
+                             Group.where(id: group_ids)
                            end
   end
 
@@ -297,9 +309,9 @@ class User < ActiveRecord::Base
   def authorized_projects
     @authorized_projects ||= begin
                                project_ids = personal_projects.pluck(:id)
-                               project_ids += groups_projects.pluck(:id)
-                               project_ids += projects.pluck(:id).uniq
-                               Project.where(id: project_ids).joins(:namespace).order('namespaces.name ASC')
+                               project_ids.push(*groups_projects.pluck(:id))
+                               project_ids.push(*projects.pluck(:id).uniq)
+                               Project.where(id: project_ids)
                              end
   end
 
@@ -322,6 +334,10 @@ class User < ActiveRecord::Base
     keys.count == 0
   end
 
+  def require_password?
+    password_automatically_set? && !ldap_user?
+  end
+
   def can_change_username?
     gitlab_config.username_changing_enabled
   end
@@ -389,7 +405,7 @@ class User < ActiveRecord::Base
   end
 
   def tm_of(project)
-    project.team_member_by_id(self.id)
+    project.project_member_by_id(self.id)
   end
 
   def already_forked?(project)
@@ -407,7 +423,11 @@ class User < ActiveRecord::Base
   end
 
   def ldap_user?
-    extern_uid && provider.start_with?('ldap')
+    identities.exists?(["provider LIKE ? AND extern_uid IS NOT NULL", "ldap%"])
+  end
+
+  def ldap_identity
+    @ldap_identity ||= identities.find_by(["provider LIKE ?", "ldap%"])
   end
 
   def accessible_deploy_keys
@@ -425,6 +445,19 @@ class User < ActiveRecord::Base
     end
   end
 
+  def set_notification_email
+    if self.notification_email.blank? || !self.all_emails.include?(self.notification_email)
+      self.notification_email = self.email
+    end
+  end
+
+  def set_projects_limit
+    connection_default_value_defined = new_record? && !projects_limit_changed?
+    return unless self.projects_limit.nil? || connection_default_value_defined
+
+    self.projects_limit = current_application_settings.default_projects_limit
+  end
+
   def requires_ldap_check?
     if !Gitlab.config.ldap.enabled
       false
@@ -483,7 +516,7 @@ class User < ActiveRecord::Base
   end
 
   def temp_oauth_email?
-    email =~ /\Atemp-email-for-oauth/
+    email.start_with?('temp-email-for-oauth')
   end
 
   def public_profile?
@@ -492,12 +525,16 @@ class User < ActiveRecord::Base
 
   def avatar_url(size = nil)
     if avatar.present?
-      [gitlab_config.url, avatar.url].join("/")
+      [gitlab_config.url, avatar.url].join
     else
       GravatarService.new.execute(email, size)
     end
   end
 
+  def all_emails
+    [self.email, *self.emails.map(&:email)]
+  end
+
   def hook_attrs
     {
       name: name,
@@ -517,7 +554,7 @@ class User < ActiveRecord::Base
 
   def post_create_hook
     log_info("User \"#{self.name}\" (#{self.email}) was created")
-    notification_service.new_user(self, @reset_token)
+    notification_service.new_user(self, @reset_token) if self.created_by_id
     system_hook_service.execute_hooks_for(self, :create)
   end
 
@@ -551,4 +588,26 @@ class User < ActiveRecord::Base
       UsersStarProject.create!(project: project, user: self)
     end
   end
+
+  def manageable_namespaces
+    @manageable_namespaces ||=
+      begin
+        namespaces = []
+        namespaces << namespace
+        namespaces += owned_groups
+        namespaces += masters_groups
+      end
+  end
+
+  def oauth_authorized_tokens
+    Doorkeeper::AccessToken.where(resource_owner_id: self.id, revoked_at: nil)
+  end
+
+  def contributed_projects_ids
+    Event.contributions.where(author_id: self).
+      where("created_at > ?", Time.now - 1.year).
+      reorder(project_id: :desc).
+      select(:project_id).
+      uniq.map(&:project_id)
+  end
 end
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index b9ab6702c539faa2a24a80216d06a0151a281056..e9413c34baed37f1e8008f5c7c8f14f8f8f1c5d7 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -43,7 +43,7 @@ class WikiPage
     @attributes[:slug]
   end
 
-  alias :to_param :slug
+  alias_method :to_param, :slug
 
   # The formatted title of this page.
   def title
@@ -179,7 +179,8 @@ class WikiPage
     if valid? && project_wiki.send(method, *args)
 
       page_details = if method == :update_page
-                       @page.path
+                       # Use url_path instead of path to omit format extension
+                       @page.url_path
                      else
                        title
                      end
diff --git a/app/services/base_service.rb b/app/services/base_service.rb
index 0d46eeaa18f11539eb8018ad47f861b26b7cbd6f..6d9ed345914b356688422ad6dfbd72bf44d138b0 100644
--- a/app/services/base_service.rb
+++ b/app/services/base_service.rb
@@ -1,4 +1,6 @@
 class BaseService
+  include Gitlab::CurrentSettings
+
   attr_accessor :project, :current_user, :params
 
   def initialize(project, user, params = {})
@@ -29,13 +31,31 @@ class BaseService
     SystemHooksService.new
   end
 
+  # Add an error to the specified model for restricted visibility levels
+  def deny_visibility_level(model, denied_visibility_level = nil)
+    denied_visibility_level ||= model.visibility_level
+
+    level_name = 'Unknown'
+    Gitlab::VisibilityLevel.options.each do |name, level|
+      level_name = name if level == denied_visibility_level
+    end
+
+    model.errors.add(
+      :visibility_level,
+      "#{level_name} visibility has been restricted by your GitLab administrator"
+    )
+  end
+
   private
 
-  def error(message)
-    {
+  def error(message, http_status = nil)
+    result = {
       message: message,
       status: :error
     }
+
+    result[:http_status] = http_status if http_status
+    result
   end
 
   def success
diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb
index 901f67bafb31b71b7a73bba0d879c87a59781bc4..cf7ae4345f36b85fa8d21425e7b991ce4e5a8ca4 100644
--- a/app/services/create_branch_service.rb
+++ b/app/services/create_branch_service.rb
@@ -17,10 +17,15 @@ class CreateBranchService < BaseService
     new_branch = repository.find_branch(branch_name)
 
     if new_branch
-      Event.create_ref_event(project, current_user, new_branch, 'add')
-      return success(new_branch)
+      push_data = build_push_data(project, current_user, new_branch)
+
+      EventCreateService.new.push(project, current_user, push_data)
+      project.execute_hooks(push_data.dup, :push_hooks)
+      project.execute_services(push_data.dup, :push_hooks)
+
+      success(new_branch)
     else
-      return error('Invalid reference name')
+      error('Invalid reference name')
     end
   end
 
@@ -29,4 +34,9 @@ class CreateBranchService < BaseService
     out[:branch] = branch
     out
   end
+
+  def build_push_data(project, user, branch)
+    Gitlab::PushDataBuilder.
+      build(project, user, Gitlab::Git::BLANK_SHA, branch.target, "#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch.name}", [])
+  end
 end
diff --git a/app/services/create_snippet_service.rb b/app/services/create_snippet_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..101a3df5eee44f8cdaa6151f88f16bb28582d2b5
--- /dev/null
+++ b/app/services/create_snippet_service.rb
@@ -0,0 +1,20 @@
+class CreateSnippetService < BaseService
+  def execute
+    if project.nil?
+      snippet = PersonalSnippet.new(params)
+    else
+      snippet = project.snippets.build(params)
+    end
+
+    unless Gitlab::VisibilityLevel.allowed_for?(current_user,
+                                                params[:visibility_level])
+      deny_visibility_level(snippet)
+      return snippet
+    end
+
+    snippet.author = current_user
+
+    snippet.save
+    snippet
+  end
+end
diff --git a/app/services/create_tag_service.rb b/app/services/create_tag_service.rb
index 9b2a2270233d80129fd2a4e546f7acf0cd65eec0..4115d6899255fbb5fddd6f1c165d5e313156bc8d 100644
--- a/app/services/create_tag_service.rb
+++ b/app/services/create_tag_service.rb
@@ -21,10 +21,15 @@ class CreateTagService < BaseService
     new_tag = repository.find_tag(tag_name)
 
     if new_tag
-      Event.create_ref_event(project, current_user, new_tag, 'add', 'refs/tags')
-      return success(new_tag)
+      push_data = create_push_data(project, current_user, new_tag)
+
+      EventCreateService.new.push(project, current_user, push_data)
+      project.execute_hooks(push_data.dup, :tag_push_hooks)
+      project.execute_services(push_data.dup, :tag_push_hooks)
+
+      success(new_tag)
     else
-      return error('Invalid reference name')
+      error('Invalid reference name')
     end
   end
 
@@ -33,4 +38,10 @@ class CreateTagService < BaseService
     out[:tag] = branch
     out
   end
+
+  def create_push_data(project, user, tag)
+    commits = [project.repository.commit(tag.target)].compact
+    Gitlab::PushDataBuilder.
+      build(project, user, Gitlab::Git::BLANK_SHA, tag.target, "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}", commits, tag.message)
+  end
 end
diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb
index cae6327fe7296f0486345f8f9edfe0eab2e5f320..b19b112a0c4052560c450854dccaebc9e471c531 100644
--- a/app/services/delete_branch_service.rb
+++ b/app/services/delete_branch_service.rb
@@ -25,10 +25,15 @@ class DeleteBranchService < BaseService
     end
 
     if repository.rm_branch(branch_name)
-      Event.create_ref_event(project, current_user, branch, 'rm')
+      push_data = build_push_data(branch)
+
+      EventCreateService.new.push(project, current_user, push_data)
+      project.execute_hooks(push_data.dup, :push_hooks)
+      project.execute_services(push_data.dup, :push_hooks)
+
       success('Branch was removed')
     else
-      return error('Failed to remove branch')
+      error('Failed to remove branch')
     end
   end
 
@@ -43,4 +48,9 @@ class DeleteBranchService < BaseService
     out[:message] = message
     out
   end
+
+  def build_push_data(branch)
+    Gitlab::PushDataBuilder
+      .build(project, current_user, branch.target, Gitlab::Git::BLANK_SHA, "#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch.name}", [])
+  end
 end
diff --git a/app/services/delete_tag_service.rb b/app/services/delete_tag_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0c8364011367b419d2762da155000afd86d8ec37
--- /dev/null
+++ b/app/services/delete_tag_service.rb
@@ -0,0 +1,42 @@
+require_relative 'base_service'
+
+class DeleteTagService < BaseService
+  def execute(tag_name)
+    repository = project.repository
+    tag = repository.find_tag(tag_name)
+
+    # No such tag
+    unless tag
+      return error('No such tag', 404)
+    end
+
+    if repository.rm_tag(tag_name)
+      push_data = build_push_data(tag)
+      
+      EventCreateService.new.push(project, current_user, push_data)
+      project.execute_hooks(push_data.dup, :tag_push_hooks)
+      project.execute_services(push_data.dup, :tag_push_hooks)
+
+      success('Tag was removed')
+    else
+      error('Failed to remove tag')
+    end
+  end
+
+  def error(message, return_code = 400)
+    out = super(message)
+    out[:return_code] = return_code
+    out
+  end
+
+  def success(message)
+    out = super()
+    out[:message] = message
+    out
+  end
+
+  def build_push_data(tag)
+    Gitlab::PushDataBuilder
+      .build(project, current_user, tag.target, Gitlab::Git::BLANK_SHA, "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}", [])
+  end
+end
diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb
index 8d8a5873e625fdf91ef58509045d56e9f38c45eb..103d6b0a08bc4c3af8f385689399f39378715115 100644
--- a/app/services/event_create_service.rb
+++ b/app/services/event_create_service.rb
@@ -7,58 +7,78 @@
 #
 class EventCreateService
   def open_issue(issue, current_user)
-    create_event(issue, current_user, Event::CREATED)
+    create_record_event(issue, current_user, Event::CREATED)
   end
 
   def close_issue(issue, current_user)
-    create_event(issue, current_user, Event::CLOSED)
+    create_record_event(issue, current_user, Event::CLOSED)
   end
 
   def reopen_issue(issue, current_user)
-    create_event(issue, current_user, Event::REOPENED)
+    create_record_event(issue, current_user, Event::REOPENED)
   end
 
   def open_mr(merge_request, current_user)
-    create_event(merge_request, current_user, Event::CREATED)
+    create_record_event(merge_request, current_user, Event::CREATED)
   end
 
   def close_mr(merge_request, current_user)
-    create_event(merge_request, current_user, Event::CLOSED)
+    create_record_event(merge_request, current_user, Event::CLOSED)
   end
 
   def reopen_mr(merge_request, current_user)
-    create_event(merge_request, current_user, Event::REOPENED)
+    create_record_event(merge_request, current_user, Event::REOPENED)
   end
 
   def merge_mr(merge_request, current_user)
-    create_event(merge_request, current_user, Event::MERGED)
+    create_record_event(merge_request, current_user, Event::MERGED)
   end
 
   def open_milestone(milestone, current_user)
-    create_event(milestone, current_user, Event::CREATED)
+    create_record_event(milestone, current_user, Event::CREATED)
   end
 
   def close_milestone(milestone, current_user)
-    create_event(milestone, current_user, Event::CLOSED)
+    create_record_event(milestone, current_user, Event::CLOSED)
   end
 
   def reopen_milestone(milestone, current_user)
-    create_event(milestone, current_user, Event::REOPENED)
+    create_record_event(milestone, current_user, Event::REOPENED)
   end
 
   def leave_note(note, current_user)
-    create_event(note, current_user, Event::COMMENTED)
+    create_record_event(note, current_user, Event::COMMENTED)
+  end
+
+  def join_project(project, current_user)
+    create_event(project, current_user, Event::JOINED)
+  end
+
+  def leave_project(project, current_user)
+    create_event(project, current_user, Event::LEFT)
+  end
+
+  def create_project(project, current_user)
+    create_event(project, current_user, Event::CREATED)
+  end
+
+  def push(project, current_user, push_data)
+    create_event(project, current_user, Event::PUSHED, data: push_data)
   end
 
   private
 
-  def create_event(record, current_user, status)
-    Event.create(
-      project: record.project,
-      target_id: record.id,
-      target_type: record.class.name,
+  def create_record_event(record, current_user, status)
+    create_event(record.project, current_user, status, target_id: record.id, target_type: record.class.name)
+  end
+
+  def create_event(project, current_user, status, attributes = {})
+    attributes.reverse_merge!(
+      project: project,
       action: status,
       author_id: current_user.id
     )
+
+    Event.create(attributes)
   end
 end
diff --git a/app/services/files/create_service.rb b/app/services/files/create_service.rb
index 82e4d7b684f11dd445566e61107fe182e267077f..eeafefc25aff8597211dfd98acdb435900ed6749 100644
--- a/app/services/files/create_service.rb
+++ b/app/services/files/create_service.rb
@@ -3,20 +3,12 @@ require_relative "base_service"
 module Files
   class CreateService < BaseService
     def execute
-      allowed = if project.protected_branch?(ref)
-                  can?(current_user, :push_code_to_protected_branches, project)
-                else
-                  can?(current_user, :push_code, project)
-                end
+      allowed = Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(ref)
 
       unless allowed
         return error("You are not allowed to create file in this branch")
       end
 
-      unless repository.branch_names.include?(ref)
-        return error("You can only create files if you are on top of a branch")
-      end
-
       file_name = File.basename(path)
       file_path = path
 
@@ -27,17 +19,27 @@ module Files
         )
       end
 
-      blob = repository.blob_at_branch(ref, file_path)
+      if project.empty_repo?
+        # everything is ok because repo does not have a commits yet
+      else
+        unless repository.branch_names.include?(ref)
+          return error("You can only create files if you are on top of a branch")
+        end
 
-      if blob
-        return error("Your changes could not be committed, because file with such name exists")
+        blob = repository.blob_at_branch(ref, file_path)
+
+        if blob
+          return error("Your changes could not be committed, because file with such name exists")
+        end
       end
 
+
       new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, file_path)
       created_successfully = new_file_action.commit!(
         params[:content],
         params[:commit_message],
-        params[:encoding]
+        params[:encoding],
+        params[:new_branch]
       )
 
       if created_successfully
diff --git a/app/services/files/delete_service.rb b/app/services/files/delete_service.rb
index ff5dc6ef34c5d0c7eefb8be8b46363109c54a504..1497a0f883bcb32c5c85cdb3400a3960ea539de0 100644
--- a/app/services/files/delete_service.rb
+++ b/app/services/files/delete_service.rb
@@ -3,11 +3,7 @@ require_relative "base_service"
 module Files
   class DeleteService < BaseService
     def execute
-      allowed = if project.protected_branch?(ref)
-                  can?(current_user, :push_code_to_protected_branches, project)
-                else
-                  can?(current_user, :push_code, project)
-                end
+      allowed = ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(ref)
 
       unless allowed
         return error("You are not allowed to push into this branch")
diff --git a/app/services/files/update_service.rb b/app/services/files/update_service.rb
index a0f40154db02e28a32e83ac157043b08cc287748..0724d3ae6347b1150c0c40f81cb36fbdb7c9dea8 100644
--- a/app/services/files/update_service.rb
+++ b/app/services/files/update_service.rb
@@ -3,11 +3,7 @@ require_relative "base_service"
 module Files
   class UpdateService < BaseService
     def execute
-      allowed = if project.protected_branch?(ref)
-                  can?(current_user, :push_code_to_protected_branches, project)
-                else
-                  can?(current_user, :push_code, project)
-                end
+      allowed = ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(ref)
 
       unless allowed
         return error("You are not allowed to push into this branch")
@@ -24,17 +20,20 @@ module Files
       end
 
       edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path)
-      created_successfully = edit_file_action.commit!(
+      edit_file_action.commit!(
         params[:content],
         params[:commit_message],
-        params[:encoding]
+        params[:encoding],
+        params[:new_branch]
       )
 
-      if created_successfully
-        success
-      else
-        error("Your changes could not be committed. Maybe the file was changed by another process or there was nothing to commit?")
-      end
+      success
+    rescue Gitlab::Satellite::CheckoutFailed => ex
+      error("Your changes could not be committed because ref '#{ref}' could not be checked out", 400)
+    rescue Gitlab::Satellite::CommitFailed => ex
+      error("Your changes could not be committed. Maybe there was nothing to commit?", 409)
+    rescue Gitlab::Satellite::PushFailed => ex
+      error("Your changes could not be committed. Maybe the file was changed by another process?", 409)
     end
   end
 end
diff --git a/app/services/files/upload_service.rb b/app/services/files/upload_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..067b01c10f94691f443b844219959fc233981cff
--- /dev/null
+++ b/app/services/files/upload_service.rb
@@ -0,0 +1,40 @@
+require_relative "base_service"
+
+module Files
+  class UploadService < BaseService
+    
+    def execute
+      allowed = if project.protected_branch?(ref)
+                  can?(current_user, :push_code_to_protected_branches, project)
+                else
+                  can?(current_user, :push_code, project)
+                end
+                
+      unless allowed
+        return error("You are not allowed to push into this branch")
+      end
+
+      unless repository.branch_names.include?(ref)
+        return error("You can only create files if you are on top of a branch")
+      end
+
+      blob = repository.blob_at_branch(ref, path)
+
+      unless blob
+        return error("You can only edit text files")
+      end
+
+      edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path)
+      
+      created_successfully = edit_file_action.commit!(params[:content], 
+                                                      params[:commit_message_replace], 
+                                                      params[:encoding])
+                                                      
+      if created_successfully
+        success
+      else
+        error("Your changes could not be committed.")      
+      end
+    end
+  end
+end
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index 529af1970f6626651940a1af63644d5eccc0dbe2..1f0b29dff5ebd5ed94fca2045591605d131aab64 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -1,5 +1,7 @@
 class GitPushService
   attr_accessor :project, :user, :push_data, :push_commits
+  include Gitlab::CurrentSettings
+  include Gitlab::Access
 
   # This method will be called after each git update
   # and only if the provided user and project is present in GitLab.
@@ -21,58 +23,44 @@ class GitPushService
     project.repository.expire_cache
     project.update_repository_size
 
-    if push_to_branch?(ref)
-      if push_remove_branch?(ref, newrev)
-        @push_commits = []
-      elsif push_to_new_branch?(ref, oldrev)
-        # Re-find the pushed commits.
-        if is_default_branch?(ref)
-          # Initial push to the default branch. Take the full history of that branch as "newly pushed".
-          @push_commits = project.repository.commits(newrev)
-          # Default branch is protected by default
-          project.protected_branches.create({ name: project.default_branch })
-        else
-          # Use the pushed commits that aren't reachable by the default branch
-          # as a heuristic. This may include more commits than are actually pushed, but
-          # that shouldn't matter because we check for existing cross-references later.
-          @push_commits = project.repository.commits_between(project.default_branch, newrev)
+    if push_remove_branch?(ref, newrev)
+      @push_commits = []
+    elsif push_to_new_branch?(ref, oldrev)
+      # Re-find the pushed commits.
+      if is_default_branch?(ref)
+        # Initial push to the default branch. Take the full history of that branch as "newly pushed".
+        @push_commits = project.repository.commits(newrev)
+
+        # 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
-        process_commit_messages(ref)
-      elsif push_to_existing_branch?(ref, oldrev)
-        # Collect data for this git push
-        @push_commits = project.repository.commits_between(oldrev, newrev)
-        project.update_merge_requests(oldrev, newrev, ref, @user)
+      else
+        # Use the pushed commits that aren't reachable by the default branch
+        # as a heuristic. This may include more commits than are actually pushed, but
+        # that shouldn't matter because we check for existing cross-references later.
+        @push_commits = project.repository.commits_between(project.default_branch, newrev)
+
+        # don't process commits for the initial push to the default branch
         process_commit_messages(ref)
       end
-
-      @push_data = post_receive_data(oldrev, newrev, ref)
-      create_push_event(@push_data)
-      project.execute_hooks(@push_data.dup, :push_hooks)
-      project.execute_services(@push_data.dup)
+    elsif push_to_existing_branch?(ref, oldrev)
+      # Collect data for this git push
+      @push_commits = project.repository.commits_between(oldrev, newrev)
+      project.update_merge_requests(oldrev, newrev, ref, @user)
+      process_commit_messages(ref)
     end
-  end
 
-  # This method provide a sample data
-  # generated with post_receive_data method
-  # for given project
-  #
-  def sample_data(project, user)
-    @project, @user = project, user
-    @push_commits = project.repository.commits(project.default_branch, nil, 3)
-    post_receive_data(@push_commits.last.id, @push_commits.first.id, "refs/heads/#{project.default_branch}")
+    @push_data = build_push_data(oldrev, newrev, ref)
+
+    EventCreateService.new.push(project, user, @push_data)
+    project.execute_hooks(@push_data.dup, :push_hooks)
+    project.execute_services(@push_data.dup, :push_hooks)
   end
 
   protected
 
-  def create_push_event(push_data)
-    Event.create!(
-      project: project,
-      action: Event::PUSHED,
-      data: push_data,
-      author_id: push_data[:user_id]
-    )
-  end
-
   # Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched,
   # close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables.
   def process_commit_messages(ref)
@@ -112,85 +100,30 @@ class GitPushService
     end
   end
 
-  # Produce a hash of post-receive data
-  #
-  # data = {
-  #   before: String,
-  #   after: String,
-  #   ref: String,
-  #   user_id: String,
-  #   user_name: String,
-  #   project_id: String,
-  #   repository: {
-  #     name: String,
-  #     url: String,
-  #     description: String,
-  #     homepage: String,
-  #   },
-  #   commits: Array,
-  #   total_commits_count: Fixnum
-  # }
-  #
-  def post_receive_data(oldrev, newrev, ref)
-    # Total commits count
-    push_commits_count = push_commits.size
-
-    # Get latest 20 commits ASC
-    push_commits_limited = push_commits.last(20)
-
-    # Hash to be passed as post_receive_data
-    data = {
-      before: oldrev,
-      after: newrev,
-      ref: ref,
-      user_id: user.id,
-      user_name: user.name,
-      project_id: project.id,
-      repository: {
-        name: project.name,
-        url: project.url_to_repo,
-        description: project.description,
-        homepage: project.web_url,
-      },
-      commits: [],
-      total_commits_count: push_commits_count
-    }
-
-    # For performance purposes maximum 20 latest commits
-    # will be passed as post receive hook data.
-    #
-    push_commits_limited.each do |commit|
-      data[:commits] << commit.hook_attrs(project)
-    end
-
-    data
+  def build_push_data(oldrev, newrev, ref)
+    Gitlab::PushDataBuilder.
+      build(project, user, oldrev, newrev, ref, push_commits)
   end
 
   def push_to_existing_branch?(ref, oldrev)
-    ref_parts = ref.split('/')
-
     # Return if this is not a push to a branch (e.g. new commits)
-    ref_parts[1] =~ /heads/ && oldrev != Gitlab::Git::BLANK_SHA
+    Gitlab::Git.branch_ref?(ref) && !Gitlab::Git.blank_ref?(oldrev)
   end
 
   def push_to_new_branch?(ref, oldrev)
-    ref_parts = ref.split('/')
-
-    ref_parts[1] =~ /heads/ && oldrev == Gitlab::Git::BLANK_SHA
+    Gitlab::Git.branch_ref?(ref) && Gitlab::Git.blank_ref?(oldrev)
   end
 
   def push_remove_branch?(ref, newrev)
-    ref_parts = ref.split('/')
-
-    ref_parts[1] =~ /heads/ && newrev == Gitlab::Git::BLANK_SHA
+    Gitlab::Git.branch_ref?(ref) && Gitlab::Git.blank_ref?(newrev)
   end
 
   def push_to_branch?(ref)
-    ref =~ /refs\/heads/
+    Gitlab::Git.branch_ref?(ref)
   end
 
   def is_default_branch?(ref)
-    ref == "refs/heads/#{project.default_branch}"
+    Gitlab::Git.branch_ref?(ref) && Gitlab::Git.ref_name(ref) == project.default_branch
   end
 
   def commit_user(commit)
diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb
index 62eaf9b4f51ea591c7d1a6b3199b6ae6382aab81..bf203bbd69272c1f80103403ae87b6a7937abb02 100644
--- a/app/services/git_tag_push_service.rb
+++ b/app/services/git_tag_push_service.rb
@@ -3,38 +3,35 @@ class GitTagPushService
 
   def execute(project, user, oldrev, newrev, ref)
     @project, @user = project, user
-    @push_data = create_push_data(oldrev, newrev, ref)
 
-    create_push_event
-    project.repository.expire_cache
+    @push_data = build_push_data(oldrev, newrev, ref)
+
+    EventCreateService.new.push(project, user, @push_data)
     project.execute_hooks(@push_data.dup, :tag_push_hooks)
+    project.execute_services(@push_data.dup, :tag_push_hooks)
+
+    project.repository.expire_cache
+
+    true
   end
 
   private
 
-  def create_push_data(oldrev, newrev, ref)
-    data = {
-      ref: ref,
-      before: oldrev,
-      after: newrev,
-      user_id: user.id,
-      user_name: user.name,
-      project_id: project.id,
-      repository: {
-        name: project.name,
-        url: project.url_to_repo,
-        description: project.description,
-        homepage: project.web_url
-      }
-    }
-  end
+  def build_push_data(oldrev, newrev, ref)
+    commits = []
+    message = nil
+
+    if !Gitlab::Git.blank_ref?(newrev)
+      tag_name = Gitlab::Git.ref_name(ref)
+      tag = project.repository.find_tag(tag_name)
+      if tag && tag.target == newrev
+        commit = project.repository.commit(tag.target)
+        commits = [commit].compact
+        message = tag.message
+      end
+    end
 
-  def create_push_event
-    Event.create!(
-      project: project,
-      action: Event::PUSHED,
-      data: push_data,
-      author_id: push_data[:user_id]
-    )
+    Gitlab::PushDataBuilder.
+      build(project, user, oldrev, newrev, ref, commits, message)
   end
 end
diff --git a/app/services/gravatar_service.rb b/app/services/gravatar_service.rb
index a69c7c78377e13739a68ae45533c51699259cf49..4bee0c26a68e1e7c32c2ea91946ac8ee0c79e65a 100644
--- a/app/services/gravatar_service.rb
+++ b/app/services/gravatar_service.rb
@@ -1,6 +1,8 @@
 class GravatarService
+  include Gitlab::CurrentSettings
+
   def execute(email, size = nil)
-    if gravatar_config.enabled && email.present?
+    if current_application_settings.gravatar_enabled? && email.present?
       size = 40 if size.nil? || size <= 0
 
       sprintf gravatar_url,
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index e3371ec3c1b7c60bd11970052cd627e8021bbbc7..5e1906ad2aec637beca13b6a00b794fd2d7c7eaf 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -10,4 +10,9 @@ class IssuableBaseService < BaseService
     Note.create_milestone_change_note(
       issuable, issuable.project, current_user, issuable.milestone)
   end
+
+  def create_labels_note(issuable, added_labels, removed_labels)
+    Note.create_labels_change_note(
+      issuable, issuable.project, current_user, added_labels, removed_labels)
+  end
 end
diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb
index 755c0ef45a8be788da850b315c936b303a1ab5db..c3ca04a43438563e6e8eebb2258bee6103a66f44 100644
--- a/app/services/issues/base_service.rb
+++ b/app/services/issues/base_service.rb
@@ -1,13 +1,19 @@
 module Issues
   class BaseService < ::IssuableBaseService
 
-    private
-
-    def execute_hooks(issue, action = 'open')
+    def hook_data(issue, action)
       issue_data = issue.to_hook_data(current_user)
       issue_url = Gitlab::UrlBuilder.new(:issue).build(issue.id)
       issue_data[:object_attributes].merge!(url: issue_url, action: action)
+      issue_data
+    end
+
+    private
+
+    def execute_hooks(issue, action = 'open')
+      issue_data = hook_data(issue, action)
       issue.project.execute_hooks(issue_data, :issue_hooks)
+      issue.project.execute_services(issue_data, :issue_hooks)
     end
   end
 end
diff --git a/app/services/issues/bulk_update_service.rb b/app/services/issues/bulk_update_service.rb
index f72a346af6fffc8509c6ac1e7be68fafa98c0960..eb07413ee9439e393b266049fc9aa2d3c9f1ec8e 100644
--- a/app/services/issues/bulk_update_service.rb
+++ b/app/services/issues/bulk_update_service.rb
@@ -1,38 +1,23 @@
 module Issues
   class BulkUpdateService < BaseService
     def execute
-      update_data = params[:update]
+      issues_ids   = params.delete(:issues_ids).split(",")
+      issue_params = params
 
-      issues_ids   = update_data[:issues_ids].split(",")
-      milestone_id = update_data[:milestone_id]
-      assignee_id  = update_data[:assignee_id]
-      status       = update_data[:status]
-
-      new_state = nil
-
-      if status.present?
-        if status == 'closed'
-          new_state = :close
-        else
-          new_state = :reopen
-        end
-      end
-
-      opts = {}
-      opts[:milestone_id] = milestone_id if milestone_id.present?
-      opts[:assignee_id] = assignee_id if assignee_id.present?
+      issue_params.delete(:state_event)   unless issue_params[:state_event].present?
+      issue_params.delete(:milestone_id)  unless issue_params[:milestone_id].present?
+      issue_params.delete(:assignee_id)   unless issue_params[:assignee_id].present?
 
       issues = Issue.where(id: issues_ids)
-      issues = issues.select { |issue| can?(current_user, :modify_issue, issue) }
-
       issues.each do |issue|
-        issue.update_attributes(opts)
-        issue.send new_state if new_state
+        next unless can?(current_user, :modify_issue, issue)
+
+        Issues::UpdateService.new(issue.project, current_user, issue_params).execute(issue)
       end
 
       {
-        count: issues.count,
-        success: !issues.count.zero?
+        count:    issues.count,
+        success:  !issues.count.zero?
       }
     end
   end
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index ffed13a12e11925bee71e1bcb1ed65858cf160a7..f670019cc638a24d0dd2e666c8d6e1d1016fb36f 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -2,9 +2,9 @@ module Issues
   class CloseService < Issues::BaseService
     def execute(issue, commit = nil)
       if issue.close
-        notification_service.close_issue(issue, current_user)
         event_service.close_issue(issue, current_user)
         create_note(issue, commit)
+        notification_service.close_issue(issue, current_user)
         execute_hooks(issue, 'close')
       end
 
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index 0ee9635ed99edecceeb035b801fa1da01f53328b..8f04a69287a787f07900319eafd7e538d6d388c8 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -14,17 +14,27 @@ module Issues
         issue.update_nth_task(params[:task_num].to_i, false)
       end
 
+      params[:assignee_id]  = "" if params[:assignee_id] == IssuableFinder::NONE
+      params[:milestone_id] = "" if params[:milestone_id] == IssuableFinder::NONE
+
+      old_labels = issue.labels.to_a
+
       if params.present? && issue.update_attributes(params.except(:state_event,
                                                                   :task_num))
         issue.reset_events_cache
 
+        if issue.labels != old_labels
+          create_labels_note(
+            issue, issue.labels - old_labels, old_labels - issue.labels)
+        end
+
         if issue.previous_changes.include?('milestone_id')
           create_milestone_note(issue)
         end
 
         if issue.previous_changes.include?('assignee_id')
-          notification_service.reassigned_issue(issue, current_user)
           create_assignee_note(issue)
+          notification_service.reassigned_issue(issue, current_user)
         end
 
         issue.notice_added_references(issue.project, current_user)
diff --git a/app/services/merge_requests/auto_merge_service.rb b/app/services/merge_requests/auto_merge_service.rb
index 20b88d1510cfe6a1213ba73b00b01659e064755b..378b39bb9d6dd2edcb4f9aa1b6bff8701c249ced 100644
--- a/app/services/merge_requests/auto_merge_service.rb
+++ b/app/services/merge_requests/auto_merge_service.rb
@@ -5,15 +5,16 @@ module MergeRequests
   # mark merge request as merged and execute all hooks and notifications
   # Called when you do merge via GitLab UI
   class AutoMergeService < BaseMergeService
-    def execute(merge_request, current_user, commit_message)
+    def execute(merge_request, commit_message)
       merge_request.lock_mr
 
       if Gitlab::Satellite::MergeAction.new(current_user, merge_request).merge!(commit_message)
         merge_request.merge
 
-        notification.merge_mr(merge_request, current_user)
         create_merge_event(merge_request, current_user)
-        execute_project_hooks(merge_request)
+        create_note(merge_request)
+        notification_service.merge_mr(merge_request, current_user)
+        execute_hooks(merge_request)
 
         true
       else
diff --git a/app/services/merge_requests/base_merge_service.rb b/app/services/merge_requests/base_merge_service.rb
index 700a21ca01150eda33681ae25a1c21adfd0f1458..9579573adf9fb9ff34c1b59f08668b46b11b04b2 100644
--- a/app/services/merge_requests/base_merge_service.rb
+++ b/app/services/merge_requests/base_merge_service.rb
@@ -1,21 +1,10 @@
 module MergeRequests
-  class BaseMergeService
+  class BaseMergeService < MergeRequests::BaseService
 
     private
 
-    def notification
-      NotificationService.new
-    end
-
     def create_merge_event(merge_request, current_user)
       EventCreateService.new.merge_mr(merge_request, current_user)
     end
-
-    def execute_project_hooks(merge_request)
-      if merge_request.project
-        hook_data = merge_request.to_hook_data(current_user)
-        merge_request.project.execute_hooks(hook_data, :merge_request_hooks)
-      end
-    end
   end
 end
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 7f3421b8e4ba9c16dd9ef8a399ffef693427ec9f..f6e1ae6f283e836cd3400393f26ee87c4c26f9af 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -5,10 +5,19 @@ module MergeRequests
       Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state, nil)
     end
 
-    def execute_hooks(merge_request)
+    def hook_data(merge_request, action)
+      hook_data = merge_request.to_hook_data(current_user)
+      merge_request_url = Gitlab::UrlBuilder.new(:merge_request).build(merge_request.id)
+      hook_data[:object_attributes][:url] = merge_request_url
+      hook_data[:object_attributes][:action] = action
+      hook_data
+    end
+
+    def execute_hooks(merge_request, action = 'open')
       if merge_request.project
-        hook_data = merge_request.to_hook_data(current_user)
-        merge_request.project.execute_hooks(hook_data, :merge_request_hooks)
+        merge_data = hook_data(merge_request, action)
+        merge_request.project.execute_hooks(merge_data, :merge_request_hooks)
+        merge_request.project.execute_services(merge_data, :merge_request_hooks)
       end
     end
   end
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 1475973e543acfe78a64ecfdcbaaa76e5d0a81ed..a44b91166e85c3fbf4fb737d12b561e21bd7409e 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -13,12 +13,9 @@ module MergeRequests
       merge_request.target_branch ||= merge_request.target_project.default_branch
 
       unless merge_request.target_branch && merge_request.source_branch
-        return build_failed(merge_request, "You must select source and target branches")
+        return build_failed(merge_request, nil)
       end
 
-      # Generate suggested MR title based on source branch name
-      merge_request.title = merge_request.source_branch.titleize.humanize
-
       compare_result = CompareService.new.execute(
         current_user,
         merge_request.source_project,
@@ -52,6 +49,15 @@ module MergeRequests
         merge_request.compare_failed = false
       end
 
+      commits = merge_request.compare_commits
+      if commits && commits.count == 1
+        commit = commits.first
+        merge_request.title       = commit.title
+        merge_request.description = commit.description.try(:strip)
+      else
+        merge_request.title = merge_request.source_branch.titleize.humanize
+      end
+
       merge_request
 
     rescue Gitlab::Satellite::BranchesWithoutParent
@@ -59,7 +65,7 @@ module MergeRequests
     end
 
     def build_failed(merge_request, message)
-      merge_request.errors.add(:base, message)
+      merge_request.errors.add(:base, message) unless message.nil?
       merge_request.compare_commits = []
       merge_request.can_be_created = false
       merge_request
diff --git a/app/services/merge_requests/close_service.rb b/app/services/merge_requests/close_service.rb
index 64e37a23e6b57af9ff2ec87895091ab0548b5c99..47454f9f0c214f52932a55da53eb6bc8fdf22f8a 100644
--- a/app/services/merge_requests/close_service.rb
+++ b/app/services/merge_requests/close_service.rb
@@ -7,9 +7,9 @@ module MergeRequests
 
       if merge_request.close
         event_service.close_mr(merge_request, current_user)
-        notification_service.close_mr(merge_request, current_user)
         create_note(merge_request)
-        execute_hooks(merge_request)
+        notification_service.close_mr(merge_request, current_user)
+        execute_hooks(merge_request, 'close')
       end
 
       merge_request
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index 680766140bdf2ede94077110dfce5b0e7154871d..327ead4ff3fe1fdb869aa415a48ee54ab9a222a5 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -6,12 +6,13 @@ module MergeRequests
   # Called when you do merge via command line and push code
   # to target branch
   class MergeService < BaseMergeService
-    def execute(merge_request, current_user, commit_message)
+    def execute(merge_request, commit_message)
       merge_request.merge
 
-      notification.merge_mr(merge_request, current_user)
       create_merge_event(merge_request, current_user)
-      execute_project_hooks(merge_request)
+      create_note(merge_request)
+      notification_service.merge_mr(merge_request, current_user)
+      execute_hooks(merge_request, 'merge')
 
       true
     rescue
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index 74448998dddde385fc25560b16580fb08ee95221..e9b526d1fb7bc192a5fd33baafe45486d17895e2 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -1,9 +1,10 @@
 module MergeRequests
   class RefreshService < MergeRequests::BaseService
     def execute(oldrev, newrev, ref)
-      return true unless ref =~ /heads/
+      return true unless Gitlab::Git.branch_ref?(ref)
 
-      @branch_name = ref.gsub("refs/heads/", "")
+      @oldrev, @newrev = oldrev, newrev
+      @branch_name = Gitlab::Git.ref_name(ref)
       @fork_merge_requests = @project.fork_merge_requests.opened
       @commits = @project.repository.commits_between(oldrev, newrev)
 
@@ -31,10 +32,16 @@ module MergeRequests
 
 
       merge_requests.uniq.select(&:source_project).each do |merge_request|
-        MergeRequests::MergeService.new.execute(merge_request, @current_user, nil)
+        MergeRequests::MergeService.
+          new(merge_request.target_project, @current_user).
+          execute(merge_request, nil)
       end
     end
 
+    def force_push?
+      Gitlab::ForcePushCheck.force_push?(@project, @oldrev, @newrev)
+    end
+
     # Refresh merge request diff if we push to source or target branch of merge request
     # Note: we should update merge requests from forks too
     def reload_merge_requests
@@ -43,8 +50,22 @@ module MergeRequests
       merge_requests = filter_merge_requests(merge_requests)
 
       merge_requests.each do |merge_request|
-        merge_request.reload_code
-        merge_request.mark_as_unchecked
+
+        if merge_request.source_branch == @branch_name || force_push?
+          merge_request.reload_code
+          merge_request.mark_as_unchecked
+        else
+          mr_commit_ids = merge_request.commits.map(&:id)
+          push_commit_ids = @commits.map(&:id)
+          matches = mr_commit_ids & push_commit_ids
+
+          if matches.any?
+            merge_request.reload_code
+            merge_request.mark_as_unchecked
+          else
+            merge_request.mark_as_unchecked
+          end
+        end
       end
     end
 
@@ -55,8 +76,14 @@ module MergeRequests
       merge_requests = filter_merge_requests(merge_requests)
 
       merge_requests.each do |merge_request|
+        mr_commit_ids = Set.new(merge_request.commits.map(&:id))
+
+        new_commits, existing_commits = @commits.partition do |commit|
+          mr_commit_ids.include?(commit.id)
+        end
+
         Note.create_new_commits_note(merge_request, merge_request.project,
-                                     @current_user, @commits)
+                                     @current_user, new_commits, existing_commits, @oldrev)
       end
     end
 
diff --git a/app/services/merge_requests/reopen_service.rb b/app/services/merge_requests/reopen_service.rb
index bd68919a5509f93d2972d30cbc7e09cdf391b512..8279ad2001b07e42c2a4faa8ab64c4ff797c2b96 100644
--- a/app/services/merge_requests/reopen_service.rb
+++ b/app/services/merge_requests/reopen_service.rb
@@ -3,9 +3,9 @@ module MergeRequests
     def execute(merge_request)
       if merge_request.reopen
         event_service.reopen_mr(merge_request, current_user)
-        notification_service.reopen_mr(merge_request, current_user)
         create_note(merge_request)
-        execute_hooks(merge_request)
+        notification_service.reopen_mr(merge_request, current_user)
+        execute_hooks(merge_request, 'reopen')
         merge_request.reload_code
         merge_request.mark_as_unchecked
       end
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index fc26619cd173542baa47fe6f8f14008408e0286b..23af2656c375de3bad8a399b70ad05f7ee540a35 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -23,22 +23,35 @@ module MergeRequests
         merge_request.update_nth_task(params[:task_num].to_i, false)
       end
 
+      params[:assignee_id]  = "" if params[:assignee_id] == IssuableFinder::NONE
+      params[:milestone_id] = "" if params[:milestone_id] == IssuableFinder::NONE
+
+      old_labels = merge_request.labels.to_a
+
       if params.present? && merge_request.update_attributes(
         params.except(:state_event, :task_num)
       )
         merge_request.reset_events_cache
 
+        if merge_request.labels != old_labels
+          create_labels_note(
+            merge_request,
+            merge_request.labels - old_labels,
+            old_labels - merge_request.labels
+          )
+        end
+
         if merge_request.previous_changes.include?('milestone_id')
           create_milestone_note(merge_request)
         end
 
         if merge_request.previous_changes.include?('assignee_id')
-          notification_service.reassigned_merge_request(merge_request, current_user)
           create_assignee_note(merge_request)
+          notification_service.reassigned_merge_request(merge_request, current_user)
         end
 
         merge_request.notice_added_references(merge_request.project, current_user)
-        execute_hooks(merge_request)
+        execute_hooks(merge_request, 'update')
       end
 
       merge_request
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index f64006a4edcceaed27155a2b8ceb20f0420a2af3..e969061f229d8a8ee6ce266cdf9a88a50c79af45 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -17,10 +17,22 @@ module Notes
           note.references.each do |mentioned|
             Note.create_cross_reference_note(mentioned, note.noteable, note.author, note.project)
           end
+
+          execute_hooks(note)
         end
       end
 
       note
     end
+
+    def hook_data(note)
+      Gitlab::NoteDataBuilder.build(note, current_user)
+    end
+
+    def execute_hooks(note)
+      note_data = hook_data(note)
+      # TODO: Support Webhooks
+      note.project.execute_services(note_data, :note_hooks)
+    end
   end
 end
diff --git a/app/services/notes/update_service.rb b/app/services/notes/update_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..63431b82471ee5e16a9b1d1283dccc85d6ac957a
--- /dev/null
+++ b/app/services/notes/update_service.rb
@@ -0,0 +1,25 @@
+module Notes
+  class UpdateService < BaseService
+    def execute
+      note = project.notes.find(params[:note_id])
+      note.note = params[:note]
+      if note.save
+        notification_service.new_note(note)
+
+        # Skip system notes, like status changes and cross-references.
+        unless note.system
+          event_service.leave_note(note, note.author)
+
+          # Create a cross-reference note if this Note contains GFM that
+          # names an issue, merge request, or commit.
+          note.references.each do |mentioned|
+            Note.create_cross_reference_note(mentioned, note.noteable,
+                                             note.author, note.project)
+          end
+        end
+      end
+
+      note
+    end
+  end
+end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index c9a1574b84e10daffc0a3d949b3411dcb9ea8c60..cc5853144c56ef21d9e7f3b4660dc9e237b454ef 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -92,6 +92,8 @@ class NotificationService
   #
   def merge_mr(merge_request, current_user)
     recipients = reject_muted_users([merge_request.author, merge_request.assignee], merge_request.target_project)
+    recipients = add_subscribed_users(recipients, merge_request)
+    recipients = reject_unsubscribed_users(recipients, merge_request)
     recipients = recipients.concat(project_watchers(merge_request.target_project)).uniq
     recipients.delete(current_user)
 
@@ -107,7 +109,7 @@ class NotificationService
   # Notify new user with email after creation
   def new_user(user, token = nil)
     # Don't email omniauth created users
-    mailer.new_user_email(user.id, user.password, token) unless user.extern_uid?
+    mailer.new_user_email(user.id, token) unless user.identities.any?
   end
 
   # Notify users on new note in system
@@ -118,7 +120,7 @@ class NotificationService
     return true unless note.noteable_type.present?
 
     # ignore gitlab service messages
-    return true if note.note =~ /\A_Status changed to closed_/
+    return true if note.note.start_with?('Status changed to closed')
     return true if note.cross_reference? && note.system == true
 
     opts = { noteable_type: note.noteable_type, project_id: note.project_id }
@@ -144,9 +146,17 @@ class NotificationService
     # Merge project watchers
     recipients = recipients.concat(project_watchers(note.project)).compact.uniq
 
+    # Reject mention users unless mentioned in comment
+    recipients = reject_mention_users(recipients - note.mentioned_users, note.project)
+    recipients = recipients + note.mentioned_users
+
     # Reject mutes users
     recipients = reject_muted_users(recipients, note.project)
 
+    recipients = add_subscribed_users(recipients, note.noteable)
+    
+    recipients = reject_unsubscribed_users(recipients, note.noteable)
+
     # Reject author
     recipients.delete(note.author)
 
@@ -158,20 +168,20 @@ class NotificationService
     end
   end
 
-  def new_team_member(project_member)
+  def new_project_member(project_member)
     mailer.project_access_granted_email(project_member.id)
   end
 
-  def update_team_member(project_member)
+  def update_project_member(project_member)
     mailer.project_access_granted_email(project_member.id)
   end
 
-  def new_group_member(users_group)
-    mailer.group_access_granted_email(users_group.id)
+  def new_group_member(group_member)
+    mailer.group_access_granted_email(group_member.id)
   end
 
-  def update_group_member(users_group)
-    mailer.group_access_granted_email(users_group.id)
+  def update_group_member(group_member)
+    mailer.group_access_granted_email(group_member.id)
   end
 
   def project_was_moved(project)
@@ -190,11 +200,11 @@ class NotificationService
     project_members = project_member_notification(project)
 
     users_with_project_level_global = project_member_notification(project, Notification::N_GLOBAL)
-    users_with_group_level_global = users_group_notification(project, Notification::N_GLOBAL)
+    users_with_group_level_global = group_member_notification(project, Notification::N_GLOBAL)
     users = users_with_global_level_watch([users_with_project_level_global, users_with_group_level_global].flatten.uniq)
 
     users_with_project_setting = select_project_member_setting(project, users_with_project_level_global, users)
-    users_with_group_setting = select_users_group_setting(project, project_members, users_with_group_level_global, users)
+    users_with_group_setting = select_group_member_setting(project, project_members, users_with_group_level_global, users)
 
     User.where(id: users_with_project_setting.concat(users_with_group_setting).uniq).to_a
   end
@@ -209,7 +219,7 @@ class NotificationService
     end
   end
 
-  def users_group_notification(project, notification_level)
+  def group_member_notification(project, notification_level)
     if project.group
       project.group.group_members.where(notification_level: notification_level).pluck(:user_id)
     else
@@ -238,9 +248,9 @@ class NotificationService
     users
   end
 
-  # Build a list of users based on group notifcation settings
-  def select_users_group_setting(project, project_members, global_setting, users_global_level_watch)
-    uids = users_group_notification(project, Notification::N_WATCH)
+  # Build a list of users based on group notification settings
+  def select_group_member_setting(project, project_members, global_setting, users_global_level_watch)
+    uids = group_member_notification(project, Notification::N_WATCH)
 
     # Group setting is watch, add to users list if user is not project member
     users = []
@@ -264,35 +274,75 @@ class NotificationService
   # Also remove duplications and nil recipients
   def reject_muted_users(users, project = nil)
     users = users.to_a.compact.uniq
+    users = users.reject(&:blocked?)
 
     users.reject do |user|
       next user.notification.disabled? unless project
 
-      tm = project.project_members.find_by(user_id: user.id)
+      member = project.project_members.find_by(user_id: user.id)
 
-      if !tm && project.group
-        tm = project.group.group_members.find_by(user_id: user.id)
+      if !member && project.group
+        member = project.group.group_members.find_by(user_id: user.id)
       end
 
       # reject users who globally disabled notification and has no membership
-      next user.notification.disabled? unless tm
+      next user.notification.disabled? unless member
 
       # reject users who disabled notification in project
-      next true if tm.notification.disabled?
+      next true if member.notification.disabled?
 
       # reject users who have N_GLOBAL in project and disabled in global settings
-      tm.notification.global? && user.notification.disabled?
+      member.notification.global? && user.notification.disabled?
     end
   end
 
-  def new_resource_email(target, project, method)
-    if target.respond_to?(:participants)
-      recipients = target.participants
+  # Remove users with notification level 'Mentioned'
+  def reject_mention_users(users, project = nil)
+    users = users.to_a.compact.uniq
+
+    users.reject do |user|
+      next user.notification.mention? unless project
+
+      member = project.project_members.find_by(user_id: user.id)
+
+      if !member && project.group
+        member = project.group.group_members.find_by(user_id: user.id)
+      end
+
+      # reject users who globally set mention notification and has no membership
+      next user.notification.mention? unless member
+
+      # reject users who set mention notification in project
+      next true if member.notification.mention?
+
+      # reject users who have N_MENTION in project and disabled in global settings
+      member.notification.global? && user.notification.mention?
+    end
+  end
+
+  def reject_unsubscribed_users(recipients, target)
+    return recipients unless target.respond_to? :subscriptions
+    
+    recipients.reject do |user|
+      subscription = target.subscriptions.find_by_user_id(user.id)
+      subscription && !subscription.subscribed
+    end
+  end
+
+  def add_subscribed_users(recipients, target)
+    return recipients unless target.respond_to? :subscriptions
+
+    subscriptions = target.subscriptions
+
+    if subscriptions.any?
+      recipients + subscriptions.where(subscribed: true).map(&:user)
     else
-      recipients = []
+      recipients
     end
-    recipients = reject_muted_users(recipients, project)
-    recipients = recipients.concat(project_watchers(project)).uniq
+  end
+  
+  def new_resource_email(target, project, method)
+    recipients = build_recipients(target, project)
     recipients.delete(target.author)
 
     recipients.each do |recipient|
@@ -301,8 +351,7 @@ class NotificationService
   end
 
   def close_resource_email(target, project, current_user, method)
-    recipients = reject_muted_users([target.author, target.assignee], project)
-    recipients = recipients.concat(project_watchers(project)).uniq
+    recipients = build_recipients(target, project)
     recipients.delete(current_user)
 
     recipients.each do |recipient|
@@ -312,16 +361,7 @@ class NotificationService
 
   def reassign_resource_email(target, project, current_user, method)
     assignee_id_was = previous_record(target, "assignee_id")
-
-    recipients = User.where(id: [target.assignee_id, assignee_id_was])
-
-    # Add watchers to email list
-    recipients = recipients.concat(project_watchers(project))
-
-    # reject users with disabled notifications
-    recipients = reject_muted_users(recipients, project)
-
-    # Reject me from recipients if I reassign an item
+    recipients = build_recipients(target, project)
     recipients.delete(current_user)
 
     recipients.each do |recipient|
@@ -330,8 +370,7 @@ class NotificationService
   end
 
   def reopen_resource_email(target, project, current_user, method, status)
-    recipients = reject_muted_users([target.author, target.assignee], project)
-    recipients = recipients.concat(project_watchers(project)).uniq
+    recipients = build_recipients(target, project)
     recipients.delete(current_user)
 
     recipients.each do |recipient|
@@ -339,6 +378,22 @@ class NotificationService
     end
   end
 
+  def build_recipients(target, project)
+    recipients =
+      if target.respond_to?(:participants)
+        target.participants
+      else
+        [target.author, target.assignee]
+      end
+
+    recipients = reject_muted_users(recipients, project)
+    recipients = reject_mention_users(recipients, project)
+    recipients = add_subscribed_users(recipients, target)
+    recipients = recipients.concat(project_watchers(project)).uniq
+    recipients = reject_unsubscribed_users(recipients, target)
+    recipients
+  end
+
   def mailer
     Notify.delay
   end
diff --git a/app/services/oauth2/access_token_validation_service.rb b/app/services/oauth2/access_token_validation_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6194f6ce91eb334c30a14e9beba31cd63e4060ec
--- /dev/null
+++ b/app/services/oauth2/access_token_validation_service.rb
@@ -0,0 +1,41 @@
+module Oauth2::AccessTokenValidationService
+  # Results:
+  VALID = :valid
+  EXPIRED = :expired
+  REVOKED = :revoked
+  INSUFFICIENT_SCOPE = :insufficient_scope
+
+  class << self
+    def validate(token, scopes: [])
+      if token.expired?
+        return EXPIRED
+
+      elsif token.revoked?
+        return REVOKED
+
+      elsif !self.sufficient_scope?(token, scopes)
+        return INSUFFICIENT_SCOPE
+
+      else
+        return VALID
+      end
+    end
+
+    protected
+    # True if the token's scope is a superset of required scopes,
+    # or the required scopes is empty.
+    def sufficient_scope?(token, scopes)
+      if scopes.blank?
+        # if no any scopes required, the scopes of token is sufficient.
+        return true
+      else
+        # If there are scopes required, then check whether
+        # the set of authorized scopes is a superset of the set of required scopes
+        required_scopes = Set.new(scopes)
+        authorized_scopes = Set.new(token.scopes)
+
+        return authorized_scopes >= required_scopes
+      end
+    end
+  end
+end
diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7408e09ed1e9df60df177b33cade2521db187cda
--- /dev/null
+++ b/app/services/projects/autocomplete_service.rb
@@ -0,0 +1,15 @@
+module Projects
+  class AutocompleteService < BaseService
+    def initialize(project)
+      @project = project
+    end
+
+    def issues
+      @project.issues.opened.select([:iid, :title])
+    end
+
+    def merge_requests
+      @project.merge_requests.opened.select([:iid, :title])
+    end
+  end
+end
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 12386792aabd3a047e066fb52944c0bc52971196..7ffd0b3882ad747af46e60d7afd99cc44ecef066 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -7,17 +7,25 @@ module Projects
     def execute
       @project = Project.new(params)
 
-      # Reset visibility levet if is not allowed to set it
-      unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
-        @project.visibility_level = default_features.visibility_level
+      # Make sure that the user is allowed to use the specified visibility
+      # level
+      unless Gitlab::VisibilityLevel.allowed_for?(current_user,
+                                                  params[:visibility_level])
+        deny_visibility_level(@project)
+        return @project
       end
 
-      # Parametrize path for project
-      #
-      # Ex.
-      #  'GitLab HQ'.parameterize => "gitlab-hq"
-      #
-      @project.path = @project.name.dup.parameterize unless @project.path.present?
+      # Set project name from path
+      if @project.name.present? && @project.path.present?
+        # if both name and path set - everything is ok
+      elsif @project.path.present?
+        # Set project name from path
+        @project.name = @project.path.dup
+      elsif @project.name.present?
+        # For compatibility - set path from name
+        # TODO: remove this in 8.0
+        @project.path = @project.name.dup.parameterize
+      end
 
       # get namespace id
       namespace_id = params[:namespace_id]
@@ -37,37 +45,18 @@ module Projects
 
       @project.creator = current_user
 
-      if @project.save
-        log_info("#{@project.owner.name} created a new project \"#{@project.name_with_namespace}\"")
-        system_hook_service.execute_hooks_for(@project, :create)
-
-        unless @project.group
-          @project.team << [current_user, :master]
-        end
-
-        @project.update_column(:last_activity_at, @project.created_at)
+      Project.transaction do
+        @project.save
 
-        if @project.import?
-          @project.import_start
-        else
-          GitlabShellWorker.perform_async(
-            :add_repository,
-            @project.path_with_namespace
-          )
-        end
-
-        if @project.wiki_enabled?
-          begin
-            # force the creation of a wiki,
-            ProjectWiki.new(@project, @project.owner).wiki
-          rescue ProjectWiki::CouldNotCreateWikiError => ex
-            # Prevent project observer crash
-            # if failed to create wiki
-            nil
+        unless @project.import?
+          unless @project.create_repository
+            raise 'Failed to create repository'
           end
         end
       end
 
+      after_create_actions if @project.persisted?
+
       @project
     rescue => ex
       @project.errors.add(:base, "Can't save project. Please try again later")
@@ -84,5 +73,24 @@ module Projects
       namespace = Namespace.find_by(id: namespace_id)
       current_user.can?(:create_projects, namespace)
     end
+
+    def after_create_actions
+      log_info("#{@project.owner.name} created a new project \"#{@project.name_with_namespace}\"")
+
+      @project.create_wiki if @project.wiki_enabled?
+
+      event_service.create_project(@project, current_user)
+      system_hook_service.execute_hooks_for(@project, :create)
+
+      unless @project.group
+        @project.team << [current_user, :master]
+      end
+
+      @project.update_column(:last_activity_at, @project.created_at)
+
+      if @project.import?
+        @project.import_start
+      end
+    end
   end
 end
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index a59311bf942da43bdea4c04524ba2e43ca117be4..6b0d4aca3e1a4c7ad63dad2f18bf462f28c571e2 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -2,11 +2,9 @@ module Projects
   class ForkService < BaseService
     include Gitlab::ShellAdapter
 
-    def initialize(project, user)
-      @from_project, @current_user = project, user
-    end
-
     def execute
+      @from_project = @project
+
       project_params = {
         visibility_level: @from_project.visibility_level,
         description: @from_project.description,
@@ -15,8 +13,21 @@ module Projects
       project = Project.new(project_params)
       project.name = @from_project.name
       project.path = @from_project.path
-      project.namespace = current_user.namespace
-      project.creator = current_user
+      project.creator = @current_user
+      if @from_project.avatar.present? && @from_project.avatar.image?
+        project.avatar = @from_project.avatar
+      end
+
+      if namespace = @params[:namespace]
+        project.namespace = namespace
+      else
+        project.namespace = @current_user.namespace
+      end
+
+      unless @current_user.can?(:create_projects, project.namespace)
+        project.errors.add(:namespace, 'insufficient access rights')
+        return project
+      end
 
       # If the project cannot save, we do not want to trigger the project destroy
       # as this can have the side effect of deleting a repo attached to an existing
@@ -27,23 +38,23 @@ module Projects
             #First save the DB entries as they can be rolled back if the repo fork fails
             project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id)
             if project.save
-              project.team << [current_user, :master]
+              project.team << [@current_user, :master]
             end
             #Now fork the repo
             unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path)
-              raise "forking failed in gitlab-shell"
+              raise 'forking failed in gitlab-shell'
             end
             project.ensure_satellite_exists
           end
         rescue => ex
-          project.errors.add(:base, "Fork transaction failed.")
+          project.errors.add(:base, 'Fork transaction failed.')
           project.destroy
         end
       else
-        project.errors.add(:base, "Invalid fork destination")
+        project.errors.add(:base, 'Invalid fork destination')
       end
-      project
 
+      project
     end
   end
 end
diff --git a/app/services/projects/image_service.rb b/app/services/projects/image_service.rb
deleted file mode 100644
index c79ddddd972003fbfb3ec730449ddc9af165f69f..0000000000000000000000000000000000000000
--- a/app/services/projects/image_service.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-module Projects
-  class ImageService < BaseService
-    include Rails.application.routes.url_helpers
-    def initialize(repository, params, root_url)
-      @repository, @params, @root_url = repository, params.dup, root_url
-    end
-
-    def execute
-      uploader = FileUploader.new('uploads', upload_path, accepted_images)
-      image = @params['markdown_img']
-
-      if image && correct_mime_type?(image)
-        alt = image.original_filename
-        uploader.store!(image)
-        link = {
-                 'alt' => File.basename(alt, '.*'),
-                 'url' => File.join(@root_url, uploader.url) 
-               }
-      else
-        link = nil
-      end
-    end
-
-  protected
-
-    def upload_path
-      base_dir = FileUploader.generate_dir
-      File.join(@repository.path_with_namespace, base_dir)
-    end
-
-    def accepted_images
-      %w(png jpg jpeg gif)
-    end
-
-    def correct_mime_type?(image)
-      accepted_images.map{ |format| image.content_type.include? format }.any?
-    end
-  end
-end
diff --git a/app/services/projects/participants_service.rb b/app/services/projects/participants_service.rb
index c4d2c0963b783e329ed24303a560240e3d9e9e6a..bcbacbff5628e9a913a93c1e58681d525f1cd85c 100644
--- a/app/services/projects/participants_service.rb
+++ b/app/services/projects/participants_service.rb
@@ -1,17 +1,19 @@
 module Projects
   class ParticipantsService < BaseService
-    def initialize(project)
-      @project = project
+    def initialize(project, user)
+      @project  = project
+      @user     = user
     end
 
     def execute(note_type, note_id)
-      participating = if note_type && note_id
-                      participants_in(note_type, note_id)
-                    else
-                      []
-                    end
-      team_members = sorted(@project.team.members)
-      participants = all_members + team_members + participating
+      participating =
+        if note_type && note_id
+          participants_in(note_type, note_id)
+        else
+          []
+        end
+      project_members = sorted(@project.team.members)
+      participants = all_members + groups + project_members + participating
       participants.uniq
     end
 
@@ -33,11 +35,21 @@ module Projects
     end
 
     def sorted(users)
-      users.uniq.to_a.compact.sort_by(&:username).map { |user| { username: user.username, name: user.name } }
+      users.uniq.to_a.compact.sort_by(&:username).map do |user| 
+        { username: user.username, name: user.name }
+      end
+    end
+
+    def groups
+      @user.authorized_groups.sort_by(&:path).map do |group| 
+        count = group.users.count
+        { username: group.path, name: "#{group.name} (#{count})" }
+      end
     end
 
     def all_members
-      [{ username: "all", name: "Project and Group Members" }]
+      count = @project.team.members.flatten.count
+      [{ username: "all", name: "All Project and Group Members (#{count})" }]
     end
   end
 end
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index e39fe882cb17e4994fe1d6f0481bccca2af4025e..489e03bd5ef6c256b346e257f5485e3dd72f6bc0 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -12,7 +12,7 @@ module Projects
     class TransferError < StandardError; end
 
     def execute
-      namespace_id = params[:namespace_id]
+      namespace_id = params[:new_namespace_id]
       namespace = Namespace.find_by(id: namespace_id)
 
       if allowed_transfer?(current_user, project, namespace)
@@ -43,6 +43,9 @@ module Projects
         project.namespace = new_namespace
         project.save!
 
+        # Notifications
+        project.send_move_instructions
+
         # Move main repository
         unless gitlab_shell.mv_repository(old_path, new_path)
           raise TransferError.new('Cannot move project')
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 36877a61679d6cb510bf763da96e521e75d9998f..69bdd045ddfeece023c92821cd7d7cdb3cd89853 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -2,8 +2,13 @@ module Projects
   class UpdateService < BaseService
     def execute
       # check that user is allowed to set specified visibility_level
-      unless can?(current_user, :change_visibility_level, project) && Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
-        params[:visibility_level] = project.visibility_level
+      new_visibility = params[:visibility_level]
+      if new_visibility && new_visibility.to_i != project.visibility_level
+        unless can?(current_user, :change_visibility_level, project) &&
+          Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
+          deny_visibility_level(project, new_visibility)
+          return project
+        end
       end
 
       new_branch = params[:default_branch]
diff --git a/app/services/projects/upload_service.rb b/app/services/projects/upload_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a186c97628fce4d8ad5b67df1169dd1d24523bca
--- /dev/null
+++ b/app/services/projects/upload_service.rb
@@ -0,0 +1,22 @@
+module Projects
+  class UploadService < BaseService
+    def initialize(project, file)
+      @project, @file = project, file
+    end
+
+    def execute
+      return nil unless @file
+
+      uploader = FileUploader.new(@project)
+      uploader.store!(@file)
+
+      filename = uploader.image? ? uploader.file.basename : uploader.file.filename
+
+      {
+        'alt'       => filename,
+        'url'       => uploader.secure_url,
+        'is_image'  => uploader.image?
+      }
+    end
+  end
+end
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index 44e494525b350bd5103e1adf22f75f7a47de8a79..c5d0b08845ba79d1c3131f47d3b8a6ba10e9d0c6 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -41,7 +41,7 @@ class SystemHooksService
         path_with_namespace: model.path_with_namespace,
         project_id: model.id,
         owner_name: owner.name,
-        owner_email: owner.respond_to?(:email) ?  owner.email : nil,
+        owner_email: owner.respond_to?(:email) ?  owner.email : "",
         project_visibility: Project.visibility_levels.key(model.visibility_level_field).downcase
       })
     when User
@@ -60,6 +60,26 @@ class SystemHooksService
         access_level: model.human_access,
         project_visibility: Project.visibility_levels.key(model.project.visibility_level_field).downcase
       })
+    when Group
+      owner = model.owner
+
+      data.merge!(
+        name: model.name,
+        path: model.path,
+        group_id: model.id,
+        owner_name: owner.respond_to?(:name) ? owner.name : nil,
+        owner_email: owner.respond_to?(:email) ? owner.email : nil,
+      )
+    when GroupMember
+      data.merge!(
+        group_name: model.group.name,
+        group_path: model.group.path,
+        group_id: model.group.id,
+        user_name: model.user.name,
+        user_email: model.user.email,
+        user_id: model.user.id,
+        group_access: model.human_access,
+      )
     end
   end
 
@@ -68,6 +88,9 @@ class SystemHooksService
     when ProjectMember
       return "user_add_to_team"      if event == :create
       return "user_remove_from_team" if event == :destroy
+    when GroupMember
+      return 'user_add_to_group'      if event == :create
+      return 'user_remove_from_group' if event == :destroy
     else
       "#{model.class.name.downcase}_#{event.to_s}"
     end
diff --git a/app/services/test_hook_service.rb b/app/services/test_hook_service.rb
index b6b1ef29b51840cc4038c9681d07be6381652d71..21ec2c01cb86a43c6223a41f95bf87c540a713aa 100644
--- a/app/services/test_hook_service.rb
+++ b/app/services/test_hook_service.rb
@@ -1,9 +1,6 @@
 class TestHookService
   def execute(hook, current_user)
-    data = GitPushService.new.sample_data(hook.project, current_user)
+    data = Gitlab::PushDataBuilder.build_sample(hook.project, current_user)
     hook.execute(data)
-    true
-  rescue SocketError
-    false
   end
 end
diff --git a/app/services/update_snippet_service.rb b/app/services/update_snippet_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9d181c2d2aba1d3edaaa84cbe37c129105feea2a
--- /dev/null
+++ b/app/services/update_snippet_service.rb
@@ -0,0 +1,22 @@
+class UpdateSnippetService < BaseService
+  attr_accessor :snippet
+
+  def initialize(project, user, snippet, params)
+    super(project, user, params)
+    @snippet = snippet
+  end
+
+  def execute
+    # check that user is allowed to set specified visibility_level
+    new_visibility = params[:visibility_level]
+    if new_visibility && new_visibility.to_i != snippet.visibility_level
+      unless can?(current_user, :change_visibility_level, snippet) &&
+        Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
+        deny_visibility_level(snippet, new_visibility)
+        return snippet
+      end
+    end
+
+    snippet.update_attributes(params)
+  end
+end
diff --git a/app/uploaders/attachment_uploader.rb b/app/uploaders/attachment_uploader.rb
index 29a55b36ca5a94657516c50d346ef1d67a322634..a9691bee46e23f20eca66b96e0577b700769b0e1 100644
--- a/app/uploaders/attachment_uploader.rb
+++ b/app/uploaders/attachment_uploader.rb
@@ -3,8 +3,6 @@
 class AttachmentUploader < CarrierWave::Uploader::Base
   storage :file
 
-  after :store, :reset_events_cache
-
   def store_dir
     "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
   end
@@ -22,19 +20,7 @@ class AttachmentUploader < CarrierWave::Uploader::Base
     false
   end
 
-  def secure_url
-    Gitlab.config.gitlab.relative_url_root + "/files/#{model.class.to_s.underscore}/#{model.id}/#{file.filename}"
-  end
-
-  def url
-    Gitlab.config.gitlab.relative_url_root + super unless super.nil?
-  end
-
   def file_storage?
     self.class.storage == CarrierWave::Storage::File
   end
-
-  def reset_events_cache(file)
-    model.reset_events_cache if model.is_a?(User)
-  end
 end
diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7cad044555b1aeae2eacba6b7eb57386fdf565b8
--- /dev/null
+++ b/app/uploaders/avatar_uploader.rb
@@ -0,0 +1,32 @@
+# encoding: utf-8
+
+class AvatarUploader < CarrierWave::Uploader::Base
+  storage :file
+
+  after :store, :reset_events_cache
+
+  def store_dir
+    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
+  end
+
+  def image?
+    img_ext = %w(png jpg jpeg gif bmp tiff)
+    if file.respond_to?(:extension)
+      img_ext.include?(file.extension.downcase)
+    else
+      # Not all CarrierWave storages respond to :extension
+      ext = file.path.split('.').last.downcase
+      img_ext.include?(ext)
+    end
+  rescue
+    false
+  end
+
+  def file_storage?
+    self.class.storage == CarrierWave::Storage::File
+  end
+
+  def reset_events_cache(file)
+    model.reset_events_cache if model.is_a?(User)
+  end
+end
diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb
index 0fa987c93f641fdcfaa194833cbc6ca0e8945342..f9673abbfe8a5d0f1ea0d4b6a176c2be373a4128 100644
--- a/app/uploaders/file_uploader.rb
+++ b/app/uploaders/file_uploader.rb
@@ -2,40 +2,47 @@
 class FileUploader < CarrierWave::Uploader::Base
   storage :file
 
-  def initialize(base_dir, path = '', allowed_extensions = nil)
-    @base_dir = base_dir
-    @path = path
-    @allowed_extensions = allowed_extensions
+  attr_accessor :project, :secret
+
+  def initialize(project, secret = self.class.generate_secret)
+    @project = project
+    @secret = secret
   end
 
   def base_dir
-    @base_dir
+    "uploads"
   end
 
   def store_dir
-    File.join(@base_dir, @path)
+    File.join(base_dir, @project.path_with_namespace, @secret)
   end
 
   def cache_dir
-    File.join(@base_dir, 'tmp', @path)
+    File.join(base_dir, 'tmp', @project.path_with_namespace, @secret)
   end
 
-  def extension_white_list
-    @allowed_extensions
+  def self.generate_secret
+    SecureRandom.hex
   end
 
-  def store!(file)
-    @filename = self.class.generate_filename(file)
-    super
+  def secure_url
+    File.join(Gitlab.config.gitlab.url, @project.path_with_namespace, "uploads", @secret, file.filename)
   end
 
-  def self.generate_filename(file)
-    original_filename = File.basename(file.original_filename, '.*')
-    extension = File.extname(file.original_filename)
-    new_filename = Digest::MD5.hexdigest(original_filename) + extension
+  def file_storage?
+    self.class.storage == CarrierWave::Storage::File
   end
 
-  def self.generate_dir
-    SecureRandom.hex(5)
+  def image?
+    img_ext = %w(png jpg jpeg gif bmp tiff)
+    if file.respond_to?(:extension)
+      img_ext.include?(file.extension.downcase)
+    else
+      # Not all CarrierWave storages respond to :extension
+      ext = file.path.split('.').last.downcase
+      img_ext.include?(ext)
+    end
+  rescue
+    false
   end
 end
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..edfcccfcf4cfe7fec302b12b27050038f4d53a41
--- /dev/null
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -0,0 +1,64 @@
+= form_for @application_setting, url: admin_application_settings_path, html: { class: 'form-horizontal fieldset-form' } do |f|
+  - if @application_setting.errors.any?
+    #error_explanation
+      .alert.alert-danger
+        - @application_setting.errors.full_messages.each do |msg|
+          %p= msg
+
+  %fieldset
+    %legend Features
+    .form-group
+      .col-sm-offset-2.col-sm-10
+        .checkbox
+          = f.label :signup_enabled do
+            = f.check_box :signup_enabled
+            Signup enabled
+    .form-group
+      .col-sm-offset-2.col-sm-10
+        .checkbox
+          = f.label :signin_enabled do
+            = f.check_box :signin_enabled
+            Signin enabled
+    .form-group
+      .col-sm-offset-2.col-sm-10
+        .checkbox
+          = f.label :gravatar_enabled do
+            = f.check_box :gravatar_enabled
+            Gravatar enabled
+    .form-group
+      .col-sm-offset-2.col-sm-10
+        .checkbox
+          = f.label :twitter_sharing_enabled do
+            = f.check_box :twitter_sharing_enabled, :'aria-describedby' => 'twitter_help_block'
+            %strong Twitter enabled
+          %span.help-block#twitter_help_block Show users a button to share their newly created public or internal projects on twitter
+  %fieldset
+    %legend Misc
+    .form-group
+      = f.label :default_projects_limit, class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.number_field :default_projects_limit, class: 'form-control'
+    .form-group
+      = f.label :default_branch_protection, class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control'
+    .form-group
+      = f.label :restricted_visibility_levels, class: 'control-label col-sm-2'
+      .col-sm-10
+        - data_attrs = { toggle: 'buttons' }
+        .btn-group{ data: data_attrs }
+          - restricted_level_checkboxes('restricted-visibility-help').each do |level|
+            = level
+        %span.help-block#restricted-visibility-help Selected levels cannot be used by non-admin users for projects or snippets
+    .form-group
+      = f.label :home_page_url, class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.text_field :home_page_url, class: 'form-control', placeholder: 'http://company.example.com', :'aria-describedby' => 'home_help_block'
+        %span.help-block#home_help_block We will redirect non-logged in users to this page
+    .form-group
+      = f.label :sign_in_text, class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.text_area :sign_in_text, class: 'form-control', rows: 4
+        .help-block Markdown enabled
+  .form-actions
+    = f.submit 'Save', class: 'btn btn-primary'
diff --git a/app/views/admin/application_settings/show.html.haml b/app/views/admin/application_settings/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..39b66647a5a878754f9afc1ac642ab387d9c91db
--- /dev/null
+++ b/app/views/admin/application_settings/show.html.haml
@@ -0,0 +1,3 @@
+%h3.page-title Application settings
+%hr
+= render 'form'
diff --git a/app/views/admin/applications/_delete_form.html.haml b/app/views/admin/applications/_delete_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..3147cbd659f20a3efec6beee52498e3cd8feb8f3
--- /dev/null
+++ b/app/views/admin/applications/_delete_form.html.haml
@@ -0,0 +1,4 @@
+- submit_btn_css ||= 'btn btn-link btn-remove btn-sm'
+= form_tag admin_application_path(application) do
+  %input{:name => "_method", :type => "hidden", :value => "delete"}/
+  = submit_tag 'Destroy', onclick: "return confirm('Are you sure?')", class: submit_btn_css
\ No newline at end of file
diff --git a/app/views/admin/applications/_form.html.haml b/app/views/admin/applications/_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..b77d188a38d5053062d7fda5eab4dd4e601a09bb
--- /dev/null
+++ b/app/views/admin/applications/_form.html.haml
@@ -0,0 +1,24 @@
+= form_for [:admin, @application], url: @url, html: {class: 'form-horizontal', role: 'form'} do |f|
+  - if application.errors.any?
+    .alert.alert-danger{"data-alert" => ""}
+      %p Whoops! Check your form for possible errors
+  = content_tag :div, class: "form-group#{' has-error' if application.errors[:name].present?}" do
+    = f.label :name, class: 'col-sm-2 control-label'
+    .col-sm-10
+      = f.text_field :name, class: 'form-control'
+      = doorkeeper_errors_for application, :name
+  = content_tag :div, class: "form-group#{' has-error' if application.errors[:redirect_uri].present?}" do
+    = f.label :redirect_uri, class: 'col-sm-2 control-label'
+    .col-sm-10
+      = f.text_area :redirect_uri, class: 'form-control'
+      = doorkeeper_errors_for application, :redirect_uri
+      %span.help-block
+        Use one line per URI
+      - if Doorkeeper.configuration.native_redirect_uri
+        %span.help-block
+          Use
+          %code= Doorkeeper.configuration.native_redirect_uri
+          for local tests
+  .form-actions
+    = f.submit 'Submit', class: "btn btn-primary wide"
+    = link_to "Cancel", admin_applications_path, class: "btn btn-default"
diff --git a/app/views/admin/applications/edit.html.haml b/app/views/admin/applications/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..e408ae2f29d0647bae76bf1c039e33ec525ff34a
--- /dev/null
+++ b/app/views/admin/applications/edit.html.haml
@@ -0,0 +1,3 @@
+%h3.page-title Edit application
+- @url = admin_application_path(@application)
+= render 'form', application: @application
\ No newline at end of file
diff --git a/app/views/admin/applications/index.html.haml b/app/views/admin/applications/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..d550278710ebeaf8555308eb868cf9e34f83d55b
--- /dev/null
+++ b/app/views/admin/applications/index.html.haml
@@ -0,0 +1,22 @@
+%h3.page-title
+  System OAuth applications
+%p.light
+  System OAuth application does not belong to certain user and can be managed only by admins
+%hr
+%p= link_to 'New Application', new_admin_application_path, class: 'btn btn-success'
+%table.table.table-striped
+  %thead
+    %tr
+      %th Name
+      %th Callback URL
+      %th Clients
+      %th
+      %th
+  %tbody.oauth-applications
+    - @applications.each do |application|
+      %tr{:id => "application_#{application.id}"}
+        %td= link_to application.name, admin_application_path(application)
+        %td= application.redirect_uri
+        %td= application.access_tokens.map(&:resource_owner_id).uniq.count
+        %td= link_to 'Edit', edit_admin_application_path(application), class: 'btn btn-link'
+        %td= render 'delete_form', application: application
diff --git a/app/views/admin/applications/new.html.haml b/app/views/admin/applications/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..7c62425f19c94bd3bee5c05d9ed9a944b0a2b1a4
--- /dev/null
+++ b/app/views/admin/applications/new.html.haml
@@ -0,0 +1,3 @@
+%h3.page-title New application
+- @url = admin_applications_path
+= render 'form', application: @application
\ No newline at end of file
diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..2abe390ce13e7b853e11d7c6f28766375dd2c1d6
--- /dev/null
+++ b/app/views/admin/applications/show.html.haml
@@ -0,0 +1,26 @@
+%h3.page-title
+  Application: #{@application.name}
+
+
+%table.table
+  %tr
+    %td
+      Application Id
+    %td
+      %code#application_id= @application.uid
+  %tr
+    %td
+      Secret:
+    %td
+      %code#secret= @application.secret
+
+  %tr
+    %td
+      Callback url
+    %td
+      - @application.redirect_uri.split.each do |uri|
+        %div
+          %span.monospace= uri
+.form-actions
+  = link_to 'Edit', edit_admin_application_path(@application), class: 'btn btn-primary wide pull-left'
+  = render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10'
diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml
index 7b483ee65565308e58aeac49244221560a1d5abb..7e29311bf42c6f8d7cf8a6f18f362a11af4ef902 100644
--- a/app/views/admin/broadcast_messages/index.html.haml
+++ b/app/views/admin/broadcast_messages/index.html.haml
@@ -21,13 +21,11 @@
   .form-group.js-toggle-colors-container.hide
     = f.label :color, "Background Color", class: 'control-label'
     .col-sm-10
-      = f.text_field :color, placeholder: "#AA33EE", class: "form-control"
-      .light 6 character hex values starting with a # sign.
+      = f.color_field :color, value: "#AA33EE", class: "form-control"
   .form-group.js-toggle-colors-container.hide
     = f.label :font, "Font Color", class: 'control-label'
     .col-sm-10
-      = f.text_field :font, placeholder: "#224466", class: "form-control"
-      .light 6 character hex values starting with a # sign.
+      = f.color_field :font, value: "#224466", class: "form-control"
   .form-group
     = f.label :starts_at, class: 'control-label'
     .col-sm-10.datetime-controls
@@ -52,7 +50,7 @@
             %strong
               #{broadcast_message.ends_at.to_s(:short)}
           &nbsp;
-          = link_to [:admin, broadcast_message], method: :delete, remote: true, class: 'remove-row btn btn-tiny' do
+          = link_to [:admin, broadcast_message], method: :delete, remote: true, class: 'remove-row btn btn-xs' do
             %i.fa.fa-times.cred
 
         .message= broadcast_message.message
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 7427cea7e8b66bc9fa69ca4f6c677c159e9174cc..d1c586328a26abf645b9a3b65b1e3f7b43a3f8e8 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -1,69 +1,7 @@
-%h3.page-title
-  Admin area
-%p.light
-  You can manage projects, users and other GitLab data from here.
-%hr
 .admin-dashboard
-  .row
-    .col-sm-4
-      .light-well
-        %h4 Projects
-        .data
-          = link_to admin_projects_path do
-            %h1= Project.count
-          %hr
-          = link_to 'New Project', new_project_path, class: "btn btn-new"
-    .col-sm-4
-      .light-well
-        %h4 Users
-        .data
-          = link_to admin_users_path do
-            %h1= User.count
-          %hr
-          = link_to 'New User', new_admin_user_path, class: "btn btn-new"
-    .col-sm-4
-      .light-well
-        %h4 Groups
-        .data
-          = link_to admin_groups_path do
-            %h1= Group.count
-          %hr
-          = link_to 'New Group', new_admin_group_path, class: "btn btn-new"
-
-  .row.prepend-top-10
-    .col-md-4
-      %h4 Latest projects
-      %hr
-      - @projects.each do |project|
-        %p
-          = link_to project.name_with_namespace, [:admin, project], class: 'str-truncated'
-          %span.light.pull-right
-            #{time_ago_with_tooltip(project.created_at)}
-
-    .col-md-4
-      %h4 Latest users
-      %hr
-      - @users.each do |user|
-        %p
-          = link_to [:admin, user], class: 'str-truncated' do
-            = user.name
-          %span.light.pull-right
-            #{time_ago_with_tooltip(user.created_at)}
-
-    .col-md-4
-      %h4 Latest groups
-      %hr
-      - @groups.each do |group|
-        %p
-          = link_to [:admin, group], class: 'str-truncated' do
-            = group.name
-          %span.light.pull-right
-            #{time_ago_with_tooltip(group.created_at)}
-
-  %br
   .row
     .col-md-4
-      %h4 Stats
+      %h4 Statistics
       %hr
       %p
         Forks
@@ -94,9 +32,9 @@
         %span.light.pull-right
           = Milestone.count
       %p
-        Active users last 30 days
+        Active Users
         %span.light.pull-right
-          = User.where("current_sign_in_at > ?", 30.days.ago).count
+          = User.active.count
     .col-md-4
       %h4
         Features
@@ -104,7 +42,7 @@
       %p
         Sign up
         %span.light.pull-right
-          = boolean_to_icon gitlab_config.signup_enabled
+          = boolean_to_icon signup_enabled?
       %p
         LDAP
         %span.light.pull-right
@@ -112,7 +50,7 @@
       %p
         Gravatar
         %span.light.pull-right
-          = boolean_to_icon Gitlab.config.gravatar.enabled
+          = boolean_to_icon gravatar_enabled?
       %p
         OmniAuth
         %span.light.pull-right
@@ -141,3 +79,59 @@
         Rails
         %span.pull-right
           #{Rails::VERSION::STRING}
+  %hr
+  .row
+    .col-sm-4
+      .light-well
+        %h4 Projects
+        .data
+          = link_to admin_namespaces_projects_path do
+            %h1= Project.count
+          %hr
+          = link_to('New Project', new_project_path, class: "btn btn-new")
+    .col-sm-4
+      .light-well
+        %h4 Users
+        .data
+          = link_to admin_users_path do
+            %h1= User.count
+          %hr
+          = link_to 'New User', new_admin_user_path, class: "btn btn-new"
+    .col-sm-4
+      .light-well
+        %h4 Groups
+        .data
+          = link_to admin_groups_path do
+            %h1= Group.count
+          %hr
+          = link_to 'New Group', new_admin_group_path, class: "btn btn-new"
+
+  .row.prepend-top-10
+    .col-md-4
+      %h4 Latest projects
+      %hr
+      - @projects.each do |project|
+        %p
+          = link_to project.name_with_namespace, [:admin, project.namespace.becomes(Namespace), project], class: 'str-truncated'
+          %span.light.pull-right
+            #{time_ago_with_tooltip(project.created_at)}
+
+    .col-md-4
+      %h4 Latest users
+      %hr
+      - @users.each do |user|
+        %p
+          = link_to [:admin, user], class: 'str-truncated' do
+            = user.name
+          %span.light.pull-right
+            #{time_ago_with_tooltip(user.created_at)}
+
+    .col-md-4
+      %h4 Latest groups
+      %hr
+      - @groups.each do |group|
+        %p
+          = link_to [:admin, group], class: 'str-truncated' do
+            = group.name
+          %span.light.pull-right
+            #{time_ago_with_tooltip(group.created_at)}
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index f4d7e25fd74ecabfe2b9680d9e23c1da6a81dcf2..9e7751830a4477d972ae68484a8d8466d076c3ae 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -14,24 +14,13 @@
     .form-group
       .col-sm-2
       .col-sm-10
-        .bs-callout.bs-callout-info
+        .alert.alert-info
           = render 'shared/group_tips'
     .form-actions
       = f.submit 'Create group', class: "btn btn-create"
       = link_to  'Cancel', admin_groups_path, class: "btn btn-cancel"
 
   - else
-    .form-group.group_name_holder
-      = f.label :path, class: 'control-label' do
-        %span Group path
-      .col-sm-10
-        = f.text_field :path, placeholder: "example-group", class: "form-control danger"
-        .bs-callout.bs-callout-danger
-          %ul
-            %li Changing group path can have unintended side effects.
-            %li Renaming group path will rename directory for all related projects
-            %li It will change web url for access group and group projects.
-            %li It will change the git path to repositories under this group.
     .form-actions
       = f.submit 'Save changes', class: "btn btn-primary"
       = link_to  'Cancel', admin_group_path(@group), class: "btn btn-cancel"
diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml
index 1d7fef43184b5fabaeafda924f22a99f05b95e02..4c53ff55708790a7d5e5a9e47df5c3fe91086668 100644
--- a/app/views/admin/groups/index.html.haml
+++ b/app/views/admin/groups/index.html.haml
@@ -8,10 +8,31 @@
 
 %hr
 = form_tag admin_groups_path, method: :get, class: 'form-inline' do
+  = hidden_field_tag :sort, @sort
   .form-group
     = text_field_tag :name, params[:name], class: "form-control input-mn-300"
   = button_tag "Search", class: "btn submit btn-primary"
 
+  .pull-right
+    .dropdown.inline
+      %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
+        %span.light sort:
+        - if @sort.present?
+          = sort_options_hash[@sort]
+        - else
+          = sort_title_recently_created
+        %b.caret
+      %ul.dropdown-menu
+        %li
+          = link_to admin_groups_path(sort: sort_value_recently_created) do
+            = sort_title_recently_created
+          = link_to admin_groups_path(sort: sort_value_oldest_created) do
+            = sort_title_oldest_created
+          = link_to admin_groups_path(sort: sort_value_recently_updated) do
+            = sort_title_recently_updated
+          = link_to admin_groups_path(sort: sort_value_oldest_updated) do
+            = sort_title_oldest_updated
+
 %hr
 
 %ul.bordered-list
@@ -19,8 +40,8 @@
     %li
       .clearfix
         .pull-right.prepend-top-10
-          = link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small"
-          = link_to 'Destroy', [:admin, group], data: {confirm: "REMOVE #{group.name}? Are you sure?"}, method: :delete, class: "btn btn-small btn-remove"
+          = link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-sm"
+          = link_to 'Destroy', [:admin, group], data: {confirm: "REMOVE #{group.name}? Are you sure?"}, method: :delete, class: "btn btn-sm btn-remove"
 
         %h4
           = link_to [:admin, group] do
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 8057de38805e7b2ce2fd5834c64d6fd3dff6d66e..7d292118075efa50b0b60e858f78849ea3c3349b 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -12,7 +12,7 @@
         Group info:
       %ul.well-list
         %li
-          = image_tag group_icon(@group.path), class: "avatar s60"
+          = image_tag group_icon(@group), class: "avatar s60"
         %li
           %span.light Name:
           %strong= @group.name
@@ -41,7 +41,7 @@
         - @projects.each do |project|
           %li
             %strong
-              = link_to project.name_with_namespace, [:admin, project]
+              = link_to project.name_with_namespace, [:admin, project.namespace.becomes(Namespace), project]
               %span.label.label-gray
                 = repository_size(project)
             %span.pull-right.light
@@ -58,13 +58,13 @@
           Read more about project permissions
           %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
 
-        = form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put  do
+        = form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put  do
           %div
             = users_select_tag(:user_ids, multiple: true)
           %div.prepend-top-10
             = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2"
           %hr
-          = button_tag 'Add users into group', class: "btn btn-create"
+          = button_tag 'Add users to group', class: "btn btn-create"
     .panel.panel-default
       .panel-heading
         %h3.panel-title
@@ -80,7 +80,7 @@
                 = link_to user.name, admin_user_path(user)
             %span.pull-right.light
               = member.human_access
-              = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
+              = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do
                 %i.fa.fa-minus.fa-inverse
       .panel-footer
         = paginate @members, param_name: 'members_page', theme: 'gitlab'
diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index 0c5db0805f9972dbcc40ef0da40a80a86fc73193..7a9dc113f2a93df806c6aa1d3c6b28c69020f8e1 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -33,5 +33,5 @@
               %strong= hook.url
 
           .pull-right
-            = link_to 'Test Hook', admin_hook_test_path(hook), class: "btn btn-small"
-            = link_to 'Remove', admin_hook_path(hook), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-remove btn-small"
+            = link_to 'Test Hook', admin_hook_test_path(hook), class: "btn btn-sm"
+            = link_to 'Remove', admin_hook_path(hook), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-remove btn-sm"
diff --git a/app/views/admin/keys/show.html.haml b/app/views/admin/keys/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..5b23027b3abdbee6c68b0589bf846054c37a5b5e
--- /dev/null
+++ b/app/views/admin/keys/show.html.haml
@@ -0,0 +1 @@
+= render "profiles/keys/key_details", admin: true
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index 2cd6b12be7f47c6fc0ee17a6c16e494702cabdb2..3bbe10bc270ca0ef8977b835a94f96d6172f0df8 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -1,7 +1,9 @@
 .row
-  .col-md-3
+  = link_to '#aside', class: 'show-aside' do
+    %i.fa.fa-angle-left
+  %aside.col-md-3
     .admin-filter
-      = form_tag admin_projects_path, method: :get, class: '' do
+      = form_tag admin_namespaces_projects_path, method: :get, class: '' do
         .form-group
           = label_tag :name, 'Name:'
           = text_field_tag :name, params[:name], class: "form-control"
@@ -13,15 +15,13 @@
         .form-group
           %strong Activity
           .checkbox
-            = label_tag :with_push, 'Not empty'
-            = check_box_tag :with_push, 1, params[:with_push]
-            &nbsp;
-            %span.light Projects with push events
+            = label_tag :with_push do
+              = check_box_tag :with_push, 1, params[:with_push]
+              %span Projects with push events
           .checkbox
-            = label_tag :abandoned, 'Abandoned'
-            = check_box_tag :abandoned, 1, params[:abandoned]
-            &nbsp;
-            %span.light No activity over 6 month
+            = label_tag :abandoned do
+              = check_box_tag :abandoned, 1, params[:abandoned]
+              %span No activity over 6 month
 
         %fieldset
           %strong Visibility level:
@@ -36,48 +36,46 @@
         %hr
         = hidden_field_tag :sort, params[:sort]
         = button_tag "Search", class: "btn submit btn-primary"
-        = link_to "Reset", admin_projects_path, class: "btn btn-cancel"
+        = link_to "Reset", admin_namespaces_projects_path, class: "btn btn-cancel"
 
-  .col-md-9
+  %section.col-md-9
     .panel.panel-default
       .panel-heading
         Projects (#{@projects.total_count})
         .panel-head-actions
           .dropdown.inline
-            %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
+            %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'}
               %span.light sort:
               - if @sort.present?
-                = @sort.humanize
+                = sort_options_hash[@sort]
               - else
-                Name
+                = sort_title_recently_created
               %b.caret
             %ul.dropdown-menu
               %li
-                = link_to admin_projects_path(sort: nil) do
-                  Name
-                = link_to admin_projects_path(sort: 'newest') do
-                  Newest
-                = link_to admin_projects_path(sort: 'oldest') do
-                  Oldest
-                = link_to admin_projects_path(sort: 'recently_updated') do
-                  Recently updated
-                = link_to admin_projects_path(sort: 'last_updated') do
-                  Last updated
-                = link_to admin_projects_path(sort: 'largest_repository') do
-                  Largest repository
-          = link_to 'New Project', new_project_path, class: "btn btn-new"
+                = link_to admin_namespaces_projects_path(sort: sort_value_recently_created) do
+                  = sort_title_recently_created
+                = link_to admin_namespaces_projects_path(sort: sort_value_oldest_created) do
+                  = sort_title_oldest_created
+                = link_to admin_namespaces_projects_path(sort: sort_value_recently_updated) do
+                  = sort_title_recently_updated
+                = link_to admin_namespaces_projects_path(sort: sort_value_oldest_updated) do
+                  = sort_title_oldest_updated
+                = link_to admin_namespaces_projects_path(sort: sort_value_largest_repo) do
+                  = sort_title_largest_repo
+          = link_to 'New Project', new_project_path, class: "btn btn-sm btn-success"
       %ul.well-list
         - @projects.each do |project|
           %li
             .list-item-name
               %span{ class: visibility_level_color(project.visibility_level) }
                 = visibility_level_icon(project.visibility_level)
-              = link_to project.name_with_namespace, [:admin, project]
+              = link_to project.name_with_namespace, [:admin, project.namespace.becomes(Namespace), project]
             .pull-right
               %span.label.label-gray
                 = repository_size(project)
-              = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
-              = link_to 'Destroy', [project], data: { confirm: remove_project_message(project) }, method: :delete, class: "btn btn-small btn-remove"
+              = link_to 'Edit', edit_namespace_project_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn btn-sm"
+              = link_to 'Destroy', [project.namespace.becomes(Namespace), project], data: { confirm: remove_project_message(project) }, method: :delete, class: "btn btn-sm btn-remove"
         - if @projects.blank?
           .nothing-here-block 0 projects matches
     = paginate @projects, theme: "gitlab"
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 6d5361998518d5ce068faa561eea40b70b3744f7..05372f4124fb1f8a925905bc7c6fe1a868cf4dbd 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -68,6 +68,11 @@
             %strong.cred
               does not exist
 
+        - if @project.archived?
+          %li
+            %span.light archived:
+            %strong repository is read-only
+
         %li
           %span.light access:
           %strong
@@ -79,11 +84,11 @@
       .panel-heading
         Transfer project
       .panel-body
-        = form_for @project, url: transfer_admin_project_path(@project), method: :put, html: { class: 'form-horizontal' } do |f|
+        = form_for @project, url: transfer_admin_namespace_project_path(@project.namespace, @project), method: :put, html: { class: 'form-horizontal' } do |f|
           .form-group
-            = f.label :namespace_id, "Namespace", class: 'control-label'
+            = f.label :new_namespace_id, "Namespace", class: 'control-label'
             .col-sm-10
-              = namespace_select_tag :namespace_id, selected: params[:namespace_id], class: 'input-large'
+              = namespace_select_tag :new_namespace_id, selected: params[:namespace_id], class: 'input-large'
 
           .form-group
             .col-sm-2
@@ -97,7 +102,7 @@
           %strong #{@group.name}
           group members (#{@group.group_members.count})
           .pull-right
-            = link_to admin_group_path(@group), class: 'btn btn-small' do
+            = link_to admin_group_path(@group), class: 'btn btn-xs' do
               %i.fa.fa-pencil-square-o
         %ul.well-list
           - @group_members.each do |member|
@@ -111,10 +116,10 @@
         %small
           (#{@project.users.count})
         .pull-right
-          = link_to project_team_index_path(@project), class: "btn btn-tiny" do
+          = link_to namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-xs" do
             %i.fa.fa-pencil-square-o
             Manage Access
-      %ul.well-list.team_members
+      %ul.well-list.project_members
         - @project_members.each do |project_member|
           - user = project_member.user
           %li.project_member
@@ -126,7 +131,7 @@
                 %span.light Owner
               - else
                 %span.light= project_member.human_access
-                = link_to project_team_member_path(@project, user), data: { confirm: remove_from_project_team_message(@project, user)}, method: :delete, remote: true, class: "btn btn-small btn-remove" do
+                = link_to namespace_project_project_member_path(@project.namespace, @project, user), data: { confirm: remove_from_project_team_message(@project, user)}, method: :delete, remote: true, class: "btn btn-sm btn-remove" do
                   %i.fa.fa-times
       .panel-footer
         = paginate @project_members, param_name: 'project_members_page', theme: 'gitlab'
diff --git a/app/views/admin/services/_form.html.haml b/app/views/admin/services/_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..eb7a099bfe266dd46051dbdc7a44d36a9a29dc42
--- /dev/null
+++ b/app/views/admin/services/_form.html.haml
@@ -0,0 +1,94 @@
+%h3.page-title
+  = @service.title
+
+%p #{@service.description} template
+
+= form_for :service, url: admin_application_settings_service_path, method: :put, html: { class: 'form-horizontal fieldset-form' } do |f|
+  - if @service.errors.any?
+    #error_explanation
+      .alert.alert-danger
+        - @service.errors.full_messages.each do |msg|
+          %p= msg
+  - if @service.help.present?
+    .well
+      = preserve do
+        = markdown @service.help
+
+  .form-group
+    = f.label :active, "Active", class: "control-label"
+    .col-sm-10
+      = f.check_box :active
+
+  - if @service.supported_events.length > 1
+    .form-group
+      = f.label :url, "Trigger", class: 'control-label'
+      .col-sm-10
+        - if @service.supported_events.include?("push")
+          %div
+            = f.check_box :push_events, class: 'pull-left'
+            .prepend-left-20
+              = f.label :push_events, class: 'list-label' do
+                %strong Push events
+              %p.light
+                This url will be triggered by a push to the repository
+        - if @service.supported_events.include?("tag_push")
+          %div
+            = f.check_box :tag_push_events, class: 'pull-left'
+            .prepend-left-20
+              = f.label :tag_push_events, class: 'list-label' do
+                %strong Tag push events
+              %p.light
+                This url will be triggered when a new tag is pushed to the repository
+        - if @service.supported_events.include?("note")
+          %div
+            = f.check_box :note_events, class: 'pull-left'
+            .prepend-left-20
+              = f.label :note_events, class: 'list-label' do
+                %strong Comments
+              %p.light
+                This url will be triggered when someone adds a comment
+        - if @service.supported_events.include?("issue")
+          %div
+            = f.check_box :issues_events, class: 'pull-left'
+            .prepend-left-20
+              = f.label :issues_events, class: 'list-label' do
+                %strong Issues events
+              %p.light
+                This url will be triggered when an issue is created
+        - if @service.supported_events.include?("merge_request")
+          %div
+            = f.check_box :merge_requests_events, class: 'pull-left'
+            .prepend-left-20
+              = f.label :merge_requests_events, class: 'list-label' do
+                %strong Merge Request events
+              %p.light
+                This url will be triggered when a merge request is created
+
+  - @service.fields.each do |field|
+    - name = field[:name]
+    - title = field[:title] || name.humanize
+    - value = @service.send(name) unless field[:type] == 'password'
+    - type = field[:type]
+    - placeholder = field[:placeholder]
+    - choices = field[:choices]
+    - default_choice = field[:default_choice]
+    - help = field[:help]
+
+    .form-group
+      = f.label name, title, class: "control-label"
+      .col-sm-10
+        - if type == 'text'
+          = f.text_field name, class: "form-control", placeholder: placeholder
+        - elsif type == 'textarea'
+          = f.text_area name, rows: 5, class: "form-control", placeholder: placeholder
+        - elsif type == 'checkbox'
+          = f.check_box name
+        - elsif type == 'select'
+          = f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" }
+        - elsif type == 'password'
+          = f.password_field name, class: 'form-control'
+        - if help
+          %span.help-block= help
+
+  .form-actions
+    = f.submit 'Save', class: 'btn btn-save'
diff --git a/app/views/admin/services/edit.html.haml b/app/views/admin/services/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..bcc5832792fea10b70d29a9fb15633f06e001dd0
--- /dev/null
+++ b/app/views/admin/services/edit.html.haml
@@ -0,0 +1 @@
+= render 'form'
diff --git a/app/views/admin/services/index.html.haml b/app/views/admin/services/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..0093fb97765b7aa30666f1540a3c8ff74688eb4f
--- /dev/null
+++ b/app/views/admin/services/index.html.haml
@@ -0,0 +1,22 @@
+%h3.page-title Service templates
+%p.light Service template allows you to set default values for project services
+
+%table.table
+  %thead
+    %tr
+      %th
+      %th Service
+      %th Description
+      %th Last edit
+  - @services.sort_by(&:title).each do |service|
+    %tr
+      %td
+        = icon("copy", class: 'clgray')
+      %td
+        = link_to edit_admin_application_settings_service_path(service.id) do
+          %strong= service.title
+      %td
+        = service.description
+      %td.light
+        = time_ago_in_words service.updated_at
+        ago
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index 92c619738a23dcdec8574c8789588a21d1d0039b..25c1730ef70ef93259aef634e0a8ca9582756505 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -1,5 +1,7 @@
 .row
-  .col-md-3
+  = link_to '#aside', class: 'show-aside' do
+    %i.fa.fa-angle-left
+  %aside.col-md-3
     .admin-filter
       %ul.nav.nav-pills.nav-stacked
         %li{class: "#{'active' unless params[:filter]}"}
@@ -27,32 +29,37 @@
       %hr
       = link_to 'Reset', admin_users_path, class: "btn btn-cancel"
 
-  .col-md-9
+  %section.col-md-9
     .panel.panel-default
       .panel-heading
         Users (#{@users.total_count})
         .panel-head-actions
           .dropdown.inline
-            %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
+            %a.dropdown-toggle.btn.btn-sm{href: '#', "data-toggle" => "dropdown"}
               %span.light sort:
               - if @sort.present?
-                = @sort.humanize
+                = sort_options_hash[@sort]
               - else
-                Name
+                = sort_title_name
               %b.caret
             %ul.dropdown-menu
               %li
-                = link_to admin_users_path(sort: nil) do
-                  Name
-                = link_to admin_users_path(sort: 'recent_sign_in') do
-                  Recent sign in
-                = link_to admin_users_path(sort: 'oldest_sign_in') do
-                  Oldest sign in
-                = link_to admin_users_path(sort: 'recently_created') do
-                  Recently created
-                = link_to admin_users_path(sort: 'late_created') do
-                  Late created
-          = link_to 'New User', new_admin_user_path, class: "btn btn-new"
+                = link_to admin_users_path(sort: sort_value_name) do
+                  = sort_title_name
+                = link_to admin_users_path(sort: sort_value_recently_signin) do
+                  = sort_title_recently_signin
+                = link_to admin_users_path(sort: sort_value_oldest_signin) do
+                  = sort_title_oldest_signin
+                = link_to admin_users_path(sort: sort_value_recently_created) do
+                  = sort_title_recently_created
+                = link_to admin_users_path(sort: sort_value_oldest_created) do
+                  = sort_title_oldest_created
+                = link_to admin_users_path(sort: sort_value_recently_updated) do
+                  = sort_title_recently_updated
+                = link_to admin_users_path(sort: sort_value_oldest_updated) do
+                  = sort_title_oldest_updated
+
+          = link_to 'New User', new_admin_user_path, class: "btn btn-new btn-sm"
       %ul.well-list
         - @users.each do |user|
           %li
@@ -71,11 +78,11 @@
                 %i.fa.fa-envelope
                 = mail_to user.email, user.email, class: 'light'
               &nbsp;
-              = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-small"
+              = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-sm"
               - unless user == current_user
                 - if user.blocked?
-                  = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn btn-small success"
+                  = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn btn-sm success"
                 - else
-                  = link_to 'Block', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-small btn-remove"
-                = link_to 'Destroy', [:admin, user], data: { confirm: "USER #{user.name} WILL BE REMOVED! All tickets linked to this user will also be removed! Maybe block the user instead? Are you sure?" }, method: :delete, class: "btn btn-small btn-remove"
+                  = link_to 'Block', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-sm btn-remove"
+                = link_to 'Destroy', [:admin, user], data: { confirm: "USER #{user.name} WILL BE REMOVED! All tickets linked to this user will also be removed! Maybe block the user instead? Are you sure?" }, method: :delete, class: "btn btn-sm btn-remove"
     = paginate @users, theme: "gitlab"
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 211d77d51850d55be65c2439131d8b8ae8a3aa14..0a2934d3bdacb4afea2cf161c7768efb8d33f728 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -20,6 +20,8 @@
     %a{"data-toggle" => "tab", href: "#groups"} Groups
   %li
     %a{"data-toggle" => "tab", href: "#projects"} Projects
+  %li
+    %a{"data-toggle" => "tab", href: "#ssh-keys"} SSH keys
 
 .tab-content
   #account.tab-pane.active
@@ -44,7 +46,7 @@
               %li
                 %span.light Secondary email:
                 %strong= email.email
-                = link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn-tiny btn btn-remove pull-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do
+                = link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn-xs btn btn-remove pull-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do
                   %i.fa.fa-times
 
             %li
@@ -95,7 +97,7 @@
               %li
                 %span.light LDAP uid:
                 %strong
-                  = @user.extern_uid
+                  = @user.ldap_identity.extern_uid
 
             - if @user.created_by
               %li
@@ -106,45 +108,49 @@
       .col-md-6
         - unless @user == current_user
           - if @user.blocked?
-            .alert.alert-info
-              %h4 This user is blocked
-              %p Blocking user has the following effects:
-              %ul
-                %li User will not be able to login
-                %li User will not be able to access git repositories
-                %li User will be removed from joined projects and groups
-                %li Personal projects will be left
-                %li Owned groups will be left
-              %br
-              = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-new", data: { confirm: 'Are you sure?' }
+            .panel.panel-info
+              .panel-heading
+                This user is blocked
+              .panel-body
+                %p Blocking user has the following effects:
+                %ul
+                  %li User will not be able to login
+                  %li User will not be able to access git repositories
+                  %li Personal projects will be left
+                  %li Owned groups will be left
+                %br
+                = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' }
           - else
-            .alert.alert-warning
-              %h4 Block this user
-              %p Blocking user has the following effects:
+            .panel.panel-warning
+              .panel-heading
+                Block this user
+              .panel-body
+                %p Blocking user has the following effects:
+                %ul
+                  %li User will not be able to login
+                  %li User will not be able to access git repositories
+                  %li User will be removed from joined projects and groups
+                  %li Personal projects will be left
+                  %li Owned groups will be left
+                %br
+                = link_to 'Block user', block_admin_user_path(@user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put, class: "btn btn-warning"
+
+          .panel.panel-danger
+            .panel-heading
+              Remove user
+            .panel-body
+              %p Deleting a user has the following effects:
               %ul
-                %li User will not be able to login
-                %li User will not be able to access git repositories
-                %li User will be removed from joined projects and groups
-                %li Personal projects will be left
-                %li Owned groups will be left
+                %li All user content like authored issues, snippets, comments will be removed
+                - rp = @user.personal_projects.count
+                - unless rp.zero?
+                  %li #{pluralize rp, 'personal project'} will be removed and cannot be restored
+                - if @user.solo_owned_groups.present?
+                  %li
+                    Next groups with all content will be removed:
+                    %strong #{@user.solo_owned_groups.map(&:name).join(', ')}
               %br
-              = link_to 'Block user', block_admin_user_path(@user), data: { confirm: 'USER WILL BE BLOCKED! Are you sure?' }, method: :put, class: "btn btn-remove"
-
-          .alert.alert-danger
-            %h4
-              Remove user
-            %p Deleting a user has the following effects:
-            %ul
-              %li All user content like authored issues, snippets, comments will be removed
-              - rp = @user.personal_projects.count
-              - unless rp.zero?
-                %li #{pluralize rp, 'personal project'} will be removed and cannot be restored
-              - if @user.solo_owned_groups.present?
-                %li
-                  Next groups with all content will be removed:
-                  %strong #{@user.solo_owned_groups.map(&:name).join(', ')}
-            %br
-            = link_to 'Remove user', [:admin, @user], data: { confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-remove"
+              = link_to 'Remove user', [:admin, @user], data: { confirm: "USER #{@user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-remove"
 
   #profile.tab-pane
     .row
@@ -168,15 +174,15 @@
       .panel.panel-default
         .panel-heading Groups:
         %ul.well-list
-          - @user.group_members.each do |user_group|
-            - group = user_group.group
+          - @user.group_members.each do |group_member|
+            - group = group_member.group
             %li.group_member
-              %span{class: ("list-item-name" unless user_group.owner?)}
+              %span{class: ("list-item-name" unless group_member.owner?)}
                 %strong= link_to group.name, admin_group_path(group)
               .pull-right
-                %span.light= user_group.human_access
-                - unless user_group.owner?
-                  = link_to group_group_member_path(group, user_group), data: { confirm: remove_user_from_group_message(group, @user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
+                %span.light= group_member.human_access
+                - unless group_member.owner?
+                  = link_to group_group_member_path(group, group_member), data: { confirm: remove_user_from_group_message(group, @user) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do
                     %i.fa.fa-times.fa-inverse
     - else
       .nothing-here-block This user has no groups.
@@ -201,19 +207,21 @@
           .panel-heading Joined projects (#{@joined_projects.count})
           %ul.well-list
             - @joined_projects.sort_by(&:name_with_namespace).each do |project|
-              - tm = project.team.find_tm(@user.id)
+              - member = project.team.find_member(@user.id)
               %li.project_member
                 .list-item-name
-                  = link_to admin_project_path(project), class: dom_class(project) do
+                  = link_to admin_namespace_project_path(project.namespace, project), class: dom_class(project) do
                     = project.name_with_namespace
 
-                - if tm
+                - if member
                   .pull-right
-                    - if tm.owner?
+                    - if member.owner?
                       %span.light Owner
                     - else
-                      %span.light= tm.human_access
+                      %span.light= member.human_access
 
-                      - if tm.respond_to? :project
-                        = link_to project_team_member_path(project, @user), data: { confirm: remove_from_project_team_message(project, @user) }, remote: true, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from project' do
+                      - if member.respond_to? :project
+                        = link_to namespace_project_project_member_path(project.namespace, project, @user), data: { confirm: remove_from_project_team_message(project, @user) }, remote: true, method: :delete, class: "btn-xs btn btn-remove", title: 'Remove user from project' do
                           %i.fa.fa-times
+  #ssh-keys.tab-pane
+    = render 'profiles/keys/key_table', admin: true
diff --git a/app/views/dashboard/_activities.html.haml b/app/views/dashboard/_activities.html.haml
index fdf96dd6f562c577a50b6f0ded048e4a0edb1abe..c1fc1602d0a2a4bea19efffb85df499d9836c229 100644
--- a/app/views/dashboard/_activities.html.haml
+++ b/app/views/dashboard/_activities.html.haml
@@ -1,9 +1,4 @@
 = render "events/event_last_push", event: @last_push
 = render 'shared/event_filter'
-
-- if @events.any?
-  .content_list
-- else
-  .nothing-here-block Projects activity will be displayed here
-
+.content_list
 = spinner
diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml
deleted file mode 100644
index 5460cf56f22f98a70b630657d2658cbb033fa87f..0000000000000000000000000000000000000000
--- a/app/views/dashboard/_groups.html.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-.panel.panel-default
-  .panel-heading.clearfix
-    = search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter form-control'
-    - if current_user.can_create_group?
-      = link_to new_group_path, class: "btn btn-new pull-right" do
-        %i.fa.fa-plus
-        New group
-  %ul.well-list.dash-list
-    - groups.each do |group|
-      %li.group-row
-        = link_to group_path(id: group.path), class: dom_class(group) do
-          = image_tag group_icon(group.path), class: "avatar s24"
-          %span.group-name.filter-title
-            = truncate(group.name, length: 35)
-          %span.arrow
-            %i.fa.fa-angle-right
-    - if groups.blank?
-      %li
-        .nothing-here-block You have no groups yet.
diff --git a/app/views/dashboard/_project.html.haml b/app/views/dashboard/_project.html.haml
deleted file mode 100644
index 89ed51027543180163d1347c684073b478b0ec60..0000000000000000000000000000000000000000
--- a/app/views/dashboard/_project.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-= link_to project_path(project), class: dom_class(project) do
-  .dash-project-access-icon
-    = visibility_level_icon(project.visibility_level)
-  %span.str-truncated
-    %span.namespace-name
-      - if project.namespace
-        = project.namespace.human_name
-        \/
-    %span.project-name.filter-title
-      = project.name
-  %span.arrow
-    %i.fa.fa-angle-right
diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml
index 3598425777fa2afb17a7b3dc8bf160995dd72d65..d676576067cf0c486aaf925dc36bd847e013463f 100644
--- a/app/views/dashboard/_projects.html.haml
+++ b/app/views/dashboard/_projects.html.haml
@@ -1,24 +1,10 @@
 .panel.panel-default
   .panel-heading.clearfix
-    = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'dash-filter form-control'
-    - if current_user.can_create_project?
-      = link_to new_project_path, class: "btn btn-new pull-right" do
-        %i.fa.fa-plus
-        New project
+    .input-group
+      = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control'
+      - if current_user.can_create_project?
+        %span.input-group-btn
+          = link_to new_project_path, class: 'btn btn-success' do
+            New project
 
-  %ul.well-list.dash-list
-    - projects.each do |project|
-      %li.project-row
-        = render "project", project: project
-
-    - if projects.blank?
-      %li
-        .nothing-here-block There are no projects here.
-    - if @projects_count > @projects_limit
-      %li.bottom
-        %span.light
-          #{@projects_limit} of #{pluralize(@projects_count, 'project')} displayed.
-        .pull-right
-          = link_to projects_dashboard_path do
-            Show all
-            %i.fa.fa-angle-right
+  = render 'shared/projects_list', projects: @projects, projects_limit: 20
diff --git a/app/views/dashboard/_projects_filter.html.haml b/app/views/dashboard/_projects_filter.html.haml
deleted file mode 100644
index b65e882e6935654ec16b580cd71c9b27e3322d3b..0000000000000000000000000000000000000000
--- a/app/views/dashboard/_projects_filter.html.haml
+++ /dev/null
@@ -1,55 +0,0 @@
-%fieldset
-  %ul.nav.nav-pills.nav-stacked
-    = nav_tab :scope, nil do
-      = link_to projects_dashboard_filter_path(scope: nil) do
-        All
-        %span.pull-right
-          = current_user.authorized_projects.count
-    = nav_tab :scope, 'personal' do
-      = link_to projects_dashboard_filter_path(scope: 'personal') do
-        Personal
-        %span.pull-right
-          = current_user.personal_projects.count
-    = nav_tab :scope, 'joined' do
-      = link_to projects_dashboard_filter_path(scope: 'joined') do
-        Joined
-        %span.pull-right
-          = current_user.authorized_projects.joined(current_user).count
-    = nav_tab :scope, 'owned' do
-      = link_to projects_dashboard_filter_path(scope: 'owned') do
-        Owned
-        %span.pull-right
-          = current_user.owned_projects.count
-
-%fieldset
-  %legend Visibility
-  %ul.nav.nav-pills.nav-stacked.nav-small.visibility-filter
-    - Gitlab::VisibilityLevel.values.each do |level|
-      %li{ class: (level.to_s == params[:visibility_level]) ? 'active' : 'light' }
-        = link_to projects_dashboard_filter_path(visibility_level: level) do
-          = visibility_level_icon(level)
-          = visibility_level_label(level)
-
-- if @groups.present?
-  %fieldset
-    %legend Groups
-    %ul.nav.nav-pills.nav-stacked.nav-small
-      - @groups.each do |group|
-        %li{ class: (group.name == params[:group]) ? 'active' : 'light' }
-          = link_to projects_dashboard_filter_path(group: group.name) do
-            %i.fa.fa-folder-o
-            = group.name
-            %small.pull-right
-              = group.projects.count
-
-
-
-- if @tags.present?
-  %fieldset
-    %legend Tags
-    %ul.nav.nav-pills.nav-stacked.nav-small
-      - @tags.each do |tag|
-        %li{ class: (tag.name == params[:tag]) ? 'active' : 'light' }
-          = link_to projects_dashboard_filter_path(scope: params[:scope], tag: tag.name) do
-            %i.fa.fa-tag
-            = tag.name
diff --git a/app/views/dashboard/_sidebar.html.haml b/app/views/dashboard/_sidebar.html.haml
index add9eb7fa29b2c5135fedad70d73b14f7a67a73a..78f695be9160396b2f12a3517ff0cb1e207f6ee3 100644
--- a/app/views/dashboard/_sidebar.html.haml
+++ b/app/views/dashboard/_sidebar.html.haml
@@ -1,25 +1,3 @@
-%ul.nav.nav-tabs.dash-sidebar-tabs
-  %li.active
-    = link_to '#projects', 'data-toggle' => 'tab', id: 'sidebar-projects-tab' do
-      Projects
-      %span.badge= @projects_count
-  %li
-    = link_to '#groups', 'data-toggle' => 'tab', id: 'sidebar-groups-tab' do
-      Groups
-      %span.badge= @groups.count
-
-.tab-content
-  .tab-pane.active#projects
-    = render "projects", projects: @projects
-  .tab-pane#groups
-    = render "groups", groups: @groups
-
+= render "dashboard/projects", projects: @projects
 .prepend-top-20
-  %span.rss-icon
-    = link_to dashboard_path(:atom, { private_token: current_user.private_token }) do
-      %strong
-        %i.fa.fa-rss
-        News Feed
-
-%hr
-= render 'shared/promo'
+  = render 'shared/promo'
diff --git a/app/views/dashboard/_zero_authorized_projects.html.haml b/app/views/dashboard/_zero_authorized_projects.html.haml
index 5d133cd8285b87561e0277591e38514fd7597082..4e7d66397276efd4090e82acea5fa1944d35ec57 100644
--- a/app/views/dashboard/_zero_authorized_projects.html.haml
+++ b/app/views/dashboard/_zero_authorized_projects.html.haml
@@ -1,10 +1,11 @@
+- publicish_project_count = Project.publicish(current_user).count
 %h3.page-title Welcome to GitLab!
 %p.light Self hosted Git management application.
 %hr
 %div
   .dashboard-intro-icon
     %i.fa.fa-bookmark-o
-  %div
+  .dashboard-intro-text
     %p.slead
       You don't have access to any projects right now.
       %br
@@ -17,34 +18,36 @@
     - if current_user.can_create_project?
       .link_holder
         = link_to new_project_path, class: "btn btn-new" do
-          New project »
+          %i.fa.fa-plus
+          New Project
 
 - if current_user.can_create_group?
   %hr
   %div
     .dashboard-intro-icon
       %i.fa.fa-users
-    %div
+    .dashboard-intro-text
       %p.slead
         You can create a group for several dependent projects.
         %br
         Groups are the best way to manage projects and members.
       .link_holder
         = link_to new_group_path, class: "btn btn-new" do
-          New group »
+          %i.fa.fa-plus
+          New Group
 
--if @publicish_project_count > 0
+-if publicish_project_count > 0
   %hr
   %div
     .dashboard-intro-icon
       %i.fa.fa-globe
-    %div
+    .dashboard-intro-text
       %p.slead
         There are
-        %strong= @publicish_project_count
+        %strong= publicish_project_count
         public projects on this server.
         %br
         Public projects are an easy way to allow everyone to have read-only access.
       .link_holder
         = link_to trending_explore_projects_path, class: "btn btn-new" do
-          Browse public projects »
+          Browse public projects
diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..165db214d750dda1a20a8be5113921ba0cd76c17
--- /dev/null
+++ b/app/views/dashboard/groups/index.html.haml
@@ -0,0 +1,40 @@
+%h3.page-title
+  Group Membership
+  - if current_user.can_create_group?
+    %span.pull-right
+      = link_to new_group_path, class: "btn btn-new" do
+        %i.fa.fa-plus
+        New Group
+%p.light
+  Group members have access to all group projects.
+%hr
+.panel.panel-default
+  .panel-heading
+    %strong Groups
+    (#{@group_members.count})
+  %ul.well-list
+    - @group_members.each do |group_member|
+      - group = group_member.group
+      %li
+        .pull-right
+          - if can?(current_user, :manage_group, group)
+            = link_to edit_group_path(group), class: "btn-sm btn btn-grouped" do
+              %i.fa.fa-cogs
+              Settings
+
+          - if can?(current_user, :destroy_group_member, group_member)
+            = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Remove user from group' do
+              %i.fa.fa-sign-out
+              Leave
+
+        = image_tag group_icon(group), class: "avatar s40 avatar-tile"
+        = link_to group, class: 'group-name' do
+          %strong= group.name
+
+        as
+        %strong #{group_member.human_access}
+
+        %div.light
+          #{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")}
+
+= paginate @group_members
diff --git a/app/views/dashboard/issues.atom.builder b/app/views/dashboard/issues.atom.builder
index f54135577839221bd66dbfc10e914e4853556296..72e9e361dc3d4f984b8cae48ff87e34baddf4650 100644
--- a/app/views/dashboard/issues.atom.builder
+++ b/app/views/dashboard/issues.atom.builder
@@ -1,24 +1,13 @@
 xml.instruct!
 xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
   xml.title   "#{current_user.name} issues"
-  xml.link    :href => issues_dashboard_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml"
-  xml.link    :href => issues_dashboard_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html"
-  xml.id      issues_dashboard_url(:private_token => current_user.private_token)
+  xml.link    href: issues_dashboard_url(:atom, private_token: current_user.private_token), rel: "self", type: "application/atom+xml"
+  xml.link    href: issues_dashboard_url(private_token: current_user.private_token), rel: "alternate", type: "text/html"
+  xml.id      issues_dashboard_url(private_token: current_user.private_token)
   xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
 
   @issues.each do |issue|
-    xml.entry do
-      xml.id      project_issue_url(issue.project, issue)
-      xml.link    :href => project_issue_url(issue.project, issue)
-      xml.title   truncate(issue.title, :length => 80)
-      xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
-      xml.media   :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
-      xml.author do |author|
-        xml.name issue.author_name
-        xml.email issue.author_email
-      end
-      xml.summary issue.title
-    end
+    issue_to_atom(xml, issue)
   end
 end
 
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index 7c1f1ddbb80241e1104316a1cd482ddfe079ecde..db19a46cb263dd075e79dbcd6dc1e62e4396d5a7 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -5,10 +5,6 @@
   List all issues from all projects you have access to.
 %hr
 
-.row
-  .fixed.sidebar-expand-button.hidden-lg.hidden-md
-    %i.fa.fa-list.fa-2x
-  .col-md-3.responsive-side
-    = render 'shared/filter', entity: 'issue'
-  .col-md-9
-    = render 'shared/issues'
+.append-bottom-20
+  = render 'shared/issuable_filter'
+= render 'shared/issues'
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index c96584c7b6bae8b384ae6958960251e680710eec..97a42461b4e0f54d32a91c139bf1ac3818f1f46b 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -5,10 +5,6 @@
 %p.light
   List all merge requests from all projects you have access to.
 %hr
-.row
-  .fixed.sidebar-expand-button.hidden-lg.hidden-md
-    %i.fa.fa-list.fa-2x
-  .col-md-3.responsive-side
-    = render 'shared/filter', entity: 'merge_request'
-  .col-md-9
-    = render 'shared/merge_requests'
+.append-bottom-20
+  = render 'shared/issuable_filter'
+= render 'shared/merge_requests'
diff --git a/app/views/dashboard/milestones/_issue.html.haml b/app/views/dashboard/milestones/_issue.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f689b9698eb76806e1f50a6fdaa1e1eb9e9058bd
--- /dev/null
+++ b/app/views/dashboard/milestones/_issue.html.haml
@@ -0,0 +1,10 @@
+%li{ id: dom_id(issue, 'sortable'), class: 'issue-row', 'data-iid' => issue.iid }
+  %span.milestone-row
+    - project = issue.project
+    %strong #{project.name_with_namespace} &middot;
+    = link_to [project.namespace.becomes(Namespace), project, issue] do
+      %span.cgray ##{issue.iid}
+    = link_to_gfm issue.title, [project.namespace.becomes(Namespace), project, issue], title: issue.title
+  .pull-right.assignee-icon
+    - if issue.assignee
+      = image_tag avatar_icon(issue.assignee.email, 16), class: "avatar s16"
diff --git a/app/views/dashboard/milestones/_issues.html.haml b/app/views/dashboard/milestones/_issues.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..9f350b772bd90e324398e5981d32510384dc83d9
--- /dev/null
+++ b/app/views/dashboard/milestones/_issues.html.haml
@@ -0,0 +1,6 @@
+.panel.panel-default
+  .panel-heading= title
+  %ul{ class: "well-list issues-sortable-list" }
+    - if issues
+      - issues.each do |issue|
+        = render 'issue', issue: issue
diff --git a/app/views/dashboard/milestones/_merge_request.html.haml b/app/views/dashboard/milestones/_merge_request.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..8f5c4cce529b601421a4cb813422e6b86cb99a87
--- /dev/null
+++ b/app/views/dashboard/milestones/_merge_request.html.haml
@@ -0,0 +1,10 @@
+%li{ id: dom_id(merge_request, 'sortable'),  class: 'mr-row', 'data-iid' => merge_request.iid }
+  %span.milestone-row
+    - project = merge_request.project
+    %strong #{project.name_with_namespace} &middot;
+    = link_to [project.namespace.becomes(Namespace), project, merge_request] do
+      %span.cgray ##{merge_request.iid}
+    = link_to_gfm merge_request.title, [project.namespace.becomes(Namespace), project, merge_request], title: merge_request.title
+  .pull-right.assignee-icon
+    - if merge_request.assignee
+      = image_tag avatar_icon(merge_request.assignee.email, 16), class: "avatar s16"
diff --git a/app/views/dashboard/milestones/_merge_requests.html.haml b/app/views/dashboard/milestones/_merge_requests.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..50057e2c636db5cb19c5dbf8184ed9a9d5547432
--- /dev/null
+++ b/app/views/dashboard/milestones/_merge_requests.html.haml
@@ -0,0 +1,6 @@
+.panel.panel-default
+  .panel-heading= title
+  %ul{ class: "well-list merge_requests-sortable-list" }
+    - if merge_requests
+      - merge_requests.each do |merge_request|
+        = render 'merge_request', merge_request: merge_request
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..caf3b6858645afa4b11bfbad0de2f2e716eefa7f
--- /dev/null
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -0,0 +1,38 @@
+%h3.page-title
+  Milestones
+  %span.pull-right #{@dashboard_milestones.count} milestones
+
+%p.light
+  List all milestones from all projects you have access to.
+
+%hr
+
+= render 'shared/milestones_filter'
+.milestones
+  .panel.panel-default
+    %ul.well-list
+      - if @dashboard_milestones.blank?
+        %li
+          .nothing-here-block No milestones to show
+      - else
+        - @dashboard_milestones.each do |milestone|
+          %li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
+            %h4
+              = link_to_gfm truncate(milestone.title, length: 100), dashboard_milestone_path(milestone.safe_title, title: milestone.title)
+            %div
+              %div
+                = link_to dashboard_milestone_path(milestone.safe_title, title: milestone.title) do
+                  = pluralize milestone.issue_count, 'Issue'
+                &nbsp;
+                = link_to dashboard_milestone_path(milestone.safe_title, title: milestone.title) do
+                  = pluralize milestone.merge_requests_count, 'Merge Request'
+                &nbsp;
+                %span.light #{milestone.percent_complete}% complete
+              = milestone_progress_bar(milestone)
+              %div
+                %br
+                - milestone.milestones.each do |milestone|
+                  = link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) do
+                    %span.label.label-default
+                      = milestone.project.name_with_namespace
+  = paginate @dashboard_milestones, theme: "gitlab"
diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..57cce9ab749ec85fe3e65118a0864c01311c4b72
--- /dev/null
+++ b/app/views/dashboard/milestones/show.html.haml
@@ -0,0 +1,81 @@
+%h4.page-title
+  .issue-box{ class: "issue-box-#{@dashboard_milestone.closed? ? 'closed' : 'open'}" }
+    - if @dashboard_milestone.closed?
+      Closed
+    - else
+      Open
+  Milestone #{@dashboard_milestone.title}
+
+%hr
+- if (@dashboard_milestone.total_items_count == @dashboard_milestone.closed_items_count) && @dashboard_milestone.active?
+  .alert.alert-success
+    %span All issues for this milestone are closed. You may close the milestone now.
+
+.description
+%table.table
+  %thead
+    %tr
+      %th Project
+      %th Open issues
+      %th State
+      %th Due date
+  - @dashboard_milestone.milestones.each do |milestone|
+    %tr
+      %td
+        = link_to "#{milestone.project.name_with_namespace}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
+      %td
+        = milestone.issues.opened.count
+      %td
+        - if milestone.closed?
+          Closed
+        - else
+          Open
+      %td
+        = milestone.expires_at
+
+.context
+  %p.lead
+    Progress:
+    #{@dashboard_milestone.closed_items_count} closed
+    &ndash;
+    #{@dashboard_milestone.open_items_count} open
+  = milestone_progress_bar(@dashboard_milestone)
+
+%ul.nav.nav-tabs
+  %li.active
+    = link_to '#tab-issues', 'data-toggle' => 'tab' do
+      Issues
+      %span.badge= @dashboard_milestone.issue_count
+  %li
+    = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do
+      Merge Requests
+      %span.badge= @dashboard_milestone.merge_requests_count
+  %li
+    = link_to '#tab-participants', 'data-toggle' => 'tab' do
+      Participants
+      %span.badge= @dashboard_milestone.participants.count
+
+.tab-content
+  .tab-pane.active#tab-issues
+    .row
+      .col-md-6
+        = render 'issues', title: "Open", issues: @dashboard_milestone.opened_issues
+      .col-md-6
+        = render 'issues', title: "Closed", issues: @dashboard_milestone.closed_issues
+
+  .tab-pane#tab-merge-requests
+    .row
+      .col-md-6
+        = render 'merge_requests', title: "Open", merge_requests: @dashboard_milestone.opened_merge_requests
+      .col-md-6
+        = render 'merge_requests', title: "Closed", merge_requests: @dashboard_milestone.closed_merge_requests
+
+  .tab-pane#tab-participants
+    %ul.bordered-list
+      - @dashboard_milestone.participants.each do |user|
+        %li
+          = link_to user, title: user.name, class: "darken" do
+            = image_tag avatar_icon(user.email, 32), class: "avatar s32"
+            %strong= truncate(user.name, lenght: 40)
+            %br
+            %small.cgray= user.username
diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml
deleted file mode 100644
index f124c688be19ad0926a9c06f829879851fbf94e2..0000000000000000000000000000000000000000
--- a/app/views/dashboard/projects.html.haml
+++ /dev/null
@@ -1,73 +0,0 @@
-%h3.page-title
-  My Projects
-.pull-right
-  .dropdown.inline
-    %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
-      %span.light sort:
-      - if @sort.present?
-        = @sort.humanize
-      - else
-        Name
-      %b.caret
-    %ul.dropdown-menu
-      %li
-        = link_to projects_dashboard_filter_path(sort: nil) do
-          Name
-        = link_to projects_dashboard_filter_path(sort: 'newest') do
-          Newest
-        = link_to projects_dashboard_filter_path(sort: 'oldest') do
-          Oldest
-        = link_to projects_dashboard_filter_path(sort: 'recently_updated') do
-          Recently updated
-        = link_to projects_dashboard_filter_path(sort: 'last_updated') do
-          Last updated
-%p.light
-  All projects you have access to are listed here. Public projects are not included here unless you are a member
-%hr
-.row
-  .col-md-3.hidden-sm.hidden-xs.side-filters
-    = render "projects_filter"
-  .col-md-9
-    %ul.bordered-list.my-projects.top-list
-      - @projects.each do |project|
-        %li.my-project-row
-          %h4.project-title
-            .project-access-icon
-              = visibility_level_icon(project.visibility_level)
-            = link_to project_path(project), class: dom_class(project) do
-              = project.name_with_namespace
-
-            - if current_user.can_leave_project?(project)
-              .pull-right
-                = link_to leave_project_team_members_path(project), data: { confirm: "Leave project?"}, method: :delete, remote: true, class: "btn-tiny btn remove-row", title: 'Leave project' do
-                  %i.fa.fa-sign-out
-                  Leave
-
-            - if project.forked_from_project
-              %small.pull-right
-                %i.fa.fa-code-fork
-                Forked from:
-                = link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project)
-          .project-info
-            .pull-right
-              - if project.archived?
-                %span.label
-                  %i.fa.fa-archive
-                  Archived
-              - project.tags.each do |tag|
-                %span.label.label-info
-                  %i.fa.fa-tag
-                  = tag.name
-            - if project.description.present?
-              %p= truncate project.description, length: 100
-            .last-activity
-              %span.light Last activity:
-              %span.date= project_last_activity(project)
-
-
-        - if @projects.blank?
-          %li
-            .nothing-here-block There are no projects here.
-    .bottom
-      = paginate @projects, theme: "gitlab"
-
diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..670f5ac7af79addb5510d2d6c22108bc3872e479
--- /dev/null
+++ b/app/views/dashboard/projects/starred.html.haml
@@ -0,0 +1,23 @@
+- if @projects.any?
+  .dashboard.row
+    %section.activities.col-md-8
+      = render 'dashboard/activities'
+    %aside.col-md-4
+      .panel.panel-default
+        .panel-heading.clearfix
+          .input-group
+            = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control'
+            - if current_user.can_create_project?
+              %span.input-group-btn
+                = link_to new_project_path, class: 'btn btn-success' do
+                  New project
+
+        = render 'shared/projects_list', projects: @projects,
+          projects_limit: 20, stars: true, avatar: false
+
+    = link_to '#aside', class: 'show-aside' do
+      %i.fa.fa-angle-left
+
+- else
+  %h3 You dont have starred projects yet
+  %p.slead Visit project page and press on star icon and it will appear on this page.
diff --git a/app/views/dashboard/show.atom.builder b/app/views/dashboard/show.atom.builder
index f4cf24ccd9982521073598156c5499711900bb4b..da631ecb33e00f01a6f08002da08d78b8f47464c 100644
--- a/app/views/dashboard/show.atom.builder
+++ b/app/views/dashboard/show.atom.builder
@@ -1,29 +1,12 @@
 xml.instruct!
 xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
   xml.title   "Dashboard feed#{" - #{current_user.name}" if current_user.name.present?}"
-  xml.link    :href => dashboard_url(:atom), :rel => "self", :type => "application/atom+xml"
-  xml.link    :href => dashboard_url, :rel => "alternate", :type => "text/html"
+  xml.link    href: dashboard_url(:atom), rel: "self", type: "application/atom+xml"
+  xml.link    href: dashboard_url, rel: "alternate", type: "text/html"
   xml.id      projects_url
   xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
 
   @events.each do |event|
-    if event.proper?
-      xml.entry do
-        event_link = event_feed_url(event)
-        event_title = event_feed_title(event)
-        event_summary = event_feed_summary(event)
-
-        xml.id      "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
-        xml.link    :href => event_link
-        xml.title   truncate(event_title, :length => 80)
-        xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
-        xml.media   :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
-        xml.author do |author|
-          xml.name event.author_name
-          xml.email event.author_email
-        end
-        xml.summary(:type => "xhtml") { |x| x << event_summary unless event_summary.nil? }
-      end
-    end
+    event_to_atom(xml, event)
   end
 end
diff --git a/app/views/dashboard/show.html.haml b/app/views/dashboard/show.html.haml
index 10951af6a0952b992b3f46afed6d5a11e8e98f42..fa8946011b741331df864f866420150af171f20c 100644
--- a/app/views/dashboard/show.html.haml
+++ b/app/views/dashboard/show.html.haml
@@ -1,12 +1,11 @@
-- if @has_authorized_projects
+- if @projects.any?
   .dashboard.row
     %section.activities.col-md-8
       = render 'activities'
-    %aside.side.col-md-4.left.responsive-side
+    %aside.col-md-4
       = render 'sidebar'
-
-  .fixed.sidebar-expand-button.hidden-lg.hidden-md
-    %i.fa.fa-list.fa-2x
+    = link_to '#aside', class: 'show-aside' do
+      %i.fa.fa-angle-left
 
 - else
   = render "zero_authorized_projects"
diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml
old mode 100755
new mode 100644
index 8d17f39eba2bb376555887860dcabc38ca660b1e..970ba1471118bfb89a7e2fa6545ede4a72092531
--- a/app/views/devise/confirmations/new.html.haml
+++ b/app/views/devise/confirmations/new.html.haml
@@ -7,7 +7,8 @@
         = devise_error_messages!
       .clearfix.append-bottom-20
         = f.email_field :email, placeholder: 'Email', class: "form-control", required: true
-      .clearfix.append-bottom-10
+      .clearfix
         = f.submit "Resend confirmation instructions", class: 'btn btn-success'
-  .login-footer
-    = render 'devise/shared/sign_in_link'
+
+.clearfix.prepend-top-20
+  = render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb
index cb1291cf3bfb4772f082e31809cd1cc9e0c95ff4..c6fa8f0ee361b4aa7fe07005943820586a46df7d 100644
--- a/app/views/devise/mailer/confirmation_instructions.html.erb
+++ b/app/views/devise/mailer/confirmation_instructions.html.erb
@@ -6,4 +6,4 @@
   <p>You can confirm your account through the link below:</p>
 <% end %>
 
-<p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>
+<p><%= link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token) %></p>
diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb
index 7913e88beb6edf2c43b5d241ca3e54c9724832e5..23b31da92d807854ac82c7bab7bc85b4acdacd12 100644
--- a/app/views/devise/mailer/reset_password_instructions.html.erb
+++ b/app/views/devise/mailer/reset_password_instructions.html.erb
@@ -2,7 +2,7 @@
 
 <p>Someone has requested a link to change your password, and you can do this through the link below.</p>
 
-<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>
+<p><%= link_to 'Change your password', edit_password_url(@resource, reset_password_token: @token) %></p>
 
 <p>If you didn't request this, please ignore this email.</p>
 <p>Your password won't change until you access the link above and create a new one.</p>
diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb
index 8c2a4f0c2d95330835b13ed587398b343a8ed4f1..79d6c761d8fce48f4bf9e757392c13cff3ecf16d 100644
--- a/app/views/devise/mailer/unlock_instructions.html.erb
+++ b/app/views/devise/mailer/unlock_instructions.html.erb
@@ -4,4 +4,4 @@
 
 <p>Click the link below to unlock your account:</p>
 
-<p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>
+<p><%= link_to 'Unlock your account', unlock_url(@resource, unlock_token: @token) %></p>
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index f6cbf9b82ba4edfb24486384e1173fb1d76feb12..56048e99c17f834100138efe080de281fb875821 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -6,13 +6,14 @@
       .devise-errors
         = devise_error_messages!
       = f.hidden_field :reset_password_token
-      .form-group#password-strength
-        = f.password_field :password, class: "form-control top", id: "user_password_recover", placeholder: "New password", required: true
+      %div
+        = f.password_field :password, class: "form-control top", placeholder: "New password", required: true
       %div
         = f.password_field :password_confirmation, class: "form-control bottom", placeholder: "Confirm new password", required: true
-      .clearfix.append-bottom-10
-        = f.submit "Change my password", class: "btn btn-primary"
-  .login-footer
-    %p
-      = link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name)
-    = render 'devise/shared/sign_in_link'
+      .clearfix
+        = f.submit "Change your password", class: "btn btn-primary"
+
+.clearfix.prepend-top-20
+  %p
+    = link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name)
+  = render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml
old mode 100755
new mode 100644
index b8af1b8693a4feb3e2f32f9c5f66946c4dc28d05..e8820daf58fe98f28d2bb8bdf6595e4217ae26a6
--- a/app/views/devise/passwords/new.html.haml
+++ b/app/views/devise/passwords/new.html.haml
@@ -7,7 +7,8 @@
         = devise_error_messages!
       .clearfix.append-bottom-20
         = f.email_field :email, placeholder: "Email",  class: "form-control", required: true
-      .clearfix.append-bottom-10
+      .clearfix
         = f.submit "Reset password", class: "btn-primary btn"
-  .login-footer
-    = render 'devise/shared/sign_in_link'
+
+.clearfix.prepend-top-20
+  = render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb
index b11817af95dbf3e7bf70460e8b485a8b4c4d6b4d..f379e71ae5b444c683b5ee1fd97f69c732f8aa35 100644
--- a/app/views/devise/registrations/edit.html.erb
+++ b/app/views/devise/registrations/edit.html.erb
@@ -21,8 +21,8 @@
 <div><%= f.submit "Update", class: "input_button" %></div>
 <% end %>
 
-<h3>Cancel my account</h3>
+<h3>Cancel your account</h3>
 
-<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>.</p>
+<p>Unhappy? <%= link_to "Cancel your account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>.</p>
 
 <%= link_to "Back", :back %>
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index 123de881f594e914bbe23dbb51c08384a896773e..d3e37f7494c99a4455b05e95bf2aa4804a307dde 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -1,27 +1,3 @@
-.login-box
-  .login-heading
-    %h3 Sign up
-  .login-body
-    = form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
-      .devise-errors
-        = devise_error_messages!
-      %div
-        = f.text_field :name, class: "form-control top", placeholder: "Name", required: true
-      %div
-        = f.text_field :username, class: "form-control middle", placeholder: "Username", required: true
-      %div
-        = f.email_field :email, class: "form-control middle", placeholder: "Email", required: true
-      .form-group#password-strength
-        = f.password_field :password, class: "form-control middle", id: "user_password_sign_up", placeholder: "Password", required: true
-      %div
-        = f.password_field :password_confirmation, class: "form-control bottom", placeholder: "Confirm password", required: true
-      %div
-        = f.submit "Sign up", class: "btn-create btn"
-  .login-footer
-    %p
-      %span.light
-        Have an account?
-      %strong
-        = link_to "Sign in", new_session_path(resource_name)
-    %p
-      = link_to "Forgot your password?", new_password_path(resource_name)
+= render 'devise/shared/signup_box'
+
+= render 'devise/shared/sign_in_link'
\ No newline at end of file
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index e819847e5eabafc10a2cf14d2b88c5040c6d17ef..54a397267714112be0444d0726685a0648b352bc 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -2,11 +2,11 @@
   = f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus"
   = f.password_field :password, class: "form-control bottom", placeholder: "Password"
   - if devise_mapping.rememberable?
-    .clearfix.append-bottom-10
-      %label.checkbox.remember_me{for: "user_remember_me"}
+    .remember-me.checkbox
+      %label{for: "user_remember_me"}
         = f.check_box :remember_me
         %span Remember me
-        .pull-right
-          = link_to "Forgot your password?", new_password_path(resource_name)
+      .pull-right
+        = link_to "Forgot your password?", new_password_path(resource_name)
   %div
     = f.submit "Sign in", class: "btn btn-save"
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index bf8a593c254e65753763ca6e034b2e7e3169da87..812e22373a74b8b3297491ac2937ef0d1eb2d6ed 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -1,5 +1,4 @@
-= form_tag(user_omniauth_callback_path(provider), id: 'new_ldap_user' ) do
-  = text_field_tag :username, nil, {class: "form-control top", placeholder: "LDAP Login", autofocus: "autofocus"}
+= form_tag(user_omniauth_callback_path(server['provider_name']), id: 'new_ldap_user' ) do
+  = text_field_tag :username, nil, {class: "form-control top", placeholder: "#{server['label']} Login", autofocus: "autofocus"}
   = password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"}
-  %br/
-  = button_tag "LDAP Sign in", class: "btn-save btn"
+  = button_tag "#{server['label']} Sign in", class: "btn-save btn"
diff --git a/app/views/devise/sessions/_oauth_providers.html.haml b/app/views/devise/sessions/_oauth_providers.html.haml
deleted file mode 100644
index 15048a78063f38ae2ee2eca6a6886ea807aff34a..0000000000000000000000000000000000000000
--- a/app/views/devise/sessions/_oauth_providers.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-- providers = (enabled_oauth_providers - [:ldap])
-- if providers.present?
-  .bs-callout.bs-callout-info{:'data-no-turbolink' => 'data-no-turbolink'}
-    %span Sign in with: &nbsp;
-    - providers.each do |provider|
-      %span
-        - if default_providers.include?(provider)
-          = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
-        - else
-          = link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn"
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index ca7e9570b432729f7f49445752a593f7de29b776..89e4e229ac0dd3d1b5c91d65b03f037a23cc79ec 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -1,43 +1,18 @@
-.login-box
-  .login-heading
-    %h3 Sign in
-  .login-body
-    - if ldap_enabled?
-      %ul.nav.nav-tabs
-        - @ldap_servers.each_with_index do |server, i|
-          %li{class: (:active if i.zero?)}
-            = link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab'
-        - if gitlab_config.signin_enabled
-          %li
-            = link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab'
-      .tab-content
-        - @ldap_servers.each_with_index do |server, i|
-          %div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero?)}
-            = render 'devise/sessions/new_ldap', provider: server['provider_name']
-        - if gitlab_config.signin_enabled
-          %div#tab-signin.tab-pane
-            = render 'devise/sessions/new_base'
+%div
+  - if signin_enabled? || ldap_enabled?
+    = render 'devise/shared/signin_box'
 
-    - elsif gitlab_config.signin_enabled
-      = render 'devise/sessions/new_base'
-    - else
-      %div
-        No authentication methods configured.
+  -# Omniauth fits between signin/ldap signin and signup and does not have a surrounding box
+  - if Gitlab.config.omniauth.enabled && devise_mapping.omniauthable?
+    .clearfix.prepend-top-20
+      = render 'devise/shared/omniauth_box'
 
-    = render 'devise/sessions/oauth_providers' if Gitlab.config.omniauth.enabled && devise_mapping.omniauthable?
+  -# Signup only makes sense if you can also sign-in
+  - if signin_enabled? && signup_enabled?
+    .prepend-top-20
+      = render 'devise/shared/signup_box'
 
-  .login-footer
-    - if gitlab_config.signup_enabled
-      %p
-        %span.light
-          Don't have an account?
-        %strong
-          = link_to "Sign up", new_registration_path(resource_name)
-
-    %p
-      %span.light Did not receive confirmation email?
-      = link_to "Send again", new_confirmation_path(resource_name)
-
-    - if extra_config.has_key?('sign_in_text')
-      %hr
-      = markdown(extra_config.sign_in_text)
+  -# Show a message if none of the mechanisms above are enabled
+  - if !signin_enabled? && !ldap_enabled? && !(Gitlab.config.omniauth.enabled && devise_mapping.omniauthable?)
+    %div
+      No authentication methods configured.
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..b647b906b712b27e56b9511f34dbc333e409f5bb
--- /dev/null
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -0,0 +1,10 @@
+%p
+  %span.light
+    Sign in with &nbsp;
+  - providers = additional_providers
+  - providers.each do |provider|
+    %span.light
+      - if default_providers.include?(provider)
+        = link_to oauth_image_tag(provider), omniauth_authorize_path(resource_name, provider), class: 'oauth-image-link'
+      - else
+        = link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn"
diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..c76574db457d3581a3c73a9599ce902e1572aeee
--- /dev/null
+++ b/app/views/devise/shared/_signin_box.html.haml
@@ -0,0 +1,26 @@
+.login-box
+  - if signup_enabled?
+    .login-heading
+      %h3 Existing user? Sign in
+  - else
+    .login-heading
+      %h3 Sign in
+  .login-body
+    - if ldap_enabled?
+      %ul.nav.nav-tabs
+        - @ldap_servers.each_with_index do |server, i|
+          %li{class: (:active if i.zero?)}
+            = link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab'
+        - if signin_enabled?
+          %li
+            = link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab'
+      .tab-content
+        - @ldap_servers.each_with_index do |server, i|
+          %div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero?)}
+            = render 'devise/sessions/new_ldap', server: server
+        - if signin_enabled?
+          %div#tab-signin.tab-pane
+            = render 'devise/sessions/new_base'
+
+    - elsif signin_enabled?
+      = render 'devise/sessions/new_base'
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..dcf60c90430f0aba8f1cfa64452ef52a77253cf6
--- /dev/null
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -0,0 +1,26 @@
+.login-box
+  - if signin_enabled?
+    .login-heading
+      %h3 New user? Create an account
+  - else
+    .login-heading
+      %h3 Create an account
+  .login-body
+    = form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
+      .devise-errors
+        = devise_error_messages!
+      %div
+        = f.text_field :name, class: "form-control top", placeholder: "Name", required: true
+      %div
+        = f.text_field :username, class: "form-control middle", placeholder: "Username", required: true
+      %div
+        = f.email_field :email, class: "form-control middle", placeholder: "Email", required: true
+      .form-group.append-bottom-20#password-strength
+        = f.password_field :password, class: "form-control bottom", id: "user_password_sign_up", placeholder: "Password", required: true
+      %div
+        = f.submit "Sign up", class: "btn-create btn"
+
+.clearfix.prepend-top-20
+  %p
+    %span.light Did not receive confirmation email?
+    = link_to "Send again", new_confirmation_path(resource_name)
\ No newline at end of file
diff --git a/app/views/doorkeeper/applications/_delete_form.html.haml b/app/views/doorkeeper/applications/_delete_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..6a5c917049defbf478f305a9a8aca35c2f5ac420
--- /dev/null
+++ b/app/views/doorkeeper/applications/_delete_form.html.haml
@@ -0,0 +1,4 @@
+- submit_btn_css ||= 'btn btn-link btn-remove btn-sm'
+= form_tag oauth_application_path(application) do
+  %input{:name => "_method", :type => "hidden", :value => "delete"}/
+  = submit_tag 'Destroy', onclick: "return confirm('Are you sure?')", class: submit_btn_css
\ No newline at end of file
diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..a5fec2fabdb400b00c1c3cf02f025e152c37027f
--- /dev/null
+++ b/app/views/doorkeeper/applications/_form.html.haml
@@ -0,0 +1,24 @@
+= form_for application, url: doorkeeper_submit_path(application), html: {class: 'form-horizontal', role: 'form'} do |f|
+  - if application.errors.any?
+    .alert.alert-danger{"data-alert" => ""}
+      %p Whoops! Check your form for possible errors
+  = content_tag :div, class: "form-group#{' has-error' if application.errors[:name].present?}" do
+    = f.label :name, class: 'col-sm-2 control-label'
+    .col-sm-10
+      = f.text_field :name, class: 'form-control'
+      = doorkeeper_errors_for application, :name
+  = content_tag :div, class: "form-group#{' has-error' if application.errors[:redirect_uri].present?}" do
+    = f.label :redirect_uri, class: 'col-sm-2 control-label'
+    .col-sm-10
+      = f.text_area :redirect_uri, class: 'form-control'
+      = doorkeeper_errors_for application, :redirect_uri
+      %span.help-block
+        Use one line per URI
+      - if Doorkeeper.configuration.native_redirect_uri
+        %span.help-block
+          Use
+          %code= Doorkeeper.configuration.native_redirect_uri
+          for local tests
+  .form-actions
+    = f.submit 'Submit', class: "btn btn-primary wide"
+    = link_to "Cancel", applications_profile_path, class: "btn btn-default"
diff --git a/app/views/doorkeeper/applications/edit.html.haml b/app/views/doorkeeper/applications/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..61584eb9c498af026e0e0f97767639830a5c3555
--- /dev/null
+++ b/app/views/doorkeeper/applications/edit.html.haml
@@ -0,0 +1,2 @@
+%h3.page-title Edit application
+= render 'form', application: @application
\ No newline at end of file
diff --git a/app/views/doorkeeper/applications/index.html.haml b/app/views/doorkeeper/applications/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..e5be4b4bcac03d41252ecc84df4bc7ee5ce6f577
--- /dev/null
+++ b/app/views/doorkeeper/applications/index.html.haml
@@ -0,0 +1,16 @@
+%h3.page-title Your applications
+%p= link_to 'New Application', new_oauth_application_path, class: 'btn btn-success'
+%table.table.table-striped
+  %thead
+    %tr
+      %th Name
+      %th Callback URL
+      %th
+      %th
+  %tbody
+    - @applications.each do |application|
+      %tr{:id => "application_#{application.id}"}
+        %td= link_to application.name, oauth_application_path(application)
+        %td= application.redirect_uri
+        %td= link_to 'Edit', edit_oauth_application_path(application), class: 'btn btn-link'
+        %td= render 'delete_form', application: application
\ No newline at end of file
diff --git a/app/views/doorkeeper/applications/new.html.haml b/app/views/doorkeeper/applications/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..655845e4af55121df2abf04be73e524669f0bfda
--- /dev/null
+++ b/app/views/doorkeeper/applications/new.html.haml
@@ -0,0 +1,2 @@
+%h3.page-title New application
+= render 'form', application: @application
\ No newline at end of file
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..82e78b4af132472bfe0ba411d4e67b25b5781baf
--- /dev/null
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -0,0 +1,26 @@
+%h3.page-title
+  Application: #{@application.name}
+
+
+%table.table
+  %tr
+    %td
+      Application Id
+    %td
+      %code#application_id= @application.uid
+  %tr
+    %td
+      Secret:
+    %td
+      %code#secret= @application.secret
+
+  %tr
+    %td
+      Callback url
+    %td
+      - @application.redirect_uri.split.each do |uri|
+        %div
+          %span.monospace= uri
+.form-actions
+  = link_to 'Edit', edit_oauth_application_path(@application), class: 'btn btn-primary wide pull-left'
+  = render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10'
diff --git a/app/views/doorkeeper/authorizations/error.html.haml b/app/views/doorkeeper/authorizations/error.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..7561ec85ed9563c07b4f2115872892cea55c8c4c
--- /dev/null
+++ b/app/views/doorkeeper/authorizations/error.html.haml
@@ -0,0 +1,3 @@
+%h3.page-title An error has occurred
+%main{:role => "main"}
+  %pre= @pre_auth.error_response.body[:error_description]
\ No newline at end of file
diff --git a/app/views/doorkeeper/authorizations/new.html.haml b/app/views/doorkeeper/authorizations/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..15f9ee266c15a257b806e3997708a42333001df4
--- /dev/null
+++ b/app/views/doorkeeper/authorizations/new.html.haml
@@ -0,0 +1,28 @@
+%h3.page-title Authorize required
+%main{:role => "main"}
+  %p.h4
+    Authorize
+    %strong.text-info= @pre_auth.client.name
+    to use your account?
+  - if @pre_auth.scopes
+    #oauth-permissions
+      %p This application will be able to:
+      %ul.text-info
+        - @pre_auth.scopes.each do |scope|
+          %li= t scope, scope: [:doorkeeper, :scopes]
+  %hr/
+  .actions
+    = form_tag oauth_authorization_path, method: :post do
+      = hidden_field_tag :client_id, @pre_auth.client.uid
+      = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
+      = hidden_field_tag :state, @pre_auth.state
+      = hidden_field_tag :response_type, @pre_auth.response_type
+      = hidden_field_tag :scope, @pre_auth.scope
+      = submit_tag "Authorize", class: "btn btn-success wide pull-left"
+    = form_tag oauth_authorization_path, method: :delete do
+      = hidden_field_tag :client_id, @pre_auth.client.uid
+      = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
+      = hidden_field_tag :state, @pre_auth.state
+      = hidden_field_tag :response_type, @pre_auth.response_type
+      = hidden_field_tag :scope, @pre_auth.scope
+      = submit_tag "Deny", class: "btn btn-danger prepend-left-10"
\ No newline at end of file
diff --git a/app/views/doorkeeper/authorizations/show.html.haml b/app/views/doorkeeper/authorizations/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..9a402007194b0a898a1088b547cb21f77248ac62
--- /dev/null
+++ b/app/views/doorkeeper/authorizations/show.html.haml
@@ -0,0 +1,3 @@
+%h3.page-title Authorization code:
+%main{:role => "main"}
+  %code#authorization_code= params[:code]
\ No newline at end of file
diff --git a/app/views/doorkeeper/authorized_applications/_delete_form.html.haml b/app/views/doorkeeper/authorized_applications/_delete_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..4bba72167e3ebc8a0a55721befcfcffa091eec77
--- /dev/null
+++ b/app/views/doorkeeper/authorized_applications/_delete_form.html.haml
@@ -0,0 +1,4 @@
+- submit_btn_css ||= 'btn btn-link btn-remove'
+= form_tag oauth_authorized_application_path(application) do
+  %input{:name => "_method", :type => "hidden", :value => "delete"}/
+  = submit_tag 'Revoke', onclick: "return confirm('Are you sure?')", class: 'btn btn-link btn-remove btn-sm'
\ No newline at end of file
diff --git a/app/views/doorkeeper/authorized_applications/index.html.haml b/app/views/doorkeeper/authorized_applications/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..814cdc987ef7c466f4dbccab541d16be2845947b
--- /dev/null
+++ b/app/views/doorkeeper/authorized_applications/index.html.haml
@@ -0,0 +1,16 @@
+%header.page-header
+  %h1 Your authorized applications
+%main{:role => "main"}
+  %table.table.table-striped
+    %thead
+      %tr
+        %th Application
+        %th Created At
+        %th
+        %th
+    %tbody
+      - @applications.each do |application|
+        %tr
+          %td= application.name
+          %td= application.created_at.strftime('%Y-%m-%d %H:%M:%S')
+          %td= render 'delete_form', application: application
\ No newline at end of file
diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml
index f0c34def14585e1d133bb8d5b06146397ea4353b..c86ce9ae651ad9f9ceb220a69371ccb1766e6b8b 100644
--- a/app/views/events/_commit.html.haml
+++ b/app/views/events/_commit.html.haml
@@ -1,5 +1,5 @@
 %li.commit
   .commit-row-title
-    = link_to truncate_sha(commit[:id]), project_commit_path(project, commit[:id]), class: "commit_short_id", alt: ''
+    = link_to truncate_sha(commit[:id]), namespace_project_commit_path(project.namespace, project, commit[:id]), class: "commit_short_id", alt: ''
     &nbsp;
     = gfm event_commit_title(commit[:message]), project
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 613833153739e0afb591217d189971b424932473..02b1dec753c98b24b347ce2da6c889234cf822f5 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -3,13 +3,14 @@
     .event-item-timestamp
       #{time_ago_with_tooltip(event.created_at)}
 
-    = cache event do
+    = cache [event, current_user] do
       = image_tag avatar_icon(event.author_email, 24), class: "avatar s24", alt:''
 
       - if event.push?
         = render "events/event/push", event: event
-      - elsif event.note?
+      - elsif event.commented?
         = render "events/event/note", event: event
+      - elsif event.created_project?
+        = render "events/event/created_project", event: event
       - else
-        = render "events/event/common", event: event
-
+        = render "events/event/common", event: event
\ No newline at end of file
diff --git a/app/views/events/_event_issue.atom.haml b/app/views/events/_event_issue.atom.haml
index eba2b63797a8135b8cf2248b0cbad23d4b692925..0edb61ea2467fefc2f5cc5d2c793a781d541dfb0 100644
--- a/app/views/events/_event_issue.atom.haml
+++ b/app/views/events/_event_issue.atom.haml
@@ -1,3 +1,3 @@
 %div{xmlns: "http://www.w3.org/1999/xhtml"}
   - if issue.description.present?
-    = markdown issue.description
+    = markdown(issue.description, xhtml: true)
diff --git a/app/views/events/_event_last_push.html.haml b/app/views/events/_event_last_push.html.haml
index 4c9a39bcc272b73f115fe9eecf8c6f0947036814..d2f0005142abd0599bc46fc1c58dae39177dc3d3 100644
--- a/app/views/events/_event_last_push.html.haml
+++ b/app/views/events/_event_last_push.html.haml
@@ -2,13 +2,13 @@
   .event-last-push
     .event-last-push-text
       %span You pushed to
-      = link_to project_commits_path(event.project, event.ref_name) do
+      = link_to namespace_project_commits_path(event.project.namespace, event.project, event.ref_name) do
         %strong= event.ref_name
       at
       %strong= link_to_project event.project
       #{time_ago_with_tooltip(event.created_at)}
 
     .pull-right
-      = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-create btn-small" do
+      = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-create btn-sm" do
         Create Merge Request
   %hr
diff --git a/app/views/events/_event_merge_request.atom.haml b/app/views/events/_event_merge_request.atom.haml
index 0aea2d17d6531179d3b75c76a256ee63f348f4a1..1a8b62abeab17fa7eb392fbafc5e541cfc6f1cda 100644
--- a/app/views/events/_event_merge_request.atom.haml
+++ b/app/views/events/_event_merge_request.atom.haml
@@ -1,3 +1,3 @@
 %div{xmlns: "http://www.w3.org/1999/xhtml"}
   - if merge_request.description.present?
-    = markdown merge_request.description
+    = markdown(merge_request.description, xhtml: true)
diff --git a/app/views/events/_event_note.atom.haml b/app/views/events/_event_note.atom.haml
index be0e05481ed7c1036ee2918c0d4a7c3b0637b0a7..b49c331ccf2a7151a20e73d9e39fb27787ddfd83 100644
--- a/app/views/events/_event_note.atom.haml
+++ b/app/views/events/_event_note.atom.haml
@@ -1,2 +1,2 @@
 %div{xmlns: "http://www.w3.org/1999/xhtml"}
-  = markdown note.note
+  = markdown(note.note, xhtml: true)
diff --git a/app/views/events/_event_push.atom.haml b/app/views/events/_event_push.atom.haml
index 2b63519edace1e15acc6bc7991901e057ebdae38..5d14def8f75bd90cd2344f07ad3d32d9f6d34661 100644
--- a/app/views/events/_event_push.atom.haml
+++ b/app/views/events/_event_push.atom.haml
@@ -2,11 +2,11 @@
   - event.commits.first(15).each do |commit|
     %p
       %strong= commit[:author][:name]
-      = link_to "(##{truncate_sha(commit[:id])})", project_commit_path(event.project, id: commit[:id])
+      = link_to "(##{truncate_sha(commit[:id])})", namespace_project_commit_path(event.project.namespace, event.project, id: commit[:id])
       %i
         at
         = commit[:timestamp].to_time.to_s(:short)
-    %blockquote= markdown(escape_once(commit[:message]))
+    %blockquote= markdown(escape_once(commit[:message]), xhtml: true)
   - if event.commits_count > 15
     %p
       %i
diff --git a/app/views/events/_events.html.haml b/app/views/events/_events.html.haml
index 3d62d4788690528c4d2c3f06019d73605e466423..68c19df092da7f0ca114cbf5c958f10ba1d7e3d8 100644
--- a/app/views/events/_events.html.haml
+++ b/app/views/events/_events.html.haml
@@ -1 +1 @@
-= render @events
+= render partial: 'events/event', collection: @events
diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml
index a9d3adf41dfb3e070a3e0feb7fc08ceab9f59c61..a39e62e9dacc72732f325c415919d7475ea8558d 100644
--- a/app/views/events/event/_common.html.haml
+++ b/app/views/events/event/_common.html.haml
@@ -1,15 +1,17 @@
 .event-title
   %span.author_name= link_to_author event
-  %span.event_label{class: event.action_name}= event_action_name(event)
+  %span.event_label{class: event.action_name}
+    = event_action_name(event)
+
   - if event.target
-    %strong= link_to "##{event.target_iid}", [event.project, event.target]
-  - else
-    %strong= gfm event.target_title
-  at
+    %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target]
+    at
+
   - if event.project
     = link_to_project event.project
   - else
     = event.project_name
+    
 - if event.target.respond_to?(:title)
   .event-body
     .event-note
diff --git a/app/views/events/event/_created_project.html.haml b/app/views/events/event/_created_project.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..3c7153d235f2fea147f061fd2803a061f18da9b3
--- /dev/null
+++ b/app/views/events/event/_created_project.html.haml
@@ -0,0 +1,27 @@
+.event-title
+  %span.author_name= link_to_author event
+  %span.event_label{class: event.action_name}
+    = event_action_name(event)
+
+  - if event.project
+    = link_to_project event.project
+  - else
+    = event.project_name
+
+- if current_user == event.author && !event.project.private? && twitter_sharing_enabled?
+  .event-body
+    .event-note
+      .md
+        %p
+          Congratulations! Why not share your accomplishment with the world?
+
+          %a.twitter-share-button{ |
+            href: "https://twitter.com/share", |
+            "data-url" => event.project.web_url, |
+            "data-text" => "I just created a new project in GitLab! GitLab is version control on your server.", |
+            "data-size" => "medium", |
+            "data-related" => "gitlab", |
+            "data-hashtags" => "gitlab", |
+            "data-count" => "none"}
+            Tweet
+          %script{src: "//platform.twitter.com/widgets.js"}
\ No newline at end of file
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index 6ec8e54fba5617c6dfe018850753b7bb4a9e8e86..4ef18c0906018b63829f78bfbb68e73d1ce7fca2 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -1,6 +1,10 @@
 .event-title
   %span.author_name= link_to_author event
-  %span.event_label commented on #{event_note_title_html(event)} at
+  %span.event_label
+    = event.action_name
+    = event_note_title_html(event)
+    at
+    
   - if event.project
     = link_to_project event.project
   - else
@@ -14,9 +18,9 @@
     - note = event.target
     - if note.attachment.url
       - if note.attachment.image?
-        = link_to note.attachment.secure_url, target: '_blank' do
-          = image_tag note.attachment.secure_url, class: 'note-image-attach'
+        = link_to note.attachment.url, target: '_blank' do
+          = image_tag note.attachment.url, class: 'note-image-attach'
       - else
-        = link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do
+        = link_to note.attachment.url, target: "_blank", class: 'note-file-attach' do
           %i.fa.fa-paperclip
           = note.attachment_identifier
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index b912b5e092fccf78d63f9978fee8a13780fa2894..60d7978b13f07a19b2ee23445335cee072c3f6ec 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -1,10 +1,10 @@
 .event-title
   %span.author_name= link_to_author event
-  %span.event_label.pushed #{event.push_action_name} #{event.ref_type}
+  %span.event_label.pushed #{event.action_name} #{event.ref_type}
   - if event.rm_ref?
     %strong= event.ref_name
   - else
-    = link_to project_commits_path(event.project, event.ref_name) do
+    = link_to namespace_project_commits_path(event.project.namespace, event.project, event.ref_name) do
       %strong= event.ref_name
   at
   = link_to_project event.project
@@ -21,5 +21,11 @@
         %li.commits-stat
           - if event.commits_count > 2
             %span ... and #{event.commits_count - 2} more commits.
-          = link_to project_compare_path(event.project, from: event.commit_from, to: event.commit_to) do
-            %strong Compare &rarr; #{truncate_sha(event.commit_from)}...#{truncate_sha(event.commit_to)}
+          - if event.md_ref?
+            - from = event.commit_from
+            - from_label = truncate_sha(from)
+          - else
+            - from = event.project.default_branch
+            - from_label = from
+          = link_to namespace_project_compare_path(event.project.namespace, event.project, from: from, to: event.commit_to) do
+            %strong Compare &rarr; #{from_label}...#{truncate_sha(event.commit_to)}
diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml
index 709d062df8351e15f0273d995aceb801dac1db75..2ea6cb186558187b19d27566ee9143ebe291b419 100644
--- a/app/views/explore/groups/index.html.haml
+++ b/app/views/explore/groups/index.html.haml
@@ -1,6 +1,7 @@
 .clearfix
   .pull-left
     = form_tag explore_groups_path, method: :get, class: 'form-inline form-tiny' do |f|
+      = hidden_field_tag :sort, @sort
       .form-group
         = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input input-mn-300", id: "groups_search"
       .form-group
@@ -8,25 +9,23 @@
 
   .pull-right
     .dropdown.inline
-      %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
+      %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
         %span.light sort:
         - if @sort.present?
-          = @sort.humanize
+          = sort_options_hash[@sort]
         - else
-          Name
+          = sort_title_recently_created
         %b.caret
       %ul.dropdown-menu
         %li
-          = link_to explore_groups_path(sort: nil) do
-            Name
-          = link_to explore_groups_path(sort: 'newest') do
-            Newest
-          = link_to explore_groups_path(sort: 'oldest') do
-            Oldest
-          = link_to explore_groups_path(sort: 'recently_updated') do
-            Recently updated
-          = link_to explore_groups_path(sort: 'last_updated') do
-            Last updated
+          = link_to explore_groups_path(sort: sort_value_recently_created) do
+            = sort_title_recently_created
+          = link_to explore_groups_path(sort: sort_value_oldest_created) do
+            = sort_title_oldest_created
+          = link_to explore_groups_path(sort: sort_value_recently_updated) do
+            = sort_title_recently_updated
+          = link_to explore_groups_path(sort: sort_value_oldest_updated) do
+            = sort_title_oldest_updated
 
 %hr
 
diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..b3963a9d9013327d4e6a67237993884b0036689c
--- /dev/null
+++ b/app/views/explore/projects/_filter.html.haml
@@ -0,0 +1,67 @@
+.pull-left
+  = form_tag explore_projects_filter_path, method: :get, class: 'form-inline form-tiny' do |f|
+    .form-group
+      = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input input-mn-300", id: "projects_search"
+    .form-group
+      = button_tag 'Search', class: "btn btn-primary wide"
+
+.pull-right.hidden-sm.hidden-xs
+  - if current_user
+    .dropdown.inline.append-right-10
+      %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
+        %i.fa.fa-globe
+        %span.light Visibility:
+        - if params[:visibility_level].present?
+          = visibility_level_label(params[:visibility_level].to_i)
+        - else
+          Any
+        %b.caret
+      %ul.dropdown-menu
+        %li
+          = link_to explore_projects_filter_path(visibility_level: nil) do
+            Any
+        - Gitlab::VisibilityLevel.values.each do |level|
+          %li{ class: (level.to_s == params[:visibility_level]) ? 'active' : 'light' }
+            = link_to explore_projects_filter_path(visibility_level: level) do
+              = visibility_level_icon(level)
+              = visibility_level_label(level)
+
+  - if @tags.present?
+    .dropdown.inline.append-right-10
+      %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
+        %i.fa.fa-tags
+        %span.light Tags:
+        - if params[:tag].present?
+          = params[:tag]
+        - else
+          Any
+        %b.caret
+      %ul.dropdown-menu
+        %li
+          = link_to explore_projects_filter_path(tag: nil) do
+            Any
+
+        - @tags.each do |tag|
+          %li{ class: (tag.name == params[:tag]) ? 'active' : 'light' }
+            = link_to explore_projects_filter_path(tag: tag.name) do
+              %i.fa.fa-tag
+              = tag.name
+
+  .dropdown.inline
+    %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
+      %span.light sort:
+      - if @sort.present?
+        = sort_options_hash[@sort]
+      - else
+        = sort_title_recently_created
+      %b.caret
+    %ul.dropdown-menu
+      %li
+        = link_to explore_projects_filter_path(sort: sort_value_recently_created) do
+          = sort_title_recently_created
+        = link_to explore_projects_filter_path(sort: sort_value_oldest_created) do
+          = sort_title_oldest_created
+        = link_to explore_projects_filter_path(sort: sort_value_recently_updated) do
+          = sort_title_recently_updated
+        = link_to explore_projects_filter_path(sort: sort_value_oldest_updated) do
+          = sort_title_oldest_updated
diff --git a/app/views/explore/projects/_project.html.haml b/app/views/explore/projects/_project.html.haml
index ffbddbae4d660af054bb665d546afead94fd8cd5..d65fb529373131b7bae68e3f217644124380854b 100644
--- a/app/views/explore/projects/_project.html.haml
+++ b/app/views/explore/projects/_project.html.haml
@@ -2,12 +2,10 @@
   %h4.project-title
     .project-access-icon
       = visibility_level_icon(project.visibility_level)
-    = link_to project.name_with_namespace, project
-
-    - if current_page?(starred_explore_projects_path)
-      %strong.pull-right
-        %i.fa.fa-star
-        = pluralize project.star_count, 'star'
+    = link_to project.name_with_namespace, [project.namespace.becomes(Namespace), project]
+    %span.pull-right
+      %i.fa.fa-star
+      = project.star_count
 
   .project-info
     - if project.description.present?
@@ -16,11 +14,11 @@
 
     .repo-info
       - unless project.empty_repo?
-        = link_to pluralize(project.repository.round_commit_count, 'commit'), project_commits_path(project, project.default_branch)
+        = link_to pluralize(project.repository.round_commit_count, 'commit'), namespace_project_commits_path(project.namespace, project, project.default_branch)
         &middot;
-        = link_to pluralize(project.repository.branch_names.count, 'branch'), project_branches_path(project)
+        = link_to pluralize(project.repository.branch_names.count, 'branch'), namespace_project_branches_path(project.namespace, project)
         &middot;
-        = link_to pluralize(project.repository.tag_names.count, 'tag'), project_tags_path(project)
+        = link_to pluralize(project.repository.tag_names.count, 'tag'), namespace_project_tags_path(project.namespace, project)
       - else
         %i.fa.fa-exclamation-triangle
         Empty repository
diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml
index f797c4e3830d0250f57fdae04c391c1c2743371e..5086b58cd03e93e359fb991457a4e0204df4455d 100644
--- a/app/views/explore/projects/index.html.haml
+++ b/app/views/explore/projects/index.html.haml
@@ -1,32 +1,5 @@
 .clearfix
-  .pull-left
-    = form_tag explore_projects_path, method: :get, class: 'form-inline form-tiny' do |f|
-      .form-group
-        = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input input-mn-300", id: "projects_search"
-      .form-group
-        = button_tag 'Search', class: "btn btn-primary wide"
-
-  .pull-right
-    .dropdown.inline
-      %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
-        %span.light sort:
-        - if @sort.present?
-          = @sort.humanize
-        - else
-          Name
-        %b.caret
-      %ul.dropdown-menu
-        %li
-          = link_to explore_projects_path(sort: nil) do
-            Name
-          = link_to explore_projects_path(sort: 'newest') do
-            Newest
-          = link_to explore_projects_path(sort: 'oldest') do
-            Oldest
-          = link_to explore_projects_path(sort: 'recently_updated') do
-            Recently updated
-          = link_to explore_projects_path(sort: 'last_updated') do
-            Last updated
+  = render 'filter'
 
 %hr
 .public-projects
diff --git a/app/views/groups/_filter.html.haml b/app/views/groups/_filter.html.haml
deleted file mode 100644
index 393be3f1d12e192916d8b8d81c114d92b447a6e9..0000000000000000000000000000000000000000
--- a/app/views/groups/_filter.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-= form_tag group_filter_path(entity), method: 'get' do
-  %fieldset
-    %ul.nav.nav-pills.nav-stacked
-      %li{class: ("active" if (params[:status] == 'active' || !params[:status]))}
-        = link_to group_filter_path(entity, status: 'active') do
-          Active
-      %li{class: ("active" if params[:status] == 'closed')}
-        = link_to group_filter_path(entity, status: 'closed') do
-          Closed
-      %li{class: ("active" if params[:status] == 'all')}
-        = link_to group_filter_path(entity, status: 'all') do
-          All
diff --git a/app/views/groups/_new_group_member.html.haml b/app/views/groups/_new_group_member.html.haml
deleted file mode 100644
index e590ddbf931feb9aa1c6a0891ef6cb7cc23f2ed4..0000000000000000000000000000000000000000
--- a/app/views/groups/_new_group_member.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-= form_for @users_group, url: group_group_members_path(@group), html: { class: 'form-horizontal users-group-form' } do |f|
-  .form-group
-    = f.label :user_ids, "People", class: 'control-label'
-    .col-sm-10= users_select_tag(:user_ids, multiple: true, class: 'input-large')
-
-  .form-group
-    = f.label :access_level, "Group Access", class: 'control-label'
-    .col-sm-10= select_tag :access_level, options_for_select(GroupMember.access_level_roles, @users_group.access_level), class: "project-access-select select2"
-
-  .form-actions
-    = f.submit 'Add users into group', class: "btn btn-create"
diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml
index 2c65b3049e3b9c59ed6df12d8f21836455be8f25..4f8aec1c67e9a4f767febb7cc0f7c5313edef0b9 100644
--- a/app/views/groups/_projects.html.haml
+++ b/app/views/groups/_projects.html.haml
@@ -1,21 +1,10 @@
 .panel.panel-default
-  .panel-heading
-    Projects (#{projects.count})
-    - if can? current_user, :create_projects, @group
-      .panel-head-actions
-        = link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do
-          %i.fa.fa-plus
-          New project
-  %ul.well-list
-    - if projects.blank?
-      .nothing-here-block This group has no projects yet
-    - projects.each do |project|
-      %li.project-row
-        = link_to project_path(project), class: dom_class(project) do
-          .dash-project-access-icon
-            = visibility_level_icon(project.visibility_level)
-          %span.str-truncated
-            %span.project-name
-              = project.name
-          %span.arrow
-            %i.fa.fa-angle-right
+  .panel-heading.clearfix
+    .input-group
+      = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control'
+      - if can? current_user, :create_projects, @group
+        %span.input-group-btn
+          = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-success' do
+            New project
+
+  = render 'shared/projects_list', projects: @projects, projects_limit: 20
diff --git a/app/views/groups/_settings_nav.html.haml b/app/views/groups/_settings_nav.html.haml
index ec1fb4a2c00effb343fa4f88a362c1bd9ee715a1..e6aee22e529a1e0afe43511d962dc5b2ca9a2d59 100644
--- a/app/views/groups/_settings_nav.html.haml
+++ b/app/views/groups/_settings_nav.html.haml
@@ -1,10 +1,11 @@
-%ul.nav.nav-pills.nav-stacked.nav-stacked-menu
+%ul.sidebar-subnav
   = nav_link(path: 'groups#edit') do
-    = link_to edit_group_path(@group) do
+    = link_to edit_group_path(@group), title: 'Group' do
       %i.fa.fa-pencil-square-o
-      Group
+      %span
+        Group
   = nav_link(path: 'groups#projects') do
-    = link_to projects_group_path(@group) do
+    = link_to projects_group_path(@group), title: 'Projects' do
       %i.fa.fa-folder
-      Projects
-
+      %span
+        Projects
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index eb24fd65d9ee060bba1bfc60d708a910c27c7a65..49e7180bf9873a6d171a77481f04bfc5379f56a9 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -1,41 +1,37 @@
-.row
-  .col-md-2
-    = render 'settings_nav'
-  .col-md-10
-    .panel.panel-default
-      .panel-heading
-        %strong= @group.name
-        group settings:
-      .panel-body
-        = form_for @group, html: { multipart: true, class: "form-horizontal" }, authenticity_token: true do |f|
-          - if @group.errors.any?
-            .alert.alert-danger
-              %span= @group.errors.full_messages.first
-          = render 'shared/group_form', f: f
+.panel.panel-default
+  .panel-heading
+    %strong= @group.name
+    group settings:
+  .panel-body
+    = form_for @group, html: { multipart: true, class: "form-horizontal" }, authenticity_token: true do |f|
+      - if @group.errors.any?
+        .alert.alert-danger
+          %span= @group.errors.full_messages.first
+      = render 'shared/group_form', f: f
 
-          .form-group
-            .col-sm-2
-            .col-sm-10
-              = image_tag group_icon(@group.to_param), alt: '', class: 'avatar s160'
-              %p.light
-                - if @group.avatar?
-                  You can change your group avatar here
-                - else
-                  You can upload a group avatar here
-              = render 'shared/choose_group_avatar_button', f: f
-              - if @group.avatar?
-                %hr
-                = link_to 'Remove avatar', group_avatar_path(@group.to_param), data: { confirm: "Group avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar"
+      .form-group
+        .col-sm-2
+        .col-sm-10
+          = image_tag group_icon(@group), alt: '', class: 'avatar group-avatar s160'
+          %p.light
+            - if @group.avatar?
+              You can change your group avatar here
+            - else
+              You can upload a group avatar here
+          = render 'shared/choose_group_avatar_button', f: f
+          - if @group.avatar?
+            %hr
+            = link_to 'Remove avatar', group_avatar_path(@group.to_param), data: { confirm: "Group avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
 
-          .form-actions
-            = f.submit 'Save group', class: "btn btn-save"
+      .form-actions
+        = f.submit 'Save group', class: "btn btn-save"
 
-    .panel.panel-danger
-      .panel-heading Remove group
-      .panel-body
-        %p
-          Removing group will cause all child projects and resources to be removed.
-          %br
-          %strong Removed group can not be restored!
+.panel.panel-danger
+  .panel-heading Remove group
+  .panel-body
+    %p
+      Removing group will cause all child projects and resources to be removed.
+      %br
+      %strong Removed group can not be restored!
 
-        = link_to 'Remove Group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove"
+    = link_to 'Remove Group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove"
diff --git a/app/views/groups/group_members/_group_member.html.haml b/app/views/groups/group_members/_group_member.html.haml
index d05016d9c3f514c1c78808cfa01548e315ce8093..30e5faf822eaee3d5ba87d73e33878a708c403f6 100644
--- a/app/views/groups/group_members/_group_member.html.haml
+++ b/app/views/groups/group_members/_group_member.html.haml
@@ -1,6 +1,7 @@
 - user = member.user
 - return unless user
 - show_roles = true if show_roles.nil?
+
 %li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)}
   %span{class: ("list-item-name" if show_controls)}
     = image_tag avatar_icon(user.email, 16), class: "avatar s16"
@@ -8,24 +9,31 @@
     %span.cgray= user.username
     - if user == current_user
       %span.label.label-success It's you
+    - if user.blocked?
+      %label.label.label-danger
+        %strong Blocked
 
   - if show_roles
     %span.pull-right
       %strong= member.human_access
       - if show_controls
-        - if can?(current_user, :modify, member)
-          = link_to '#', class: "btn-tiny btn js-toggle-button", title: 'Edit access level' do
+        - if can?(current_user, :modify_group_member, member)
+          = button_tag class: "btn-xs btn js-toggle-button",
+                       title: 'Edit access level', type: 'button' do
             %i.fa.fa-pencil-square-o
-        - if can?(current_user, :destroy, member)
-          - if current_user == member.user
-            = link_to leave_profile_group_path(@group), data: { confirm: leave_group_message(@group.name)}, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
+        - if can?(current_user, :destroy_group_member, member)
+          &nbsp;
+          - if current_user == user
+            = link_to leave_group_group_members_path(@group), data: { confirm: leave_group_message(@group.name)}, method: :delete, class: "btn-xs btn btn-remove", title: 'Remove user from group' do
               %i.fa.fa-minus.fa-inverse
           - else
-            = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
+            = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do
               %i.fa.fa-minus.fa-inverse
 
     .edit-member.hide.js-toggle-content
+      %br
       = form_for [@group, member], remote: true do |f|
-        .alert.prepend-top-20
-          = f.select :access_level, options_for_select(GroupMember.access_level_roles, member.access_level)
-          = f.submit 'Save', class: 'btn btn-save btn-small'
+        .prepend-top-10
+          = f.select :access_level, options_for_select(GroupMember.access_level_roles, member.access_level), {}, class: 'form-control'
+        .prepend-top-10
+          = f.submit 'Save', class: 'btn btn-save btn-sm'
diff --git a/app/views/groups/group_members/_new_group_member.html.haml b/app/views/groups/group_members/_new_group_member.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..a52b81973849508c3e851330733a5b0a525e72ba
--- /dev/null
+++ b/app/views/groups/group_members/_new_group_member.html.haml
@@ -0,0 +1,15 @@
+= form_for @group_member, url: group_group_members_path(@group), html: { class: 'form-horizontal users-group-form' } do |f|
+  .form-group
+    = f.label :user_ids, "People", class: 'control-label'
+    .col-sm-10= users_select_tag(:user_ids, multiple: true, class: 'input-large', scope: :all)
+
+  .form-group
+    = f.label :access_level, "Group Access", class: 'control-label'
+    .col-sm-10
+      = select_tag :access_level, options_for_select(GroupMember.access_level_roles, @group_member.access_level), class: "project-access-select select2"
+      .help-block
+        Read more about role permissions
+        %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
+
+  .form-actions
+    = f.submit 'Add users to group', class: "btn btn-create"
diff --git a/app/views/groups/members.html.haml b/app/views/groups/group_members/index.html.haml
similarity index 87%
rename from app/views/groups/members.html.haml
rename to app/views/groups/group_members/index.html.haml
index d2ebcdab7e1ec4a9974b2a69ffcf501c709956d5..0d501fe7bd37be44261cab3f060f80e53fb56609 100644
--- a/app/views/groups/members.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -1,4 +1,5 @@
 - show_roles = should_user_see_group_roles?(current_user, @group)
+
 %h3.page-title
   Group members
 - if show_roles
@@ -10,14 +11,14 @@
 %hr
 
 .clearfix.js-toggle-container
-  = form_tag members_group_path(@group), method: :get, class: 'form-inline member-search-form'  do
+  = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form'  do
     .form-group
       = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input input-mn-300' }
     = button_tag 'Search', class: 'btn'
 
   - if current_user && current_user.can?(:manage_group, @group)
     .pull-right
-      = link_to '#', class: 'btn btn-new js-toggle-button' do
+      = button_tag class: 'btn btn-new js-toggle-button', type: 'button' do
         Add members
         %i.fa.fa-chevron-down
 
@@ -33,6 +34,7 @@
   %ul.well-list
     - @members.each do |member|
       = render 'groups/group_members/group_member', member: member, show_roles: show_roles, show_controls: true
+
 = paginate @members, theme: 'gitlab'
 
 :coffeescript
diff --git a/app/views/groups/issues.atom.builder b/app/views/groups/issues.atom.builder
index f2005193f830181987058910753be4115113473b..240001967f36a8e55664e6c7d99da2c95634f2db 100644
--- a/app/views/groups/issues.atom.builder
+++ b/app/views/groups/issues.atom.builder
@@ -7,18 +7,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
   xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
 
   @issues.each do |issue|
-    xml.entry do
-      xml.id      project_issue_url(issue.project, issue)
-      xml.link    :href => project_issue_url(issue.project, issue)
-      xml.title   truncate(issue.title, :length => 80)
-      xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
-      xml.media   :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
-      xml.author do |author|
-        xml.name issue.author_name
-        xml.email issue.author_email
-      end
-      xml.summary issue.title
-    end
+    issue_to_atom(xml, issue)
   end
 end
 
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index 1932ba2f6440e3d5dcf743b8f9f93421b6ac2eb3..6c0d89c4e7cbf7e67aecb1fd8333a7526c50de86 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -9,10 +9,6 @@
     To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page.
 %hr
 
-.row
-  .fixed.sidebar-expand-button.hidden-lg.hidden-md
-    %i.fa.fa-list.fa-2x
-  .col-md-3.responsive-side
-    = render 'shared/filter', entity: 'issue'
-  .col-md-9
-    = render 'shared/issues'
+.append-bottom-20
+  = render 'shared/issuable_filter'
+= render 'shared/issues'
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 86d5acdaa320c9c707652afb5d5dfdc273b7ce3a..1ad74905636f7f3b0637696bcaa6262b36ab4766 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -8,10 +8,6 @@
   - if current_user
     To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page.
 %hr
-.row
-  .fixed.sidebar-expand-button.hidden-lg.hidden-md
-    %i.fa.fa-list.fa-2x
-  .col-md-3.responsive-side
-    = render 'shared/filter', entity: 'merge_request'
-  .col-md-9
-    = render 'shared/merge_requests'
+.append-bottom-20
+  = render 'shared/issuable_filter'
+= render 'shared/merge_requests'
diff --git a/app/views/groups/milestones/_issue.html.haml b/app/views/groups/milestones/_issue.html.haml
index c95c2e89670eb73fd14d6d6ee70cb0873a4931a3..27d0c62df8c210505422a3ee28f9f535849520a2 100644
--- a/app/views/groups/milestones/_issue.html.haml
+++ b/app/views/groups/milestones/_issue.html.haml
@@ -2,9 +2,9 @@
   %span.milestone-row
     - project = issue.project
     %strong #{project.name} &middot;
-    = link_to [project, issue] do
+    = link_to [project.namespace.becomes(Namespace), project, issue] do
       %span.cgray ##{issue.iid}
-    = link_to_gfm issue.title, [project, issue], title: issue.title
+    = link_to_gfm issue.title, [project.namespace.becomes(Namespace), project, issue], title: issue.title
   .pull-right.assignee-icon
     - if issue.assignee
       = image_tag avatar_icon(issue.assignee.email, 16), class: "avatar s16"
diff --git a/app/views/groups/milestones/_merge_request.html.haml b/app/views/groups/milestones/_merge_request.html.haml
index e0c903bfdb2856da35f3b9d8e7a3b11266d845d8..b2d2097dfab4441aa9784040580306464503af85 100644
--- a/app/views/groups/milestones/_merge_request.html.haml
+++ b/app/views/groups/milestones/_merge_request.html.haml
@@ -2,9 +2,9 @@
   %span.milestone-row
     - project = merge_request.project
     %strong #{project.name} &middot;
-    = link_to [project, merge_request] do
+    = link_to [project.namespace.becomes(Namespace), project, merge_request] do
       %span.cgray ##{merge_request.iid}
-    = link_to_gfm merge_request.title, [project, merge_request], title: merge_request.title
+    = link_to_gfm merge_request.title, [project.namespace.becomes(Namespace), project, merge_request], title: merge_request.title
   .pull-right.assignee-icon
     - if merge_request.assignee
       = image_tag avatar_icon(merge_request.assignee.email, 16), class: "avatar s16"
diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml
index 2727525f070d2a273ed139270dcdceb04fabd57e..57dc235f5bb32cece11fec15ade4afa25270f483 100644
--- a/app/views/groups/milestones/index.html.haml
+++ b/app/views/groups/milestones/index.html.haml
@@ -9,42 +9,38 @@
 
 %hr
 
-.row
-  .fixed.sidebar-expand-button.hidden-lg.hidden-md
-    %i.fa.fa-list.fa-2x
-  .col-md-3.responsive-side
-    = render 'groups/filter', entity: 'milestone'
-  .col-md-9
-    .panel.panel-default
-      %ul.well-list
-        - if @group_milestones.blank?
-          %li
-            .nothing-here-block No milestones to show
-        - else
-          - @group_milestones.each do |milestone|
-            %li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
-              .pull-right
-                - if can?(current_user, :manage_group, @group)
-                  - if milestone.closed?
-                    = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped btn-reopen"
-                  - else
-                    = link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-close"
-              %h4
-                = link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title)
+= render 'shared/milestones_filter'
+.milestones
+  .panel.panel-default
+    %ul.well-list
+      - if @group_milestones.blank?
+        %li
+          .nothing-here-block No milestones to show
+      - else
+        - @group_milestones.each do |milestone|
+          %li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
+            .pull-right
+              - if can?(current_user, :manage_group, @group)
+                - if milestone.closed?
+                  = link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen"
+                - else
+                  = link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close"
+            %h4
+              = link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title)
+            %div
               %div
-                %div
-                  = link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
-                    = pluralize milestone.issue_count, 'Issue'
-                  &nbsp;
-                  = link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
-                    = pluralize milestone.merge_requests_count, 'Merge Request'
-                  &nbsp;
-                  %span.light #{milestone.percent_complete}% complete
-                .progress.progress-info
-                  .progress-bar{style: "width: #{milestone.percent_complete}%;"}
-                %div
-                  %br
-                  - milestone.projects.each do |project|
+                = link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
+                  = pluralize milestone.issue_count, 'Issue'
+                &nbsp;
+                = link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
+                  = pluralize milestone.merge_requests_count, 'Merge Request'
+                &nbsp;
+                %span.light #{milestone.percent_complete}% complete
+              = milestone_progress_bar(milestone)
+              %div
+                %br
+                - milestone.milestones.each do |milestone|
+                  = link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) do
                     %span.label.label-default
-                      = project.name
-    = paginate @group_milestones, theme: "gitlab"
+                      = milestone.project.name
+  = paginate @group_milestones, theme: "gitlab"
diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml
index 411d1822be0d79ec0f3dd66a1ec66779cb54fd33..fea70f5cbc37f18f06f6fb2a3b133ab045e093e4 100644
--- a/app/views/groups/milestones/show.html.haml
+++ b/app/views/groups/milestones/show.html.haml
@@ -1,52 +1,51 @@
-%h3.page-title
+%h4.page-title
+  .issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" }
+    - if @group_milestone.closed?
+      Closed
+    - else
+      Open
   Milestone #{@group_milestone.title}
   .pull-right
     - if can?(current_user, :manage_group, @group)
       - if @group_milestone.active?
-        = link_to 'Close Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-close"
+        = link_to 'Close Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close"
       - else
-        = link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped btn-reopen"
+        = link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen"
 
+%hr
 - if (@group_milestone.total_items_count == @group_milestone.closed_items_count) && @group_milestone.active?
   .alert.alert-success
     %span All issues for this milestone are closed. You may close the milestone now.
 
-.back-link
-  = link_to group_milestones_path(@group) do
-    &larr; To milestones list
-
-.issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" }
-  .state.clearfix
-    .state-label
-      - if @group_milestone.closed?
-        Closed
-      - else
-        Open
-
-  %h4.title
-    = gfm escape_once(@group_milestone.title)
-
-  .description
-    - @group_milestone.milestones.each do |milestone|
-      %hr
-      %h4
-        = link_to "#{milestone.project.name} - #{milestone.title}", project_milestone_path(milestone.project, milestone)
-        %span.pull-right= milestone.expires_at
+.description
+%table.table
+  %thead
+    %tr
+      %th Project
+      %th Open issues
+      %th State
+      %th Due date
+  - @group_milestone.milestones.each do |milestone|
+    %tr
+      %td
+        = link_to "#{milestone.project.name}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
+      %td
+        = milestone.issues.opened.count
+      %td
         - if milestone.closed?
-          %span.label.label-danger #{milestone.state}
-      = preserve do
-        - if milestone.description.present?
-          = milestone.description
-
-  .context
-    %p
-      Progress:
-      #{@group_milestone.closed_items_count} closed
-      &ndash;
-      #{@group_milestone.open_items_count} open
+          Closed
+        - else
+          Open
+      %td
+        = milestone.expires_at
 
-    .progress.progress-info
-      .progress-bar{style: "width: #{@group_milestone.percent_complete}%;"}
+.context
+  %p.lead
+    Progress:
+    #{@group_milestone.closed_items_count} closed
+    &ndash;
+    #{@group_milestone.open_items_count} open
+  = milestone_progress_bar(@group_milestone)
 
 %ul.nav.nav-tabs
   %li.active
diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml
index 65a66355c563a9a98d948c9487f44d8c3ffead1e..dd1fa3840d5b233675db462946de57e0b400d54b 100644
--- a/app/views/groups/projects.html.haml
+++ b/app/views/groups/projects.html.haml
@@ -1,29 +1,25 @@
-.row
-  .col-md-2
-    = render 'settings_nav'
-  .col-md-10
-    .panel.panel-default
-      .panel-heading
-        %strong= @group.name
-        projects:
-        - if can? current_user, :manage_group, @group
-          .panel-head-actions
-            = link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do
-              %i.fa.fa-plus
-              New Project
-      %ul.well-list
-        - @projects.each do |project|
-          %li
-            .list-item-name
-              = visibility_level_icon(project.visibility_level)
-              %strong= link_to project.name_with_namespace, project
-              %span.label.label-gray
-                = repository_size(project)
-            .pull-right
-              = link_to 'Members', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
-              = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
-              = link_to 'Remove', project, data: { confirm: remove_project_message(project)}, method: :delete, class: "btn btn-small btn-remove"
-        - if @projects.blank?
-          .nothing-here-block This group has no projects yet
+.panel.panel-default
+  .panel-heading
+    %strong= @group.name
+    projects:
+    - if can? current_user, :manage_group, @group
+      .panel-head-actions
+        = link_to new_project_path(namespace_id: @group.id), class: "btn btn-sm btn-success" do
+          %i.fa.fa-plus
+          New Project
+  %ul.well-list
+    - @projects.each do |project|
+      %li
+        .list-item-name
+          = visibility_level_icon(project.visibility_level)
+          %strong= link_to project.name_with_namespace, project
+          %span.label.label-gray
+            = repository_size(project)
+        .pull-right
+          = link_to 'Members', namespace_project_project_members_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn btn-sm"
+          = link_to 'Edit', edit_namespace_project_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn btn-sm"
+          = link_to 'Remove', project, data: { confirm: remove_project_message(project)}, method: :delete, class: "btn btn-sm btn-remove"
+    - if @projects.blank?
+      .nothing-here-block This group has no projects yet
 
-    = paginate @projects, theme: "gitlab"
+= paginate @projects, theme: "gitlab"
diff --git a/app/views/groups/show.atom.builder b/app/views/groups/show.atom.builder
index e07bb7d2fb7145b863b9d6cf9cf950971f446765..c78bd1bd2637f2412f6f1f90a346ea86fe495e57 100644
--- a/app/views/groups/show.atom.builder
+++ b/app/views/groups/show.atom.builder
@@ -1,28 +1,12 @@
 xml.instruct!
 xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
   xml.title   "Group feed - #{@group.name}"
-  xml.link    :href => group_path(@group, :atom), :rel => "self", :type => "application/atom+xml"
-  xml.link    :href => group_path(@group), :rel => "alternate", :type => "text/html"
+  xml.link    href: group_path(@group, :atom), rel: "self", type: "application/atom+xml"
+  xml.link    href: group_path(@group), rel: "alternate", type: "text/html"
   xml.id      projects_url
   xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
 
   @events.each do |event|
-    if event.proper?
-      xml.entry do
-        event_link = event_feed_url(event)
-        event_title = event_feed_title(event)
-
-        xml.id      "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
-        xml.link    :href => event_link
-        xml.title   truncate(event_title, :length => 80)
-        xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
-        xml.media   :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
-        xml.author do |author|
-          xml.name event.author_name
-          xml.email event.author_email
-        end
-        xml.summary event_title
-      end
-    end
+    event_to_atom(xml, event)
   end
 end
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index d876e87852c7161431b297425b0ff7bf50d50719..8df9366ecbe9d9a9e2cc91dd63f08dac2e0a1a5f 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -1,37 +1,22 @@
 .dashboard
-  %section.activities.col-md-8.hidden-sm.hidden-xs
-    - if current_user
-      = render "events/event_last_push", event: @last_push
-      = link_to dashboard_path, class: 'btn btn-tiny' do
-        &larr; To dashboard
-      &nbsp;
-    %span.cgray
-      Currently you are only seeing events from the
+  .header-with-avatar.clearfix
+    = image_tag group_icon(@group), class: "avatar group-avatar s90"
+    %h3
       = @group.name
-      group
-    %hr
-    = render 'shared/event_filter'
-    - if @events.any?
+    .username
+      @#{@group.path}
+    - if @group.description.present?
+      .description
+        = escaped_autolink(@group.description)
+  %hr
+  .row
+    %section.activities.col-md-8
+      - if current_user
+        = render "events/event_last_push", event: @last_push
+        = render 'shared/event_filter'
       .content_list
-    - else
-      .nothing-here-block Project activity will be displayed here
-    = spinner
-  %aside.side.col-md-4
-    .light-well.append-bottom-20
-      = image_tag group_icon(@group.path), class: "avatar s90"
-      .clearfix.light
-        %h3.page-title
-          = @group.name
-        - if @group.description.present?
-          %p
-            = escaped_autolink(@group.description)
-    = render "projects", projects: @projects
-    - if current_user
-      .prepend-top-20
-        = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed" do
-          %strong
-            %i.fa.fa-rss
-            News Feed
-
-    %hr
-    = render 'shared/promo'
+      = spinner
+    %aside.side.col-md-4
+      = render "projects", projects: @projects
+    = link_to '#aside', class: 'show-aside' do
+      %i.fa.fa-angle-left
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 7b8193abfdf6674d81c0c840718bf5f8dc5c6965..af39dfeac5b5834f5fe7f43feacfdf19a496adf3 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -42,3 +42,9 @@
         %li
           Use
           = link_to 'shortcuts', '#', onclick: 'Shortcuts.showHelp(event)'
+        %li
+          Get a support
+          = link_to 'subscription', 'https://about.gitlab.com/pricing/'
+        %li
+          = link_to 'Compare', 'https://about.gitlab.com/features/#compare'
+          GitLab editions
diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml
index 67f9cc41cf36510050719ca5d15972c1a9586248..eca34dbff06fabb474c16aab5517d9585e58601d 100644
--- a/app/views/help/show.html.haml
+++ b/app/views/help/show.html.haml
@@ -1,2 +1,2 @@
 .documentation.wiki
-  = markdown File.read(Rails.root.join('doc', @category, @file + '.md'))
+  = markdown File.read(Rails.root.join('doc', @category, @file + '.md')).gsub("$your_email", current_user.email)
diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..246a6c1bdfd5dbd46bd4d7f915e9ec9e8a9b1317
--- /dev/null
+++ b/app/views/help/ui.html.haml
@@ -0,0 +1,227 @@
+- lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed fermentum nisi sapien, non consequat lectus aliquam ultrices. Suspendisse sodales est euismod nunc condimentum, a consectetur diam ornare."
+
+.gitlab-ui-dev-kit
+  %h1 GitLab UI development kit
+  %p.light
+    Use page inspector in your browser to check element classes and structure
+    of examples below.
+  %hr
+  %ul
+    %li
+      = link_to 'Blocks', '#blocks'
+    %li
+      = link_to 'Lists', '#lists'
+    %li
+      = link_to 'Tables', '#tables'
+    %li
+      = link_to 'Buttons', '#buttons'
+    %li
+      = link_to 'Panels', '#panels'
+    %li
+      = link_to 'Alerts', '#alerts'
+    %li
+      = link_to 'Forms', '#forms'
+    %li
+      = link_to 'Files', '#file'
+    %li
+      = link_to 'Markdown', '#markdown'
+
+  %h2#blocks Blocks
+
+  %h3
+    %code .well
+
+
+  .well
+    %h4 Something
+    = lorem
+
+
+  %h2#lists Lists
+
+  %h3
+    %code .well-list
+  %ul.well-list
+    %li
+      One item
+    %li
+      One item
+    %li
+      One item
+
+  %h3
+    %code .panel .well-list
+
+  .panel.panel-default
+    .panel-heading Your list
+    %ul.well-list
+      %li
+        One item
+      %li
+        One item
+      %li
+        One item
+
+  %h3
+    %code .bordered-list
+  %ul.bordered-list
+    %li
+      One item
+    %li
+      One item
+    %li
+      One item
+
+
+
+  %h2#tables Tables
+
+  .example
+    %table.table
+      %thead
+        %tr
+          %th #
+          %th First Name
+          %th Last Name
+          %th Username
+      %tbody
+        %tr
+          %td 1
+          %td Mark
+          %td Otto
+          %td @mdo
+        %tr
+          %td 2
+          %td Jacob
+          %td Thornton
+          %td @fat
+        %tr
+          %td 3
+          %td Larry
+          %td the Bird
+          %td @twitter
+
+
+  %h2#buttons Buttons
+
+  .example
+    %button.btn.btn-default{:type => "button"} Default
+    %button.btn.btn-primary{:type => "button"} Primary
+    %button.btn.btn-success{:type => "button"} Success
+    %button.btn.btn-info{:type => "button"} Info
+    %button.btn.btn-warning{:type => "button"} Warning
+    %button.btn.btn-danger{:type => "button"} Danger
+    %button.btn.btn-link{:type => "button"} Link
+
+  %h2#panels Panels
+
+  .row
+    .col-md-6
+      .panel.panel-success
+        .panel-heading Success
+        .panel-body
+          = lorem
+      .panel.panel-primary
+        .panel-heading Primary
+        .panel-body
+          = lorem
+      .panel.panel-info
+        .panel-heading Info
+        .panel-body
+          = lorem
+    .col-md-6
+      .panel.panel-warning
+        .panel-heading Warning
+        .panel-body
+          = lorem
+      .panel.panel-danger
+        .panel-heading Danger
+        .panel-body
+          = lorem
+
+  %h2#alert Alerts
+
+  .row
+    .col-md-6
+      .alert.alert-success
+        = lorem
+      .alert.alert-primary
+        = lorem
+      .alert.alert-info
+        = lorem
+    .col-md-6
+      .alert.alert-warning
+        = lorem
+      .alert.alert-danger
+        = lorem
+
+  %h2#forms Forms
+
+  %h3
+    %code form.horizontal-form
+
+  %form.form-horizontal
+    .form-group
+      %label.col-sm-2.control-label{:for => "inputEmail3"} Email
+      .col-sm-10
+        %input#inputEmail3.form-control{:placeholder => "Email", :type => "email"}/
+    .form-group
+      %label.col-sm-2.control-label{:for => "inputPassword3"} Password
+      .col-sm-10
+        %input#inputPassword3.form-control{:placeholder => "Password", :type => "password"}/
+    .form-group
+      .col-sm-offset-2.col-sm-10
+        .checkbox
+          %label
+            %input{:type => "checkbox"}/
+            Remember me
+    .form-group
+      .col-sm-offset-2.col-sm-10
+        %button.btn.btn-default{:type => "submit"} Sign in
+
+  %h3
+    %code form
+
+  %form
+    .form-group
+      %label{:for => "exampleInputEmail1"} Email address
+      %input#exampleInputEmail1.form-control{:placeholder => "Enter email", :type => "email"}/
+    .form-group
+      %label{:for => "exampleInputPassword1"} Password
+      %input#exampleInputPassword1.form-control{:placeholder => "Password", :type => "password"}/
+    .checkbox
+      %label
+        %input{:type => "checkbox"}/
+        Remember me
+    %button.btn.btn-default{:type => "submit"} Sign in
+
+  %h2#file File
+  %h3
+    %code .file-holder
+
+  - blob = Snippet.new(content: "Wow\nSuch\nFile")
+  .example
+    .file-holder
+      .file-title
+        Awesome file
+        .file-actions
+          .btn-group
+            %a.btn Edit
+            %a.btn Remove
+      .file-contenta.code
+        = render 'shared/file_highlight', blob: blob
+
+
+  %h2#markdown Markdown
+  %h3
+    %code .md or .wiki and others
+
+  Markdown rendering has a bit different css and presented in next UI elements:
+
+  %ul
+    %li comment
+    %li issue, merge request description
+    %li wiki page
+    %li help page
+
+  You can check how markdown rendered at #{link_to 'Markdown help page', help_page_path("markdown", "markdown")}.
diff --git a/app/views/import/base/create.js.haml b/app/views/import/base/create.js.haml
new file mode 100644
index 0000000000000000000000000000000000000000..8d10722628f98efa4d9a6f78fc68f8e379b93af4
--- /dev/null
+++ b/app/views/import/base/create.js.haml
@@ -0,0 +1,25 @@
+- if @already_been_taken
+  :plain
+    target_field = $("tr#repo_#{@repo_id} .import-target")
+    origin_target = target_field.text()
+    project_name = "#{@project_name}"
+    origin_namespace = "#{@target_namespace}"
+    target_field.empty()
+    target_field.append("<p class='alert alert-danger'>This namespace already been taken! Please choose another one</p>")
+    target_field.append("<input type='text' name='target_namespace' />")
+    target_field.append("/" + project_name)
+    target_field.data("project_name", project_name)
+    target_field.find('input').prop("value", origin_namespace)
+- elsif @access_denied
+  :plain
+    job = $("tr#repo_#{@repo_id}")
+    job.find(".import-actions").html("<p class='alert alert-danger'>Access denied! Please verify you can add deploy keys to this repository.</p>"")
+- else
+  :plain
+    job = $("tr#repo_#{@repo_id}")
+    job.attr("id", "project_#{@project.id}")
+    target_field = job.find(".import-target")
+    target_field.empty()
+    target_field.append('<strong>#{link_to @project.path_with_namespace, [@project.namespace.becomes(Namespace), @project]}</strong>')
+    $("table.import-jobs tbody").prepend(job)
+    job.addClass("active").find(".import-actions").html("<i class='fa fa-spinner fa-spin'></i> started")
diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..4e49bbbc7fa1184bb16fd77049776d82eab15893
--- /dev/null
+++ b/app/views/import/bitbucket/status.html.haml
@@ -0,0 +1,45 @@
+%h3.page-title
+  %i.fa.fa-bitbucket
+  Import projects from Bitbucket
+
+%p.light
+  Select projects you want to import.
+%hr
+%p
+  = button_tag 'Import all projects', class: "btn btn-success js-import-all"
+
+%table.table.import-jobs
+  %thead
+    %tr
+      %th From Bitbucket
+      %th To GitLab
+      %th Status
+  %tbody
+    - @already_added_projects.each do |project|
+      %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+        %td
+          = link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: "_blank"
+        %td
+          %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
+        %td.job-status
+          - if project.import_status == 'finished'
+            %span
+              %i.fa.fa-check
+              done
+          - elsif project.import_status == 'started'
+            %i.fa.fa-spinner.fa-spin
+            started
+          - else
+            = project.human_import_status_name
+
+    - @repos.each do |repo|
+      %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"}
+        %td
+          = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank"
+        %td.import-target
+          = "#{repo["owner"]}/#{repo["slug"]}"
+        %td.import-actions.job-status
+          = button_tag "Import", class: "btn js-add-to-import"
+
+:coffeescript
+  new ImporterStatus("#{jobs_import_bitbucket_path}", "#{import_bitbucket_path}")
diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f0bc3e6b1ac91abca4c2510d93712920526381fd
--- /dev/null
+++ b/app/views/import/github/status.html.haml
@@ -0,0 +1,45 @@
+%h3.page-title
+  %i.fa.fa-github
+  Import projects from GitHub
+
+%p.light
+  Select projects you want to import.
+%hr
+%p
+  = button_tag 'Import all projects', class: "btn btn-success js-import-all"
+
+%table.table.import-jobs
+  %thead
+    %tr
+      %th From GitHub
+      %th To GitLab
+      %th Status
+  %tbody
+    - @already_added_projects.each do |project|
+      %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+        %td
+          = link_to project.import_source, "https://github.com/#{project.import_source}", target: "_blank"
+        %td
+          %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
+        %td.job-status
+          - if project.import_status == 'finished'
+            %span
+              %i.fa.fa-check
+              done
+          - elsif project.import_status == 'started'
+            %i.fa.fa-spinner.fa-spin
+            started
+          - else
+            = project.human_import_status_name
+
+    - @repos.each do |repo|
+      %tr{id: "repo_#{repo.id}"}
+        %td
+          = link_to repo.full_name, "https://github.com/#{repo.full_name}", target: "_blank"
+        %td.import-target
+          = repo.full_name
+        %td.import-actions.job-status
+          = button_tag "Import", class: "btn js-add-to-import"
+
+:coffeescript
+  new ImporterStatus("#{jobs_import_github_path}", "#{import_github_path}")
diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..33b0a21acf3b187e1c1d996c7fd3f57a6d5463f5
--- /dev/null
+++ b/app/views/import/gitlab/status.html.haml
@@ -0,0 +1,45 @@
+%h3.page-title
+  %i.fa.fa-heart
+  Import projects from GitLab.com
+
+%p.light
+  Select projects you want to import.
+%hr
+%p
+  = button_tag 'Import all projects', class: "btn btn-success js-import-all"
+
+%table.table.import-jobs
+  %thead
+    %tr
+      %th From GitLab.com
+      %th To this GitLab instance
+      %th Status
+  %tbody
+    - @already_added_projects.each do |project|
+      %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+        %td
+          = link_to project.import_source, "https://gitlab.com/#{project.import_source}", target: "_blank"
+        %td
+          %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
+        %td.job-status
+          - if project.import_status == 'finished'
+            %span
+              %i.fa.fa-check
+              done
+          - elsif project.import_status == 'started'
+            %i.fa.fa-spinner.fa-spin
+            started
+          - else
+            = project.human_import_status_name
+
+    - @repos.each do |repo|
+      %tr{id: "repo_#{repo["id"]}"}
+        %td
+          = link_to repo["path_with_namespace"], "https://gitlab.com/#{repo["path_with_namespace"]}", target: "_blank"
+        %td.import-target
+          = repo["path_with_namespace"]
+        %td.import-actions.job-status
+          = button_tag "Import", class: "btn js-add-to-import"
+
+:coffeescript
+  new ImporterStatus("#{jobs_import_gitlab_path}", "#{import_gitlab_path}")
diff --git a/app/views/import/gitorious/status.html.haml b/app/views/import/gitorious/status.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..78c5e957be0f3d1feb65952da4de5c3a9ad8c487
--- /dev/null
+++ b/app/views/import/gitorious/status.html.haml
@@ -0,0 +1,45 @@
+%h3.page-title
+  %i.icon-gitorious.icon-gitorious-big
+  Import projects from Gitorious.org
+
+%p.light
+  Select projects you want to import.
+%hr
+%p
+  = button_tag 'Import all projects', class: "btn btn-success js-import-all"
+
+%table.table.import-jobs
+  %thead
+    %tr
+      %th From Gitorious.org
+      %th To GitLab
+      %th Status
+  %tbody
+    - @already_added_projects.each do |project|
+      %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+        %td
+          = link_to project.import_source, "https://gitorious.org/#{project.import_source}", target: "_blank"
+        %td
+          %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
+        %td.job-status
+          - if project.import_status == 'finished'
+            %span
+              %i.fa.fa-check
+              done
+          - elsif project.import_status == 'started'
+            %i.fa.fa-spinner.fa-spin
+            started
+          - else
+            = project.human_import_status_name
+
+    - @repos.each do |repo|
+      %tr{id: "repo_#{repo.id}"}
+        %td
+          = link_to repo.full_name, "https://gitorious.org/#{repo.full_name}", target: "_blank"
+        %td.import-target
+          = repo.full_name
+        %td.import-actions.job-status
+          = button_tag "Import", class: "btn js-add-to-import"
+
+:coffeescript
+  new ImporterStatus("#{jobs_import_gitorious_path}", "#{import_gitorious_path}")
diff --git a/app/views/layouts/_collapse_button.html.haml b/app/views/layouts/_collapse_button.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..2ed51d87ca1332d8c9d7b34ba3a7219b662a53f9
--- /dev/null
+++ b/app/views/layouts/_collapse_button.html.haml
@@ -0,0 +1,4 @@
+- if nav_menu_collapsed?
+  = link_to icon('angle-right'), '#', class: 'toggle-nav-collapse', title: "Open/Close"
+- else
+  = link_to icon('angle-left'), '#', class: 'toggle-nav-collapse', title: "Open/Close"
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index fa6aecb66619b00f3a8af5fd08901551e9609a3a..d12145651af0f5f833419a7e20aa63fa0affec46 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -1,12 +1,5 @@
 %head
   %meta{charset: "utf-8"}
-
-  -# Go repository retrieval support
-  -# Need to be the fist thing in the head
-  -# Since Go is using an XML parser to process HTML5
-  -# https://github.com/gitlabhq/gitlabhq/pull/5958#issuecomment-45397555
-  - if controller_name == 'projects' && action_name == 'show'
-    %meta{name: "go-import", content: "#{@project.web_url_without_protocol} git #{@project.web_url}.git"}
   %meta{content: "GitLab Community Edition", name: "description"}
 
   %title
@@ -18,7 +11,8 @@
   = javascript_include_tag "application"
   = csrf_meta_tags
   = include_gon
-  %meta{name: 'viewport', content: 'width=device-width, initial-scale=1.0'}
+  %meta{name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1'}
+  %meta{name: 'theme-color', content: '#474D57'}
 
   = render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id')
   = render 'layouts/piwik' if extra_config.has_key?('piwik_url') && extra_config.has_key?('piwik_site_id')
@@ -29,6 +23,6 @@
       = auto_discovery_link_tag :atom, projects_url(:atom, private_token: current_user.private_token), title: "Dashboard feed"
     - if @project && !@project.new_record?
       - if current_controller?(:tree, :commits)
-        = auto_discovery_link_tag(:atom, project_commits_url(@project, @ref, format: :atom, private_token: current_user.private_token), title: "Recent commits to #{@project.name}:#{@ref}")
+        = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "Recent commits to #{@project.name}:#{@ref}")
       - if current_controller?(:issues)
-        = auto_discovery_link_tag(:atom, project_issues_url(@project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues")
+        = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues")
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index 5dcaee2fa0219391e20680c950332a2c64a87ee3..b1c2e1a7b1953b87499d41ed105f2b01b7ab5af4 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -1,11 +1,9 @@
-%header.navbar.navbar-static-top.navbar-gitlab
+%header.navbar.navbar-fixed-top.navbar-gitlab
   .navbar-inner
     .container
       %div.app_logo
-        %span.separator
         = link_to root_path, class: "home has_bottom_tooltip", title: "Dashboard" do
-          %h1 GITLAB
-        %span.separator
+          = brand_header_logo
       %h1.title= title
 
       %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"}
@@ -27,7 +25,7 @@
             = link_to explore_root_path, title: "Explore", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do
               %i.fa.fa-globe
           %li
-            = link_to user_snippets_path(current_user), title: "My snippets", class: 'has_bottom_tooltip', 'data-original-title' => 'My snippets' do
+            = link_to user_snippets_path(current_user), title: "Your snippets", class: 'has_bottom_tooltip', 'data-original-title' => 'Your snippets' do
               %i.fa.fa-clipboard
           - if current_user.is_admin?
             %li
@@ -44,5 +42,7 @@
             = link_to destroy_user_session_path, class: "logout", method: :delete, title: "Logout", class: 'has_bottom_tooltip', 'data-original-title' => 'Logout'  do
               %i.fa.fa-sign-out
           %li.hidden-xs
-            = link_to current_user, class: "profile-pic", id: 'profile-pic' do
-              = image_tag avatar_icon(current_user.email, 26), alt: 'User activity'
+            = link_to current_user, class: "profile-pic has_bottom_tooltip", id: 'profile-pic', 'data-original-title' => 'Your profile' do
+              = image_tag avatar_icon(current_user.email, 60), alt: 'User activity'
+
+= render 'shared/outdated_browser'
diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml
index 353f7ce34f1273604f4d6a9aa08d646c8e3c79a5..3c58f10e759f30200430684c241545265cbe1e97 100644
--- a/app/views/layouts/_init_auto_complete.html.haml
+++ b/app/views/layouts/_init_auto_complete.html.haml
@@ -1,3 +1,3 @@
 :javascript
-  GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_project_path(@project, type: @noteable.class, type_id: params[:id])}"
+  GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(@project.namespace, @project, type: @noteable.class, type_id: params[:id])}"
   GitLab.GfmAutoComplete.setup();
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..422966cdc5556d22e1dae102fd17636f3da6e2d0
--- /dev/null
+++ b/app/views/layouts/_page.html.haml
@@ -0,0 +1,23 @@
+- if defined?(sidebar)
+  .page-with-sidebar{ class: nav_sidebar_class }
+    = render "layouts/broadcast"
+    .sidebar-wrapper
+      = render(sidebar)
+      .collapse-nav
+        = render partial: 'layouts/collapse_button'
+    .content-wrapper
+      .container-fluid
+        .content
+          = render "layouts/flash"
+          .clearfix
+            = yield
+- else
+  .container.navless-container
+    .content
+      = yield
+
+= yield :embedded_scripts
+
+:coffeescript
+  $('.page-sidebar-collapsed .nav-sidebar a').tooltip placement: "right"
+
diff --git a/app/views/layouts/_public_head_panel.html.haml b/app/views/layouts/_public_head_panel.html.haml
index 9bfc14d16c1b6ff6dc3546ba89fe729ec5c477dc..3d6d2bfc00a9f4f4fd5232cfce0aa5a7d63a48b8 100644
--- a/app/views/layouts/_public_head_panel.html.haml
+++ b/app/views/layouts/_public_head_panel.html.haml
@@ -1,22 +1,22 @@
-%header.navbar.navbar-static-top.navbar-gitlab
+%header.navbar.navbar-fixed-top.navbar-gitlab
   .navbar-inner
     .container
       %div.app_logo
-        %span.separator
         = link_to explore_root_path, class: "home" do
-          %h1 GITLAB
-        %span.separator
+          = brand_header_logo
       %h1.title= title
 
       %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"}
         %span.sr-only Toggle navigation
         %i.fa.fa-bars
 
-      .pull-right.hidden-xs
-        = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-new'
+      - unless current_controller?('sessions')
+        .pull-right.hidden-xs
+          = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-new append-right-10'
 
-      .navbar-collapse.collapse
-        %ul.nav.navbar-nav
-          %li.visible-xs
-            = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes')
+        .navbar-collapse.collapse
+          %ul.nav.navbar-nav
+            %li.visible-xs
+              = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes')
 
+= render 'shared/outdated_browser'
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index 2460a6a014d9103bd045f158720602e0dd5c2597..04f79846858dbe2c3b5094f57285e9db24b3ecb8 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -4,7 +4,16 @@
     = hidden_field_tag :group_id, @group.try(:id)
     - if @project && @project.persisted?
       = hidden_field_tag :project_id, @project.id
-      = hidden_field_tag :search_code, true
+
+      - if current_controller?(:issues)
+        = hidden_field_tag :scope, 'issues'
+      - elsif current_controller?(:merge_requests)
+        = hidden_field_tag :scope, 'merge_requests'
+      - elsif current_controller?(:wikis)
+        = hidden_field_tag :scope, 'wiki_blobs'
+      - else
+        = hidden_field_tag :search_code, true
+
     - if @snippet || @snippets
       = hidden_field_tag :snippets, true
     = hidden_field_tag :repository_ref, @ref
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index 207ab22f4c7d529a8a23cbd7bb6c85021569c50c..ab84e87c300209e2a7d3a42c7c15e9d003d86f6c 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -1,13 +1,6 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: "Admin area"
-  %body{class: "#{app_theme} admin", :'data-page' => body_data_page}
-    = render "layouts/broadcast"
-    = render "layouts/head_panel", title: "Admin area"
-    %nav.main-nav.navbar-collapse.collapse
-      .container= render 'layouts/nav/admin'
-    .container
-      .content
-        = render "layouts/flash"
-        = yield
-    = yield :embedded_scripts
+  %body{class: "#{app_theme}  admin", :'data-page' => body_data_page}
+    = render "layouts/head_panel", title: link_to("Admin area", admin_root_path)
+    = render 'layouts/page', sidebar: 'layouts/nav/admin'
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 7d0819aa93ef7b1c58f2669120d71b799ceb948b..6bd8ac4adb85e4e9b9e6d8469963c36b0dd20fb0 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -1,12 +1,6 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: "Dashboard"
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page }
-    = render "layouts/broadcast"
-    = render "layouts/head_panel", title: "Dashboard"
-    %nav.main-nav.navbar-collapse.collapse
-      .container= render 'layouts/nav/dashboard'
-    .container
-      .content
-        = render "layouts/flash"
-        = yield
+  %body{class: "#{app_theme}  application", :'data-page' => body_data_page }
+    = render "layouts/head_panel", title: link_to("Dashboard", root_path)
+    = render 'layouts/page', sidebar: 'layouts/nav/dashboard'
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 06de03eadad967ba3e8047ae12fb58cfdc2a5718..6f805f1c9d1ccba4d3c62dae35b7d0e9e9399abf 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -1,35 +1,32 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head"
-  %body.ui_basic.login-page
-    .container
-      .content
-        .login-title
-          %h1= brand_title
-    %hr
-    .container
+  %body.ui_mars.login-page.application
+    = render "layouts/broadcast"
+    = render "layouts/public_head_panel", title: ''
+    .container.navless-container
       .content
         = render "layouts/flash"
-        .row
-          .col-md-7.brand-holder
+        .row.prepend-top-20
+          .col-sm-5.pull-right
+            = yield
+          .col-sm-7.brand-holder.pull-left
+            %h1
+              = brand_title
             - if brand_item
-              .brand-image
-                = brand_image
-              .brand_text
-                = brand_text
+              = brand_image
+              = brand_text
             - else
-              .brand-image.default-brand-image.hidden-sm.hidden-xs
-                = image_tag 'brand_logo.png'
-              .brand_text.hidden-xs
-                %h2 Open source software to collaborate on code
+              %h3 Open source software to collaborate on code
 
-                %p.lead
-                  Manage git repositories with fine grained access controls that keep your code secure.
-                  Perform code reviews and enhance collaboration with merge requests.
-                  Each project can also have an issue tracker and a wiki.
+              %p
+                Manage git repositories with fine grained access controls that keep your code secure.
+                Perform code reviews and enhance collaboration with merge requests.
+                Each project can also have an issue tracker and a wiki.
+
+            - if extra_sign_in_text.present?
+              = markdown(extra_sign_in_text)
 
-          .col-md-5
-            = yield
     %hr
     .container
       .footer-links
diff --git a/app/views/layouts/errors.html.haml b/app/views/layouts/errors.html.haml
index 16df9c10fbb0c0c2f6042bbd47196bd699291202..e51fd4cb8208e4e758d1a3776b55bdd97f922f95 100644
--- a/app/views/layouts/errors.html.haml
+++ b/app/views/layouts/errors.html.haml
@@ -1,7 +1,7 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: "Error"
-  %body{class: "#{app_theme} application"}
+  %body{class: "#{app_theme}  application"}
     = render "layouts/head_panel", title: "" if current_user
     .container.navless-container
       = render "layouts/flash"
diff --git a/app/views/layouts/explore.html.haml b/app/views/layouts/explore.html.haml
index d023846c5eb73717304ca765e3f71398f7a3b515..2bd0b8d85c91b0e929ad7258eda7f791bbb82b89 100644
--- a/app/views/layouts/explore.html.haml
+++ b/app/views/layouts/explore.html.haml
@@ -2,12 +2,12 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: page_title
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page}
+  %body{class: "#{app_theme}  application", :'data-page' => body_data_page}
     = render "layouts/broadcast"
     - if current_user
-      = render "layouts/head_panel", title: page_title
+      = render "layouts/head_panel", title: link_to(page_title, explore_root_path)
     - else
-      = render "layouts/public_head_panel", title: page_title
+      = render "layouts/public_head_panel", title: link_to(page_title, explore_root_path)
     .container.navless-container
       .content
         .explore-title
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index f22fb236cb5b48d69fcc2a49d13dfe8b38655583..f4a6bee15f68c6e6022179bb4378e7bca15a64af 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -1,12 +1,6 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: group_head_title
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page}
-    = render "layouts/broadcast"
-    = render "layouts/head_panel", title: "group: #{@group.name}"
-    %nav.main-nav.navbar-collapse.collapse
-      .container= render 'layouts/nav/group'
-    .container
-      .content
-        = render "layouts/flash"
-        = yield
+  %body{class: "#{app_theme}  application", :'data-page' => body_data_page}
+    = render "layouts/head_panel", title: link_to(@group.name, group_path(@group))
+    = render 'layouts/page', sidebar: 'layouts/nav/group'
diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml
index c57216f01c8bd84685692cb92516e80ce99f5cd4..2f38d596c65ecfb8cf0cfdf779052fc14a3f23b0 100644
--- a/app/views/layouts/nav/_admin.html.haml
+++ b/app/views/layouts/nav/_admin.html.haml
@@ -1,19 +1,60 @@
-%ul
+%ul.nav.nav-sidebar
   = nav_link(controller: :dashboard, html_options: {class: 'home'}) do
     = link_to admin_root_path, title: "Stats" do
-      Overview
+      %i.fa.fa-dashboard
+      %span
+        Overview
   = nav_link(controller: :projects) do
-    = link_to "Projects", admin_projects_path
+    = link_to admin_namespaces_projects_path, title: 'Projects' do
+      %i.fa.fa-cube
+      %span
+        Projects
   = nav_link(controller: :users) do
-    = link_to "Users", admin_users_path
+    = link_to admin_users_path, title: 'Users' do
+      %i.fa.fa-user
+      %span
+        Users
   = nav_link(controller: :groups) do
-    = link_to "Groups", admin_groups_path
+    = link_to admin_groups_path, title: 'Groups' do
+      %i.fa.fa-group
+      %span
+        Groups
   = nav_link(controller: :logs) do
-    = link_to "Logs", admin_logs_path
+    = link_to admin_logs_path, title: 'Logs' do
+      %i.fa.fa-file-text
+      %span
+        Logs
   = nav_link(controller: :broadcast_messages) do
-    = link_to "Messages", admin_broadcast_messages_path
+    = link_to admin_broadcast_messages_path, title: 'Broadcast Messages' do
+      %i.fa.fa-bullhorn
+      %span
+        Messages
   = nav_link(controller: :hooks) do
-    = link_to "Hooks", admin_hooks_path
+    = link_to admin_hooks_path, title: 'Hooks' do
+      %i.fa.fa-external-link
+      %span
+        Hooks
   = nav_link(controller: :background_jobs) do
-    = link_to "Background Jobs", admin_background_jobs_path
+    = link_to admin_background_jobs_path, title: 'Background Jobs' do
+      %i.fa.fa-cog
+      %span
+        Background Jobs
+
+  = nav_link(controller: :applications) do
+    = link_to admin_applications_path, title: 'Applications' do
+      %i.fa.fa-cloud
+      %span
+        Applications
+
+  = nav_link(controller: :services) do
+    = link_to admin_application_settings_services_path, title: 'Service Templates' do
+      %i.fa.fa-copy
+      %span
+        Service Templates
+
+  = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do
+    = link_to admin_application_settings_path, title: 'Settings' do
+      %i.fa.fa-cogs
+      %span
+        Settings
 
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index a6e9772d93f506e01d4ff050b49fff42023ba0b4..e4f630c6a18a317859c9cb33a8ea46dfa978813f 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -1,18 +1,38 @@
-%ul
+%ul.nav.nav-sidebar
   = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
     = link_to root_path, title: 'Home', class: 'shortcuts-activity' do
-      Activity
-  = nav_link(path: 'dashboard#projects') do
-    = link_to projects_dashboard_path, class: 'shortcuts-projects' do
-      Projects
+      %i.fa.fa-dashboard
+      %span
+        Your Projects
+  = nav_link(path: 'projects#starred') do
+    = link_to starred_dashboard_projects_path, title: 'Starred Projects' do
+      %i.fa.fa-star
+      %span
+        Starred Projects
+  = nav_link(controller: :groups) do
+    = link_to dashboard_groups_path, title: 'Groups' do
+      %i.fa.fa-group
+      %span
+        Groups
+  = nav_link(controller: :milestones) do
+    = link_to dashboard_milestones_path, title: 'Milestones' do
+      %i.fa.fa-clock-o
+      %span
+        Milestones
   = nav_link(path: 'dashboard#issues') do
-    = link_to issues_dashboard_path, class: 'shortcuts-issues' do
-      Issues
-      %span.count= current_user.assigned_issues.opened.count
+    = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'shortcuts-issues' do
+      %i.fa.fa-exclamation-circle
+      %span
+        Issues
+        %span.count= current_user.assigned_issues.opened.count
   = nav_link(path: 'dashboard#merge_requests') do
-    = link_to merge_requests_dashboard_path, class: 'shortcuts-merge_requests' do
-      Merge Requests
-      %span.count= current_user.assigned_merge_requests.opened.count
+    = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do
+      %i.fa.fa-tasks
+      %span
+        Merge Requests
+        %span.count= current_user.assigned_merge_requests.opened.count
   = nav_link(controller: :help) do
-    = link_to "Help", help_path
-
+    = link_to help_path, title: 'Help' do
+      %i.fa.fa-question-circle
+      %span
+        Help
diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml
index 9095a843c9ff5c5813aade4e3059d7ac3f191d2d..32fe0e37df872764b53622cba16cb8d8045cd640 100644
--- a/app/views/layouts/nav/_group.html.haml
+++ b/app/views/layouts/nav/_group.html.haml
@@ -1,25 +1,42 @@
-%ul
+%ul.nav.nav-sidebar
   = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
     = link_to group_path(@group), title: "Home" do
-      Activity
-  = nav_link(controller: [:group, :milestones]) do
-    = link_to group_milestones_path(@group) do
-      Milestones
+      %i.fa.fa-dashboard
+      %span
+        Activity
+  - if current_user
+    = nav_link(controller: [:group, :milestones]) do
+      = link_to group_milestones_path(@group), title: 'Milestones' do
+        %i.fa.fa-clock-o
+        %span
+          Milestones
   = nav_link(path: 'groups#issues') do
-    = link_to issues_group_path(@group) do
-      Issues
-      - if current_user
-        %span.count= current_user.assigned_issues.opened.of_group(@group).count
+    = link_to issues_group_path(@group), title: 'Issues' do
+      %i.fa.fa-exclamation-circle
+      %span
+        Issues
+        - if current_user
+          %span.count= Issue.opened.of_group(@group).count
   = nav_link(path: 'groups#merge_requests') do
-    = link_to merge_requests_group_path(@group) do
-      Merge Requests
-      - if current_user
-        %span.count= current_user.cared_merge_requests.opened.of_group(@group).count
-  = nav_link(path: 'groups#members') do
-    = link_to "Members", members_group_path(@group)
+    = link_to merge_requests_group_path(@group), title: 'Merge Requests' do
+      %i.fa.fa-tasks
+      %span
+        Merge Requests
+        - if current_user
+          %span.count= MergeRequest.opened.of_group(@group).count
+  = nav_link(controller: [:group_members]) do
+    = link_to group_group_members_path(@group), title: 'Members' do
+      %i.fa.fa-users
+      %span
+        Members
 
   - if can?(current_user, :manage_group, @group)
-    = nav_link(path: 'groups#edit') do
-      = link_to edit_group_path(@group), class: "tab " do
-        Settings
+    = nav_link(html_options: { class: "#{"active" if group_settings_page?} separate-item" }) do
+      = link_to edit_group_path(@group), title: 'Settings', class: "tab no-highlight" do
+        %i.fa.fa-cogs
+        %span
+          Settings
+          %i.fa.fa-angle-down
 
+  - if group_settings_page?
+    = render 'groups/settings_nav'
diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml
index 1de5ee99cf496e60bb4e95239a8bdf98cf4f6aad..d88e862829d6c44527d2b86a95efbe515287d8c0 100644
--- a/app/views/layouts/nav/_profile.html.haml
+++ b/app/views/layouts/nav/_profile.html.haml
@@ -1,26 +1,50 @@
-%ul
+%ul.nav.nav-sidebar
   = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
     = link_to profile_path, title: "Profile" do
-      Profile
+      %i.fa.fa-user
+      %span
+        Profile
   = nav_link(controller: :accounts) do
-    = link_to "Account", profile_account_path
+    = link_to profile_account_path, title: 'Account' do
+      %i.fa.fa-gear
+      %span
+        Account
+  = nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new']) do
+    = link_to applications_profile_path, title: 'Applications' do
+      %i.fa.fa-cloud
+      %span
+        Applications
   = nav_link(controller: :emails) do
-    = link_to profile_emails_path do
-      Emails
-      %span.count= current_user.emails.count + 1
+    = link_to profile_emails_path, title: 'Emails' do
+      %i.fa.fa-envelope-o
+      %span
+        Emails
+        %span.count= current_user.emails.count + 1
   - unless current_user.ldap_user?
     = nav_link(controller: :passwords) do
-      = link_to "Password", edit_profile_password_path
+      = link_to edit_profile_password_path, title: 'Password' do
+        %i.fa.fa-lock
+        %span
+          Password
   = nav_link(controller: :notifications) do
-    = link_to "Notifications", profile_notifications_path
+    = link_to profile_notifications_path, title: 'Notifications' do
+      %i.fa.fa-inbox
+      %span
+        Notifications
+
   = nav_link(controller: :keys) do
-    = link_to profile_keys_path do
-      SSH Keys
-      %span.count= current_user.keys.count
+    = link_to profile_keys_path, title: 'SSH Keys' do
+      %i.fa.fa-key
+      %span
+        SSH Keys
+        %span.count= current_user.keys.count
   = nav_link(path: 'profiles#design') do
-    = link_to "Design", design_profile_path
-  = nav_link(controller: :groups) do
-    = link_to "Groups", profile_groups_path
+    = link_to design_profile_path, title: 'Design' do
+      %i.fa.fa-image
+      %span
+        Design
   = nav_link(path: 'profiles#history') do
-    = link_to "History", history_profile_path
-
+    = link_to history_profile_path, title: 'History' do
+      %i.fa.fa-history
+      %span
+        History
diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml
index 6cb2a82bac85abe439c1ddb1ea09da665b8262ee..52681865d642469e488bf2742f630a61663b3054 100644
--- a/app/views/layouts/nav/_project.html.haml
+++ b/app/views/layouts/nav/_project.html.haml
@@ -1,45 +1,97 @@
-%ul.project-navigation
-  = nav_link(path: 'projects#show', html_options: {class: "home"}) do
-    = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
-      Project
-  - if project_nav_tab? :files
-    = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do
-      = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref), class: 'shortcuts-tree'
-
-  - if project_nav_tab? :commits
-    = nav_link(controller: %w(commit commits compare repositories tags branches)) do
-      = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref), class: 'shortcuts-commits'
-
-  - if project_nav_tab? :network
-    = nav_link(controller: %w(network)) do
-      = link_to "Network", project_network_path(@project, @ref || @repository.root_ref), class: 'shortcuts-network'
-
-  - if project_nav_tab? :graphs
-    = nav_link(controller: %w(graphs)) do
-      = link_to "Graphs", project_graph_path(@project, @ref || @repository.root_ref), class: 'shortcuts-graphs'
-
-  - if project_nav_tab? :issues
-    = nav_link(controller: %w(issues milestones labels)) do
-      = link_to url_for_project_issues, class: 'shortcuts-issues' do
-        Issues
-        - if @project.used_default_issues_tracker?
-          %span.count.issue_counter= @project.issues.opened.count
-
-  - if project_nav_tab? :merge_requests
-    = nav_link(controller: :merge_requests) do
-      = link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests'  do
-        Merge Requests
-        %span.count.merge_counter= @project.merge_requests.opened.count
-
-  - if project_nav_tab? :wiki
-    = nav_link(controller: :wikis) do
-      = link_to 'Wiki', project_wiki_path(@project, :home), class: 'shortcuts-wiki'
-
-  - if project_nav_tab? :snippets
-    = nav_link(controller: :snippets) do
-      = link_to 'Snippets', project_snippets_path(@project), class: 'shortcuts-snippets'
-
-  - if project_nav_tab? :settings
-    = nav_link(html_options: {class: "#{project_tab_class}"}) do
-      = link_to edit_project_path(@project), class: "stat-tab tab " do
-        Settings
+%ul.project-navigation.nav.nav-sidebar
+  - if @project_settings_nav
+    = nav_link do
+      = link_to project_path(@project), title: 'Back to project', class: "" do
+        %i.fa.fa-caret-square-o-left
+        %span
+          Back to project
+
+    %li.separate-item
+
+    = render 'projects/settings_nav'
+
+  - else
+    = nav_link(path: 'projects#show', html_options: {class: "home"}) do
+      = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
+        %i.fa.fa-dashboard
+        %span
+          Project
+    - if project_nav_tab? :files
+      = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do
+        = link_to namespace_project_tree_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Files',  class: 'shortcuts-tree' do
+          %i.fa.fa-files-o
+          %span
+            Files
+
+    - if project_nav_tab? :commits
+      = nav_link(controller: %w(commit commits compare repositories tags branches)) do
+        = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Commits', class: 'shortcuts-commits' do
+          %i.fa.fa-history
+          %span
+            Commits
+
+    - if project_nav_tab? :network
+      = nav_link(controller: %w(network)) do
+        = link_to namespace_project_network_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Network', class: 'shortcuts-network' do
+          %i.fa.fa-code-fork
+          %span
+            Network
+
+    - if project_nav_tab? :graphs
+      = nav_link(controller: %w(graphs)) do
+        = link_to namespace_project_graph_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Graphs',  class: 'shortcuts-graphs' do
+          %i.fa.fa-area-chart
+          %span
+            Graphs
+
+    - if project_nav_tab? :milestones
+      = nav_link(controller: :milestones) do
+        = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do
+          %i.fa.fa-clock-o
+          %span
+            Milestones
+
+    - if project_nav_tab? :issues
+      = nav_link(controller: :issues) do
+        = link_to url_for_project_issues, title: 'Issues', class: 'shortcuts-issues' do
+          %i.fa.fa-exclamation-circle
+          %span
+            Issues
+            - if @project.default_issues_tracker?
+              %span.count.issue_counter= @project.issues.opened.count
+
+    - if project_nav_tab? :merge_requests
+      = nav_link(controller: :merge_requests) do
+        = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests'  do
+          %i.fa.fa-tasks
+          %span
+            Merge Requests
+            %span.count.merge_counter= @project.merge_requests.opened.count
+
+    - if project_nav_tab? :labels
+      = nav_link(controller: :labels) do
+        = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do
+          %i.fa.fa-tags
+          %span
+            Labels
+
+    - if project_nav_tab? :wiki
+      = nav_link(controller: :wikis) do
+        = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do
+          %i.fa.fa-book
+          %span
+            Wiki
+
+    - if project_nav_tab? :snippets
+      = nav_link(controller: :snippets) do
+        = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do
+          %i.fa.fa-file-text-o
+          %span
+            Snippets
+
+    - if project_nav_tab? :settings
+      = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do
+        = link_to edit_project_path(@project), title: 'Settings', class: "stat-tab tab no-highlight" do
+          %i.fa.fa-cogs
+          %span
+            Settings
diff --git a/app/views/layouts/navless.html.haml b/app/views/layouts/navless.html.haml
index 2c5fffe384f92488f264fa883f5c7a2f3fa5c8d8..4d0278251a67ff87bd1914ceaed35437cd60ed17 100644
--- a/app/views/layouts/navless.html.haml
+++ b/app/views/layouts/navless.html.haml
@@ -1,9 +1,9 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: @title
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page}
+  %body{class: "#{app_theme}  application", :'data-page' => body_data_page}
     = render "layouts/broadcast"
-    = render "layouts/head_panel", title: @title
+    = render "layouts/head_panel", title: defined?(@title_url) ? link_to(@title, @title_url) : @title
     .container.navless-container
       .content
         = render "layouts/flash"
diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml
index da4519613273e5139686c28de0c7e569cdc81661..7eec93abdf69b1c6876f04e9878ff688d52b19fc 100644
--- a/app/views/layouts/notify.html.haml
+++ b/app/views/layouts/notify.html.haml
@@ -16,7 +16,19 @@
       font-size:small;
       color:#777
     }
-
+    pre.commit-message {
+      white-space: pre-wrap;
+    }
+    .file-stats a {
+      text-decoration: none;
+    }
+    .file-stats .new-file {
+      color: #090;
+    }
+    .file-stats .deleted-file {
+      color: #B00;
+    }
+    #{add_email_highlight_css}
   %body
     %div.content
       = yield
@@ -24,8 +36,8 @@
       %p
         \—
         %br
-        - if @project
-          You're receiving this notification because you are a member of the #{link_to_unless @target_url, @project.name_with_namespace, project_url(@project)} project team.
         - if @target_url
           #{link_to "View it on GitLab", @target_url}
           = email_action @target_url
+        - if @project && !@disable_footer
+          You're receiving this notification because you are a member of the #{link_to_unless @target_url, @project.name_with_namespace, namespace_project_url(@project.namespace, @project)} project team.
diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml
index 1d0ab84d26fdaca53850065717777c271ffefd94..2b5be7fc37202a5ea3735941d94a44a6f96c055d 100644
--- a/app/views/layouts/profile.html.haml
+++ b/app/views/layouts/profile.html.haml
@@ -1,12 +1,6 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: "Profile"
-  %body{class: "#{app_theme} profile", :'data-page' => body_data_page}
-    = render "layouts/broadcast"
-    = render "layouts/head_panel", title: "Profile"
-    %nav.main-nav.navbar-collapse.collapse
-      .container= render 'layouts/nav/profile'
-    .container
-      .content
-        = render "layouts/flash"
-        = yield
+  %body{class: "#{app_theme}  profile", :'data-page' => body_data_page}
+    = render "layouts/head_panel", title: link_to("Profile", profile_path)
+    = render 'layouts/page', sidebar: 'layouts/nav/profile'
diff --git a/app/views/layouts/project_settings.html.haml b/app/views/layouts/project_settings.html.haml
index c8b8f4ba97178d003eb56f9794981f52f6589982..0a0039dec169e5f5d5d047685ebf29e1d7fbc8a3 100644
--- a/app/views/layouts/project_settings.html.haml
+++ b/app/views/layouts/project_settings.html.haml
@@ -1,19 +1,8 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: @project.name_with_namespace
-  %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id }
-    = render "layouts/broadcast"
+  %body{class: "#{app_theme}  project", :'data-page' => body_data_page, :'data-project-id' => @project.id }
     = render "layouts/head_panel", title: project_title(@project)
     = render "layouts/init_auto_complete"
-    - if can?(current_user, :download_code, @project)
-      = render 'shared/no_ssh'
-    %nav.main-nav.navbar-collapse.collapse
-      .container= render 'layouts/nav/project'
-    .container
-      .content
-        = render "layouts/flash"
-        .row
-          .col-md-2
-            = render "projects/settings_nav"
-          .col-md-10
-            = yield
+    - @project_settings_nav = true
+    = render 'layouts/page', sidebar: 'layouts/nav/project'
diff --git a/app/views/layouts/projects.html.haml b/app/views/layouts/projects.html.haml
index 8ad2f1659460f9b3994e1f5bc048ff0db01243c0..dde0964f47f4961035bcf2467b24438ee0602404 100644
--- a/app/views/layouts/projects.html.haml
+++ b/app/views/layouts/projects.html.haml
@@ -1,16 +1,7 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: project_head_title
-  %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id }
-    = render "layouts/broadcast"
+  %body{class: "#{app_theme}  project", :'data-page' => body_data_page, :'data-project-id' => @project.id }
     = render "layouts/head_panel", title: project_title(@project)
     = render "layouts/init_auto_complete"
-    - if can?(current_user, :download_code, @project)
-      = render 'shared/no_ssh'
-    %nav.main-nav.navbar-collapse.collapse
-      .container= render 'layouts/nav/project'
-    .container
-      .content
-        = render "layouts/flash"
-        = yield
-    = yield :embedded_scripts
+    = render 'layouts/page', sidebar: 'layouts/nav/project'
diff --git a/app/views/layouts/public_group.html.haml b/app/views/layouts/public_group.html.haml
index a289b784725315f6e3423396864e3cdde4d55201..b9b1d03e08ee8a05288b207fcfbad755778f6da4 100644
--- a/app/views/layouts/public_group.html.haml
+++ b/app/views/layouts/public_group.html.haml
@@ -1,10 +1,6 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: group_head_title
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page}
-    = render "layouts/broadcast"
-    = render "layouts/public_head_panel", title: "group: #{@group.name}"
-    %nav.main-nav.navbar-collapse.collapse
-      .container= render 'layouts/nav/group'
-    .container
-      .content= yield
+  %body{class: "#{app_theme}  application", :'data-page' => body_data_page}
+    = render "layouts/public_head_panel", title: link_to(@group.name, group_path(@group))
+    = render 'layouts/page', sidebar: 'layouts/nav/group'
diff --git a/app/views/layouts/public_projects.html.haml b/app/views/layouts/public_projects.html.haml
index 2a9230244f89a38391ccfa4a205f1ff07135f23c..04fa7c84e73c75ccaf700be683062e90fa0ce75e 100644
--- a/app/views/layouts/public_projects.html.haml
+++ b/app/views/layouts/public_projects.html.haml
@@ -1,10 +1,6 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: @project.name_with_namespace
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page}
-    = render "layouts/broadcast"
+  %body{class: "#{app_theme}  application", :'data-page' => body_data_page}
     = render "layouts/public_head_panel", title: project_title(@project)
-    %nav.main-nav.navbar-collapse.collapse
-      .container= render 'layouts/nav/project'
-    .container
-      .content= yield
+    = render 'layouts/page', sidebar: 'layouts/nav/project'
diff --git a/app/views/layouts/public_users.html.haml b/app/views/layouts/public_users.html.haml
index 4aa258fea0d8d5aa83d65d401a287da3581ced3b..71c16bd168418d1a0771abe37c692c26f12178c5 100644
--- a/app/views/layouts/public_users.html.haml
+++ b/app/views/layouts/public_users.html.haml
@@ -1,8 +1,6 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: @title
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page}
-    = render "layouts/broadcast"
-    = render "layouts/public_head_panel", title: @title
-    .container.navless-container
-      .content= yield
+  %body{class: "#{app_theme}  application", :'data-page' => body_data_page}
+    = render "layouts/public_head_panel", title: defined?(@title_url) ? link_to(@title, @title_url) : @title
+    = render 'layouts/page'
diff --git a/app/views/layouts/search.html.haml b/app/views/layouts/search.html.haml
index 084ff7ec830b9f0a4377c407ed36fa1674672300..f9d8db06e10635c0023a48fe20b103b6a851e2d8 100644
--- a/app/views/layouts/search.html.haml
+++ b/app/views/layouts/search.html.haml
@@ -1,9 +1,9 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: "Search"
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page}
+  %body{class: "#{app_theme}  application", :'data-page' => body_data_page}
     = render "layouts/broadcast"
-    = render "layouts/head_panel", title: "Search"
+    = render "layouts/head_panel", title: link_to("Search", search_path)
     .container.navless-container
       .content
         = render "layouts/flash"
diff --git a/app/views/notify/_note_message.html.haml b/app/views/notify/_note_message.html.haml
index 5272dfa0edec4ce0e6fc0ca80b9dbd254b806f03..778a78acf56b83ee70d7392d18dc013b243b977a 100644
--- a/app/views/notify/_note_message.html.haml
+++ b/app/views/notify/_note_message.html.haml
@@ -1,2 +1,2 @@
 %div
-  = markdown(@note.note)
+  = replace_image_links_with_base64(markdown(@note.note), @note.project)
diff --git a/app/views/notify/_reassigned_issuable_email.text.erb b/app/views/notify/_reassigned_issuable_email.text.erb
index 817d030c362d0c0fe2da1888509770eecd1982b1..855d37429d9fe64adc541e280366f5901b23be9c 100644
--- a/app/views/notify/_reassigned_issuable_email.text.erb
+++ b/app/views/notify/_reassigned_issuable_email.text.erb
@@ -1,6 +1,6 @@
 Reassigned <%= issuable.class.model_name.human.titleize %> <%= issuable.iid %>
 
-<%= url_for([issuable.project, issuable, {only_path: false}]) %>
+<%= url_for([issuable.project.namespace.becomes(Namespace), issuable.project, issuable, {only_path: false}]) %>
 
 Assignee changed <%= "from #{@previous_assignee.name}" if @previous_assignee -%>
  to <%= "#{issuable.assignee_id ? issuable.assignee_name : 'Unassigned'}" %>
diff --git a/app/views/notify/closed_issue_email.text.haml b/app/views/notify/closed_issue_email.text.haml
index 49f160a0d5fbf397b237e36a036d05fa9412bf56..ac703b31eddf5d4f6ea739612a122b1274f58902 100644
--- a/app/views/notify/closed_issue_email.text.haml
+++ b/app/views/notify/closed_issue_email.text.haml
@@ -1,3 +1,3 @@
 = "Issue was closed by #{@updated_by.name}"
 
-Issue ##{@issue.iid}: #{project_issue_url(@issue.project, @issue)}
+Issue ##{@issue.iid}: #{namespace_project_issue_url(@issue.project.namespace, @issue.project, @issue)}
diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml
index d6b76e906c526184b60beeefc5e0ca23e06a3158..59db86b08bc404062f8723b0fb6689e295b25bdb 100644
--- a/app/views/notify/closed_merge_request_email.text.haml
+++ b/app/views/notify/closed_merge_request_email.text.haml
@@ -1,6 +1,6 @@
 = "Merge Request ##{@merge_request.iid} was closed by #{@updated_by.name}"
 
-Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
+Merge Request url: #{namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request)}
 
 = merge_path_description(@merge_request, 'to')
 
diff --git a/app/views/notify/group_access_granted_email.html.haml b/app/views/notify/group_access_granted_email.html.haml
index 823ebf7734729d361ecd52239c9dbb2a29bde90b..f1916d624b6b35d9fabe1808660022197e8b324d 100644
--- a/app/views/notify/group_access_granted_email.html.haml
+++ b/app/views/notify/group_access_granted_email.html.haml
@@ -1,4 +1,4 @@
 %p
-  = "You have been granted #{@membership.human_access} access to group"
+  = "You have been granted #{@group_member.human_access} access to group"
   = link_to group_url(@group) do
     = @group.name
diff --git a/app/views/notify/group_access_granted_email.text.erb b/app/views/notify/group_access_granted_email.text.erb
index 331bb98d5c94ab22439e93c8617a00b59f5cdc7f..ef9617bfc16ad3d47aa75524e5d28a379ca1639b 100644
--- a/app/views/notify/group_access_granted_email.text.erb
+++ b/app/views/notify/group_access_granted_email.text.erb
@@ -1,4 +1,4 @@
 
-You have been granted <%= @membership.human_access %> access to group <%= @group.name %>
+You have been granted <%= @group_member.human_access %> access to group <%= @group.name %>
 
 <%= url_for(group_url(@group)) %>
diff --git a/app/views/notify/issue_status_changed_email.text.erb b/app/views/notify/issue_status_changed_email.text.erb
index 4200881f7e8a009086be96aac46dcc8b8b41accd..e6ab3fcde7705471517f92f92114475ab90876c4 100644
--- a/app/views/notify/issue_status_changed_email.text.erb
+++ b/app/views/notify/issue_status_changed_email.text.erb
@@ -1,4 +1,4 @@
 Issue was <%= @issue_status %> by <%= @updated_by.name %>
 
-Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
+Issue <%= @issue.iid %>: <%= url_for(namespace_project_issue_url(@issue.project.namespace, @issue.project, @issue)) %>
 
diff --git a/app/views/notify/merge_request_status_email.text.haml b/app/views/notify/merge_request_status_email.text.haml
index 8750bf86e2cd84d358d52b9fc36b3f83278775e7..b96dd0fd8abb901acb088d37cfd2841c77c31fbd 100644
--- a/app/views/notify/merge_request_status_email.text.haml
+++ b/app/views/notify/merge_request_status_email.text.haml
@@ -1,6 +1,6 @@
 = "Merge Request ##{@merge_request.iid} was #{@mr_status} by #{@updated_by.name}"
 
-Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
+Merge Request url: #{namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request)}
 
 = merge_path_description(@merge_request, 'to')
 
diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml
index 360da60bc3f84028d161746b2dacba14d5b3b89b..9db75bdb19e48aff9b07415aedda6b07429fefcb 100644
--- a/app/views/notify/merged_merge_request_email.text.haml
+++ b/app/views/notify/merged_merge_request_email.text.haml
@@ -1,6 +1,6 @@
 = "Merge Request ##{@merge_request.iid} was merged"
 
-Merge Request Url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
+Merge Request Url: #{namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request)}
 
 = merge_path_description(@merge_request, 'to')
 
diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml
index f2f8eee18c49cd18b374ba822a38db2610bc443f..03cbee94608285950a47d037a6e33e4a783c970b 100644
--- a/app/views/notify/new_issue_email.html.haml
+++ b/app/views/notify/new_issue_email.html.haml
@@ -1,5 +1,5 @@
 -if @issue.description
-  = markdown(@issue.description)
+  = replace_image_links_with_base64(markdown(@issue.description), @issue.project)
 
 - if @issue.assignee_id.present?
   %p
diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb
index d36f54eb1ca582d6fd271bf666f56ce2df187976..0cc629354985870100d6ac548af74ffdc8ca8d40 100644
--- a/app/views/notify/new_issue_email.text.erb
+++ b/app/views/notify/new_issue_email.text.erb
@@ -1,5 +1,5 @@
 New Issue was created.
 
-Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
+Issue <%= @issue.iid %>: <%= url_for(namespace_project_issue_url(@issue.project.namespace, @issue.project, @issue)) %>
 Author:   <%= @issue.author_name %>
 Asignee:  <%= @issue.assignee_name %>
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index f02d5111b22c333ed48c0c3c36041e6f86da5431..729a7bb505d3ae8829121bc25fbc341edf994316 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -6,4 +6,4 @@
     Assignee: #{@merge_request.author_name} &rarr; #{@merge_request.assignee_name}
 
 -if @merge_request.description
-  = markdown(@merge_request.description)
+  = replace_image_links_with_base64(markdown(@merge_request.description), @merge_request.project)
diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb
index 16be4bb619f04a68b749777f2e3e2c276a225222..f08039ad045c39f745a2d2400823032f9a4a3d58 100644
--- a/app/views/notify/new_merge_request_email.text.erb
+++ b/app/views/notify/new_merge_request_email.text.erb
@@ -1,6 +1,6 @@
 New Merge Request #<%= @merge_request.iid %>
 
-<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
+<%= url_for(namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request)) %>
 
 <%= merge_path_description(@merge_request, 'to') %>
 Author:   <%= @merge_request.author_name %>
diff --git a/app/views/notify/note_commit_email.text.erb b/app/views/notify/note_commit_email.text.erb
index aab8e5cfb6cf7b6f9ce2c7f632d74acb7ceb2cbc..aaeaf5fdf731c498ea6a46f570b9e7e9c5e924f7 100644
--- a/app/views/notify/note_commit_email.text.erb
+++ b/app/views/notify/note_commit_email.text.erb
@@ -1,6 +1,6 @@
 New comment for Commit <%= @commit.short_id %>
 
-<%= url_for(project_commit_url(@note.project, id: @commit.id, anchor: "note_#{@note.id}")) %>
+<%= url_for(namespace_project_commit_url(@note.project.namespace, @note.project, id: @commit.id, anchor: "note_#{@note.id}")) %>
 
 
 Author: <%= @note.author_name %>
diff --git a/app/views/notify/note_issue_email.text.erb b/app/views/notify/note_issue_email.text.erb
index 8a61f54a33744880c46f9ff36bbb57df1bd7df40..e33cbcd70f2298d4b286f825c61fc5f71e32c195 100644
--- a/app/views/notify/note_issue_email.text.erb
+++ b/app/views/notify/note_issue_email.text.erb
@@ -1,6 +1,6 @@
 New comment for Issue <%= @issue.iid %>
 
-<%= url_for(project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}")) %>
+<%= url_for(namespace_project_issue_url(@issue.project.namespace, @issue.project, @issue, anchor: "note_#{@note.id}")) %>
 
 
 Author: <%= @note.author_name %>
diff --git a/app/views/notify/note_merge_request_email.text.erb b/app/views/notify/note_merge_request_email.text.erb
index 79e72ca16c6fbb7d1cdcbd16dd461251830cd53d..1d1411992a653493d1b5fb1f35f584ee6b004efc 100644
--- a/app/views/notify/note_merge_request_email.text.erb
+++ b/app/views/notify/note_merge_request_email.text.erb
@@ -1,6 +1,6 @@
 New comment for Merge Request <%= @merge_request.iid %>
 
-<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")) %>
+<%= url_for(namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")) %>
 
 
 <%= @note.author_name %>
diff --git a/app/views/notify/project_access_granted_email.html.haml b/app/views/notify/project_access_granted_email.html.haml
index 4596205f39bc55dbff7115ca778e41ff3a416af3..dfc30a2d360cd312cfdb959731994ea6cafa8138 100644
--- a/app/views/notify/project_access_granted_email.html.haml
+++ b/app/views/notify/project_access_granted_email.html.haml
@@ -1,5 +1,5 @@
 %p
   = "You have been granted #{@project_member.human_access} access to project"
 %p
-  = link_to project_url(@project) do
+  = link_to namespace_project_url(@project.namespace, @project) do
     = @project.name_with_namespace
diff --git a/app/views/notify/project_access_granted_email.text.erb b/app/views/notify/project_access_granted_email.text.erb
index de24feb802f6dc2542ce366863424ee7cd24747c..68eb1611ba7e6f4e73faa8d09ca8de7d01892ba9 100644
--- a/app/views/notify/project_access_granted_email.text.erb
+++ b/app/views/notify/project_access_granted_email.text.erb
@@ -1,4 +1,4 @@
 
 You have been granted <%= @project_member.human_access %> access to project <%= @project.name_with_namespace %>
 
-<%= url_for(project_url(@project)) %>
+<%= url_for(namespace_project_url(@project.namespace, @project)) %>
diff --git a/app/views/notify/project_was_moved_email.html.haml b/app/views/notify/project_was_moved_email.html.haml
index fe248584e55f46a02524effd5c7bd21dc6fdaf12..3cd759f1f5766f91cc0f08414640bc767dcd59dc 100644
--- a/app/views/notify/project_was_moved_email.html.haml
+++ b/app/views/notify/project_was_moved_email.html.haml
@@ -2,14 +2,14 @@
   Project was moved to another location
 %p
   The project is now located under
-  = link_to project_url(@project) do
+  = link_to namespace_project_url(@project.namespace, @project) do
     = @project.name_with_namespace
 %p
   To update the remote url in your local repository run (for ssh):
-%p{ style: "background:#f5f5f5; padding:10px; border:1px solid #ddd" }
+%p{ style: "background: #f5f5f5; padding:10px; border:1px solid #ddd" }
   git remote set-url origin #{@project.ssh_url_to_repo}
 %p
   or for http(s):
-%p{ style: "background:#f5f5f5; padding:10px; border:1px solid #ddd" }
+%p{ style: "background: #f5f5f5; padding:10px; border:1px solid #ddd" }
   git remote set-url origin #{@project.http_url_to_repo}
 %br
diff --git a/app/views/notify/project_was_moved_email.text.erb b/app/views/notify/project_was_moved_email.text.erb
index 664148fb3ba3f007573d4d60876563f52449579c..b3f18b35a4d606a0b46dcddc9ffe3faafef02576 100644
--- a/app/views/notify/project_was_moved_email.text.erb
+++ b/app/views/notify/project_was_moved_email.text.erb
@@ -1,7 +1,7 @@
 Project was moved to another location
 
 The project is now located under 
-<%= project_url(@project) %>
+<%= namespace_project_url(@project.namespace, @project) %>
 
 
 To update the remote url in your local repository run (for ssh):
diff --git a/app/views/notify/repository_push_email.html.haml b/app/views/notify/repository_push_email.html.haml
index 3cf50bf0826005b54d4fc98c8ece766e274e3a2e..bbf7004c9063464be57d900f1f0b190ba1bac660 100644
--- a/app/views/notify/repository_push_email.html.haml
+++ b/app/views/notify/repository_push_email.html.haml
@@ -1,28 +1,67 @@
-%h3 #{@author.name} pushed to #{@branch} at #{link_to @project.name_with_namespace, project_url(@project)}
+%h3 #{@author.name} #{@action_name} #{@ref_type} #{@ref_name} at #{link_to @project.name_with_namespace, namespace_project_url(@project.namespace, @project)}
 
-%h4 Commits:
+- if @compare
+  - if @reverse_compare
+    %p
+      %strong WARNING:
+      The push did not contain any new commits, but force pushed to delete the commits and changes below.
 
-%ul
-  - @commits.each do |commit|
-    %li
-      %strong #{link_to commit.short_id, project_commit_url(@project, commit)}
-      %span by #{commit.author_name}
-      %pre #{commit.safe_message}
+  %h4
+    = @reverse_compare ? "Deleted commits:" : "Commits:"
 
-%h4 Changes:
-- @diffs.each do |diff|
-  %li
-    %strong
-      - if diff.old_path == diff.new_path
-        = diff.new_path
-      - elsif diff.new_path && diff.old_path
-        #{diff.old_path} &rarr; #{diff.new_path}
-      - else
-        = diff.new_path || diff.old_path
-    %hr
-    %pre
-      = diff.diff
-    %br
+  %ul
+    - @commits.each do |commit|
+      %li
+        %strong #{link_to commit.short_id, namespace_project_commit_url(@project.namespace, @project, commit)}
+        %div
+          %span by #{commit.author_name}
+          %i at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")}
+        %pre.commit-message 
+          = commit.safe_message
 
-- if @compare.timeout
-  %h5 Huge diff. To prevent performance issues changes are hidden
+  %h4 #{pluralize @diffs.count, "changed file"}:
+
+  %ul
+    - @diffs.each_with_index do |diff, i|
+      %li.file-stats
+        %a{href: "#{@target_url if @disable_diffs}#diff-#{i}" }
+          - if diff.deleted_file
+            %span.deleted-file
+              &minus;
+              = diff.old_path
+          - elsif diff.renamed_file
+            = diff.old_path
+            &rarr;
+            = diff.new_path
+          - elsif diff.new_file
+            %span.new-file
+              &plus;
+              = diff.new_path
+          - else
+            = diff.new_path
+
+  - unless @disable_diffs
+    %h4 Changes:
+    - @diffs.each_with_index do |diff, i|
+      %li{id: "diff-#{i}"}
+        %a{href: @target_url + "#diff-#{i}"}
+          - if diff.deleted_file
+            %strong
+              = diff.old_path
+            deleted
+          - elsif diff.renamed_file
+            %strong
+              = diff.old_path
+            &rarr;
+            %strong
+              = diff.new_path
+          - else
+            %strong
+              = diff.new_path
+        %hr
+        %pre
+          = color_email_diff(diff.diff)
+        %br
+
+  - if @compare.timeout
+    %h5 Huge diff. To prevent performance issues changes are hidden
diff --git a/app/views/notify/repository_push_email.text.haml b/app/views/notify/repository_push_email.text.haml
index 6f5f9eda2c560708e40ea9b12d0b5f4d70cdf21d..97a176ed2a3800577ce0ec8340c0c6d7428c41dc 100644
--- a/app/views/notify/repository_push_email.text.haml
+++ b/app/views/notify/repository_push_email.text.haml
@@ -1,25 +1,49 @@
-#{@author.name} pushed to #{@branch} at #{link_to @project.name_with_namespace, project_url(@project)}
-
-\
-Commits:
-- @commits.each do |commit|
-  #{link_to commit.short_id, project_commit_url(@project, commit)} by #{commit.author_name}
-  #{commit.safe_message}
-  \- - - - -
-\
-\
-Changes:
-- @diffs.each do |diff|
+#{@author.name} #{@action_name} #{@ref_type} #{@ref_name} at #{@project.name_with_namespace}
+- if @compare
   \
-  \=====================================
-  - if diff.old_path == diff.new_path
-    = diff.new_path
-  - elsif diff.new_path && diff.old_path
-    #{diff.old_path} &rarr; #{diff.new_path}
-  - else
-    = diff.new_path || diff.old_path
-  \=====================================
-  != diff.diff
-\
-- if @compare.timeout
-  Huge diff. To prevent performance issues it was hidden
+  \
+  - if @reverse_compare
+    WARNING: The push did not contain any new commits, but force pushed to delete the commits and changes below.
+    \
+    \
+  = @reverse_compare ? "Deleted commits:" : "Commits:"
+  - @commits.each do |commit|
+    #{commit.short_id} by #{commit.author_name} at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")}
+    #{commit.safe_message}
+    \- - - - -
+  \
+  \
+  #{pluralize @diffs.count, "changed file"}:
+  \
+  - @diffs.each do |diff|
+    - if diff.deleted_file
+      \- − #{diff.old_path}
+    - elsif diff.renamed_file
+      \- #{diff.old_path} → #{diff.new_path}
+    - elsif diff.new_file
+      \- + #{diff.new_path}
+    - else
+      \- #{diff.new_path}
+  - unless @disable_diffs
+    \
+    \
+    Changes:
+    - @diffs.each do |diff|
+      \
+      \=====================================
+      - if diff.deleted_file
+        #{diff.old_path} deleted
+      - elsif diff.renamed_file
+        #{diff.old_path} → #{diff.new_path}
+      - else
+        = diff.new_path
+      \=====================================
+      != diff.diff
+  - if @compare.timeout
+    \
+    \
+    Huge diff. To prevent performance issues it was hidden
+  - if @target_url
+    \
+    \
+    View it on GitLab: #{@target_url}
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index a21dcff41c069f92e609bd8465e6aae3235201cf..5bffb4acc1d7530c08a00d699be68843c1680684 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -1,16 +1,11 @@
-%h3.page-title
-  Account settings
-%p.light
-  You can change your username and private token here.
-  - if current_user.ldap_user?
+- if current_user.ldap_user?
+  .alert.alert-info
     Some options are unavailable for LDAP accounts
-%hr
-
 
 .account-page
   %fieldset.update-token
     %legend
-      Private token
+      Reset Private token
     %div
       = form_for @user, url: reset_private_token_profile_path, method: :put do |f|
         .data
@@ -25,7 +20,7 @@
             - if current_user.private_token
               = text_field_tag "token", current_user.private_token, class: "form-control"
               %div
-                = f.submit 'Reset', data: { confirm: "Are you sure?" }, class: "btn btn-primary btn-build-token"
+                = f.submit 'Reset private token', data: { confirm: "Are you sure?" }, class: "btn btn-primary btn-build-token"
             - else
               %span You don`t have one yet. Click generate to fix it.
               = f.submit 'Generate', class: "btn success btn-build-token"
@@ -33,17 +28,21 @@
 
   - if show_profile_social_tab?
     %fieldset
-      %legend Social Accounts
-      .oauth_select_holder.append-bottom-10
+      %legend Connected Accounts
+      .oauth-buttons.append-bottom-10
         %p Click on icon to activate signin with one of the following services
         - enabled_social_providers.each do |provider|
-          %span{class: oauth_active_class(provider) }
-            = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider)
+          .btn-group
+            = link_to oauth_image_tag(provider), omniauth_authorize_path(User, provider),
+              class: "btn btn-lg #{'active' if oauth_active?(provider)}"
+            - if oauth_active?(provider)
+              = link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'btn btn-lg' do
+                %i.fa.fa-close
 
   - if show_profile_username_tab?
     %fieldset.update-username
       %legend
-        Username
+        Change Username
       = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
         %p
           Changing your username will change path to all personal projects!
@@ -57,7 +56,7 @@
         %p.light
           = user_url(@user)
         %div
-          = f.submit 'Save username', class: "btn btn-save"
+          = f.submit 'Save username', class: "btn btn-warning"
 
   - if show_profile_remove_tab?
     %fieldset.remove-account
@@ -75,3 +74,4 @@
               The following groups will be abandoned. You should transfer or remove them:
               %strong #{current_user.solo_owned_groups.map(&:name).join(', ')}
         = link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove"
+
diff --git a/app/views/profiles/applications.html.haml b/app/views/profiles/applications.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..97e98948f36647b7021e32cd3bd7e769365f75c0
--- /dev/null
+++ b/app/views/profiles/applications.html.haml
@@ -0,0 +1,49 @@
+%h3.page-title
+  Application Settings
+%p.light
+  OAuth2 protocol settings below.
+
+%fieldset.oauth-applications
+  %legend Your applications
+  %p= link_to 'New Application', new_oauth_application_path, class: 'btn btn-success'
+  - if @applications.any?
+    %table.table.table-striped
+      %thead
+        %tr
+          %th Name
+          %th Callback URL
+          %th Clients
+          %th
+          %th
+      %tbody
+        - @applications.each do |application|
+          %tr{:id => "application_#{application.id}"}
+            %td= link_to application.name, oauth_application_path(application)
+            %td
+              - application.redirect_uri.split.each do |uri|
+                %div= uri
+            %td= application.access_tokens.count
+            %td= link_to 'Edit', edit_oauth_application_path(application), class: 'btn btn-link btn-sm'
+            %td= render 'doorkeeper/applications/delete_form', application: application
+
+%fieldset.oauth-authorized-applications.prepend-top-20
+  %legend Authorized applications
+
+  - if @authorized_tokens.any?
+    %table.table.table-striped
+      %thead
+        %tr
+          %th Name
+          %th Authorized At
+          %th Scope
+          %th
+      %tbody
+        - @authorized_apps.each do |app|
+          - token = app.authorized_tokens.order('created_at desc').first
+          %tr{:id => "application_#{app.id}"}
+            %td= app.name
+            %td= token.created_at
+            %td= token.scopes
+            %td= render 'doorkeeper/authorized_applications/delete_form', application: app
+  - else
+    %p.light You dont have any authorized applications
diff --git a/app/views/profiles/design.html.haml b/app/views/profiles/design.html.haml
index 0d8075b7d43209d67a02913b40844b46c558a6d8..cc00d08d03b526230d2a8566801d8ea0139c9da4 100644
--- a/app/views/profiles/design.html.haml
+++ b/app/views/profiles/design.html.haml
@@ -1,7 +1,7 @@
 %h3.page-title
-  My appearance settings
+  Design Settings
 %p.light
-  Appearance settings saved to your profile and available across all devices
+  Appearance settings will be saved to your profile and made available across all devices.
 %hr
 
 = form_for @user, url: profile_path, remote: true, method: :put do |f|
@@ -33,6 +33,11 @@
         .prev.violet
         = f.radio_button :theme_id, 5
         Violet
+
+      = label_tag do
+        .prev.blue
+        = f.radio_button :theme_id, 6
+        Blue
     %br
     .clearfix
 
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index ca980db2f3c3e6bbb8d45acf90c8fdec262c58af..9d8f33cbbaaadfbd8a1364c89fad32895a8a75ea 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -1,9 +1,13 @@
 %h3.page-title
-  My email addresses
+  Email Settings
 %p.light
   Your
   %b Primary Email
-  will be used for account notifications, avatar detection and web based operations, such as edits and merges.
+  will be used for avatar detection and web based operations, such as edits and merges.
+  %br
+  Your
+  %b Notification Email
+  will be used for account notifications.
   %br
   All email addresses will be used to identify your commits.
 
@@ -21,7 +25,7 @@
         %strong= email.email
         %span.cgray
           added #{time_ago_with_tooltip(email.created_at)}
-        = link_to 'Remove', profile_email_path(email), data: { confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-small btn-remove pull-right'
+        = link_to 'Remove', profile_email_path(email), data: { confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-sm btn-remove pull-right'
 
 %h4 Add email address
 = form_for 'email', url: profile_emails_path, html: { class: 'form-horizontal' } do |f|
@@ -30,4 +34,4 @@
     .col-sm-10
       = f.text_field :email, class: 'form-control'
   .form-actions
-    = f.submit 'Add', class: 'btn btn-create'
+    = f.submit 'Add email address', class: 'btn btn-create'
diff --git a/app/views/profiles/groups/index.html.haml b/app/views/profiles/groups/index.html.haml
deleted file mode 100644
index e9ffca8faf4941d01936dcdfbee5ff026c9d12d1..0000000000000000000000000000000000000000
--- a/app/views/profiles/groups/index.html.haml
+++ /dev/null
@@ -1,39 +0,0 @@
-%h3.page-title
-  Group membership
-  - if current_user.can_create_group?
-    %span.pull-right
-      = link_to new_group_path, class: "btn btn-new" do
-        %i.fa.fa-plus
-        New Group
-%p.light
-  Group members have access to all a group's projects
-%hr
-.panel.panel-default
-  .panel-heading
-    %strong Groups
-    (#{@user_groups.count})
-  %ul.well-list
-    - @user_groups.each do |user_group|
-      - group = user_group.group
-      %li
-        .pull-right
-          - if can?(current_user, :manage_group, group)
-            = link_to edit_group_path(group), class: "btn-small btn btn-grouped" do
-              %i.fa.fa-cogs
-              Settings
-
-          - if can?(current_user, :destroy, user_group)
-            = link_to leave_profile_group_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-small btn btn-grouped", title: 'Remove user from group' do
-              %i.fa.fa-sign-out
-              Leave
-
-        = link_to group, class: 'group-name' do
-          %strong= group.name
-
-        as
-        %strong #{user_group.human_access}
-
-        %div.light
-          #{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")}
-
-= paginate @user_groups
diff --git a/app/views/profiles/history.html.haml b/app/views/profiles/history.html.haml
index 3951c47b5f275c300ae60c47d62d57b0b0af5a19..b1ab433f48fb90552dd70f288b7a62fd86c34e50 100644
--- a/app/views/profiles/history.html.haml
+++ b/app/views/profiles/history.html.haml
@@ -1,7 +1,7 @@
 %h3.page-title
-  Account history
+  Your Account History
 %p.light
-  All events created by your account are listed here
+  All events created by your account are listed below.
 %hr
 .profile_history
   = render @events
diff --git a/app/views/profiles/keys/_key.html.haml b/app/views/profiles/keys/_key.html.haml
index 81411a7565e1fe042fb2b5e199dbeae835c45e0c..fe5770f45c383d54ae38223a193facfaa361d5d4 100644
--- a/app/views/profiles/keys/_key.html.haml
+++ b/app/views/profiles/keys/_key.html.haml
@@ -1,9 +1,12 @@
-%li
-  = link_to profile_key_path(key) do
-    %strong= key.title
-  %span
-    (#{key.fingerprint})
-  %span.cgray
-    added #{time_ago_with_tooltip(key.created_at)}
-
-  = link_to 'Remove', profile_key_path(key), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-small btn-remove delete-key pull-right"
+%tr
+  %td
+    = link_to path_to_key(key, is_admin) do
+      %strong= key.title
+  %td
+    %span
+      (#{key.fingerprint})
+  %td
+    %span.cgray
+      added #{time_ago_with_tooltip(key.created_at)}
+  %td
+    = link_to 'Remove', path_to_key(key, is_admin), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-sm btn-remove delete-key pull-right"
diff --git a/app/views/profiles/keys/_key_details.html.haml b/app/views/profiles/keys/_key_details.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..8bac22a2e1a8130d1a3a4169d509871b792b39fe
--- /dev/null
+++ b/app/views/profiles/keys/_key_details.html.haml
@@ -0,0 +1,22 @@
+- is_admin = defined?(admin) ? true : false
+.row
+  .col-md-4
+    .panel.panel-default
+      .panel-heading
+        SSH Key
+      %ul.well-list
+        %li
+          %span.light Title:
+          %strong= @key.title
+        %li
+          %span.light Created on:
+          %strong= @key.created_at.stamp("Aug 21, 2011")
+
+  .col-md-8
+    %p
+      %span.light Fingerprint:
+      %strong= @key.fingerprint
+    %pre.well-pre
+      = @key.key
+  .pull-right
+    = link_to 'Remove', path_to_key(@key, is_admin), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
diff --git a/app/views/profiles/keys/_key_table.html.haml b/app/views/profiles/keys/_key_table.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..ef0075aad3b20598c45a21fed3453a8cd65131b6
--- /dev/null
+++ b/app/views/profiles/keys/_key_table.html.haml
@@ -0,0 +1,19 @@
+- is_admin = defined?(admin) ? true : false
+.panel.panel-default
+  - if @keys.any?
+    %table.table
+      %thead.panel-heading
+        %tr
+          %th Title
+          %th Fingerprint
+          %th Added at
+          %th
+      %tbody
+        - @keys.each do |key|
+          = render 'profiles/keys/key', key: key, is_admin: is_admin
+  - else
+    .nothing-here-block
+      - if is_admin
+        User has no ssh keys
+      - else
+        There are no SSH keys with access to your account.
diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml
index a322f82f2362708410fb72139f86eb590aa4c13b..0904c50c88b99e8fffa697fa317c30786cc2b474 100644
--- a/app/views/profiles/keys/index.html.haml
+++ b/app/views/profiles/keys/index.html.haml
@@ -1,22 +1,10 @@
 %h3.page-title
-  My SSH keys
+  SSH Keys Settings
   .pull-right
     = link_to "Add SSH Key", new_profile_key_path, class: "btn btn-new"
 %p.light
-  SSH keys allow you to establish a secure connection between your computer and GitLab
-  %br
   Before you can add an SSH key you need to
-  = link_to "generate it", help_page_path("ssh", "ssh")
+  = link_to "generate it.", help_page_path("ssh", "README")
 %hr
 
-
-.panel.panel-default
-  .panel-heading
-    SSH Keys (#{@keys.count})
-  %ul.well-list#keys-table
-    = render @keys
-    - if @keys.blank?
-      %li
-        .nothing-here-block There are no SSH keys with access to your account.
-
-
+= render 'key_table'
diff --git a/app/views/profiles/keys/new.html.haml b/app/views/profiles/keys/new.html.haml
index c02b47b0ad59f75e8a8563782b6164f11568bb70..ccec716d0c66f02c9c6d86e6802251ea668a5740 100644
--- a/app/views/profiles/keys/new.html.haml
+++ b/app/views/profiles/keys/new.html.haml
@@ -8,9 +8,9 @@
   $('#key_key').on('focusout', function(){
     var title = $('#key_title'),
         val      = $('#key_key').val(),
-        key_mail = val.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+|\.[a-zA-Z0-9._-]+)/gi);
+        comment = val.match(/^\S+ \S+ (.+)$/);
 
-    if( key_mail && key_mail.length > 0 && title.val() == '' ){
-      $('#key_title').val( key_mail );
+    if( comment && comment.length > 1 && title.val() == '' ){
+      $('#key_title').val( comment[1] );
     }
   });
diff --git a/app/views/profiles/keys/show.html.haml b/app/views/profiles/keys/show.html.haml
index c4fc1bb269c0610eb54db901fb508b4be771b333..cfd53298962f50c7b1fd064a3421568ad8084e3d 100644
--- a/app/views/profiles/keys/show.html.haml
+++ b/app/views/profiles/keys/show.html.haml
@@ -1,22 +1 @@
-.row
-  .col-md-4
-    .panel.panel-default
-      .panel-heading
-        SSH Key
-      %ul.well-list
-        %li
-          %span.light Title:
-          %strong= @key.title
-        %li
-          %span.light Created on:
-          %strong= @key.created_at.stamp("Aug 21, 2011")
-
-  .col-md-8
-    %p
-      %span.light Fingerprint:
-      %strong= @key.fingerprint
-    %pre.well-pre
-      = @key.key
-
-.pull-right
-  = link_to 'Remove', profile_key_path(@key), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
+= render "key_details"
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index a044fad8fa3cd879519707ed485502a1ac571891..273e72f8a4dfc26bf133cbc98afeee4c4107b6a0 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -1,33 +1,56 @@
 %h3.page-title
-  Notifications settings
+  Notifications Settings
 %p.light
-  GitLab uses the email specified in your profile for notifications
+  These are your global notification settings.
 %hr
-= form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications form-horizontal global-notifications-form' do
+
+= form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications form-horizontal global-notifications-form' } do |f|
+  -if @user.errors.any?
+    %div.alert.alert-danger
+      %ul
+        - @user.errors.full_messages.each do |msg|
+          %li= msg
+
   = hidden_field_tag :notification_type, 'global'
 
-  = label_tag :notification_level, 'Notification level', class: 'control-label'
-  .col-sm-10
-    .radio
-      = label_tag nil, class: '' do
-        = radio_button_tag :notification_level, Notification::N_DISABLED, @notification.disabled?, class: 'trigger-submit'
-        .level-title
-          Disabled
-        %p You will not get any notifications via email
-
-    .radio
-      = label_tag nil, class: '' do
-        = radio_button_tag :notification_level, Notification::N_PARTICIPATING, @notification.participating?, class: 'trigger-submit'
-        .level-title
-          Participating
-        %p You will only receive notifications from related resources (e.g. from your commits or assigned issues)
-
-    .radio
-      = label_tag nil, class: '' do
-        = radio_button_tag :notification_level, Notification::N_WATCH, @notification.watch?, class: 'trigger-submit'
-        .level-title
-          Watch
-        %p You will receive all notifications from projects in which you participate
+  .form-group
+    = f.label :notification_email, class: "control-label"
+    .col-sm-10
+      = f.select :notification_email, @user.all_emails, { include_blank: false }, class: "form-control"
+
+  .form-group
+    = f.label :notification_level, class: 'control-label'
+    .col-sm-10
+      .radio
+        = f.label :notification_level, value: Notification::N_DISABLED do
+          = f.radio_button :notification_level, Notification::N_DISABLED
+          .level-title
+            Disabled
+          %p You will not get any notifications via email
+
+      .radio
+        = f.label :notification_level, value: Notification::N_MENTION do
+          = f.radio_button :notification_level, Notification::N_MENTION
+          .level-title
+            Mention
+          %p You will receive notifications only for comments in which you were @mentioned
+
+      .radio
+        = f.label :notification_level, value: Notification::N_PARTICIPATING do
+          = f.radio_button :notification_level, Notification::N_PARTICIPATING
+          .level-title
+            Participating
+          %p You will only receive notifications from related resources (e.g. from your commits or assigned issues)
+
+      .radio
+        = f.label :notification_level, value: Notification::N_WATCH do
+          = f.radio_button :notification_level, Notification::N_WATCH
+          .level-title
+            Watch
+          %p You will receive all notifications from projects in which you participate
+
+  .form-actions
+    = f.submit 'Save changes', class: "btn btn-create"
 
 .clearfix
   %hr
@@ -36,16 +59,16 @@
     %p
       You can also specify notification level per group or per project.
       %br
-      By default all projects and groups uses notification level set above.
+      By default, all projects and groups will use the notification level set above.
     %h4 Groups:
     %ul.bordered-list
-      - @group_members.each do |users_group|
-        - notification = Notification.new(users_group)
-        = render 'settings', type: 'group', membership: users_group, notification: notification
+      - @group_members.each do |group_member|
+        - notification = Notification.new(group_member)
+        = render 'settings', type: 'group', membership: group_member, notification: notification
 
   .col-md-6
     %p
-      To specify notification level per project of a group you belong to,
+      To specify the notification level per project of a group you belong to,
       %br
       you need to be a member of the project itself, not only its group.
     %h4 Projects:
diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml
index 425200ff523120d225cc10bb11d6207a4b123092..4b04b113e89bd35066320a600811ad8a679210c3 100644
--- a/app/views/profiles/passwords/edit.html.haml
+++ b/app/views/profiles/passwords/edit.html.haml
@@ -1,33 +1,38 @@
-%h3.page-title Password
+%h3.page-title Password Settings
 %p.light
-  Change your password or recover your current one.
+  - if @user.password_automatically_set?
+    Set your password.
+  - else
+    Change your password or recover your current one.
 %hr
 .update-password
   = form_for @user, url: profile_password_path, method: :put, html: { class: 'form-horizontal' }  do |f|
     %div
       %p.slead
-        You must provide current password in order to change it.
-        %br
-        After a successful password update you will be redirected to login page where you should login with your new password
+        - unless @user.password_automatically_set?
+          You must provide current password in order to change it.
+          %br
+        After a successful password update, you will be redirected to the login page where you can log in with your new password.
       -if @user.errors.any?
         .alert.alert-danger
           %ul
             - @user.errors.full_messages.each do |msg|
               %li= msg
-      .form-group
-        = f.label :current_password, class: 'control-label'
-        .col-sm-10
-          = f.password_field :current_password, required: true, class: 'form-control'
-          %div
-            = link_to "Forgot your password?", reset_profile_password_path, method: :put
+      - unless @user.password_automatically_set?
+        .form-group
+          = f.label :current_password, class: 'control-label'
+          .col-sm-10
+            = f.password_field :current_password, required: true, class: 'form-control'
+            %div
+              = link_to "Forgot your password?", reset_profile_password_path, method: :put
 
       .form-group
         = f.label :password, 'New password', class: 'control-label'
         .col-sm-10
-          = f.password_field :password, required: true, class: 'form-control', id: 'user_password_profile'
+          = f.password_field :password, required: true, class: 'form-control'
       .form-group
         = f.label :password_confirmation, class: 'control-label'
         .col-sm-10
           = f.password_field :password_confirmation, required: true, class: 'form-control'
       .form-actions
-        = f.submit 'Save password', class: "btn btn-save"
+        = f.submit 'Save password', class: "btn btn-create"
diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml
index 42d2d0db29c4eac0e9bde4327fa8aceecbf72083..8bed6e0dbee1f4fcd1e21fd1c3a654a5402324e5 100644
--- a/app/views/profiles/passwords/new.html.haml
+++ b/app/views/profiles/passwords/new.html.haml
@@ -10,13 +10,14 @@
       %ul
         - @user.errors.full_messages.each do |msg|
           %li= msg
-
-  .form-group
-    = f.label :current_password, class: 'control-label'
-    .col-sm-10= f.password_field :current_password, required: true, class: 'form-control'
+  
+  - unless @user.password_automatically_set?
+    .form-group
+      = f.label :current_password, class: 'control-label'
+      .col-sm-10= f.password_field :current_password, required: true, class: 'form-control'
   .form-group
     = f.label :password, class: 'control-label'
-    .col-sm-10= f.password_field :password, required: true, class: 'form-control', id: 'user_password_profile'
+    .col-sm-10= f.password_field :password, required: true, class: 'form-control'
   .form-group
     = f.label :password_confirmation, class: 'control-label'
     .col-sm-10
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index d6b52f86154d4e9f768a2acd03a5a36498503d00..5a501e4314984ba700bf0be11c356b34c323d02b 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -1,7 +1,7 @@
 %h3.page-title
-  Profile settings
+  Profile Settings
 %p.light
-  This information appears on your profile.
+  This information will appear on your profile.
   - if current_user.ldap_user?
     Some options are unavailable for LDAP accounts
 %hr
@@ -53,10 +53,13 @@
       .form-group
         = f.label :website_url, 'Website', class: "control-label"
         .col-sm-10= f.text_field :website_url, class: "form-control"
+      .form-group
+        = f.label :location, 'Location', class: "control-label"
+        .col-sm-10= f.text_field :location, class: "form-control"
       .form-group
         = f.label :bio, class: "control-label"
         .col-sm-10
-          = f.text_area :bio, rows: 6, class: "form-control", maxlength: 250
+          = f.text_area :bio, rows: 4, class: "form-control", maxlength: 250
           %span.help-block Tell us about yourself in fewer than 250 characters.
 
     .col-md-5
@@ -77,22 +80,26 @@
                   %br
                   or change it at #{link_to "gravatar.com", "http://gravatar.com"}
             %hr
-            %a.choose-btn.btn.btn-small.js-choose-user-avatar-button
+            %a.choose-btn.btn.btn-sm.js-choose-user-avatar-button
               %i.fa.fa-paperclip
               %span Choose File ...
             &nbsp;
             %span.file_name.js-avatar-filename File name...
             = f.file_field :avatar, class: "js-user-avatar-input hidden"
-            .light The maximum file size allowed is 100KB.
+            .light The maximum file size allowed is 200KB.
             - if @user.avatar?
               %hr
-              = link_to 'Remove avatar', profile_avatar_path, data: { confirm: "Avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar"
+              = link_to 'Remove avatar', profile_avatar_path, data: { confirm: "Avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
 
       - if @user.public_profile?
-        .bs-callout.bs-callout-info
+        .alert.alert-info
           %h4 Public profile
           %p Your profile is publicly visible because you joined public project(s)
 
 
-  .form-actions
-    = f.submit 'Save changes', class: "btn btn-save"
+  .row
+    .col-md-7
+      .form-group
+        .col-sm-2 &nbsp;
+        .col-sm-10
+          = f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/profiles/update.js.erb b/app/views/profiles/update.js.erb
index 04b5cf4827de0bd5d07fc077af4ad691bf350dcd..e664ac2a52ab81cd0cb1f128664ff86909bb8ab3 100644
--- a/app/views/profiles/update.js.erb
+++ b/app/views/profiles/update.js.erb
@@ -1,6 +1,6 @@
 // Remove body class for any previous theme, re-add current one
-$('body').removeClass('ui_basic ui_mars ui_modern ui_gray ui_color')
-$('body').addClass('<%= app_theme %>')
+$('body').removeClass('ui_basic ui_mars ui_modern ui_gray ui_color light_theme dark_theme')
+$('body').addClass('<%= app_theme %> <%= theme_type %>')
 
 // Re-render the header to reflect the new theme
 $('header').html('<%= escape_javascript(render("layouts/head_panel", title: "Profile")) %>')
diff --git a/app/views/projects/_bitbucket_import_modal.html.haml b/app/views/projects/_bitbucket_import_modal.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..07d4d602769b7d07fdd6f5968f3e93c9c6990cd2
--- /dev/null
+++ b/app/views/projects/_bitbucket_import_modal.html.haml
@@ -0,0 +1,13 @@
+%div#bitbucket_import_modal.modal.hide
+  .modal-dialog
+    .modal-content
+      .modal-header
+        %a.close{href: "#", "data-dismiss" => "modal"} ×
+        %h3 Import projects from Bitbucket
+      .modal-body
+        To enable importing projects from Bitbucket, 
+        - if current_user.admin?
+          you need to
+        - else
+          your GitLab administrator needs to
+        == #{link_to 'setup OAuth integration', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/bitbucket.md'}.
diff --git a/app/views/projects/_commit_button.html.haml b/app/views/projects/_commit_button.html.haml
index fd8320adb8dd2b2486ad302ec94574476d59d761..35f7e7bb34bcfc190ca41af464136482bba56ebd 100644
--- a/app/views/projects/_commit_button.html.haml
+++ b/app/views/projects/_commit_button.html.haml
@@ -2,8 +2,5 @@
   .commit-button-annotation
     = button_tag 'Commit Changes',
                  class: 'btn commit-btn js-commit-button btn-create'
-    .message
-      to branch
-      %strong= ref
   = link_to 'Cancel', cancel_path,
             class: 'btn btn-cancel', data: {confirm: leave_edit_message}
diff --git a/app/views/projects/_dropdown.html.haml b/app/views/projects/_dropdown.html.haml
index 6ff46970336bcad465451755b2faa00d0e7e2851..f4f4c2662cf597a0e81d4ba0dfb1e9a142bfa9a4 100644
--- a/app/views/projects/_dropdown.html.haml
+++ b/app/views/projects/_dropdown.html.haml
@@ -9,24 +9,24 @@
             New issue
       - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project)
         %li
-          = link_to new_project_merge_request_path(@project), title: "New Merge Request" do
+          = link_to new_namespace_project_merge_request_path(@project.namespace, @project), title: "New Merge Request" do
             New merge request
       - if @project.snippets_enabled && can?(current_user, :write_snippet, @project)
         %li
-          = link_to new_project_snippet_path(@project), title: "New Snippet" do
+          = link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "New Snippet" do
             New snippet
-      - if can?(current_user, :admin_team_member, @project)
+      - if can?(current_user, :admin_project_member, @project)
         %li
-          = link_to new_project_team_member_path(@project), title: "New project member" do
+          = link_to namespace_project_project_members_path(@project.namespace, @project), title: "New project member" do
             New project member
       - if can? current_user, :push_code, @project
         %li.divider
         %li
-          = link_to new_project_branch_path(@project) do
+          = link_to new_namespace_project_branch_path(@project.namespace, @project) do
             %i.fa.fa-code-fork
             Git branch
         %li
-          = link_to new_project_tag_path(@project) do
+          = link_to new_namespace_project_tag_path(@project.namespace, @project) do
             %i.fa.fa-tag
             Git tag
 
diff --git a/app/views/projects/_github_import_modal.html.haml b/app/views/projects/_github_import_modal.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..e88a0f7d6899263da37682cf0625f9cc8c9fa31a
--- /dev/null
+++ b/app/views/projects/_github_import_modal.html.haml
@@ -0,0 +1,13 @@
+%div#github_import_modal.modal.hide
+  .modal-dialog
+    .modal-content
+      .modal-header
+        %a.close{href: "#", "data-dismiss" => "modal"} ×
+        %h3 Import projects from GitHub
+      .modal-body
+        To enable importing projects from GitHub, 
+        - if current_user.admin?
+          you need to
+        - else
+          your GitLab administrator needs to
+        == #{link_to 'setup OAuth integration', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/github.md'}.
\ No newline at end of file
diff --git a/app/views/projects/_gitlab_import_modal.html.haml b/app/views/projects/_gitlab_import_modal.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..52212b6ae025f12132985f407da71caf2ce9936e
--- /dev/null
+++ b/app/views/projects/_gitlab_import_modal.html.haml
@@ -0,0 +1,13 @@
+%div#gitlab_import_modal.modal.hide
+  .modal-dialog
+    .modal-content
+      .modal-header
+        %a.close{href: "#", "data-dismiss" => "modal"} ×
+        %h3 Import projects from GitLab.com
+      .modal-body
+        To enable importing projects from GitLab.com, 
+        - if current_user.admin?
+          you need to
+        - else
+          your GitLab administrator needs to
+        == #{link_to 'setup OAuth integration', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/gitlab.md'}.
\ No newline at end of file
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 672a91e0eef02d7d4a9669fd186fdd8d029b106c..5689bdee1c69e6b408e3ff2a622b5281a67809d0 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -1,42 +1,43 @@
 - empty_repo = @project.empty_repo?
 .project-home-panel{:class => ("empty-project" if empty_repo)}
-  .project-home-row
+  .project-identicon-holder
+    = project_icon(@project, alt: '', class: 'avatar project-avatar')
+  .project-home-row.project-home-row-top
     .project-home-desc
       - if @project.description.present?
         = escaped_autolink(@project.description)
       - if can?(current_user, :admin_project, @project)
         &ndash;
-        = link_to 'Edit', edit_project_path
+        = link_to 'Edit', edit_namespace_project_path
       - elsif !@project.empty_repo? && @repository.readme
         - readme = @repository.readme
         &ndash;
-        = link_to project_blob_path(@project, tree_join(@repository.root_ref, readme.name)) do
+        = link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)) do
           = readme.name
-    .star-fork-buttons
+    .project-repo-buttons
+      .inline.star.js-toggler-container{class: @show_star ? 'on' : ''}
+        - if current_user
+          = link_to_toggle_star('Star this project.', false)
+          = link_to_toggle_star('Unstar this project.', true)
+        - else
+          = link_to new_user_session_path, class: 'btn star-btn has_tooltip', title: 'You must sign in to star a project' do
+            %span
+              = icon('star')
+              Star
+            %span.count
+              = @project.star_count
       - unless @project.empty_repo?
-        .fork-buttons
-          - if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
-            - if current_user.already_forked?(@project)
-              = link_to project_path(current_user.fork_of(@project)), title: 'Go to my fork' do
+        - if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
+          .inline.fork-buttons.prepend-left-10
+            - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
+              = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-sm btn-default' do
                 = link_to_toggle_fork
             - else
-              = link_to fork_project_path(@project), title: "Fork project", method: "POST" do
+              = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-sm btn-default' do
                 = link_to_toggle_fork
 
-      .star-buttons
-        %span.star.js-toggler-container{class: @show_star ? 'on' : ''}
-          - if current_user
-            = link_to_toggle_star('Star this project.', false, true)
-            = link_to_toggle_star('Unstar this project.', true, true)
-          - else
-            = link_to_toggle_star('You must sign in to star a project.', false, false)
-
-  .project-home-row
+  .project-home-row.hidden-xs
     - if current_user && !empty_repo
       .project-home-dropdown
         = render "dropdown"
-    - unless @project.empty_repo?
-      - if can? current_user, :download_code, @project
-        .pull-right.prepend-left-10
-          = render 'projects/repositories/download_archive', split_button: true
     = render "shared/clone_panel"
diff --git a/app/views/projects/_issuable_form.html.haml b/app/views/projects/_issuable_form.html.haml
index 6cdfab933b41c06b3b30f6c401998bdafdb4c0be..e321a84974ecf0985c17e2b24e17cdf36088ae47 100644
--- a/app/views/projects/_issuable_form.html.haml
+++ b/app/views/projects/_issuable_form.html.haml
@@ -14,17 +14,20 @@
 .form-group.issuable-description
   = f.label :description, 'Description', class: 'control-label'
   .col-sm-10
-    = render 'projects/zen', f: f, attr: :description,
-                             classes: 'description form-control'
-    .col-sm-12.hint
-      .pull-left
-        Parsed with
-        #{link_to 'GitLab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}.
-      .pull-right
-        Attach images (JPG, PNG, GIF) by dragging &amp; dropping
-        or #{link_to 'selecting them', '#', class: 'markdown-selector' }.
-    .clearfix
-    .error-alert
+
+    = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do
+      = render 'projects/zen', f: f, attr: :description,
+                               classes: 'description form-control'
+      .col-sm-12.hint
+        .pull-left
+          Parsed with
+          #{link_to 'GitLab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}.
+        .pull-right
+          Attach files by dragging &amp; dropping
+          or #{link_to 'selecting them', '#', class: 'markdown-selector' }.
+
+      .clearfix
+      .error-alert
 %hr
 .form-group
   .issue-assignee
@@ -32,8 +35,8 @@
       %i.fa.fa-user
       Assign to
     .col-sm-10
-      = project_users_select_tag("#{issuable.class.model_name.param_key}[assignee_id]",
-          placeholder: 'Select a user', class: 'custom-form-control',
+      = users_select_tag("#{issuable.class.model_name.param_key}[assignee_id]",
+          placeholder: 'Select a user', class: 'custom-form-control', null_user: true,
           selected: issuable.assignee_id)
       &nbsp;
       = link_to 'Assign to me', '#', class: 'btn assign-to-me-link'
@@ -47,23 +50,32 @@
         = f.select(:milestone_id, milestone_options(issuable),
           { include_blank: 'Select milestone' }, { class: 'select2' })
       - else
+        .prepend-top-10
         %span.light No open milestones available.
       &nbsp;
-      = link_to 'Create new milestone', new_project_milestone_path(issuable.project)
+      - if can? current_user, :admin_milestone, issuable.project
+        = link_to 'Create new milestone', new_namespace_project_milestone_path(issuable.project.namespace, issuable.project), target: :blank
 .form-group
   = f.label :label_ids, class: 'control-label' do
-    %i.icon-tag
+    %i.fa.fa-tag
     Labels
   .col-sm-10
     - if issuable.project.labels.any?
       = f.collection_select :label_ids, issuable.project.labels.all, :id, :name,
         { selected: issuable.label_ids }, multiple: true, class: 'select2'
     - else
+      .prepend-top-10
       %span.light No labels yet.
     &nbsp;
-    = link_to 'Create new label', new_project_label_path(issuable.project)
+    - if can? current_user, :admin_label, issuable.project
+      = link_to 'Create new label', new_namespace_project_label_path(issuable.project.namespace, issuable.project), target: :blank
 
 .form-actions
+  - if !issuable.project.empty_repo? && (guide_url = contribution_guide_url(issuable.project)) && !issuable.persisted?
+    %p
+      Please review the
+      %strong #{link_to 'guidelines for contribution', guide_url}
+      to this repository.
   - if issuable.new_record?
     = f.submit "Submit new #{issuable.class.model_name.human.downcase}", class: 'btn btn-create'
   - else
@@ -72,4 +84,4 @@
     - cancel_project = issuable.source_project
   - else
     - cancel_project = issuable.project
-  = link_to 'Cancel', [cancel_project, issuable], class: 'btn btn-cancel'
+  = link_to 'Cancel', [cancel_project.namespace.becomes(Namespace), cancel_project, issuable], class: 'btn btn-cancel'
diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f356a25dbfa23738996debf3fca8d7c94acd4511
--- /dev/null
+++ b/app/views/projects/_md_preview.html.haml
@@ -0,0 +1,13 @@
+%ul.nav.nav-tabs
+  %li.active
+    = link_to '#md-write-holder', class: 'js-md-write-button' do
+      Write
+  %li
+    = link_to '#md-preview-holder', class: 'js-md-preview-button',
+        data: { url: markdown_preview_namespace_project_path(@project.namespace, @project) } do
+      Preview
+%div
+  .md-write-holder
+    = yield
+  .md-preview-holder.hide
+    .js-md-preview{class: (preview_class if defined?(preview_class))}
diff --git a/app/views/projects/_settings_nav.html.haml b/app/views/projects/_settings_nav.html.haml
index 2008f8c558dc1b2878ce0cb70f77ac1fc8c649e0..281a84a3d3c84ddc77a0ec4a8249883eba47a64e 100644
--- a/app/views/projects/_settings_nav.html.haml
+++ b/app/views/projects/_settings_nav.html.haml
@@ -1,25 +1,31 @@
-%ul.nav.nav-pills.nav-stacked.nav-stacked-menu.append-bottom-20.project-settings-nav
+%ul.project-settings-nav.sidebar-subnav
   = nav_link(path: 'projects#edit') do
-    = link_to edit_project_path(@project), class: "stat-tab tab " do
+    = link_to edit_project_path(@project), title: 'Project', class: "stat-tab tab " do
       %i.fa.fa-pencil-square-o
-      Project
-  = nav_link(controller: [:team_members, :teams]) do
-    = link_to project_team_index_path(@project), class: "team-tab tab" do
+      %span
+        Project
+  = nav_link(controller: [:project_members, :teams]) do
+    = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: "team-tab tab" do
       %i.fa.fa-users
-      Members
+      %span
+        Members
   = nav_link(controller: :deploy_keys) do
-    = link_to project_deploy_keys_path(@project) do
+    = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do
       %i.fa.fa-key
-      Deploy Keys
+      %span
+        Deploy Keys
   = nav_link(controller: :hooks) do
-    = link_to project_hooks_path(@project) do
+    = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Web Hooks' do
       %i.fa.fa-link
-      Web Hooks
+      %span
+        Web Hooks
   = nav_link(controller: :services) do
-    = link_to project_services_path(@project) do
+    = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do
       %i.fa.fa-cogs
-      Services
+      %span
+        Services
   = nav_link(controller: :protected_branches) do
-    = link_to project_protected_branches_path(@project) do
+    = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do
       %i.fa.fa-lock
-      Protected branches
+      %span
+        Protected branches
diff --git a/app/views/projects/_visibility_level.html.haml b/app/views/projects/_visibility_level.html.haml
index 5f34e66b3edd9678741e7d8eac65ee31b5565f4d..42c8e685224c022894f724ce9140d50d6be4273e 100644
--- a/app/views/projects/_visibility_level.html.haml
+++ b/app/views/projects/_visibility_level.html.haml
@@ -7,8 +7,8 @@
       - Gitlab::VisibilityLevel.values.each do |level|
         .radio
           - restricted = restricted_visibility_levels.include?(level)
-          = f.radio_button :visibility_level, level, checked: (visibility_level == level), disabled: restricted
           = label :project_visibility_level, level do
+            = f.radio_button :visibility_level, level, checked: (visibility_level == level), disabled: restricted
             = visibility_level_icon(level)
             .option-title
               = visibility_level_label(level)
diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml
index 2bbc49e8eb5d38f23a1090672839e43377bf7741..cf1c55ecca6535a3f1b6ec4a172e793dfb6c8b2a 100644
--- a/app/views/projects/_zen.html.haml
+++ b/app/views/projects/_zen.html.haml
@@ -1,7 +1,10 @@
 .zennable
-  %input#zen-toggle-comment{ tabindex: '-1', type: 'checkbox' }
+  %input#zen-toggle-comment.zen-toggle-comment{ tabindex: '-1', type: 'checkbox' }
   .zen-backdrop
     - classes << ' js-gfm-input markdown-area'
     = f.text_area attr, class: classes, placeholder: 'Leave a comment'
-    %label{ for: 'zen-toggle-comment', class: 'expand' } Edit in fullscreen
-    %label{ for: 'zen-toggle-comment', class: 'collapse' }
+    = link_to nil, class: 'zen-enter-link', tabindex: '-1' do
+      %i.fa.fa-expand
+      Edit in fullscreen
+    = link_to nil, class: 'zen-leave-link' do
+      %i.fa.fa-compress
diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml
index bdf02c6285de557e1643525123bda7cc20b4cae1..e6a859fea8fbe96445adf1327777199c9c570c1f 100644
--- a/app/views/projects/blame/show.html.haml
+++ b/app/views/projects/blame/show.html.haml
@@ -4,10 +4,11 @@
   .file-holder
     .file-title
       %i.fa.fa-file
-      %span.file_name
+      %strong
         = @path
-        %small= number_to_human_size @blob.size
-      %span.options= render "projects/blob/actions"
+      %small= number_to_human_size @blob.size
+      .file-actions
+        = render "projects/blob/actions"
     .file-content.blame.highlight
       %table
         - @blame.each do |commit, lines, since|
@@ -15,20 +16,20 @@
           %tr
             %td.blame-commit
               %span.commit
-                = link_to commit.short_id, project_commit_path(@project, commit), class: "commit_short_id"
+                = link_to commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit), class: "commit_short_id"
                 &nbsp;
                 = commit_author_link(commit, avatar: true, size: 16)
                 &nbsp;
-                = link_to_gfm truncate(commit.title, length: 20), project_commit_path(@project, commit.id), class: "row_title"
+                = link_to_gfm truncate(commit.title, length: 20), namespace_project_commit_path(@project.namespace, @project, commit.id), class: "row_title"
             %td.lines.blame-numbers
               %pre
                 - (since...(since + lines.count)).each do |i|
                   = i
                   \
             %td.lines
-              %pre
-                %code{ class: highlightjs_class(@blob.name) }
+              %pre{class: 'code highlight white'}
+                %code
                   :erb
                     <% lines.each do |line| %>
-                    <%= line %>
+                      <%= highlight(@blob.name, line, true).html_safe %>
                     <% end %>
diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml
index 812d88a873087ae886b8881642bea8475864c325..468093b48971f4ff1edc1397c69e4ee70c919b7f 100644
--- a/app/views/projects/blob/_actions.html.haml
+++ b/app/views/projects/blob/_actions.html.haml
@@ -1,28 +1,26 @@
 .btn-group.tree-btn-group
-  -# only show edit link for text files
-  - if @blob.text?
-    - if allowed_tree_edit?
-      = link_to 'Edit', project_edit_tree_path(@project, @id),
-          class: 'btn btn-small'
-    - else
-      %span.btn.btn-small.disabled Edit
-  = link_to 'Raw', project_raw_path(@project, @id),
-      class: 'btn btn-small', target: '_blank'
+  = edit_blob_link(@project, @ref, @path)
+  = link_to 'Raw', namespace_project_raw_path(@project.namespace, @project, @id),
+      class: 'btn btn-sm', target: '_blank'
   -# only show normal/blame view links for text files
   - if @blob.text?
-    - if current_page? project_blame_path(@project, @id)
-      = link_to 'Normal View', project_blob_path(@project, @id),
-          class: 'btn btn-small'
+    - if current_page? namespace_project_blame_path(@project.namespace, @project, @id)
+      = link_to 'Normal View', namespace_project_blob_path(@project.namespace, @project, @id),
+          class: 'btn btn-sm'
     - else
-      = link_to 'Blame', project_blame_path(@project, @id),
-          class: 'btn btn-small' unless @blob.empty?
-  = link_to 'History', project_commits_path(@project, @id),
-      class: 'btn btn-small'
+      = link_to 'Blame', namespace_project_blame_path(@project.namespace, @project, @id),
+          class: 'btn btn-sm' unless @blob.empty?
+  = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id),
+      class: 'btn btn-sm'
   - if @ref != @commit.sha
-    = link_to 'Permalink', project_blob_path(@project,
-        tree_join(@commit.sha, @path)), class: 'btn btn-small'
+    = link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project,
+        tree_join(@commit.sha, @path)), class: 'btn btn-sm'
 
 - if allowed_tree_edit?
+  = button_tag class: 'btn btn-small btn-primary btn-xs',
+      'data-toggle' => 'modal', 'data-target' => '#modal-replace-blob' do
+    Replace	 
+  = |
   = button_tag class: 'remove-blob btn btn-small btn-remove',
       'data-toggle' => 'modal', 'data-target' => '#modal-remove-blob' do
     Remove
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index 492dff437b5c118ead3f6a178540e1490b28305e..65c3ab10e0215ef997ff9740fd92fe97a0f6643d 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -1,32 +1,34 @@
 %ul.breadcrumb.repo-breadcrumb
   %li
     %i.fa.fa-angle-right
-    = link_to project_tree_path(@project, @ref) do
+    = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
       = @project.path
   - tree_breadcrumbs(@tree, 6) do |title, path|
     %li
       - if path
         - if path.end_with?(@path)
-          = link_to project_blob_path(@project, path) do
+          = link_to namespace_project_blob_path(@project.namespace, @project, path) do
             %strong
               = truncate(title, length: 40)
         - else
-          = link_to truncate(title, length: 40), project_tree_path(@project, path)
+          = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path)
       - else
         = link_to title, '#'
 
-%ul.blob-commit-info.bs-callout.bs-callout-info.hidden-xs
-  - blob_commit = @repository.last_commit_for_path(@commit.id, @blob.path)
+%ul.blob-commit-info.well.hidden-xs
+  - blob_commit = @repository.last_commit_for_path(@commit.id, blob.path)
   = render blob_commit, project: @project
 
 %div#tree-content-holder.tree-content-holder
   %article.file-holder
-    .file-title.clearfix
-      %i.fa.fa-file
-      %span.file_name
+    .file-title
+      = blob_icon blob.mode, blob.name
+      %strong
         = blob.name
-        %small= number_to_human_size blob.size
-      %span.options.hidden-xs= render "actions"
+      %small
+        = number_to_human_size(blob.size)
+      .file-actions.hidden-xs
+        = render "actions"
     - if blob.text?
       = render "text", blob: blob
     - elsif blob.image?
diff --git a/app/views/projects/blob/_download.html.haml b/app/views/projects/blob/_download.html.haml
index c24eeea49317b4e8c4d4d0fdb795e8937343e0f5..f2c5e95ecf4252d8612c8399d1ff2525b2e4907c 100644
--- a/app/views/projects/blob/_download.html.haml
+++ b/app/views/projects/blob/_download.html.haml
@@ -1,6 +1,6 @@
 .file-content.blob_file.blob-no-preview
   .center
-    = link_to project_raw_path(@project, @id) do
+    = link_to namespace_project_raw_path(@project.namespace, @project, @id) do
       %h1.light
         %i.fa.fa-download
       %h4
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..96f188e4aa7ab644487318d53faf2a021a4053b7
--- /dev/null
+++ b/app/views/projects/blob/_editor.html.haml
@@ -0,0 +1,25 @@
+.file-holder.file
+  .file-title
+    .editor-ref
+      %i.fa.fa-code-fork
+      = ref
+    %span.editor-file-name
+      - if @path
+        %span.monospace
+          = @path
+
+      - if current_action?(:new) || current_action?(:create)
+        \/
+        = text_field_tag 'file_name', params[:file_name], placeholder: "File name",
+          required: true, class: 'form-control new-file-name'
+        .pull-right
+          = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'form-control'
+
+  .file-content.code
+    %pre.js-edit-mode-pane#editor
+      = params[:content] || local_assigns[:blob_data]
+    - if local_assigns[:path]
+      .js-edit-mode-pane#preview.hide
+        .center
+          %h2
+            %i.icon-spinner.icon-spin
diff --git a/app/views/projects/blob/_remove.html.haml b/app/views/projects/blob/_remove.html.haml
index c5568315cb1002b8719fe9bf6373e888761e7a9d..09559a4967b929b0a0a8c61754587dc6bf26c6e6 100644
--- a/app/views/projects/blob/_remove.html.haml
+++ b/app/views/projects/blob/_remove.html.haml
@@ -9,7 +9,7 @@
           %strong= @ref
 
       .modal-body
-        = form_tag project_blob_path(@project, @id), method: :delete, class: 'form-horizontal' do
+        = form_tag namespace_project_blob_path(@project.namespace, @project, @id), method: :delete, class: 'form-horizontal' do
           = render 'shared/commit_message_container', params: params,
                    placeholder: 'Removed this file because...'
           .form-group
diff --git a/app/views/projects/blob/_replace.html.haml b/app/views/projects/blob/_replace.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..920fa8bb043e20f8694bb8e2a8686b1d16459852
--- /dev/null
+++ b/app/views/projects/blob/_replace.html.haml
@@ -0,0 +1,35 @@
+#modal-replace-blob.modal.hide
+  .modal-dialog
+    .modal-content
+      .modal-header
+        %a.close{href: "#", "data-dismiss" => "modal"} ×
+        %h3.page-title Replace #{@blob.name}
+        %p.light
+          From branch
+          %strong= @ref
+      .modal-body
+        = form_tag project_new_tree_path(@project, @id), method: :put, class: 'form-horizontal', :multipart => true, :onChange => 'checkFile()' do
+          %br
+          .form-group
+            .col-sm-2
+            .col-sm-10
+              = file_field_tag :file_upload, :id => "file-upload", :class => "file_up"
+          %br
+          = render 'shared/commit_message_replace_container', params: params,
+                  placeholder: 'Replace this file because...'
+          .form-group
+            .col-sm-2
+            .col-sm-10
+              = button_tag 'Replace file', class: 'btn btn-small btn-primary', id: 'replace_btn'
+              = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
+:javascript 
+  function checkFile(){
+    str=document.getElementById('file_upload').value; 
+    if(str.length < 1){
+      alert('Please select file!');
+    }
+  }
+  disableButtonIfAnyEmptyField('#commit_message_replace')
+
+
+
diff --git a/app/views/projects/blob/_text.html.haml b/app/views/projects/blob/_text.html.haml
index 7cbea7c3eb6b8925994fbafe3566c8d7935647d4..f6bd62f239baab71521db45ea9131ac41c99a4bc 100644
--- a/app/views/projects/blob/_text.html.haml
+++ b/app/views/projects/blob/_text.html.haml
@@ -8,6 +8,6 @@
 - else
   .file-content.code
     - unless blob.empty?
-      = render 'shared/file_hljs', blob: blob
+      = render 'shared/file_highlight', blob: blob
     - else
       .nothing-here-block Empty file
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..1f61a0b940c84b940e1517111b65e67180c8d889
--- /dev/null
+++ b/app/views/projects/blob/edit.html.haml
@@ -0,0 +1,31 @@
+.file-editor
+  %ul.nav.nav-tabs.js-edit-mode
+    %li.active
+      = link_to '#editor' do
+        %i.fa.fa-edit
+        Edit file
+
+    %li
+      = link_to '#preview', 'data-preview-url' => namespace_project_preview_blob_path(@project.namespace, @project, @id) do
+        %i.fa.fa-eye
+        = editing_preview_title(@blob.name)
+
+  = form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: "form-horizontal") do
+    = render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data
+    = render 'shared/commit_message_container', params: params,
+             placeholder: "Update #{@blob.name}"
+
+    .form-group.branch
+      = label_tag 'branch', class: 'control-label' do
+        Branch
+      .col-sm-10
+        = text_field_tag 'new_branch', @ref, class: "form-control"
+
+    = hidden_field_tag 'last_commit', @last_commit
+    = hidden_field_tag 'content', '', id: "file-content"
+    = hidden_field_tag 'from_merge_request_id', params[:from_merge_request_id]
+    = render 'projects/commit_button', ref: @ref,
+              cancel_path: @after_edit_path
+
+:javascript
+  blob = new EditBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", "#{@blob.language.try(:ace_mode)}")
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..d78a01f6422ceed88b7dbdd057a297499adb1ff4
--- /dev/null
+++ b/app/views/projects/blob/new.html.haml
@@ -0,0 +1,19 @@
+%h3.page-title New file
+.file-editor
+  = form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal form-new-file') do
+    = render 'projects/blob/editor', ref: @ref
+    = render 'shared/commit_message_container', params: params,
+             placeholder: 'Add new file'
+
+    .form-group.branch
+      = label_tag 'branch', class: 'control-label' do
+        Branch
+      .col-sm-10
+        = text_field_tag 'new_branch', @ref, class: "form-control"
+
+    = hidden_field_tag 'content', '', id: 'file-content'
+    = render 'projects/commit_button', ref: @ref,
+              cancel_path: namespace_project_tree_path(@project.namespace, @project, @id)
+
+:javascript
+  blob = new NewBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", null)
diff --git a/app/views/projects/edit_tree/preview.html.haml b/app/views/projects/blob/preview.html.haml
similarity index 100%
rename from app/views/projects/edit_tree/preview.html.haml
rename to app/views/projects/blob/preview.html.haml
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index 69167654c39d9fac445e6c80245c154fd1baa86f..8f9f950afb4ce7a6a49c2b3d410757fe23fba5f5 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -6,3 +6,5 @@
 
 - if allowed_tree_edit?
   = render 'projects/blob/remove'
+- if allowed_tree_edit?
+  = render 'projects/blob/replace'
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 8e58f3c247a39ee1b1272361a35386e51289644b..0de8c509f2b16c753274b1a6343a00461438d83f 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -1,7 +1,7 @@
 - commit = @repository.commit(branch.target)
 %li(class="js-branch-#{branch.name}")
   %h4
-    = link_to project_tree_path(@project, branch.name) do
+    = link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do
       %strong.str-truncated= branch.name
       - if branch.name == @repository.root_ref
         %span.label.label-info default
@@ -11,14 +11,14 @@
           protected
     .pull-right
       - if can?(current_user, :download_code, @project)
-        = render 'projects/repositories/download_archive', ref: branch.name, btn_class: 'btn-grouped btn-group-small'
+        = render 'projects/repositories/download_archive', ref: branch.name, btn_class: 'btn-grouped btn-group-sm'
       - if branch.name != @repository.root_ref
-        = link_to project_compare_index_path(@project, from: @repository.root_ref, to: branch.name), class: 'btn btn-grouped btn-small', method: :post, title: "Compare" do
+        = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-grouped btn-sm', method: :post, title: "Compare" do
           %i.fa.fa-files-o
           Compare
 
       - if can_remove_branch?(@project, branch.name)
-        = link_to project_branch_path(@project, branch.name), class: 'btn btn-grouped btn-small btn-remove remove-row', method: :delete, data: { confirm: 'Removed branch cannot be restored. Are you sure?'}, remote: true do
+        = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-grouped btn-sm btn-remove remove-row', method: :delete, data: { confirm: 'Removed branch cannot be restored. Are you sure?'}, remote: true do
           %i.fa.fa-trash-o
 
   - if commit
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index 9f2b1b59292aaf0cf2d33477c36208247ad3854a..a313ffcf27294a07dc1e6024d5c2ac2077d4f6f6 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -3,12 +3,12 @@
   Branches
   .pull-right
     - if can? current_user, :push_code, @project
-      = link_to new_project_branch_path(@project), class: 'btn btn-create' do
+      = link_to new_namespace_project_branch_path(@project.namespace, @project), class: 'btn btn-create' do
         %i.fa.fa-add-sign
         New branch
       &nbsp;
     .dropdown.inline
-      %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
+      %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
         %span.light sort:
         - if @sort.present?
           = @sort.humanize
@@ -17,12 +17,12 @@
         %b.caret
       %ul.dropdown-menu
         %li
-          = link_to project_branches_path(sort: nil) do
+          = link_to namespace_project_branches_path(sort: nil) do
             Name
-          = link_to project_branches_path(sort: 'recently_updated') do
-            Recently updated
-          = link_to project_branches_path(sort: 'last_updated') do
-            Last updated
+          = link_to namespace_project_branches_path(sort: 'recently_updated') do
+            = sort_title_recently_updated
+          = link_to namespace_project_branches_path(sort: 'last_updated') do
+            = sort_title_oldest_updated
 %hr
 - unless @branches.empty?
   %ul.bordered-list.top-list.all-branches
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index a6623240da1e393195dae245916d3759f92e4ca8..e5fcb98c68cb00d8f561619a77cfea206579c100 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -5,7 +5,7 @@
 %h3.page-title
   %i.fa.fa-code-fork
   New branch
-= form_tag project_branches_path, method: :post, class: "form-horizontal" do
+= form_tag namespace_project_branches_path, method: :post, id: "new-branch-form", class: "form-horizontal" do
   .form-group
     = label_tag :branch_name, 'Name for new branch', class: 'control-label'
     .col-sm-10
@@ -16,9 +16,10 @@
       = text_field_tag :ref, params[:ref], placeholder: 'existing branch name, tag or commit SHA', required: true, tabindex: 2, class: 'form-control'
   .form-actions
     = button_tag 'Create branch', class: 'btn btn-create', tabindex: 3
-    = link_to 'Cancel', project_branches_path(@project), class: 'btn btn-cancel'
+    = link_to 'Cancel', namespace_project_branches_path(@project.namespace, @project), class: 'btn btn-cancel'
 
 :javascript
+  disableButtonIfAnyEmptyField($("#new-branch-form"), ".form-control", ".btn-create");
   var availableTags = #{@project.repository.ref_names.to_json};
 
   $("#ref").autocomplete({
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index e149f017f848616a510c86c6dd3a7ba223341336..3f645b81397acc36b97a71a4d337f7b7cf564025 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -10,15 +10,16 @@
         Download as
         %span.caret
       %ul.dropdown-menu
-        %li= link_to "Email Patches", project_commit_path(@project, @commit, format: :patch)
-        %li= link_to "Plain Diff",    project_commit_path(@project, @commit, format: :diff)
-    = link_to project_tree_path(@project, @commit), class: "btn btn-primary btn-grouped" do
+        - unless @commit.parents.length > 1
+          %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch)
+        %li= link_to "Plain Diff",    namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff)
+    = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-primary btn-grouped" do
       %span Browse Code »
   %div
 
 %p
   %span.light Commit
-  = link_to @commit.id, project_commit_path(@project, @commit)
+  = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit)
 .commit-info-row
   %span.light Authored by
   %strong
@@ -35,20 +36,10 @@
 .commit-info-row
   %span.cgray= pluralize(@commit.parents.count, "parent")
   - @commit.parents.each do |parent|
-    = link_to parent.short_id, project_commit_path(@project, parent)
+    = link_to parent.short_id, namespace_project_commit_path(@project.namespace, @project, parent)
 
-- if @branches.any?
-  .commit-info-row
-    %span.cgray
-      Exists in
-    %span
-      - branch = commit_default_branch(@project, @branches)
-      = link_to(branch, project_tree_path(@project, branch))
-      - if @branches.any?
-        and in
-        = link_to("#{pluralize(@branches.count, "other branch")}", "#", class: "js-details-expand")
-        %span.js-details-content.hide
-          = commit_branches_links(@project, @branches)
+.commit-info-row.branches
+  %i.fa.fa-spinner.fa-spin
 
 .commit-box
   %h3.commit-title
@@ -56,3 +47,6 @@
   - if @commit.description.present?
     %pre.commit-description
       = preserve(gfm(escape_once(@commit.description)))
+
+:coffeescript
+  $(".commit-info-row.branches").load("#{branches_namespace_project_commit_path(@project.namespace, @project, @commit.id)}")
diff --git a/app/views/projects/commit/branches.html.haml b/app/views/projects/commit/branches.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..82aac1fbd15e4424b7c7b7b6eeeaa8a366dd4b90
--- /dev/null
+++ b/app/views/projects/commit/branches.html.haml
@@ -0,0 +1,16 @@
+- if @branches.any?
+  %span
+    - branch = commit_default_branch(@project, @branches)
+    = link_to(namespace_project_tree_path(@project.namespace, @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)
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 1eb17f760dcd32614345522935e54ad3f766f3ad..c6026f968045358927506784a4cb8bf0812f5ee4 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -1,24 +1,24 @@
 %li.commit.js-toggle-container
   .commit-row-title
-    = link_to commit.short_id, project_commit_path(project, commit), class: "commit_short_id"
-    &nbsp;
-    %span.str-truncated
-      = link_to_gfm commit.title, project_commit_path(project, commit.id), class: "commit-row-message"
+    %strong.str-truncated
+      = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message"
       - if commit.description?
         %a.text-expander.js-toggle-button ...
 
-    = link_to_browse_code(project, commit)
+    .pull-right
+      = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
 
     .notes_count
       - if @note_counts
         - note_count = @note_counts.fetch(commit.id, 0)
       - else
         - notes = project.notes.for_commit_id(commit.id)
-        - note_count = notes.count
+        - note_count = notes.user.count
 
       - if note_count > 0
-        %span.label.label-gray
-          %i.fa.fa-comment= note_count
+        %span.light
+          %i.fa.fa-comments
+          = note_count
 
   - if commit.description?
     .commit-row-description.js-toggle-content
@@ -26,6 +26,8 @@
         = preserve(gfm(escape_once(commit.description)))
 
   .commit-row-info
-    = commit_author_link(commit, avatar: true, size: 16)
+    = commit_author_link(commit, avatar: true, size: 24)
+    authored
     .committed_ago
       #{time_ago_with_tooltip(commit.committed_date)} &nbsp;
+    = link_to_browse_code(project, commit)
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index d57659065a88a3b316e38989eed2b0de988e910e..0cd9ce1f371dc0a69705db8e9696856618634fc9 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -1,11 +1,15 @@
+- unless defined?(project)
+  - project = @project
+
 - @commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits|
   .row.commits-row
-    .col-md-2
-      %h4
+    .col-md-2.hidden-xs.hidden-sm
+      %h5.commits-row-date
         %i.fa.fa-calendar
         %span= day.stamp("28 Aug, 2010")
-      %p= pluralize(commits.count, 'commit')
-    .col-md-10
+      .light
+        = pluralize(commits.count, 'commit')
+    .col-md-10.col-sm-12
       %ul.bordered-list
-        = render commits, project: @project
+        = render commits, project: project
   %hr.lists-separator
diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml
index 0c9d906481bbb0b28ca939019067e5e1bea09c09..a714f5f79e0f602ffcfcc754bd61edf224bcfa62 100644
--- a/app/views/projects/commits/_head.html.haml
+++ b/app/views/projects/commits/_head.html.haml
@@ -1,15 +1,17 @@
 %ul.nav.nav-tabs
   = nav_link(controller: [:commit, :commits]) do
-    = link_to 'Commits', project_commits_path(@project, @repository.root_ref)
+    = link_to namespace_project_commits_path(@project.namespace, @project, @repository.root_ref) do
+      Commits
+      %span.badge= number_with_precision(@repository.commit_count, precision: 0, delimiter: ',')
   = nav_link(controller: :compare) do
-    = link_to 'Compare', project_compare_index_path(@project, from: @repository.root_ref, to: @ref || @repository.root_ref)
+    = link_to 'Compare', namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref)
 
   = nav_link(html_options: {class: branches_tab_class}) do
-    = link_to project_branches_path(@project) do
+    = link_to namespace_project_branches_path(@project.namespace, @project) do
       Branches
       %span.badge.js-totalbranch-count= @repository.branches.size
 
   = nav_link(controller: :tags) do
-    = link_to project_tags_path(@project) do
+    = link_to namespace_project_tags_path(@project.namespace, @project) do
       Tags
       %span.badge.js-totaltags-count= @repository.tags.length
diff --git a/app/views/projects/commits/_inline_commit.html.haml b/app/views/projects/commits/_inline_commit.html.haml
index 574599aa2d2ce81958a23ee27fa52da6bf60ca20..c03bc3f9df9edea05d80acb1377ad88d7e363735 100644
--- a/app/views/projects/commits/_inline_commit.html.haml
+++ b/app/views/projects/commits/_inline_commit.html.haml
@@ -1,8 +1,8 @@
 %li.commit.inline-commit
   .commit-row-title
-    = link_to commit.short_id, project_commit_path(project, commit), class: "commit_short_id"
+    = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
     &nbsp;
     %span.str-truncated
-      = link_to_gfm commit.title, project_commit_path(project, commit.id), class: "commit-row-message"
+      = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message"
     .pull-right
       #{time_ago_with_tooltip(commit.committed_date)}
diff --git a/app/views/projects/commits/show.atom.builder b/app/views/projects/commits/show.atom.builder
index 32c82edb2489bc47dd721c1051c4a9dc8a2d951f..9211de72b1b49bad03734dc430e09337fdf488f5 100644
--- a/app/views/projects/commits/show.atom.builder
+++ b/app/views/projects/commits/show.atom.builder
@@ -1,15 +1,15 @@
 xml.instruct!
 xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
   xml.title   "Recent commits to #{@project.name}:#{@ref}"
-  xml.link    :href => project_commits_url(@project, @ref, format: :atom), :rel => "self", :type => "application/atom+xml"
-  xml.link    :href => project_commits_url(@project, @ref), :rel => "alternate", :type => "text/html"
-  xml.id      project_commits_url(@project, @ref)
+  xml.link    :href => namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom), :rel => "self", :type => "application/atom+xml"
+  xml.link    :href => namespace_project_commits_url(@project.namespace, @project, @ref), :rel => "alternate", :type => "text/html"
+  xml.id      namespace_project_commits_url(@project.namespace, @project, @ref)
   xml.updated @commits.first.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ") if @commits.any?
 
   @commits.each do |commit|
     xml.entry do
-      xml.id      project_commit_url(@project, :id => commit.id)
-      xml.link    :href => project_commit_url(@project, :id => commit.id)
+      xml.id      namespace_project_commit_url(@project.namespace, @project, :id => commit.id)
+      xml.link    :href => namespace_project_commit_url(@project.namespace, @project, :id => commit.id)
       xml.title   truncate(commit.title, :length => 80)
       xml.updated commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")
       xml.media   :thumbnail, :width => "40", :height => "40", :url => avatar_icon(commit.author_email)
diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml
index 5717c24c27442f16aefe6e84bcaf7ff088cf929e..7ea855e1a4e7b863c1c14f6ba2735cf8d17f1fa0 100644
--- a/app/views/projects/commits/show.html.haml
+++ b/app/views/projects/commits/show.html.haml
@@ -5,17 +5,15 @@
 
 - if current_user && current_user.private_token
   .commits-feed-holder.hidden-xs.hidden-sm
-    = link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed", class: 'btn' do
+    = link_to namespace_project_commits_path(@project.namespace, @project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed", class: 'btn' do
       %i.fa.fa-rss
       Commits feed
 
 %ul.breadcrumb.repo-breadcrumb
   = commits_breadcrumbs
-  %li.active
-    commits
 
 %div{id: dom_id(@project)}
-  #commits-list= render "commits"
+  #commits-list= render "commits", project: @project
 .clear
 = spinner
 
diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml
index cb0a3747f7d091122d054fb3a27ff4f8ccec60a8..dfb1dded9eaf70e2c12b1a425c189fb39a9f9366 100644
--- a/app/views/projects/compare/_form.html.haml
+++ b/app/views/projects/compare/_form.html.haml
@@ -1,4 +1,4 @@
-= form_tag project_compare_index_path(@project), method: :post, class: 'form-inline' do
+= form_tag namespace_project_compare_index_path(@project.namespace, @project), method: :post, class: 'form-inline' do
   .clearfix.append-bottom-20
     - if params[:to] && params[:from]
       = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'}
diff --git a/app/views/projects/create.js.haml b/app/views/projects/create.js.haml
deleted file mode 100644
index 89710d3a09afc202021444fbbb01da4a5295b3bb..0000000000000000000000000000000000000000
--- a/app/views/projects/create.js.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-- if @project.saved?
-  - if @project.import?
-    :plain
-      location.href = "#{import_project_path(@project)}";
-  - else
-    :plain
-      location.href = "#{project_path(@project)}";
-- else
-  :plain
-    $(".project-edit-errors").html("#{escape_javascript(render('errors'))}");
-    $('.project-submit').enable();
-    $('.save-project-loader').hide();
-    $('.project-edit-container').show();
diff --git a/app/views/projects/deploy_keys/_deploy_key.html.haml b/app/views/projects/deploy_keys/_deploy_key.html.haml
index a0345dbd9c36be972a2bc6b08f19a903a3d5e8e1..a2faa9d5e25a4196b49fe0c2ce4315b885a1677b 100644
--- a/app/views/projects/deploy_keys/_deploy_key.html.haml
+++ b/app/views/projects/deploy_keys/_deploy_key.html.haml
@@ -1,19 +1,20 @@
 %li
   .pull-right
     - if @available_keys.include?(deploy_key)
-      = link_to enable_project_deploy_key_path(@project, deploy_key), class: 'btn btn-small', method: :put do
+      = link_to enable_namespace_project_deploy_key_path(@project.namespace, @project, deploy_key), class: 'btn btn-sm', method: :put do
         %i.fa.fa-plus
         Enable
     - else
       - if deploy_key.projects.count > 1
-        = link_to disable_project_deploy_key_path(@project, deploy_key), class: 'btn btn-small', method: :put do
+        = link_to disable_namespace_project_deploy_key_path(@project.namespace, @project, deploy_key), class: 'btn btn-sm', method: :put do
           %i.fa.fa-power-off
           Disable
       - else
-        = link_to 'Remove', project_deploy_key_path(@project, deploy_key), data: { confirm: 'You are going to remove deploy key. Are you sure?'}, method: :delete, class: "btn btn-remove delete-key btn-small pull-right"
+        = link_to 'Remove', namespace_project_deploy_key_path(@project.namespace, @project, deploy_key), data: { confirm: 'You are going to remove deploy key. Are you sure?'}, method: :delete, class: "btn btn-remove delete-key btn-sm pull-right"
 
 
-  = link_to project_deploy_key_path(deploy_key.projects.include?(@project) ? @project : deploy_key.projects.first, deploy_key) do
+  - key_project = deploy_key.projects.include?(@project) ? @project : deploy_key.projects.first
+  = link_to namespace_project_deploy_key_path(key_project.namespace, key_project, deploy_key) do
     %i.fa.fa-key
     %strong= deploy_key.title
 
diff --git a/app/views/projects/deploy_keys/_form.html.haml b/app/views/projects/deploy_keys/_form.html.haml
index 162ef05b36737ba15b6e49e98539966c67d772df..91675b3738ecb9f2d734c2dacd415713816ea5e9 100644
--- a/app/views/projects/deploy_keys/_form.html.haml
+++ b/app/views/projects/deploy_keys/_form.html.haml
@@ -1,5 +1,5 @@
 %div
-  = form_for [@project, @key], url: project_deploy_keys_path, html: { class: 'deploy-key-form form-horizontal' } do |f|
+  = form_for [@project.namespace.becomes(Namespace), @project, @key], url: namespace_project_deploy_keys_path, html: { class: 'deploy-key-form form-horizontal' } do |f|
     -if @key.errors.any?
       .alert.alert-danger
         %ul
@@ -19,5 +19,5 @@
 
     .form-actions
       = f.submit 'Create', class: "btn-create btn"
-      = link_to "Cancel", project_deploy_keys_path(@project), class: "btn btn-cancel"
+      = link_to "Cancel", namespace_project_deploy_keys_path(@project.namespace, @project), class: "btn btn-cancel"
 
diff --git a/app/views/projects/deploy_keys/index.html.haml b/app/views/projects/deploy_keys/index.html.haml
index 6f475e0b395b70488cb0fa9a1883eed728c65b6a..c02a18146ebe2d3d32d5dea1826b38c95f501d4c 100644
--- a/app/views/projects/deploy_keys/index.html.haml
+++ b/app/views/projects/deploy_keys/index.html.haml
@@ -1,7 +1,7 @@
 %h3.page-title
   Deploy keys allow read-only access to the repository
 
-  = link_to new_project_deploy_key_path(@project), class: "btn btn-new pull-right", title: "New Deploy Key" do
+  = link_to new_namespace_project_deploy_key_path(@project.namespace, @project), class: "btn btn-new pull-right", title: "New Deploy Key" do
     %i.fa.fa-plus
     New Deploy Key
 
@@ -20,7 +20,7 @@
       = render @enabled_keys
       - if @enabled_keys.blank?
         .light-well
-          .nothing-here-block Create a #{link_to 'new deploy key', new_project_deploy_key_path(@project)} or add an existing one
+          .nothing-here-block Create a #{link_to 'new deploy key', new_namespace_project_deploy_key_path(@project.namespace, @project)} or add an existing one
   .col-md-6.available-keys
     %h5
       %strong Deploy keys
diff --git a/app/views/projects/deploy_keys/show.html.haml b/app/views/projects/deploy_keys/show.html.haml
index c66e6bc69c30f7a0b790b2c25737ee1883b573d7..405b5bcd0d3a81e8a6f7da5c10866bafd4408b6f 100644
--- a/app/views/projects/deploy_keys/show.html.haml
+++ b/app/views/projects/deploy_keys/show.html.haml
@@ -5,9 +5,9 @@
     created on
     = @key.created_at.stamp("Aug 21, 2011")
 .back-link
-  = link_to project_deploy_keys_path(@project) do
+  = link_to namespace_project_deploy_keys_path(@project.namespace, @project) do
     &larr; To keys list
 %hr
 %pre= @key.key
 .pull-right
-  = link_to 'Remove', project_deploy_key_path(@project, @key), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn-remove btn delete-key"
+  = link_to 'Remove', namespace_project_deploy_key_path(@project.namespace, @project, @key), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn-remove btn delete-key"
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index 334ea1ba82fa797e3189e0b13eb3ad4a77f6ade0..2b9b6599a7d9c1b052fd565cdcdba1fb79d56498 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -1,16 +1,9 @@
-.row
-  .col-md-8
-    = render 'projects/diffs/stats', diffs: diffs
-  .col-md-4
-    %ul.nav.nav-tabs
-      %li.pull-right{class: params[:view] == 'parallel' ? 'active' : ''}
-        - params_copy = params.dup
-        - params_copy[:view] = 'parallel'
-        = link_to "Side-by-side Diff", url_for(params_copy), {id: "commit-diff-viewtype"}
-      %li.pull-right{class: params[:view] != 'parallel' ? 'active' : ''}
-        - params_copy[:view] = 'inline'
-        = link_to "Inline Diff", url_for(params_copy), {id: "commit-diff-viewtype"}
-
+.prepend-top-20.append-bottom-20
+  .pull-right
+    .btn-group
+      = inline_diff_btn
+      = parallel_diff_btn
+  = render 'projects/diffs/stats', diffs: diffs
 
 - if show_diff_size_warning?(diffs)
   = render 'projects/diffs/warning', diffs: diffs
@@ -25,3 +18,6 @@
       Failed to collect changes
     %p
       Maybe diff is really big and operation failed with timeout. Try to get diff locally
+
+:coffeescript
+  $('.files .diff-header').stick_in_parent(recalc_every: 1, offset_top: $('.navbar').height())
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index bf7770ceedf5e0aca531f9ca42ee79d15f5cd189..672a6635321926492dd492d42d4ba73f0475c5c4 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -1,42 +1,40 @@
 - blob = project.repository.blob_for_diff(@commit, diff_file.diff)
 - return unless blob
-- blob_diff_path = diff_project_blob_path(project, tree_join(@commit.id, diff_file.file_path))
+- blob_diff_path = namespace_project_blob_diff_path(project.namespace, project, tree_join(@commit.id, diff_file.file_path))
 .diff-file{id: "diff-#{i}", data: {blob_diff_path: blob_diff_path }}
   .diff-header{id: "file-path-#{hexdigest(diff_file.new_path || diff_file.old_path)}"}
     - if diff_file.deleted_file
-      %span= diff_file.old_path
+      %span="#{diff_file.old_path} deleted"
 
       .diff-btn-group
         - if @commit.parent_ids.present?
           = view_file_btn(@commit.parent_id, diff_file, project)
+    - elsif diff_file.diff.submodule?
+      - submodule_item = project.repository.blob_at(@commit.id, diff_file.file_path)
+      = submodule_link(submodule_item, @commit.id)
     - else
-      - if diff_file.renamed_file
-        %span= "#{diff_file.old_path} renamed to #{diff_file.new_path}"
-      - else
-        %span= diff_file.new_path
-      - if diff_file.mode_changed?
-        %span.file-mode= "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}"
+      %span
+        - if diff_file.renamed_file
+          = "#{diff_file.old_path} renamed to #{diff_file.new_path}"
+        - else
+          = diff_file.new_path
+        - if diff_file.mode_changed?
+          %span.file-mode= "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}"
 
       .diff-btn-group
         - if blob.text?
-          - unless params[:view] == 'parallel'
-            %label
-              = check_box_tag nil, 1, false, class: 'js-toggle-diff-line-wrap'
-              Wrap text
-          &nbsp;
-          = link_to '#', class: 'js-toggle-diff-comments btn btn-small' do
-            %i.fa.fa-chevron-down
-            Diff comments
+          = link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do
+            %i.fa.fa-comments
           &nbsp;
 
         - if @merge_request && @merge_request.source_project
-          = link_to project_edit_tree_path(@merge_request.source_project, tree_join(@merge_request.source_branch, diff_file.new_path), from_merge_request_id: @merge_request.id), { class: 'btn btn-small' } do
-            Edit
-          &nbsp;
+          = edit_blob_link(@merge_request.source_project,
+              @merge_request.source_branch, diff_file.new_path,
+              after: '&nbsp;', from_merge_request_id: @merge_request.id)
 
         = view_file_btn(@commit.id, diff_file, project)
 
-  .diff-content
+  .diff-content.diff-wrap-lines
     -# Skipp all non non-supported blobs
     - return unless blob.respond_to?('text?')
     - if blob.text?
diff --git a/app/views/projects/diffs/_image.html.haml b/app/views/projects/diffs/_image.html.haml
index 900646dd0a4ca97704aa7fac558358aa5893ba4b..058b71b21f5173efd9c37bd02377dd691d5e7af4 100644
--- a/app/views/projects/diffs/_image.html.haml
+++ b/app/views/projects/diffs/_image.html.haml
@@ -10,7 +10,7 @@
     %div.two-up.view
       %span.wrap
         .frame.deleted
-          %a{href: project_blob_path(@project, tree_join(@commit.parent_id, diff.old_path))}
+          %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(@commit.parent_id, diff.old_path))}
             %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
         %p.image-info.hide
           %span.meta-filesize= "#{number_to_human_size old_file.size}"
@@ -22,7 +22,7 @@
           %span.meta-height
       %span.wrap
         .frame.added
-          %a{href: project_blob_path(@project, tree_join(@commit.id, diff.new_path))}
+          %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(@commit.id, diff.new_path))}
             %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
         %p.image-info.hide
           %span.meta-filesize= "#{number_to_human_size file.size}"
diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml
index 20e51d18da5678524698e33df440be60fe88a4ad..1625930615a000c8048f40278017fa5d9c1b0520 100644
--- a/app/views/projects/diffs/_stats.html.haml
+++ b/app/views/projects/diffs/_stats.html.haml
@@ -1,17 +1,14 @@
 .js-toggle-container
   .commit-stat-summary
     Showing
-    %strong.cdark #{pluralize(diffs.count, "changed file")}
+    = link_to '#', class: 'js-toggle-button' do
+      %strong #{pluralize(diffs.count, "changed file")}
     - if current_controller?(:commit)
       - unless @commit.has_zero_stats?
         with
         %strong.cgreen #{@commit.stats.additions} additions
         and
         %strong.cred #{@commit.stats.deletions} deletions
-    &nbsp;
-    = link_to '#', class: 'btn btn-small js-toggle-button' do
-      Show diff stats
-      %i.fa.fa-chevron-down
   .file-stats.js-toggle-content.hide
     %ul.bordered-list
       - diffs.each_with_index do |diff, i|
@@ -26,7 +23,7 @@
               %a{href: "#diff-#{i}"}
                 %i.fa.fa-minus
                 = diff.old_path
-                \->
+                &rarr;
                 = diff.new_path
           - elsif diff.new_file
             %span.new-file
diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml
index b1c987563f15f0efd835059a46a2222855248339..e691db9c08e1a57b4158dc5a3ad51ec157d20a64 100644
--- a/app/views/projects/diffs/_text_file.html.haml
+++ b/app/views/projects/diffs/_text_file.html.haml
@@ -16,7 +16,7 @@
       - else
         %td.old_line
           = link_to raw(type == "new" ? "&nbsp;" : line_old), "##{line_code}", id: line_code
-          - if @comments_allowed
+          - if @comments_allowed && can?(current_user, :write_note, @project)
             = link_to_new_diff_note(line_code)
         %td.new_line{data: {linenumber: line.new_pos}}
           = link_to raw(type == "old" ? "&nbsp;" : line.new_pos) , "##{line_code}", id: line_code
diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml
index 86ed6bbeaa26ccecbe3a213045e9c4f57199ddf3..47abbba2eb225940bdb849e2ce7605750089aa31 100644
--- a/app/views/projects/diffs/_warning.html.haml
+++ b/app/views/projects/diffs/_warning.html.haml
@@ -1,19 +1,19 @@
-.bs-callout.bs-callout-warning
+.alert.alert-warning
   %h4
     Too many changes.
     .pull-right
       - unless diff_hard_limit_enabled?
-        = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true)), class: "btn btn-small btn-warning"
+        = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true)), class: "btn btn-sm btn-warning"
 
       - if current_controller?(:commit) or current_controller?(:merge_requests)
         - if current_controller?(:commit)
-          = link_to "Plain diff", project_commit_path(@project, @commit, format: :diff), class: "btn btn-warning btn-small"
-          = link_to "Email patch", project_commit_path(@project, @commit, format: :patch), class: "btn btn-warning btn-small"
+          = link_to "Plain diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff), class: "btn btn-warning btn-sm"
+          = link_to "Email patch", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch), class: "btn btn-warning btn-sm"
         - elsif @merge_request && @merge_request.persisted?
-          = link_to "Plain diff", project_merge_request_path(@project, @merge_request, format: :diff), class: "btn btn-warning btn-small"
-          = link_to "Email patch", project_merge_request_path(@project, @merge_request, format: :patch), class: "btn btn-warning btn-small"
+          = link_to "Plain diff", merge_request_path(@merge_request, format: :diff), class: "btn btn-warning btn-sm"
+          = link_to "Email patch", merge_request_path(@merge_request, format: :patch), class: "btn btn-warning btn-sm"
   %p
     To preserve performance only
     %strong #{allowed_diff_size} of #{diffs.size}
-    files displayed.
+    files are displayed.
 
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index b85cf7d8d3777202f361161a6507274db651e5fb..fbf04847e489f9ec8dcdcb5ffc3c1d0f7736aed5 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -3,11 +3,11 @@
   .project-edit-content
     %div
       %h3.page-title
-        Project settings:
-      %p.light Some settings, such as "Transfer Project", are hidden inside the danger area below.
+        Project settings
       %hr
       .panel-body
-        = form_for @project, remote: true, html: { class: "edit_project form-horizontal" } do |f|
+        = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit_project form-horizontal" }, authenticity_token: true do |f|
+
           %fieldset
             .form-group.project_name_holder
               = f.label :name, class: 'control-label' do
@@ -31,14 +31,11 @@
 
           = render "visibility_level", f: f, visibility_level: @project.visibility_level, can_change_visibility_level: can?(current_user, :change_visibility_level, @project)
 
-          %fieldset.features
-            %legend
-              Tags:
-            .form-group
-              = f.label :tag_list, "Tags", class: 'control-label'
-              .col-sm-10
-                = f.text_field :tag_list, maxlength: 2000, class: "form-control"
-                %p.hint Separate tags with commas.
+          .form-group
+            = f.label :tag_list, "Tags", class: 'control-label'
+            .col-sm-10
+              = f.text_field :tag_list, maxlength: 2000, class: "form-control"
+              %p.help-block Separate tags with commas.
 
           %fieldset.features
             %legend
@@ -50,15 +47,6 @@
                   = f.check_box :issues_enabled
                   %span.descr Lightweight issue tracking system for this project
 
-            - if Project.issues_tracker.values.count > 1
-              .form-group
-                = f.label :issues_tracker, "Issues tracker", class: 'control-label'
-                .col-sm-10= f.select(:issues_tracker, project_issues_trackers(@project.issues_tracker), {}, { disabled: !@project.issues_enabled })
-
-              .form-group
-                = f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label'
-                .col-sm-10= f.text_field :issues_tracker_id, disabled: !@project.can_have_issues_tracker_id?, class: 'form-control'
-
             .form-group
               = f.label :merge_requests_enabled, "Merge Requests", class: 'control-label'
               .col-sm-10
@@ -80,6 +68,32 @@
                   = f.check_box :snippets_enabled
                   %span.descr Share code pastes with others out of git repository
 
+          %fieldset.features
+            %legend
+              Project avatar:
+            .form-group
+              .col-sm-2
+              .col-sm-10
+                - if @project.avatar?
+                  = project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar s160')
+                %p.light
+                  - if @project.avatar_in_git
+                    Project avatar in repository: #{ @project.avatar_in_git }
+                %p.light
+                  - if @project.avatar?
+                    You can change your project avatar here
+                  - else
+                    You can upload a project avatar here
+                %a.choose-btn.btn.btn-sm.js-choose-project-avatar-button
+                  %i.icon-paper-clip
+                  %span Choose File ...
+                &nbsp;
+                %span.file_name.js-avatar-filename File name...
+                = f.file_field :avatar, class: "js-project-avatar-input hidden"
+                .light The maximum file size allowed is 200KB.
+                - if @project.avatar?
+                  %hr
+                  = link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
 
           .form-actions
             = f.submit 'Save changes', class: "btn btn-save"
@@ -99,7 +113,7 @@
                 The project can be committed to.
                 %br
                 %strong Once active this project shows up in the search and on the dashboard.
-              = link_to 'Unarchive', unarchive_project_path(@project),
+              = link_to 'Unarchive', unarchive_namespace_project_path(@project.namespace, @project),
                   data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." },
                   method: :post, class: "btn btn-success"
         - else
@@ -113,7 +127,7 @@
                 It is hidden from the dashboard and doesn't show up in searches.
                 %br
                 %strong Archived projects cannot be committed to!
-              = link_to 'Archive', archive_project_path(@project),
+              = link_to 'Archive', archive_namespace_project_path(@project.namespace, @project),
                   data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." },
                   method: :post, class: "btn btn-warning"
       - else
@@ -123,7 +137,7 @@
         .panel-heading Rename repository
         .errors-holder
         .panel-body
-          = form_for(@project, html: { class: 'form-horizontal' }) do |f|
+          = form_for([@project.namespace.becomes(Namespace), @project], html: { class: 'form-horizontal' }) do |f|
             .form-group.project_name_holder
               = f.label :name, class: 'control-label' do
                 Project name
@@ -136,6 +150,8 @@
               .col-sm-9
                 .form-group
                   .input-group
+                    .input-group-addon
+                      #{URI.join(root_url, @project.namespace.path)}/
                     = f.text_field :path, class: 'form-control'
                     %span.input-group-addon .git
                 %ul
@@ -149,13 +165,13 @@
           .panel-heading Transfer project
           .errors-holder
           .panel-body
-            = form_for(@project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f|
+            = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_namespace_project_path(@project.namespace, @project), method: :put, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f|
               .form-group
-                = f.label :namespace_id, class: 'control-label' do
+                = label_tag :new_namespace_id, nil, class: 'control-label' do
                   %span Namespace
                 .col-sm-10
                   .form-group
-                    = f.select :namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace' }, { class: 'select2' }
+                    = select_tag :new_namespace_id, namespaces_options(@project.namespace_id), { prompt: 'Choose a project namespace', class: 'select2' }
                   %ul
                     %li Be careful. Changing the project's namespace can have unintended side effects.
                     %li You can only transfer the project to namespaces you manage.
@@ -169,7 +185,7 @@
         .panel.panel-default.panel.panel-danger
           .panel-heading Remove project
           .panel-body
-            = form_tag(project_path(@project), method: :delete, html: { class: 'form-horizontal'}) do
+            = form_tag(namespace_project_path(@project.namespace, @project), method: :delete, html: { class: 'form-horizontal'}) do
               %p
                 Removing the project will delete its repository and all related resources including issues, merge requests etc.
                 %br
diff --git a/app/views/projects/edit_tree/show.html.haml b/app/views/projects/edit_tree/show.html.haml
deleted file mode 100644
index 5ccde05063e6f4f5e7b64b44cbe42ccc905b4961..0000000000000000000000000000000000000000
--- a/app/views/projects/edit_tree/show.html.haml
+++ /dev/null
@@ -1,72 +0,0 @@
-.file-editor
-  %ul.nav.nav-tabs.js-edit-mode
-    %li.active
-      = link_to 'Edit', '#editor'
-    %li
-      = link_to editing_preview_title(@blob.name), '#preview', 'data-preview-url' => preview_project_edit_tree_path(@project, @id)
-
-  = form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do
-    .file-holder.file
-      .file-title
-        %i.fa.fa-file
-        %span.file_name
-          %span.monospace.light #{@ref}:
-          = @path
-        %span.options
-          .btn-group.tree-btn-group
-            = link_to "Cancel", @after_edit_path, class: "btn btn-tiny btn-cancel", data: { confirm: leave_edit_message }
-      .file-content.code
-        %pre.js-edit-mode-pane#editor
-        .js-edit-mode-pane#preview.hide
-          .center
-            %h2
-              %i.fa.fa-spinner.fa-spin
-    = render 'shared/commit_message_container', params: params,
-             placeholder: "Update #{@blob.name}"
-    = hidden_field_tag 'last_commit', @last_commit
-    = hidden_field_tag 'content', '', id: "file-content"
-    = hidden_field_tag 'from_merge_request_id', params[:from_merge_request_id]
-    = render 'projects/commit_button', ref: @ref,
-              cancel_path: @after_edit_path
-
-:javascript
-  ace.config.set("modePath", gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}/ace")
-  ace.config.loadModule("ace/ext/searchbox");
-  var ace_mode = "#{@blob.language.try(:ace_mode)}";
-  var editor = ace.edit("editor");
-  editor.setValue("#{escape_javascript(@blob.data)}");
-  if (ace_mode) {
-    editor.getSession().setMode('ace/mode/' + ace_mode);
-  }
-
-  disableButtonIfEmptyField("#commit_message", ".js-commit-button");
-
-  $(".js-commit-button").click(function(){
-    $("#file-content").val(editor.getValue());
-    $(".file-editor form").submit();
-  });
-
-  var editModePanes = $('.js-edit-mode-pane'),
-      editModeLinks = $('.js-edit-mode a');
-
-  editModeLinks.click(function(event) {
-    event.preventDefault();
-
-    var currentLink = $(this),
-        paneId = currentLink.attr('href'),
-        currentPane = editModePanes.filter(paneId);
-
-    editModeLinks.parent().removeClass('active hover');
-    currentLink.parent().addClass('active hover');
-    editModePanes.hide();
-
-    if (paneId == '#preview') {
-      currentPane.fadeIn(200);
-      $.post(currentLink.data('preview-url'), { content: editor.getValue() }, function(response) {
-        currentPane.empty().append(response);
-      })
-    } else {
-      currentPane.fadeIn(200);
-      editor.focus()
-    }
-  })
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 59f19c8b7a3c434c51ffed192e24ccda957e113a..49806ceaa9671182f21785534680362dac537c28 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -1,5 +1,20 @@
+- if current_user && can?(current_user, :download_code, @project)
+  = render 'shared/no_ssh'
+  = render 'shared/no_password'
+
 = render "home_panel"
 
+.center.well
+  %h3
+    The repository for this project is empty
+  %h4
+    You can
+    = link_to namespace_project_new_blob_path(@project.namespace, @project, 'master'), class: 'btn btn-new btn-lg' do
+      add a file
+    &nbsp;or do a push via the command line.
+
+%h4
+  %strong Command line instructions
 %div.git-empty
   %fieldset
     %legend Git global setup
@@ -31,4 +46,4 @@
 
 - if can? current_user, :remove_project, @project
   .prepend-top-20
-    = link_to 'Remove project', @project, data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right"
+    = link_to 'Remove project', [@project.namespace.becomes(Namespace), @project], data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right"
diff --git a/app/views/projects/fork.html.haml b/app/views/projects/fork.html.haml
deleted file mode 100644
index d8f5c7b98d63e93cb7c7ad34233d58008684bd5e..0000000000000000000000000000000000000000
--- a/app/views/projects/fork.html.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-.alert.alert-danger.alert-block
-  %h4
-    %i.fa.fa-code-fork
-    Fork Error!
-  %p
-    You tried to fork
-    = link_to_project @project
-    but it failed for the following reason:
-
-
-  - if @forked_project && @forked_project.errors.any?
-    %p
-      &ndash;
-      = @forked_project.errors.full_messages.first
-
-  %p
-    = link_to fork_project_path(@project), title: "Fork", class: "btn", method: "POST" do
-      %i.fa.fa-code-fork
-      Try to Fork again
diff --git a/app/views/projects/forks/error.html.haml b/app/views/projects/forks/error.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..8eb4f795971939d0d5717b5e489e83593ea41a84
--- /dev/null
+++ b/app/views/projects/forks/error.html.haml
@@ -0,0 +1,20 @@
+- if @forked_project && !@forked_project.saved?
+  .alert.alert-danger.alert-block
+    %h4
+      %i.fa.fa-code-fork
+      Fork Error!
+    %p
+      You tried to fork
+      = link_to_project @project
+      but it failed for the following reason:
+
+
+    - if @forked_project && @forked_project.errors.any?
+      %p
+        &ndash;
+        = @forked_project.errors.full_messages.first
+
+    %p
+      = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork", class: "btn" do
+        %i.fa.fa-code-fork
+        Try to Fork again
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..5a6c46f320885bd11a5d489780f52cc702450756
--- /dev/null
+++ b/app/views/projects/forks/new.html.haml
@@ -0,0 +1,39 @@
+%h3.page-title Fork project
+%p.lead
+  Click to fork the project to a user or group
+%hr
+
+.fork-namespaces
+  - @namespaces.in_groups_of(6, false) do |group|
+    .row
+      - group.each do |namespace|
+        .col-md-2.col-sm-3
+          - if fork = namespace.find_fork_of(@project)
+            .thumbnail.fork-exists-thumbnail
+              = link_to project_path(fork), title: "Visit project fork", class: 'has_tooltip' do
+                = image_tag namespace_icon(namespace, 200)
+                .caption
+                  %h4=namespace.human_name
+                  %p
+                    = namespace.path
+          - else
+            .thumbnail.fork-thumbnail
+              = link_to namespace_project_fork_path(@project.namespace, @project, namespace_key: namespace.id), title: "Fork here", method: "POST", class: 'has_tooltip' do
+                = image_tag namespace_icon(namespace, 200)
+                .caption
+                  %h4=namespace.human_name
+                  %p
+                    = namespace.path
+
+  %p.light
+    Fork is a copy of a project repository.
+    %br
+    Forking a repository allows you to do changes without affecting the original project.
+
+.save-project-loader.hide
+  .center
+    %h2
+      %i.fa.fa-spinner.fa-spin
+      Forking repository
+    %p Please wait a moment, this page will automatically refresh when ready.
+
diff --git a/app/views/projects/go_import.html.haml b/app/views/projects/go_import.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..87ac75a350fd7359245eaaf0f463207845078c71
--- /dev/null
+++ b/app/views/projects/go_import.html.haml
@@ -0,0 +1,5 @@
+!!! 5
+%html
+  %head
+    - web_url = [Gitlab.config.gitlab.url, @namespace, @id].join('/')
+    %meta{name: "go-import", content: "#{web_url.split('://')[1]} git #{web_url}.git"}
diff --git a/app/views/projects/graphs/_head.html.haml b/app/views/projects/graphs/_head.html.haml
index 9f37a760e61ad3e1ac3c0bd496802e34cc72d6c1..9383df133058ef37fe6849cf6e5a373971a1f52d 100644
--- a/app/views/projects/graphs/_head.html.haml
+++ b/app/views/projects/graphs/_head.html.haml
@@ -1,5 +1,5 @@
 %ul.nav.nav-tabs
   = nav_link(action: :show) do
-    = link_to 'Contributors', project_graph_path
+    = link_to 'Contributors', namespace_project_graph_path
   = nav_link(action: :commits) do
-    = link_to 'Commits', commits_project_graph_path
+    = link_to 'Commits', commits_namespace_project_graph_path
diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml
index a189a487135ffeb7d6588857542301a4eb842828..4a5d09b95039b228f1f34364145795a8ca736f4c 100644
--- a/app/views/projects/graphs/commits.html.haml
+++ b/app/views/projects/graphs/commits.html.haml
@@ -1,7 +1,7 @@
 = render 'head'
 
 %p.lead
-  Commits statistic for
+  Commit statistics for
   %strong #{@repository.root_ref}
   #{@commits_graph.start_date.strftime('%b %d')} - #{@commits_graph.end_date.strftime('%b %d')}
 
diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml
index 9a003c87f6812ae689fa35a0876556ed52472786..bbaddba31b9ee4bc0a2094317fa4cf8bf701e24e 100644
--- a/app/views/projects/hooks/index.html.haml
+++ b/app/views/projects/hooks/index.html.haml
@@ -7,7 +7,7 @@
 
 %hr.clearfix
 
-= form_for [@project, @hook], as: :hook, url: project_hooks_path(@project), html: { class: 'form-horizontal' } do |f|
+= form_for [@project.namespace.becomes(Namespace), @project, @hook], as: :hook, url: namespace_project_hooks_path(@project.namespace, @project), html: { class: 'form-horizontal' } do |f|
   -if @hook.errors.any?
     .alert.alert-danger
       - @hook.errors.full_messages.each do |msg|
@@ -58,8 +58,8 @@
       - @hooks.each do |hook|
         %li
           .pull-right
-            = link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn btn-small btn-grouped"
-            = link_to 'Remove', project_hook_path(@project, hook), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove btn-small btn-grouped"
+            = link_to 'Test Hook', test_namespace_project_hook_path(@project.namespace, @project, hook), class: "btn btn-sm btn-grouped"
+            = link_to 'Remove', namespace_project_hook_path(@project.namespace, @project, hook), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove btn-sm btn-grouped"
           .clearfix
             %span.monospace= hook.url
           %p
diff --git a/app/views/projects/import.html.haml b/app/views/projects/import.html.haml
deleted file mode 100644
index 4513c89e7840872a9c9545441bf96287f0215d0c..0000000000000000000000000000000000000000
--- a/app/views/projects/import.html.haml
+++ /dev/null
@@ -1,31 +0,0 @@
-- if @project.import_in_progress?
-  .save-project-loader
-    .center
-      %h2
-        %i.fa.fa-spinner.fa-spin
-        Import in progress.
-      %p.monospace git clone --bare #{hidden_pass_url(@project.import_url)}
-      %p Please wait while we import the repository for you. Refresh at will.
-      :javascript
-        new ProjectImport();
-
-- elsif @project.import_failed?
-  .save-project-loader
-    .center
-      %h2
-        Import failed. Retry?
-  %hr
-  - if can?(current_user, :admin_project, @project)
-    = form_for @project, url: retry_import_project_path(@project), method: :put, html: { class: 'form-horizontal' } do |f|
-      .form-group.import-url-data
-        = f.label :import_url, class: 'control-label' do
-          %span Import existing git repo
-        .col-sm-10
-          = f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git'
-          .bs-callout.bs-callout-info
-            This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git.
-            %br
-            The import will time out after 4 minutes. For big repositories, use a clone/push combination.
-            For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}
-      .form-actions
-        = f.submit 'Retry import', class: "btn btn-create", tabindex: 4
diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..934b6b8c017212afeb9664e0c5d7ea931463ba1b
--- /dev/null
+++ b/app/views/projects/imports/new.html.haml
@@ -0,0 +1,21 @@
+%h3.page-title
+  - if @project.import_failed?
+    Import failed. Retry?
+  - else
+    Import repository
+
+%hr
+
+= form_for @project, url: namespace_project_import_path(@project.namespace, @project), method: :post, html: { class: 'form-horizontal' } do |f|
+  .form-group.import-url-data
+    = f.label :import_url, class: 'control-label' do
+      %span Import existing git repo
+    .col-sm-10
+      = f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git'
+      .well.prepend-top-20
+        This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git.
+        %br
+        The import will time out after 4 minutes. For big repositories, use a clone/push combination.
+        For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}
+  .form-actions
+    = f.submit 'Start import', class: "btn btn-create", tabindex: 4
diff --git a/app/views/projects/imports/show.html.haml b/app/views/projects/imports/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..2d1fdafed24d31497feb9ac9dede513d38c9fbdf
--- /dev/null
+++ b/app/views/projects/imports/show.html.haml
@@ -0,0 +1,9 @@
+.save-project-loader
+  .center
+    %h2
+      %i.fa.fa-spinner.fa-spin
+      Import in progress.
+    %p.monospace git clone --bare #{hidden_pass_url(@project.import_url)}
+    %p Please wait while we import the repository for you. Refresh at will.
+    :javascript
+      new ProjectImport();
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..0d3028d50b4f3acd767dbafa1f117913bc5f9efc
--- /dev/null
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -0,0 +1,33 @@
+- content_for :note_actions do
+  - if can?(current_user, :modify_issue, @issue)
+    - if @issue.closed?
+      = link_to 'Reopen Issue', issue_path(@issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-grouped btn-reopen js-note-target-reopen", title: 'Reopen Issue'
+    - else
+      = link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close js-note-target-close", title: "Close Issue"
+.row
+  %section.col-md-9
+    .votes-holder.pull-right
+      #votes= render 'votes/votes_block', votable: @issue
+    .participants
+      %span= pluralize(@issue.participants.count, 'participant')
+      - @issue.participants.each do |participant|
+        = link_to_member(@project, participant, name: false, size: 24)
+    .voting_notes#notes= render "projects/notes/notes_with_form"
+  %aside.col-md-3
+    .issuable-affix
+      .clearfix
+        %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
+          = cross_project_reference(@project, @issue)
+      %hr
+      .context
+        = render partial: 'issue_context', locals: { issue: @issue }
+
+      - if @issue.labels.any?
+        .issuable-context-title
+          %label Labels
+        .issue-show-labels
+          - @issue.labels.each do |label|
+            = link_to namespace_project_issues_path(@project.namespace, @project, label_name: label.name) do
+              = render_colored_label(label)
+  = link_to '#aside', class: 'show-aside' do
+    %i.fa.fa-angle-left
diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml
index 64a28d8da49c025432c6f1253b65da125cb104fd..7d7217eb2a81f4804a40a17a62f49775b39faa97 100644
--- a/app/views/projects/issues/_form.html.haml
+++ b/app/views/projects/issues/_form.html.haml
@@ -1,14 +1,8 @@
 %div.issue-form-holder
-  %h3.page-title= @issue.new_record? ? "New Issue" : "Edit Issue ##{@issue.iid}"
+  %h3.page-title= @issue.new_record? ? "Create Issue" : "Edit Issue ##{@issue.iid}"
   %hr
-  - if @repository.exists? && !@repository.empty? && @repository.contribution_guide && !@issue.persisted?
-    - contribution_guide_url = project_blob_path(@project, tree_join(@repository.root_ref, @repository.contribution_guide.name))
-    .row
-      .col-sm-10.col-sm-offset-2
-        .alert.alert-info
-          = "Please review the <strong>#{link_to "guidelines for contribution", contribution_guide_url}</strong> to this repository.".html_safe
 
-  = form_for [@project, @issue], html: { class: 'form-horizontal issue-form gfm-form' } do |f|
+  = form_for [@project.namespace.becomes(Namespace), @project, @issue], html: { class: 'form-horizontal issue-form gfm-form' } do |f|
     = render 'projects/issuable_form', f: f, issuable: @issue
 
 :javascript
@@ -17,4 +11,4 @@
     e.preventDefault();
   });
 
-  window.project_image_path_upload = "#{upload_image_project_path @project}";
+  window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
diff --git a/app/views/projects/issues/_head.html.haml b/app/views/projects/issues/_head.html.haml
deleted file mode 100644
index 1d2f3ed81181e077c64925d6a4b9a11cc37437b3..0000000000000000000000000000000000000000
--- a/app/views/projects/issues/_head.html.haml
+++ /dev/null
@@ -1,36 +0,0 @@
-%ul.nav.nav-tabs
-  = nav_link(controller: :issues) do
-    = link_to project_issues_path(@project), class: "tab" do
-      Browse Issues
-  = nav_link(controller: :milestones) do
-    = link_to 'Milestones', project_milestones_path(@project), class: "tab"
-  = nav_link(controller: :labels) do
-    = link_to 'Labels', project_labels_path(@project), class: "tab"
-
-  - if current_controller?(:milestones)
-    %li.pull-right
-      %button.btn.btn-default.sidebar-expand-button
-        %i.icon.fa.fa-list
-
-  - if current_controller?(:issues)
-    - if current_user
-      %li
-        = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
-          %i.fa.fa-rss
-
-    %li.pull-right
-      .pull-right
-        %button.btn.btn-default.sidebar-expand-button
-          %i.icon.fa.fa-list
-        = form_tag project_issues_path(@project), method: :get, id: "issue_search_form", class: 'pull-left issue-search-form'  do
-          .append-right-10.hidden-xs.hidden-sm
-            = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input input-mn-300' }
-            = hidden_field_tag :state, params['state']
-            = hidden_field_tag :scope, params['scope']
-            = hidden_field_tag :assignee_id, params['assignee_id']
-            = hidden_field_tag :milestone_id, params['milestone_id']
-            = hidden_field_tag :label_id, params['label_id']
-        - if can? current_user, :write_issue, @project
-          = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do
-            %i.fa.fa-plus
-            New Issue
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 7525812696f73fe7edc4e66d539c91fac92fd78e..998e74d12cf8539b7fd7a5e9597da79de5c04cb5 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -1,25 +1,28 @@
-%li{ id: dom_id(issue), class: issue_css_classes(issue), url: project_issue_path(issue.project, issue) }
+%li{ id: dom_id(issue), class: issue_css_classes(issue), url: issue_path(issue) }
   - if controller.controller_name == 'issues'
     .issue-check
       = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
 
   .issue-title
-    %span.light= "##{issue.iid}"
     %span.str-truncated
-      = link_to_gfm issue.title, project_issue_path(issue.project, issue), class: "row_title"
-    - if issue.closed?
-      %small.pull-right
-        CLOSED
+      = link_to_gfm issue.title, issue_path(issue), class: "row_title"
+    .pull-right.light
+      - if issue.closed?
+        %span
+          CLOSED
+      - note_count = issue.notes.user.count
+      - if note_count > 0
+        &nbsp;
+        %span
+          %i.fa.fa-comments
+          = note_count
 
   .issue-info
+    = link_to "##{issue.iid}", issue_path(issue), class: "light"
     - if issue.assignee
       assigned to #{link_to_member(@project, issue.assignee)}
     - if issue.votes_count > 0
       = render 'votes/votes_inline', votable: issue
-    - if issue.notes.any?
-      %span
-        %i.fa.fa-comments
-        = issue.notes.count
     - if issue.milestone
       %span
         %i.fa.fa-clock-o
@@ -28,21 +31,21 @@
       %span.task-status
         = issue.task_status
 
-    .pull-right
+    .pull-right.issue-updated-at
       %small updated #{time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_update_ago')}
 
     .issue-labels
       - issue.labels.each do |label|
-        = link_to project_issues_path(issue.project, label_name: label.name) do
+        = link_to namespace_project_issues_path(issue.project.namespace, issue.project, label_name: label.name) do
           = render_colored_label(label)
 
   .issue-actions
     - if can? current_user, :modify_issue, issue
       - if issue.closed?
-        = link_to 'Reopen', project_issue_path(issue.project, issue, issue: {state_event: :reopen }, status_only: true), method: :put,  class: "btn btn-small btn-grouped reopen_issue btn-reopen", remote: true
+        = link_to 'Reopen', issue_path(issue, issue: {state_event: :reopen }, status_only: true), method: :put,  class: "btn btn-sm btn-grouped reopen_issue btn-reopen", remote: true
       - else
-        = link_to 'Close', project_issue_path(issue.project, issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-small btn-grouped close_issue btn-close", remote: true
-      = link_to edit_project_issue_path(issue.project, issue), class: "btn btn-small edit-issue-link btn-grouped" do
+        = link_to 'Close', issue_path(issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-sm btn-grouped close_issue btn-close", remote: true
+      = link_to edit_namespace_project_issue_path(issue.project.namespace, issue.project, issue), class: "btn btn-sm edit-issue-link btn-grouped" do
         %i.fa.fa-pencil-square-o
         Edit
 
diff --git a/app/views/projects/issues/_issue_context.html.haml b/app/views/projects/issues/_issue_context.html.haml
index 648f459dc9e975b2ca198016e14a8b628eb91ad8..52e3805041979ea08e9704e7f430095c7831ee44 100644
--- a/app/views/projects/issues/_issue_context.html.haml
+++ b/app/views/projects/issues/_issue_context.html.haml
@@ -1,25 +1,46 @@
-= form_for [@project, @issue], remote: true, html: {class: 'edit-issue inline-update'} do |f|
-  .row
-    .col-sm-6
-      %strong.append-right-10
+= form_for [@project.namespace.becomes(Namespace), @project, @issue], remote: true, html: {class: 'edit-issue inline-update'} do |f|
+  %div.prepend-top-20
+    .issuable-context-title
+      %label
         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)
+      - if issue.assignee
+        %strong= link_to_member(@project, @issue.assignee, size: 24)
       - else
-        None
+        none
+    - if can?(current_user, :modify_issue, @issue)
+      = users_select_tag('issue[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @issue.assignee_id, null_user: true)
 
-    .col-sm-6.text-right
-      %strong.append-right-10
+  %div.prepend-top-20.clearfix
+    .issuable-context-title
+      %label
         Milestone:
-      - if can?(current_user, :modify_issue, @issue)
-        = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'})
-        = hidden_field_tag :issue_context
-        = f.submit class: 'btn'
-      - elsif issue.milestone
-        = link_to project_milestone_path(@project, @issue.milestone) do
-          = @issue.milestone.title
+      - if issue.milestone
+        %span.back-to-milestone
+          = link_to namespace_project_milestone_path(@project.namespace, @project, @issue.milestone) do
+            %strong
+              %i.fa.fa-clock-o
+              = @issue.milestone.title
       - else
-        None
+        none
+    - if can?(current_user, :modify_issue, @issue)
+      = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'})
+      = hidden_field_tag :issue_context
+      = f.submit class: 'btn'
+
+  - if current_user
+    %div.prepend-top-20.clearfix
+      .issuable-context-title
+        %label
+          Subscription:
+      %button.btn.btn-block.subscribe-button
+        %i.fa.fa-eye
+        %span= @issue.subscribed?(current_user) ? "Unsubscribe" : "Subscribe"
+      - subscribtion_status = @issue.subscribed?(current_user) ? "subscribed" : "unsubscribed"
+      .subscription-status{"data-status" => subscribtion_status}
+        .description-block.unsubscribed{class: ( "hidden" if @issue.subscribed?(current_user) )}
+          You're not receiving notifications from this thread.
+        .description-block.subscribed{class: ( "hidden" unless @issue.subscribed?(current_user) )}
+          You're receiving notifications because you're subscribed to this thread.
+
+:coffeescript
+  new Subscription("#{toggle_subscription_namespace_project_issue_path(@issue.project.namespace, @project, @issue)}")
diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml
index 0bff8bdbead4b3dc24c4c3ac0be9dc0fdb8df9b2..5d243adb5fe4742e97328a5e12f30733d4e511e4 100644
--- a/app/views/projects/issues/_issues.html.haml
+++ b/app/views/projects/issues/_issues.html.haml
@@ -1,66 +1,3 @@
-.append-bottom-10
-  .check-all-holder
-    = check_box_tag "check_all_issues", nil, false, class: "check_all_issues left"
-  .issues-filters
-    .dropdown.inline
-      %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
-        %i.fa.fa-user
-        %span.light assignee:
-        - if @assignee.present?
-          %strong= @assignee.name
-        - elsif params[:assignee_id] == "0"
-          Unassigned
-        - else
-          Any
-        %b.caret
-      %ul.dropdown-menu
-        %li
-          = link_to project_filter_path(assignee_id: nil) do
-            Any
-          = link_to project_filter_path(assignee_id: 0) do
-            Unassigned
-        - @assignees.sort_by(&:name).each do |user|
-          %li
-            = link_to project_filter_path(assignee_id: user.id) do
-              = image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
-              = user.name
-
-    .dropdown.inline.prepend-left-10
-      %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
-        %i.fa.fa-clock-o
-        %span.light milestone:
-        - if @milestone.present?
-          %strong= @milestone.title
-        - elsif params[:milestone_id] == "0"
-          None (backlog)
-        - else
-          Any
-        %b.caret
-      %ul.dropdown-menu
-        %li
-          = link_to project_filter_path(milestone_id: nil) do
-            Any
-          = link_to project_filter_path(milestone_id: 0) do
-            None (backlog)
-        - project_active_milestones.each do |milestone|
-          %li
-            = link_to project_filter_path(milestone_id: milestone.id) do
-              %strong= milestone.title
-              %small.light= milestone.expires_at
-
-    .pull-right
-      = render 'shared/sort_dropdown'
-
-  .clearfix
-    .issues_bulk_update.hide
-      = form_tag bulk_update_project_issues_path(@project), method: :post  do
-        = select_tag('update[status]', options_for_select([['Open', 'open'], ['Closed', 'closed']]), prompt: "Status")
-        = project_users_select_tag('update[assignee_id]', placeholder: 'Assignee')
-        = select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
-        = hidden_field_tag 'update[issues_ids]', []
-        = hidden_field_tag :status, params[:status]
-        = button_tag "Update issues", class: "btn update_selected_issues btn-save"
-
 .panel.panel-default
   %ul.well-list.issues-list
     = render @issues
diff --git a/app/views/projects/issues/index.atom.builder b/app/views/projects/issues/index.atom.builder
index 012ba235951b0d43a1b2779703864c254a36e1bc..126f2c07faaa68192fc4b4a09dc8586eced6c497 100644
--- a/app/views/projects/issues/index.atom.builder
+++ b/app/views/projects/issues/index.atom.builder
@@ -1,23 +1,12 @@
 xml.instruct!
 xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
   xml.title   "#{@project.name} issues"
-  xml.link    :href => project_issues_url(@project, :atom), :rel => "self", :type => "application/atom+xml"
-  xml.link    :href => project_issues_url(@project), :rel => "alternate", :type => "text/html"
-  xml.id      project_issues_url(@project)
+  xml.link    :href => namespace_project_issues_url(@project.namespace, @project, :atom), :rel => "self", :type => "application/atom+xml"
+  xml.link    :href => namespace_project_issues_url(@project.namespace, @project), :rel => "alternate", :type => "text/html"
+  xml.id      namespace_project_issues_url(@project.namespace, @project)
   xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
 
   @issues.each do |issue|
-    xml.entry do
-      xml.id      project_issue_url(@project, issue)
-      xml.link    :href => project_issue_url(@project, issue)
-      xml.title   truncate(issue.title, :length => 80)
-      xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
-      xml.media   :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
-      xml.author do |author|
-        xml.name issue.author_name
-        xml.email issue.author_email
-      end
-      xml.summary issue.title
-    end
+    issue_to_atom(xml, issue)
   end
 end
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 4ec362b3063223ea0de3b342b6122694557bd6e9..d3c7ae24a752f4b3298e9951c94de9bf67511b9f 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -1,9 +1,19 @@
-= render "head"
-.row
-  .fixed.fixed.sidebar-expand-button.hidden-lg.hidden-md.hidden-xs
-    %i.fa.fa-list.fa-2x
-  .col-md-3.responsive-side
-    = render 'shared/project_filter', project_entities_path: project_issues_path(@project),
-             labels: true, redirect: 'issues', entity: 'issue'
-  .col-md-9.issues-holder
-    = render "issues"
+.append-bottom-10
+  .pull-right
+    .pull-left
+      - if current_user
+        .hidden-xs.pull-left
+          = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do
+            %i.fa.fa-rss
+
+      = render 'shared/issuable_search_form', path: namespace_project_issues_path(@project.namespace, @project)
+
+    - if can? current_user, :write_issue, @project
+      = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do
+        %i.fa.fa-plus
+        New Issue
+
+  = render 'shared/issuable_filter'
+
+.issues-holder
+  = render "issues"
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index aad58e48f6c3571c624dc3bd41aa518d5e844a1b..bd28d8a1db29a82f6f1cde6a54d7300a21606ebc 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -1,75 +1,40 @@
-%h3.page-title
-  Issue ##{@issue.iid}
-
-  %span.pull-right.issue-btn-group
-    - if can?(current_user, :write_issue, @project)
-      = link_to new_project_issue_path(@project), class: "btn btn-grouped", title: "New Issue", id: "new_issue_link" do
-        %i.fa.fa-plus
-        New Issue
-    - if can?(current_user, :modify_issue, @issue)
-      - if @issue.closed?
-        = link_to 'Reopen', project_issue_path(@project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put,  class: "btn btn-grouped btn-reopen"
-      - else
-        = link_to 'Close', project_issue_path(@project, @issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close", title: "Close Issue"
-
-      = link_to edit_project_issue_path(@project, @issue), class: "btn btn-grouped" do
-        %i.fa.fa-pencil-square-o
-        Edit
-
-.clearfix
-  .votes-holder
-    #votes= render 'votes/votes_block', votable: @issue
-
-  .back-link
-    = link_to project_issues_path(@project) do
-      &larr; To issues list
-    %span.milestone-nav-link
-      - if @issue.milestone
-        |
-        %span.light Milestone
-        = link_to project_milestone_path(@project, @issue.milestone) do
-          = @issue.milestone.title
-
-.issue-box{ class: issue_box_class(@issue) }
-  .state.clearfix
-    .state-label
-      - if @issue.closed?
-        Closed
-      - else
-        Open
-
-    .creator
-      Created by #{link_to_member(@project, @issue.author)} #{issue_timestamp(@issue)}
-
-  %h4.title
-    = gfm escape_once(@issue.title)
-
-  - if @issue.description.present?
-    .description
-      .wiki
-        = preserve do
-          = markdown(@issue.description, parse_tasks: true)
-  .context
-    %cite.cgray
-      = render partial: 'issue_context', locals: { issue: @issue }
-
-
-- content_for :note_actions do
-  - if can?(current_user, :modify_issue, @issue)
-    - if @issue.closed?
-      = link_to 'Reopen Issue', project_issue_path(@project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put, class: "btn btn-grouped btn-reopen js-note-target-reopen", title: 'Reopen Issue'
-    - else
-      = link_to 'Close Issue', project_issue_path(@project, @issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close js-note-target-close", title: "Close Issue"
-
-.participants
-  %cite.cgray
-    = pluralize(@issue.participants.count, 'participant')
-  - @issue.participants.each do |participant|
-    = link_to_member(@project, participant, name: false, size: 24)
-
-  .issue-show-labels.pull-right
-    - @issue.labels.each do |label|
-      = link_to project_issues_path(@project, label_name: label.name) do
-        = render_colored_label(label)
-
-.voting_notes#notes= render "projects/notes/notes_with_form"
+.issue
+  .issue-details
+    %h4.page-title
+      .issue-box{ class: issue_box_class(@issue) }
+        - if @issue.closed?
+          Closed
+        - else
+          Open
+      Issue ##{@issue.iid}
+      %small.creator
+        &middot; created by #{link_to_member(@project, @issue.author)} #{issue_timestamp(@issue)}
+
+      .pull-right
+        - if can?(current_user, :write_issue, @project)
+          = link_to new_namespace_project_issue_path(@project.namespace, @project), class: "btn btn-grouped new-issue-link", title: "New Issue", id: "new_issue_link" do
+            %i.fa.fa-plus
+            New Issue
+        - if can?(current_user, :modify_issue, @issue)
+          - if @issue.closed?
+            = link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen }, status_only: true), method: :put,  class: "btn btn-grouped btn-reopen"
+          - else
+            = link_to 'Close', issue_path(@issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn btn-grouped btn-close", title: "Close Issue"
+
+          = link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: "btn btn-grouped issuable-edit" do
+            %i.fa.fa-pencil-square-o
+            Edit
+
+    %hr
+    %h2.issue-title
+      = gfm escape_once(@issue.title)
+    %div
+      - if @issue.description.present?
+        .description
+          .wiki
+            = preserve do
+              = markdown(@issue.description, parse_tasks: true)
+
+    %hr
+  .issue-discussion
+    = render "projects/issues/discussion"
diff --git a/app/views/projects/issues/update.js.haml b/app/views/projects/issues/update.js.haml
index 5199e9fc61f3b05eb0a23e0a2cbfe46024c7a92b..1d38662bff8f18237bdbab4f5d1d76e635849852 100644
--- a/app/views/projects/issues/update.js.haml
+++ b/app/views/projects/issues/update.js.haml
@@ -3,8 +3,15 @@
     :plain
       $("##{dom_id(@issue)}").fadeOut();
 - elsif params[:issue_context]
-  $('.issue-box .context').effect('highlight');
+  $('.context').html("#{escape_javascript(render partial: 'issue_context', locals: { issue: @issue })}");
+  $('.context').effect('highlight');
   - 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, namespace_project_milestone_path(@issue.project.namespace, @issue.project, @issue.milestone))}</span>")
   - else
     $('.milestone-nav-link').html('')
+
+
+$('select.select2').select2({width: 'resolve', dropdownAutoWidth: true})
+$('.edit-issue.inline-update input[type="submit"]').hide();
+new UsersSelect()
+new Issue();
diff --git a/app/views/projects/labels/_form.html.haml b/app/views/projects/labels/_form.html.haml
index 72a01e1c2711dd0ef60c74397128cfba9ab9c045..ad993db6c0b584646277dfd2b5f5610a2fbc31ff 100644
--- a/app/views/projects/labels/_form.html.haml
+++ b/app/views/projects/labels/_form.html.haml
@@ -1,8 +1,8 @@
-= form_for [@project, @label], html: { class: 'form-horizontal label-form' } do |f|
+= form_for [@project.namespace.becomes(Namespace), @project, @label], html: { class: 'form-horizontal label-form' } do |f|
   -if @label.errors.any?
     .row
       .col-sm-10.col-sm-offset-2
-        .bs-callout.bs-callout-danger
+        .alert.alert-danger
           - @label.errors.full_messages.each do |msg|
             %span= msg
             %br
@@ -16,9 +16,9 @@
     .col-sm-10
       .input-group
         .input-group-addon.label-color-preview &nbsp;
-        = f.text_field :color, placeholder: "#AA33EE", class: "form-control"
+        = f.color_field :color, value: "#AA33EE", class: "form-control"
       .help-block
-        6 character hex values starting with a # sign.
+        Choose any color.
         %br
         Or you can choose one of suggested colors below
 
@@ -29,5 +29,5 @@
 
   .form-actions
     = f.submit 'Save', class: 'btn btn-save js-save-button'
-    = link_to "Cancel", project_labels_path(@project), class: 'btn btn-cancel'
+    = link_to "Cancel", namespace_project_labels_path(@project.namespace, @project), class: 'btn btn-cancel'
 
diff --git a/app/views/projects/labels/_label.html.haml b/app/views/projects/labels/_label.html.haml
index 03a8f0921b7ec98824a101283c47c5bd687c0038..82829452862406d24f4592ac91c03b0b6bca5fe0 100644
--- a/app/views/projects/labels/_label.html.haml
+++ b/app/views/projects/labels/_label.html.haml
@@ -2,9 +2,9 @@
   = render_colored_label(label)
   .pull-right
     %strong.append-right-20
-      = link_to project_issues_path(@project, label_name: label.name) do
+      = link_to namespace_project_issues_path(@project.namespace, @project, label_name: label.name) do
         = pluralize label.open_issues_count, 'open issue'
 
     - if can? current_user, :admin_label, @project
-      = link_to 'Edit', edit_project_label_path(@project, label), class: 'btn'
-      = link_to 'Remove', project_label_path(@project, label), class: 'btn btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"}
+      = link_to 'Edit', edit_namespace_project_label_path(@project.namespace, @project, label), class: 'btn'
+      = link_to 'Remove', namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"}
diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml
index 52435c5d892b65a47a2997d4a6471407c1abd44e..e003d1dfe7f586ffffed167502e51f428ddbb9be 100644
--- a/app/views/projects/labels/edit.html.haml
+++ b/app/views/projects/labels/edit.html.haml
@@ -2,7 +2,7 @@
   Edit label
   %span.light #{@label.name}
 .back-link
-  = link_to project_labels_path(@project) do
+  = link_to namespace_project_labels_path(@project.namespace, @project) do
     &larr; To labels list
 %hr
 = render 'form'
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index 06568278de8806fff198daaf54c2396c726831ac..0700e72d39c8e659a4195a009552d6e0383c28df 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -1,7 +1,5 @@
-= render "projects/issues/head"
-
 - if can? current_user, :admin_label, @project
-  = link_to new_project_label_path(@project), class: "pull-right btn btn-new" do
+  = link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do
     New label
 %h3.page-title
   Labels
@@ -14,4 +12,4 @@
     = paginate @labels, theme: 'gitlab'
   - else
     .light-well
-      .nothing-here-block Create first label or #{link_to 'generate', generate_project_labels_path(@project), method: :post} default set of labels
+      .nothing-here-block Create first label or #{link_to 'generate', generate_namespace_project_labels_path(@project.namespace, @project), method: :post} default set of labels
diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml
index 850da0b192b2658e88240559e21b38f4f9a8cc68..0683ed5d4fbcf6ae9f5b0cfb3e783cc7c6084654 100644
--- a/app/views/projects/labels/new.html.haml
+++ b/app/views/projects/labels/new.html.haml
@@ -1,6 +1,6 @@
 %h3 New label
 .back-link
-  = link_to project_labels_path(@project) do
+  = link_to namespace_project_labels_path(@project.namespace, @project) do
     &larr; To labels list
 %hr
 = render 'form'
diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..eb72eaabd8b9482c5e90e423ffc1f595304ab35d
--- /dev/null
+++ b/app/views/projects/merge_requests/_discussion.html.haml
@@ -0,0 +1,31 @@
+- content_for :note_actions do
+  - if can?(current_user, :modify_merge_request, @merge_request)
+    - if @merge_request.open?
+      = link_to 'Close', merge_request_path(@merge_request, merge_request: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close close-mr-link js-note-target-close", title: "Close merge request"
+    - if @merge_request.closed?
+      = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request"
+
+.row
+  %section.col-md-9
+    .votes-holder.pull-right
+      #votes= render 'votes/votes_block', votable: @merge_request
+    = render "projects/merge_requests/show/participants"
+    = render "projects/notes/notes_with_form"
+  %aside.col-md-3
+    .issuable-affix
+      .clearfix
+        %span.slead.has_tooltip{:"data-original-title" => 'Cross-project reference'}
+          = cross_project_reference(@project, @merge_request)
+      %hr
+      .context
+        = render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
+
+      - if @merge_request.labels.any?
+        .issuable-context-title
+          %label Labels
+        .merge-request-show-labels
+          - @merge_request.labels.each do |label|
+            = link_to namespace_project_merge_requests_path(@project.namespace, @project, label_name: label.name) do
+              = render_colored_label(label)
+  = link_to '#aside', class: 'show-aside' do
+    %i.fa.fa-angle-left
diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml
index d52e64666a0f4ea6c2c7bb7c89a36883549ae073..1c7160bce5fb495190ca0732f7991365ed18ba4e 100644
--- a/app/views/projects/merge_requests/_form.html.haml
+++ b/app/views/projects/merge_requests/_form.html.haml
@@ -1,4 +1,4 @@
-= form_for [@project, @merge_request], html: { class: 'merge-request-form form-horizontal gfm-form' } do |f|
+= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], html: { class: 'merge-request-form form-horizontal gfm-form' } do |f|
   .merge-request-form-info
     = render 'projects/issuable_form', f: f, issuable: @merge_request
 
@@ -9,4 +9,4 @@
     e.preventDefault();
   });
 
-  window.project_image_path_upload = "#{upload_image_project_path @project}";
+  window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
diff --git a/app/views/projects/merge_requests/_head.html.haml b/app/views/projects/merge_requests/_head.html.haml
index 35a86e6511cc23b55148df6c44e9e5c08f41c342..19e4dab874bcd9e805232b5abf8bd6aa1c2f2ab7 100644
--- a/app/views/projects/merge_requests/_head.html.haml
+++ b/app/views/projects/merge_requests/_head.html.haml
@@ -1,5 +1,5 @@
 .top-tabs
-  = link_to project_merge_requests_path(@project), class: "tab #{'active' if current_page?(project_merge_requests_path(@project)) }" do
+  = link_to namespace_project_merge_requests_path(@project.namespace, @project), class: "tab #{'active' if current_page?(namespace_project_merge_requests_path(@project.namespace, @project)) }" do
     %span
     Merge Requests
 
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 1ee2e1bdae848aab2e3a70771de5588a7e3d16b7..4f30d1e69f79fd0525bfb4a290bffc15ad19f011 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -1,28 +1,35 @@
 %li{ class: mr_css_classes(merge_request) }
   .merge-request-title
-    %span.light= "##{merge_request.iid}"
-    = link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.target_project, merge_request), class: "row_title"
-    - if merge_request.merged?
-      %small.pull-right
-        %i.fa.fa-check
-        MERGED
-    - else
-      %span.pull-right
-        - if merge_request.for_fork?
-          %span.light
-            #{merge_request.source_project_namespace}:
-        = truncate merge_request.source_branch, length: 25
-        %i.fa.fa-angle-right.light
-        = merge_request.target_branch
+    %span.str-truncated
+      = link_to_gfm merge_request.title, merge_request_path(merge_request), class: "row_title"
+    .pull-right.light
+      - if merge_request.merged?
+        %span
+          %i.fa.fa-check
+          MERGED
+      - elsif merge_request.closed?
+        %span
+          %i.fa.fa-close
+          CLOSED
+      - else
+        %span.hidden-xs.hidden-sm
+          %span.label-branch<
+            %i.fa.fa-code-fork
+            %span= merge_request.target_branch
+      - note_count = merge_request.mr_and_commit_notes.user.count
+      - if note_count > 0
+        &nbsp;
+        %span
+          %i.fa.fa-comments
+          = note_count
   .merge-request-info
-    - if merge_request.author
-      authored by #{link_to_member(merge_request.source_project, merge_request.author)}
+    = link_to "##{merge_request.iid}", merge_request_path(merge_request), class: "light"
+    - if merge_request.assignee
+      assigned to #{link_to_member(merge_request.source_project, merge_request.assignee)}
+    - else
+      Unassigned
     - if merge_request.votes_count > 0
       = render 'votes/votes_inline', votable: merge_request
-    - if merge_request.notes.any?
-      %span
-        %i.fa.fa-comments
-        = merge_request.mr_and_commit_notes.count
     - if merge_request.milestone_id?
       %span
         %i.fa.fa-clock-o
@@ -31,10 +38,11 @@
       %span.task-status
         = merge_request.task_status
 
-    .pull-right
+
+    .pull-right.hidden-xs
       %small updated #{time_ago_with_tooltip(merge_request.updated_at, 'bottom', 'merge_request_updated_ago')}
 
     .merge-request-labels
       - merge_request.labels.each do |label|
-        = link_to project_merge_requests_path(merge_request.project, label_name: label.name) do
+        = link_to namespace_project_merge_requests_path(merge_request.project.namespace, merge_request.project, label_name: label.name) do
           = render_colored_label(label)
diff --git a/app/views/projects/merge_requests/_merge_requests.html.haml b/app/views/projects/merge_requests/_merge_requests.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..b8a0ca9a42f31cf6aaa35adaa798e209fd2fdd34
--- /dev/null
+++ b/app/views/projects/merge_requests/_merge_requests.html.haml
@@ -0,0 +1,13 @@
+.panel.panel-default
+  %ul.well-list.mr-list
+    = render @merge_requests
+    - if @merge_requests.blank?
+      %li
+        .nothing-here-block No merge requests to show
+
+- if @merge_requests.present?
+  .pull-right
+    %span.cgray.pull-right #{@merge_requests.total_count} merge requests for this filter
+
+  = paginate @merge_requests, theme: "gitlab"
+
diff --git a/app/views/projects/merge_requests/_new_compare.html.haml b/app/views/projects/merge_requests/_new_compare.html.haml
index 9972617215491ba93d763717e2fc22b8ef4dbfad..17e76059fdbc4664ff23f3df89bd947325074b54 100644
--- a/app/views/projects/merge_requests/_new_compare.html.haml
+++ b/app/views/projects/merge_requests/_new_compare.html.haml
@@ -1,7 +1,7 @@
 %h3.page-title Compare branches for new Merge Request
 %hr
 
-= form_for [@project, @merge_request], url: new_project_merge_request_path(@project), method: :get, html: { class: "merge-request-form form-inline" } do |f|
+= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], url: new_namespace_project_merge_request_path(@project.namespace, @project), method: :get, html: { class: "merge-request-form form-inline" } do |f|
   .hide.alert.alert-danger.mr-compare-errors
   .merge-request-branches.row
     .col-md-6
@@ -60,19 +60,19 @@
     , target_branch = $("#merge_request_target_branch")
     , target_project = $("#merge_request_target_project_id");
 
-  $.get("#{branch_from_project_merge_requests_path(@source_project)}", {ref: source_branch.val() });
-  $.get("#{branch_to_project_merge_requests_path(@source_project)}", {target_project_id: target_project.val(),ref: target_branch.val() });
+  $.get("#{branch_from_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {ref: source_branch.val() });
+  $.get("#{branch_to_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {target_project_id: target_project.val(),ref: target_branch.val() });
 
   target_project.on("change", function() {
-    $.get("#{update_branches_project_merge_requests_path(@source_project)}", {target_project_id:  $(this).val() });
+    $.get("#{update_branches_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {target_project_id:  $(this).val() });
   });
   source_branch.on("change", function() {
-    $.get("#{branch_from_project_merge_requests_path(@source_project)}", {ref: $(this).val() });
+    $.get("#{branch_from_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {ref: $(this).val() });
     $(".mr-compare-errors").fadeOut();
     $(".mr-compare-btn").enable();
   });
   target_branch.on("change", function() {
-    $.get("#{branch_to_project_merge_requests_path(@source_project)}", {target_project_id: target_project.val(),ref: $(this).val() });
+    $.get("#{branch_to_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {target_project_id: target_project.val(),ref: $(this).val() });
     $(".mr-compare-errors").fadeOut();
     $(".mr-compare-btn").enable();
   });
diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml
index d4666eacd7ea3f7dc7e00b2b295e29e31843058f..d986ce67c0c6b2588e92bebd783a360bc4772445 100644
--- a/app/views/projects/merge_requests/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/_new_submit.html.haml
@@ -7,75 +7,105 @@
   %strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch}
 
   %span.pull-right
-    = link_to 'Change branches', new_project_merge_request_path(@project)
+    = link_to 'Change branches', new_namespace_project_merge_request_path(@project.namespace, @project)
 
-= form_for [@project, @merge_request], html: { class: "merge-request-form gfm-form" } do |f|
-  .panel.panel-default
+= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], html: { class: "merge-request-form form-horizontal gfm-form" } do |f|
+  .merge-request-form-info
+    .form-group
+      = f.label :title, class: 'control-label' do
+        %strong Title *
+      .col-sm-10
+        = f.text_field :title, maxlength: 255, autofocus: true, class: 'form-control pad js-gfm-input', required: true
+    .form-group.issuable-description
+      = f.label :description, 'Description', class: 'control-label'
+      .col-sm-10
+        = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do
+          = render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
 
-    .panel-body
-      .form-group
-        .light
-          = f.label :title do
-            Title *
-        = f.text_field :title, class: "form-control input-lg js-gfm-input", maxlength: 255, rows: 5, required: true
-      .form-group
-        .light
-          = f.label :description, "Description"
-        = render 'projects/zen', f: f, attr: :description,
-                                 classes: 'description form-control'
-        .clearfix.hint
-          .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
-          .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
-        .error-alert
-      .form-group
-        .issue-assignee
-          = f.label :assignee_id do
-            %i.fa.fa-user
-            Assign to
-          %div
-            = project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select a user', class: 'custom-form-control', selected: @merge_request.assignee_id, project_id: @merge_request.target_project_id)
-            &nbsp;
-            = link_to 'Assign to me', '#', class: 'btn assign-to-me-link'
-      .form-group
-        .issue-milestone
-          = f.label :milestone_id do
-            %i.fa.fa-clock-o
-            Milestone
-          %div= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2'})
-      .form-group
-        = f.label :label_ids do
-          %i.fa.fa-tag
-          Labels
-        %div
-          = f.collection_select :label_ids, @merge_request.target_project.labels.all, :id, :name, { selected: @merge_request.label_ids }, multiple: true, class: 'select2'
+          .col-sm-12-hint
+            .pull-left
+              Parsed with
+              #{link_to 'Gitlab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}.
+            .pull-right
+              Attach files by dragging &amp; dropping
+              or #{link_to 'selecting them', '#', class: 'markdown-selector'}.
 
-    .panel-footer
-      - if contribution_guide_url(@target_project)
+          .clearfix
+          .error-alert
+    %hr
+    .form-group
+      .issue-assignee
+        = f.label :assignee_id, class: 'control-label' do
+          %i.fa.fa-user
+          Assign to
+      .col-sm-10
+        = users_select_tag('merge_request[assignee_id]', placeholder: 'Select a user', class: 'custom-form-control', selected: @merge_request.assignee_id, project_id: @merge_request.target_project_id)
+        &nbsp;
+        = link_to 'Assign to me', '#', class: 'btn assign-to-me-link'
+    .form-group
+      .issue-milestone
+        = f.label :milestone_id, class: 'control-label' do
+          %i.fa.fa-clock-o
+          Milestone
+        .col-sm-10
+          - if milestone_options(@merge_request).present?
+            = f.select(:milestone_id, milestone_options(@merge_request), {include_blank: 'Select milestone'}, {class: 'select2'})
+          - else
+            %span.light No open milestones available.
+          &nbsp;
+          - if can? current_user, :admin_milestone, @merge_request.target_project
+            = link_to 'Create new milestone', new_namespace_project_milestone_path(@merge_request.target_project.namespace, @merge_request.target_project), target: :blank
+    .form-group
+      = f.label :label_ids, class: 'control-label' do
+        %i.fa.fa-tag
+        Labels
+      .col-sm-10
+        - if @merge_request.target_project.labels.any?
+          = f.collection_select :label_ids, @merge_request.target_project.labels.all, :id, :name, {selected: @merge_request.label_ids}, multiple: true, class: 'select2'
+        - else
+          %span.light No labels yet.
+        &nbsp;
+        - if can? current_user, :admin_label, @merge_request.target_project
+          = link_to 'Create new label', new_namespace_project_label_path(@merge_request.target_project.namespace, @merge_request.target_project), target: :blank
+
+    .form-actions
+      - if guide_url = contribution_guide_url(@target_project)
         %p
           Please review the
-          %strong #{link_to "guidelines for contribution", contribution_guide_url(@target_project)}
+          %strong #{link_to 'guidelines for contribution', guide_url}
           to this repository.
       = f.hidden_field :source_project_id
+      = f.hidden_field :source_branch
       = f.hidden_field :target_project_id
       = f.hidden_field :target_branch
-      = f.hidden_field :source_branch
-      = f.submit 'Submit merge request', class: "btn btn-create"
-
-.mr-compare
-  = render "projects/commits/commit_list"
+      = f.submit 'Submit merge request', class: 'btn btn-create'
 
-  %h4 Changes
-  - if @diffs.present?
-    = render "projects/diffs/diffs", diffs: @diffs, project: @project
-  - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
-    .bs-callout.bs-callout-danger
-      %h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits.
-      %p To preserve performance the line changes are not shown.
-  - else
-    .bs-callout.bs-callout-danger
-      %h4 This comparison includes huge diff.
-      %p To preserve performance the line changes are not shown.
+.mr-compare.merge-request
+  %ul.nav.nav-tabs.merge-request-tabs
+    %li.commits-tab{data: {action: 'commits'}}
+      = link_to url_for(params) do
+        %i.fa.fa-history
+        Commits
+        %span.badge= @commits.size
+    %li.diffs-tab{data: {action: 'diffs'}}
+      = link_to url_for(params) do
+        %i.fa.fa-list-alt
+        Changes
+        %span.badge= @diffs.size
 
+  .commits.tab-content
+    = render "projects/commits/commits", project: @project
+  .diffs.tab-content
+    - if @diffs.present?
+      = render "projects/diffs/diffs", diffs: @diffs, project: @project
+    - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
+      .alert.alert-danger
+        %h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits.
+        %p To preserve performance the line changes are not shown.
+    - else
+      .alert.alert-danger
+        %h4 This comparison includes a huge diff.
+        %p To preserve performance the line changes are not shown.
 
 :javascript
   $('.assign-to-me-link').on('click', function(e){
@@ -83,4 +113,11 @@
     e.preventDefault();
   });
 
-  window.project_image_path_upload = "#{upload_image_project_path @project}";
+  window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
+
+:javascript
+  var merge_request
+  merge_request = new MergeRequest({
+    action: 'commits'
+  });
+
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 7b28dd5e7da5c5770712786026788cd2de201987..a74aede4e6bacba98678caafce79a91a7ddf2009 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -1,46 +1,76 @@
-.merge-request
-  = render "projects/merge_requests/show/mr_title"
-  = render "projects/merge_requests/show/how_to_merge"
-  = render "projects/merge_requests/show/mr_box"
-  = render "projects/merge_requests/show/state_widget"
-  = render "projects/merge_requests/show/commits"
-  = render "projects/merge_requests/show/participants"
+.merge-request{'data-url' => merge_request_path(@merge_request)}
+  .merge-request-details
+    = render "projects/merge_requests/show/mr_title"
+    %hr
+    = render "projects/merge_requests/show/mr_box"
+    %hr
+    .append-bottom-20
+      .slead
+        %span From
+        - if @merge_request.for_fork?
+          %strong.label-branch<
+            - if @merge_request.source_project
+              = link_to @merge_request.source_project_namespace, namespace_project_path(@merge_request.source_project.namespace, @merge_request.source_project)
+            - else
+              \ #{@merge_request.source_project_namespace}
+            \:#{@merge_request.source_branch}
+          %span into
+          %strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch}
+        - else
+          %strong.label-branch #{@merge_request.source_branch}
+          %span into
+          %strong.label-branch #{@merge_request.target_branch}
+        - if @merge_request.open?
+          %span.pull-right
+            .btn-group
+              %a.btn.dropdown-toggle{ data: {toggle: :dropdown} }
+                %i.fa.fa-download
+                Download as
+                %span.caret
+              %ul.dropdown-menu
+                %li= link_to "Email Patches", merge_request_path(@merge_request, format: :patch)
+                %li= link_to "Plain Diff",    merge_request_path(@merge_request, format: :diff)
+
+    = render "projects/merge_requests/show/how_to_merge"
+    = render "projects/merge_requests/show/state_widget"
 
   - if @commits.present?
-    %ul.nav.nav-pills.merge-request-tabs
+    %ul.nav.nav-tabs.merge-request-tabs
       %li.notes-tab{data: {action: 'notes'}}
-        = link_to project_merge_request_path(@project, @merge_request) do
-          %i.fa.fa-comment
+        = link_to merge_request_path(@merge_request) do
+          %i.fa.fa-comments
           Discussion
-          %span.badge= @merge_request.mr_and_commit_notes.count
+          %span.badge= @merge_request.mr_and_commit_notes.user.count
+      %li.commits-tab{data: {action: 'commits'}}
+        = link_to merge_request_path(@merge_request), title: 'Commits' do
+          %i.fa.fa-history
+          Commits
+          %span.badge= @commits.size
       %li.diffs-tab{data: {action: 'diffs'}}
-        = link_to diffs_project_merge_request_path(@project, @merge_request) do
+        = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request) do
           %i.fa.fa-list-alt
           Changes
           %span.badge= @merge_request.diffs.size
 
-  - content_for :note_actions do
-    - if can?(current_user, :modify_merge_request, @merge_request)
-      - if @merge_request.open?
-        = link_to 'Close', project_merge_request_path(@project, @merge_request, merge_request: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close close-mr-link js-note-target-close", title: "Close merge request"
-      - if @merge_request.closed?
-        = link_to 'Reopen', project_merge_request_path(@project, @merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request"
-
+  .notes.tab-content.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" }
+    = render "projects/merge_requests/discussion"
+  .commits.tab-content
+    = render "projects/merge_requests/show/commits"
   .diffs.tab-content
     - if current_page?(action: 'diffs')
       = render "projects/merge_requests/show/diffs"
-  .notes.tab-content.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" }
-    = render "projects/notes/notes_with_form"
+
   .mr-loading-status
     = spinner
 
+
 :javascript
   var merge_request;
 
   merge_request = new MergeRequest({
-    url_to_automerge_check: "#{automerge_check_project_merge_request_path(@project, @merge_request)}",
+    url_to_automerge_check: "#{automerge_check_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}",
     check_enable: #{@merge_request.unchecked? ? "true" : "false"},
-    url_to_ci_check: "#{ci_status_project_merge_request_path(@project, @merge_request)}",
+    url_to_ci_check: "#{ci_status_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}",
     ci_enable: #{@project.ci_service ? "true" : "false"},
     current_status: "#{@merge_request.merge_status_name}",
     action: "#{controller.action_name}"
diff --git a/app/views/projects/merge_requests/automerge.js.haml b/app/views/projects/merge_requests/automerge.js.haml
index e01ff662e7db95a19aa7f9ec4d043f8d17e903a3..a53cbb150a41fc7f5e3a004c86496127789406da 100644
--- a/app/views/projects/merge_requests/automerge.js.haml
+++ b/app/views/projects/merge_requests/automerge.js.haml
@@ -1,7 +1,6 @@
 -if @status
   :plain
-    location.reload();
+    merge_request.mergeInProgress();
 -else
   :plain
     merge_request.alreadyOrCannotBeMerged()
-
diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml
index be638d7cac1241c59d1ae55f47fe2f590420ef79..d7992bdd19ea8a0412d94cebcaa28598514c83ff 100644
--- a/app/views/projects/merge_requests/index.html.haml
+++ b/app/views/projects/merge_requests/index.html.haml
@@ -1,78 +1,11 @@
-- if can? current_user, :write_merge_request, @project
-  = link_to new_project_merge_request_path(@project), class: "pull-right btn btn-new", title: "New Merge Request" do
-    %i.fa.fa-plus
-    New Merge Request
-%h3.page-title
-  Merge Requests
-%hr
-.row
-  .fixed.sidebar-expand-button.hidden-lg.hidden-md
-    %i.fa.fa-list.fa-2x
-  .col-md-3.responsive-side
-    = render 'shared/project_filter', project_entities_path: project_merge_requests_path(@project),
-             labels: true, redirect: 'merge_requests', entity: 'merge_request'
-  .col-md-9
-    .mr-filters.append-bottom-10
-      .dropdown.inline
-        %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
-          %i.fa.fa-user
-          %span.light assignee:
-          - if @assignee.present?
-            %strong= @assignee.name
-          - elsif params[:assignee_id] == "0"
-            Unassigned
-          - else
-            Any
-          %b.caret
-        %ul.dropdown-menu
-          %li
-            = link_to project_filter_path(assignee_id: nil) do
-              Any
-            = link_to project_filter_path(assignee_id: 0) do
-              Unassigned
-          - @assignees.sort_by(&:name).each do |user|
-            %li
-              = link_to project_filter_path(assignee_id: user.id) do
-                = image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
-                = user.name
-
-      .dropdown.inline.prepend-left-10
-        %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
-          %i.fa.fa-clock-o
-          %span.light milestone:
-          - if @milestone.present?
-            %strong= @milestone.title
-          - elsif params[:milestone_id] == "0"
-            None (backlog)
-          - else
-            Any
-          %b.caret
-        %ul.dropdown-menu
-          %li
-            = link_to project_filter_path(milestone_id: nil) do
-              Any
-            = link_to project_filter_path(milestone_id: 0) do
-              None (backlog)
-          - project_active_milestones.each do |milestone|
-            %li
-              = link_to project_filter_path(milestone_id: milestone.id) do
-                %strong= milestone.title
-                %small.light= milestone.expires_at
-
-      .pull-right
-        = render 'shared/sort_dropdown'
-
-    .panel.panel-default
-      %ul.well-list.mr-list
-        = render @merge_requests
-        - if @merge_requests.blank?
-          %li
-            .nothing-here-block No merge requests to show
-    - if @merge_requests.present?
-      .pull-right
-        %span.cgray.pull-right #{@merge_requests.total_count} merge requests for this filter
-
-      = paginate @merge_requests, theme: "gitlab"
-
-:javascript
-  $(merge_requestsPage);
+.append-bottom-10
+  .pull-right
+    = render 'shared/issuable_search_form', path: namespace_project_merge_requests_path(@project.namespace, @project)
+
+    - if can? current_user, :write_merge_request, @project
+      = link_to new_namespace_project_merge_request_path(@project.namespace, @project), class: "btn btn-new pull-left", title: "New Merge Request" do
+        %i.fa.fa-plus
+        New Merge Request
+  = render 'shared/issuable_filter'
+.merge-requests-holder
+  = render 'merge_requests'
diff --git a/app/views/projects/merge_requests/show/_commits.html.haml b/app/views/projects/merge_requests/show/_commits.html.haml
index a658740387114515ed851b1c51e5aa0622b04701..3b7f283daf0468774e60114d0c3490d26c71cefc 100644
--- a/app/views/projects/merge_requests/show/_commits.html.haml
+++ b/app/views/projects/merge_requests/show/_commits.html.haml
@@ -1,30 +1 @@
-- if @commits.present?
-  .panel.panel-default
-    .panel-heading
-      %i.fa.fa-list
-      Commits (#{@commits.count})
-    .commits.mr-commits
-      - if @commits.count > 8
-        %ul.first-commits.well-list
-          - @commits.first(8).each do |commit|
-            = render "projects/commits/commit", commit: commit, project: @merge_request.source_project
-          %li.bottom
-            8 of #{@commits.count} commits displayed.
-            %strong
-              %a.show-all-commits Click here to show all
-        - if @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
-          %ul.all-commits.hide.well-list
-            - @commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE).each do |commit|
-              = render "projects/commits/inline_commit", commit: commit, project: @merge_request.source_project
-            %li
-              other #{@commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE} commits hidden to prevent performance issues.
-        - else
-          %ul.all-commits.hide.well-list
-            - @commits.each do |commit|
-              = render "projects/commits/inline_commit", commit: commit, project: @merge_request.source_project
-
-      - else
-        %ul.well-list
-          - @commits.each do |commit|
-            = render "projects/commits/commit", commit: commit, project: @merge_request.source_project
-
+= render "projects/commits/commits", project: @merge_request.source_project
diff --git a/app/views/projects/merge_requests/show/_context.html.haml b/app/views/projects/merge_requests/show/_context.html.haml
index 089302e358828261cff70975820760bc2c8afb4f..105562fb05e31bfa02caae672989f52a1533ac7b 100644
--- a/app/views/projects/merge_requests/show/_context.html.haml
+++ b/app/views/projects/merge_requests/show/_context.html.haml
@@ -1,24 +1,48 @@
-= form_for [@project, @merge_request], remote: true, html: {class: 'edit-merge_request inline-update'} do |f|
-  .row
-    .col-sm-6
-      %strong.append-right-10
+= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], remote: true, html: {class: 'edit-merge_request inline-update'} do |f|
+  %div.prepend-top-20
+    .issuable-context-title
+      %label
         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)
+      - if @merge_request.assignee
+        %strong= link_to_member(@project, @merge_request.assignee, size: 24)
       - else
-        None
+        none
+    .issuable-context-selectbox
+      - if can?(current_user, :modify_merge_request, @merge_request)
+        = users_select_tag('merge_request[assignee_id]', placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: @merge_request.assignee_id, null_user: true)
 
-    .col-sm-6.text-right
-      %strong.append-right-10
+  %div.prepend-top-20.clearfix
+    .issuable-context-title
+      %label
         Milestone:
+      - if @merge_request.milestone
+        %span.back-to-milestone
+          = link_to namespace_project_milestone_path(@project.namespace, @project, @merge_request.milestone) do
+            %strong
+              %i.fa.fa-clock-o
+              = @merge_request.milestone.title
+      - else
+        none
+    .issuable-context-selectbox
       - if can?(current_user, :modify_merge_request, @merge_request)
         = f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'})
         = hidden_field_tag :merge_request_context
         = f.submit class: 'btn'
-      - elsif merge_request.milestone
-        = link_to merge_request.milestone.title, project_milestone_path
-      - else
-        None
+
+  - if current_user
+    %div.prepend-top-20.clearfix
+      .issuable-context-title
+        %label
+          Subscription:
+      %button.btn.btn-block.subscribe-button
+        %i.fa.fa-eye
+        %span= @merge_request.subscribed?(current_user) ? "Unsubscribe" : "Subscribe"
+      - subscribtion_status = @merge_request.subscribed?(current_user) ? "subscribed" : "unsubscribed"
+      .subscription-status{"data-status" => subscribtion_status}
+        .description-block.unsubscribed{class: ( "hidden" if @merge_request.subscribed?(current_user) )}
+          You're not receiving notifications from this thread.
+        .description-block.subscribed{class: ( "hidden" unless @merge_request.subscribed?(current_user) )}
+          You're receiving notifications because you're subscribed to this thread.
+
+:coffeescript
+  new Subscription("#{toggle_subscription_namespace_project_merge_request_path(@merge_request.project.namespace, @project, @merge_request)}")
diff --git a/app/views/projects/merge_requests/show/_diffs.html.haml b/app/views/projects/merge_requests/show/_diffs.html.haml
index d361c5f579ab41b33490c5f865195a2794afb268..786b5f39063327cf28f8dca26d3f89965b46f7cd 100644
--- a/app/views/projects/merge_requests/show/_diffs.html.haml
+++ b/app/views/projects/merge_requests/show/_diffs.html.haml
@@ -3,10 +3,10 @@
 - elsif @merge_request_diff.empty?
   .nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch}
 - else
-  .bs-callout.bs-callout-warning
+  .alert.alert-warning
     %h4
       Changes view for this comparison is extremely large.
     %p
       You can
-      = link_to "download it", project_merge_request_path(@merge_request.target_project, @merge_request, format: :diff), class: "vlink"
+      = link_to "download it", merge_request_path(@merge_request, format: :diff), class: "vlink"
       instead.
diff --git a/app/views/projects/merge_requests/show/_mr_accept.html.haml b/app/views/projects/merge_requests/show/_mr_accept.html.haml
index 4939ae039944c7cf93f30222721f51fbc4fbcd4f..9f51f84d40024e3f19be9df20b618119fe9bbfda 100644
--- a/app/views/projects/merge_requests/show/_mr_accept.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_accept.html.haml
@@ -12,28 +12,25 @@
 - if @show_merge_controls
   .automerge_widget.can_be_merged.hide
     .clearfix
-      = form_for [:automerge, @project, @merge_request], remote: true, method: :post do |f|
-        %h4
-          You can accept this request automatically.
-        .accept-merge-holder.clearfix
-          .accept-group
-            .pull-left
-              = f.submit "Accept Merge Request", class: "btn btn-create accept_merge_request"
-            - if can_remove_branch?(@merge_request.source_project, @merge_request.source_branch) && !@merge_request.for_fork?
-              .remove_branch_holder.pull-left
-                = label_tag :should_remove_source_branch, class: "checkbox" do
-                  = check_box_tag :should_remove_source_branch
-                  Remove source-branch
-            .js-toggle-container
-              %label
-                %i.fa.fa-edit
-                = link_to "modify merge commit message", "#", class: "modify-merge-commit-link js-toggle-button", title: "Modify merge commit message"
-              .js-toggle-content.hide
-                = render 'shared/commit_message_container', params: params,
-                    text: @merge_request.merge_commit_message,
-                    rows: 14, hint: true
+      = form_for [:automerge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post do |f|
+        .accept-merge-holder.clearfix.js-toggle-container
+          .accept-action
+            = f.submit "Accept Merge Request", class: "btn btn-create accept_merge_request"
+          - if can_remove_branch?(@merge_request.source_project, @merge_request.source_branch) && !@merge_request.for_fork?
+            .accept-control.checkbox
+              = label_tag :should_remove_source_branch, class: "remove_source_checkbox" do
+                = check_box_tag :should_remove_source_branch
+                Remove source-branch
+          .accept-control
+            = link_to "#", class: "modify-merge-commit-link js-toggle-button", title: "Modify merge commit message" do
+              %i.fa.fa-edit
+              Modify commit message
+          .js-toggle-content.hide.prepend-top-20
+            = render 'shared/commit_message_container', params: params,
+                text: @merge_request.merge_commit_message,
+                rows: 14, hint: true
 
-        %hr
+        %br
         .light
           If you still want to merge this request manually - use
           %strong
@@ -48,10 +45,17 @@
   .automerge_widget.cannot_be_merged.hide
     %h4
       This request can't be merged with GitLab.
-    %p
       You should do it manually with
       %strong
-        = link_to "command line", "#modal_merge_info", class: "how_to_merge_link", title: "How To Merge", "data-toggle" => "modal"
+        = link_to "#modal_merge_info", class: "underlined-link how_to_merge_link", title: "How To Merge", "data-toggle" => "modal" do
+          command line
+
+    %p
+      %button.btn.disabled
+        %i.fa.fa-warning
+        Accept Merge Request
+      &nbsp;
+      This usually happens when git can not resolve conflicts between branches automatically.
 
   .automerge_widget.unchecked
     %p
diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml
index 7e5a4eda508877ce7d5b02131b4a6d009ad6f850..ada9ae58b8f7d34905393b8a3f4d0d74be8ba5f8 100644
--- a/app/views/projects/merge_requests/show/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_box.html.haml
@@ -1,25 +1,9 @@
-.issue-box{ class: issue_box_class(@merge_request) }
-  .state.clearfix
-    .state-label
-      - if @merge_request.merged?
-        Merged
-      - elsif @merge_request.closed?
-        Closed
-      - else
-        Open
-
-    .creator
-      Created by #{link_to_member(@project, @merge_request.author)} #{time_ago_with_tooltip(@merge_request.created_at)}
-
-  %h4.title
-    = gfm escape_once(@merge_request.title)
+%h2.issue-title
+  = gfm escape_once(@merge_request.title)
 
+%div
   - if @merge_request.description.present?
     .description
       .wiki
         = preserve do
           = markdown(@merge_request.description, parse_tasks: true)
-
-  .context
-    %cite.cgray
-      = render partial: 'projects/merge_requests/show/context', locals: { merge_request: @merge_request }
diff --git a/app/views/projects/merge_requests/show/_mr_ci.html.haml b/app/views/projects/merge_requests/show/_mr_ci.html.haml
index 941b15d3b3272a218773109d7622a48a633f21fe..ffa3f7b0e36a120122527933f918f727056b69a7 100644
--- a/app/views/projects/merge_requests/show/_mr_ci.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_ci.html.haml
@@ -3,26 +3,32 @@
     %i.fa.fa-check
     %span CI build passed
     for #{@merge_request.last_commit_short_sha}.
-    = link_to "Build page", ci_build_details_path(@merge_request)
+    = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
 
 
   .ci_widget.ci-failed{style: "display:none"}
     %i.fa.fa-times
     %span CI build failed
     for #{@merge_request.last_commit_short_sha}.
-    = link_to "Build page", ci_build_details_path(@merge_request)
+    = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
 
   - [:running, :pending].each do |status|
     .ci_widget{class: "ci-#{status}", style: "display:none"}
       %i.fa.fa-clock-o
       %span CI build #{status}
       for #{@merge_request.last_commit_short_sha}.
-      = link_to "Build page", ci_build_details_path(@merge_request)
+      = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
 
   .ci_widget
     %i.fa.fa-spinner
     Checking for CI status for #{@merge_request.last_commit_short_sha}
 
+  .ci_widget.ci-canceled{style: "display:none"}
+    %i.fa.fa-times
+    %span CI build canceled
+    for #{@merge_request.last_commit_short_sha}.
+    = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
+
   .ci_widget.ci-error{style: "display:none"}
     %i.fa.fa-times
     %span Cannot connect to the CI server. Please check your settings and try again.
diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml
index 6fe765248e431d3e941e3c709564e22fdcce8d4b..46e92a9c55845956ab4172ba1df1f0055b037317 100644
--- a/app/views/projects/merge_requests/show/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_title.html.haml
@@ -1,45 +1,22 @@
-%h3.page-title
+%h4.page-title
+  .issue-box{ class: issue_box_class(@merge_request) }
+    - if @merge_request.merged?
+      Merged
+    - elsif @merge_request.closed?
+      Closed
+    - else
+      Open
   = "Merge Request ##{@merge_request.iid}"
+  %small.creator
+    &middot;
+    created by #{link_to_member(@project, @merge_request.author)} #{time_ago_with_tooltip(@merge_request.created_at)}
 
-  %span.pull-right.issue-btn-group
+  .issue-btn-group.pull-right
     - if can?(current_user, :modify_merge_request, @merge_request)
       - if @merge_request.open?
-        .btn-group.pull-left
-          %a.btn.btn-grouped.dropdown-toggle{ data: {toggle: :dropdown} }
-            %i.fa.fa-download
-            Download as
-            %span.caret
-          %ul.dropdown-menu
-            %li= link_to "Email Patches", project_merge_request_path(@project, @merge_request, format: :patch)
-            %li= link_to "Plain Diff",    project_merge_request_path(@project, @merge_request, format: :diff)
-
-        = link_to 'Close', project_merge_request_path(@project, @merge_request, merge_request: { state_event: :close }), method: :put, class: "btn btn-grouped btn-close", title: "Close merge request"
-
-        = link_to edit_project_merge_request_path(@project, @merge_request), class: "btn btn-grouped", id:"edit_merge_request" do
+        = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: "btn btn-grouped btn-close", title: "Close merge request"
+        = link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: "btn btn-grouped issuable-edit", id: "edit_merge_request" do
           %i.fa.fa-pencil-square-o
           Edit
       - if @merge_request.closed?
-        = link_to 'Reopen', project_merge_request_path(@project, @merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link", title: "Close merge request"
-
-.votes-holder.hidden-sm.hidden-xs
-  #votes= render 'votes/votes_block', votable: @merge_request
-
-.back-link
-  = link_to project_merge_requests_path(@project) do
-    &larr; To merge requests
-
-  %span.prepend-left-20
-    %span From
-    - if @merge_request.for_fork?
-      %strong.label-branch<
-        - if @merge_request.source_project
-          = link_to @merge_request.source_project_namespace, project_path(@merge_request.source_project)
-        - else
-          \ #{@merge_request.source_project_namespace}
-        \:#{@merge_request.source_branch}
-      %span into
-      %strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch}
-    - else
-      %strong.label-branch #{@merge_request.source_branch}
-      %span into
-      %strong.label-branch #{@merge_request.target_branch}
+        = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link", title: "Close merge request"
diff --git a/app/views/projects/merge_requests/show/_participants.html.haml b/app/views/projects/merge_requests/show/_participants.html.haml
index b709c89cec255e17e710b5aa1915fad1d3a64b99..4f34af1737dd93f236883cbad7416b08b5e06b21 100644
--- a/app/views/projects/merge_requests/show/_participants.html.haml
+++ b/app/views/projects/merge_requests/show/_participants.html.haml
@@ -1,9 +1,4 @@
 .participants
-  %cite.cgray #{@merge_request.participants.count} participants
+  %span #{@merge_request.participants.count} participants
   - @merge_request.participants.each do |participant|
     = link_to_member(@project, participant, name: false, size: 24)
-
-  .merge-request-show-labels.pull-right
-    - @merge_request.labels.each do |label|
-      = link_to project_merge_requests_path(@project, label_name: label.name) do
-        = render_colored_label(label)
diff --git a/app/views/projects/merge_requests/show/_remove_source_branch.html.haml b/app/views/projects/merge_requests/show/_remove_source_branch.html.haml
index 4fe5935bcf387f3bd775aa6dfab7caa902500188..59cb85edfce11b934d39718c9500c9aea963c101 100644
--- a/app/views/projects/merge_requests/show/_remove_source_branch.html.haml
+++ b/app/views/projects/merge_requests/show/_remove_source_branch.html.haml
@@ -4,7 +4,7 @@
 - elsif can_remove_branch?(@merge_request.source_project, @merge_request.source_branch) && @merge_request.merged?
   .remove_source_branch_widget
     %p Changes merged into #{@merge_request.target_branch}. You can remove source branch now
-    = link_to project_branch_path(@merge_request.source_project, @source_branch), remote: true, method: :delete, class: "btn btn-primary btn-small remove_source_branch" do
+    = link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @source_branch), remote: true, method: :delete, class: "btn btn-primary btn-sm remove_source_branch" do
       %i.fa.fa-times
       Remove Source Branch
 
@@ -12,6 +12,6 @@
     Failed to remove source branch '#{@merge_request.source_branch}'
 
   .remove_source_branch_in_progress.hide
-    %i.fa.fa-refresh.fa-spin
+    %i.fa.fa-spinner.fa-spin
     &nbsp;
     Removing source branch '#{@merge_request.source_branch}'. Please wait. Page will be automatically reloaded. &nbsp;
diff --git a/app/views/projects/merge_requests/show/_state_widget.html.haml b/app/views/projects/merge_requests/show/_state_widget.html.haml
index 87dad6140be3bf745e0639fb7d999ab0cb862e4b..44bd9347f514568c34b31d9c8c6f7b85e0abd8d6 100644
--- a/app/views/projects/merge_requests/show/_state_widget.html.haml
+++ b/app/views/projects/merge_requests/show/_state_widget.html.haml
@@ -11,21 +11,25 @@
 
     - if @merge_request.closed?
       %h4
-        Closed by #{link_to_member(@project, @merge_request.closed_event.author, avatar: false)}
-        #{time_ago_with_tooltip(@merge_request.closed_event.created_at)}
+        Closed
+        - if @merge_request.closed_event
+          by #{link_to_member(@project, @merge_request.closed_event.author, avatar: false)}
+          #{time_ago_with_tooltip(@merge_request.closed_event.created_at)}
       %p Changes were not merged into target branch
 
     - if @merge_request.merged?
       %h4
-        Merged by #{link_to_member(@project, @merge_request.merge_event.author, avatar: false)}
-        #{time_ago_with_tooltip(@merge_request.merge_event.created_at)}
+        Merged
+        - if @merge_request.merge_event
+          by #{link_to_member(@project, @merge_request.merge_event.author, avatar: false)}
+          #{time_ago_with_tooltip(@merge_request.merge_event.created_at)}
       = render "projects/merge_requests/show/remove_source_branch"
 
     - if @merge_request.locked?
       %h4
         Merge in progress...
       %p
-        GitLab tries to merge it right now. During this time merge request is locked and can not be closed.
+        Merging is in progress. While merging this request is locked and cannot be closed.
 
     - unless @commits.any?
       %h4 Nothing to merge
@@ -44,4 +48,3 @@
         Accepting this merge request will close #{@closes_issues.size == 1 ? 'issue' : 'issues'}
         = succeed '.' do
           != gfm(issues_sentence(@closes_issues))
-
diff --git a/app/views/projects/merge_requests/update.js.haml b/app/views/projects/merge_requests/update.js.haml
index 6452cc6382dbddaf31c9a107037770ab7bfae499..b4df1d20737468718827d968170df1696c4bb043 100644
--- a/app/views/projects/merge_requests/update.js.haml
+++ b/app/views/projects/merge_requests/update.js.haml
@@ -1,2 +1,8 @@
 - if params[:merge_request_context]
-  $('.issue-box .context').effect('highlight');
+  $('.context').html("#{escape_javascript(render partial: 'projects/merge_requests/show/context', locals: { issue: @issue })}");
+  $('.context').effect('highlight');
+
+  new UsersSelect()
+
+  $('select.select2').select2({width: 'resolve', dropdownAutoWidth: true});
+  merge_request = new MergeRequest();
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index 5fb01a11cc5afb0977fcad64f36e23d6cb000e23..95b7070ce5c55396029bba3488f64917e8741f6d 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -1,11 +1,11 @@
 %h3.page-title= @milestone.new_record? ? "New Milestone" : "Edit Milestone ##{@milestone.iid}"
 .back-link
-  = link_to project_milestones_path(@project) do
+  = link_to namespace_project_milestones_path(@project.namespace, @project) do
     &larr; To milestones
 
 %hr
 
-= form_for [@project, @milestone], html: {class: 'form-horizontal milestone-form gfm-form'}  do |f|
+= form_for [@project.namespace.becomes(Namespace), @project, @milestone], html: {class: 'form-horizontal milestone-form gfm-form'}  do |f|
   -if @milestone.errors.any?
     .alert.alert-danger
       %ul
@@ -18,13 +18,14 @@
         .col-sm-10
           = f.text_field :title, maxlength: 255, class: "form-control"
           %p.hint Required
-      .form-group
+      .form-group.milestone-description
         = f.label :description, "Description", class: "control-label"
         .col-sm-10
-          = render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
-          .hint
-            .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
-            .pull-left Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
+          = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do
+            = render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
+            .hint
+              .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
+              .pull-left Attach files by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
           .clearfix
           .error-alert
     .col-md-6
@@ -37,10 +38,10 @@
   .form-actions
     - if @milestone.new_record?
       = f.submit 'Create milestone', class: "btn-create btn"
-      = link_to "Cancel", project_milestones_path(@project), class: "btn btn-cancel"
+      = link_to "Cancel", namespace_project_milestones_path(@project.namespace, @project), class: "btn btn-cancel"
     -else
       = f.submit 'Save changes', class: "btn-save btn"
-      = link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn btn-cancel"
+      = link_to "Cancel", namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-cancel"
 
 
 :javascript
@@ -50,4 +51,4 @@
     onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }
   }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val()));
 
-  window.project_image_path_upload = "#{upload_image_project_path @project}";
+  window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
diff --git a/app/views/projects/milestones/_issue.html.haml b/app/views/projects/milestones/_issue.html.haml
index b5ec0fc98821cc51139d9da234f936bc832dc3dc..26c83841a222a59b88dc2bd09a323a2eda6a06ba 100644
--- a/app/views/projects/milestones/_issue.html.haml
+++ b/app/views/projects/milestones/_issue.html.haml
@@ -1,8 +1,8 @@
-%li{ id: dom_id(issue, 'sortable'), class: 'issue-row', 'data-iid' => issue.iid, 'data-url' => project_issue_path(@project, issue) }
+%li{ id: dom_id(issue, 'sortable'), class: 'issue-row', 'data-iid' => issue.iid, 'data-url' => issue_path(issue) }
   %span.str-truncated
-    = link_to [@project, issue] do
+    = link_to [@project.namespace.becomes(Namespace), @project, issue] do
       %span.cgray ##{issue.iid}
-    = link_to_gfm issue.title, [@project, issue], title: issue.title
+    = link_to_gfm issue.title, [@project.namespace.becomes(Namespace), @project, issue], title: issue.title
   .pull-right.assignee-icon
     - if issue.assignee
       = image_tag avatar_icon(issue.assignee.email, 16), class: "avatar s16"
diff --git a/app/views/projects/milestones/_merge_request.html.haml b/app/views/projects/milestones/_merge_request.html.haml
index d54cb3f8e74168d05b806d438ec7501f06489ada..42fbd0cd2caaccc22686742c5f09c2b784121ba8 100644
--- a/app/views/projects/milestones/_merge_request.html.haml
+++ b/app/views/projects/milestones/_merge_request.html.haml
@@ -1,5 +1,8 @@
-%li{ id: dom_id(merge_request, 'sortable'),  class: 'mr-row', 'data-iid' => merge_request.iid, 'data-url' => project_merge_request_path(@project, merge_request) }
+%li{ id: dom_id(merge_request, 'sortable'),  class: 'mr-row', 'data-iid' => merge_request.iid, 'data-url' => merge_request_path(merge_request) }
   %span.str-truncated
-    = link_to [@project, merge_request] do
+    = link_to [@project.namespace.becomes(Namespace), @project, merge_request] do
       %span.cgray ##{merge_request.iid}
-    = link_to_gfm merge_request.title, [@project, merge_request], title: merge_request.title
+    = link_to_gfm merge_request.title, [@project.namespace.becomes(Namespace), @project, merge_request], title: merge_request.title
+  .pull-right.assignee-icon
+    - if merge_request.assignee
+      = image_tag avatar_icon(merge_request.assignee.email, 16), class: "avatar s16"
diff --git a/app/views/projects/milestones/_milestone.html.haml b/app/views/projects/milestones/_milestone.html.haml
index 1002b9513ff89bbdbfe5ee9c7d57f2dbca67ff74..7039c85bb2c4e6f1fb7b2ef17553459fb95d90dc 100644
--- a/app/views/projects/milestones/_milestone.html.haml
+++ b/app/views/projects/milestones/_milestone.html.haml
@@ -1,12 +1,12 @@
 %li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone) }
   .pull-right
     - if can?(current_user, :admin_milestone, milestone.project) and milestone.active?
-      = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link btn-grouped" do
+      = link_to edit_namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), class: "btn btn-sm edit-milestone-link btn-grouped" do
         %i.fa.fa-pencil-square-o
         Edit
-      = link_to 'Close Milestone', project_milestone_path(@project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-small btn-close"
+      = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-sm btn-close"
   %h4
-    = link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone)
+    = link_to_gfm truncate(milestone.title, length: 100), namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
     - if milestone.expired? and not milestone.closed?
       %span.cred (Expired)
     %small
@@ -16,12 +16,11 @@
   - else
     %div
       %div
-        = link_to project_issues_path(milestone.project, milestone_id: milestone.id) do
+        = link_to namespace_project_issues_path(milestone.project.namespace, milestone.project, milestone_id: milestone.id) do
           = pluralize milestone.issues.count, 'Issue'
         &nbsp;
-        = link_to project_merge_requests_path(milestone.project, milestone_id: milestone.id) do
+        = link_to namespace_project_merge_requests_path(milestone.project.namespace, milestone.project, milestone_id: milestone.id) do
           = pluralize milestone.merge_requests.count, 'Merge Request'
         &nbsp;
         %span.light #{milestone.percent_complete}% complete
-      .progress.progress-info
-        .progress-bar{style: "width: #{milestone.percent_complete}%;"}
+      = milestone_progress_bar(milestone)
diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml
index 03367b7cdbfc534b59ef16038a8bf021a87be75a..d3eab8d6d7509d19cb1bba0bda2959999fc5974c 100644
--- a/app/views/projects/milestones/index.html.haml
+++ b/app/views/projects/milestones/index.html.haml
@@ -1,33 +1,17 @@
-= render "projects/issues/head"
-.milestones_content
-  %h3.page-title
-    Milestones
-    - if can? current_user, :admin_milestone, @project
-      = link_to new_project_milestone_path(@project), class: "pull-right btn btn-new", title: "New Milestone" do
-        %i.fa.fa-plus
-        New Milestone
+.pull-right
+  - if can? current_user, :admin_milestone, @project
+    = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "New Milestone" do
+      %i.fa.fa-plus
+      New Milestone
+= render 'shared/milestones_filter'
 
-  .row
-    .fixed.sidebar-expand-button.hidden-lg.hidden-md.hidden-xs
-      %i.fa.fa-list.fa-2x
-    .col-md-3.responsive-side
-      %ul.nav.nav-pills.nav-stacked
-        %li{class: ("active" if (params[:f] == "active" || !params[:f]))}
-          = link_to project_milestones_path(@project, f: "active") do
-            Active
-        %li{class: ("active" if params[:f] == "closed")}
-          = link_to project_milestones_path(@project, f: "closed") do
-            Closed
-        %li{class: ("active" if params[:f] == "all")}
-          = link_to project_milestones_path(@project, f: "all") do
-            All
-    .col-md-9
-      .panel.panel-default
-        %ul.well-list
-          = render @milestones
+.milestones
+  .panel.panel-default
+    %ul.well-list
+      = render @milestones
 
-          - if @milestones.blank?
-            %li
-              .nothing-here-block No milestones to show
+      - if @milestones.blank?
+        %li
+          .nothing-here-block No milestones to show
 
-      = paginate @milestones, theme: "gitlab"
+  = paginate @milestones, theme: "gitlab"
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 8263f7530a2507c5e2cd3b552a04091f370bc452..25cc00309658282dd2b31ce9c5942676f76fdd60 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -1,57 +1,49 @@
-= render "projects/issues/head"
-%h3.page-title
+%h4.page-title
+  .issue-box{ class: issue_box_class(@milestone) }
+    - if @milestone.closed?
+      Closed
+    - elsif @milestone.expired?
+      Expired
+    - else
+      Open
   Milestone ##{@milestone.iid}
+  %small.creator
+    = @milestone.expires_at
   .pull-right
     - if can?(current_user, :admin_milestone, @project)
-      = link_to edit_project_milestone_path(@project, @milestone), class: "btn btn-grouped" do
+      = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped" do
         %i.fa.fa-pencil-square-o
         Edit
       - if @milestone.active?
-        = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped"
+        = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped"
       - else
-        = link_to 'Reopen Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped"
+        = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped"
 
+%hr
 - if @milestone.issues.any? && @milestone.can_be_closed?
   .alert.alert-success
     %span All issues for this milestone are closed. You may close milestone now.
 
-.back-link
-  = link_to project_milestones_path(@project) do
-    &larr; To milestones list
-
-
-.issue-box{ class: issue_box_class(@milestone) }
-  .state.clearfix
-    .state-label
-      - if @milestone.closed?
-        Closed
-      - elsif @milestone.expired?
-        Expired
-      - else
-        Open
-    .creator
-      = @milestone.expires_at
-
-  %h4.title
-    = gfm escape_once(@milestone.title)
-
+%h3.issue-title
+  = gfm escape_once(@milestone.title)
+%div
   - if @milestone.description.present?
     .description
       .wiki
         = preserve do
           = markdown @milestone.description
 
-  .context
-    %p
-      Progress:
-      #{@milestone.closed_items_count} closed
-      &ndash;
-      #{@milestone.open_items_count} open
-      &nbsp;
-      %span.light #{@milestone.percent_complete}% complete
-      %span.pull-right= @milestone.expires_at
-    .progress.progress-info
-      .progress-bar{style: "width: #{@milestone.percent_complete}%;"}
+%hr
+.context
+  %p.lead
+    Progress:
+    #{@milestone.closed_items_count} closed
+    &ndash;
+    #{@milestone.open_items_count} open
+    &nbsp;
+    %span.light #{@milestone.percent_complete}% complete
+    %span.pull-right= @milestone.expires_at
+  = milestone_progress_bar(@milestone)
 
 
 %ul.nav.nav-tabs
@@ -68,11 +60,12 @@
       Participants
       %span.badge= @users.count
 
-  .pull-right
-    = link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn btn-small btn-grouped", title: "New Issue" do
-      %i.fa.fa-plus
-      New Issue
-    = link_to 'Browse Issues', project_issues_path(@milestone.project, milestone_id: @milestone.id), class: "btn btn-small edit-milestone-link btn-grouped"
+  - if @project.issues_enabled
+    .pull-right
+      = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { milestone_id: @milestone.id }), class: "btn  btn-grouped", title: "New Issue" do
+        %i.fa.fa-plus
+        New Issue
+      = link_to 'Browse Issues', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_id: @milestone.id), class: "btn  edit-milestone-link btn-grouped"
 
 .tab-content
   .tab-pane.active#tab-issues
diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml
index 4a21b84fb851064db34af4e7d639441ccc98cf20..c36bad1e94b6096af8c2e0b0b056aec3e330a6d2 100644
--- a/app/views/projects/network/show.html.haml
+++ b/app/views/projects/network/show.html.haml
@@ -1,7 +1,7 @@
 = render "head"
 .project-network
   .controls
-    = form_tag project_network_path(@project, @id), method: :get, class: 'form-inline network-form' do |f|
+    = form_tag namespace_project_network_path(@project.namespace, @project, @id), method: :get, class: 'form-inline network-form' do |f|
       = text_field_tag :extended_sha1, @options[:extended_sha1], placeholder: "Input an extended SHA1 syntax", class: 'search-input form-control input-mx-250 search-sha'
       = button_tag class: 'btn btn-success btn-search-sha' do
         %i.fa.fa-search
@@ -18,8 +18,8 @@
   disableButtonIfEmptyField('#extended_sha1', '.btn-search-sha')
 
   network_graph = new Network({
-    url: '#{project_network_path(@project, @ref, @options.merge(format: :json))}',
-    commit_url: '#{project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s")}',
+    url: '#{namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json))}',
+    commit_url: '#{namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s")}',
     ref: '#{@ref}',
     commit_id: '#{@commit.id}'
   })
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index f5cd0f21e013814a75bdb0a07c60742bcd4955d3..69909a8554e8325d88da6bc5da0a78e254db0a8f 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -3,12 +3,15 @@
     = render 'projects/errors'
   .project-edit-content
 
-    = form_for @project, remote: true, html: { class: 'new_project form-horizontal' } do |f|
+    = form_for @project, html: { class: 'new_project form-horizontal' } do |f|
       .form-group.project-name-holder
-        = f.label :name, class: 'control-label' do
-          %strong Project name
+        = f.label :path, class: 'control-label' do
+          %strong Project path
         .col-sm-10
-          = f.text_field :name, placeholder: "Example Project", class: "form-control", tabindex: 1, autofocus: true
+          .input-group
+            = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 1, autofocus: true
+            .input-group-addon
+              \.git
 
       - if current_user.can_select_namespace?
         .form-group
@@ -18,41 +21,67 @@
             = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'select2', tabindex: 2}
 
       %hr
-      .js-toggle-container
-        .form-group
-          .col-sm-2
-          .col-sm-10
-            = link_to "#", class: 'js-toggle-button' do
-              %i.fa.fa-pencil-square-o
-              %span Customize repository name?
-        .js-toggle-content.hide
-          .form-group
-            = f.label :path, class: 'control-label' do
-              %span Repository name
-            .col-sm-10
-              .input-group
-                = f.text_field :path, class: 'form-control'
-                %span.input-group-addon .git
 
-      .js-toggle-container
+      .project-import.js-toggle-container
         .form-group
-          .col-sm-2
+          %label.control-label Import project from
           .col-sm-10
-            = link_to "#", class: 'js-toggle-button' do
-              %i.fa.fa-upload
-              %span Import existing repository?
+            - if github_import_enabled?
+              = link_to status_import_github_path, class: 'btn' do
+                %i.fa.fa-github
+                GitHub
+            - else
+              = link_to '#', class: 'how_to_import_link light btn' do
+                %i.fa.fa-github
+                GitHub
+              = render 'github_import_modal'
+
+
+            - if bitbucket_import_enabled?
+              = link_to status_import_bitbucket_path, class: 'btn' do
+                %i.fa.fa-bitbucket
+                Bitbucket
+            - else
+              = link_to '#', class: 'how_to_import_link light btn' do
+                %i.fa.fa-bitbucket
+                Bitbucket
+              = render 'bitbucket_import_modal'
+
+            - unless request.host == 'gitlab.com'
+              - if gitlab_import_enabled?
+                = link_to status_import_gitlab_path, class: 'btn' do
+                  %i.fa.fa-heart
+                  GitLab.com
+              - else
+                = link_to '#', class: 'how_to_import_link light btn' do
+                  %i.fa.fa-heart
+                  GitLab.com
+                = render 'gitlab_import_modal'
+
+            = link_to new_import_gitorious_path, class: 'btn' do
+              %i.icon-gitorious.icon-gitorious-small
+              Gitorious.org
+
+            = link_to "#", class: 'btn js-toggle-button' do
+              %i.fa.fa-git
+              %span Any repo by URL
+
         .js-toggle-content.hide
           .form-group.import-url-data
             = f.label :import_url, class: 'control-label' do
-              %span Import existing git repo
+              %span Git repository URL
             .col-sm-10
-              = f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git'
-              .bs-callout.bs-callout-info
-                This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git.
-                %br
-                The import will time out after 4 minutes. For big repositories, use a clone/push combination.
-                For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}
-      %hr
+              = f.text_field :import_url, class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git'
+              .well.prepend-top-20
+                %ul
+                  %li
+                    The repository must be accessible over HTTP(S). If it is not publicly accessible, you can add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>.
+                  %li
+                    The import will time out after 4 minutes. For big repositories, use a clone/push combination.
+                  %li
+                    To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}.
+
+      %hr.prepend-botton-10
 
       .form-group
         = f.label :description, class: 'control-label' do
@@ -69,7 +98,7 @@
           .pull-right
             .light
               Need a group for several dependent projects?
-              = link_to new_group_path, class: "btn btn-tiny" do
+              = link_to new_group_path, class: "btn btn-xs" do
                 Create a group
 
 .save-project-loader.hide
@@ -78,3 +107,10 @@
       %i.fa.fa-spinner.fa-spin
       Creating project &amp; repository.
     %p Please wait a moment, this page will automatically refresh when ready.
+
+:coffeescript
+  $('.how_to_import_link').bind 'click', (e) ->
+    e.preventDefault()
+    import_modal = $(this).next(".modal").show()
+  $('.modal-header .close').bind 'click', ->
+    $(".modal").hide()
diff --git a/app/views/projects/new_tree/show.html.haml b/app/views/projects/new_tree/show.html.haml
deleted file mode 100644
index f09d3659774510cb2a5dd0bc90c0ab775e12b9b7..0000000000000000000000000000000000000000
--- a/app/views/projects/new_tree/show.html.haml
+++ /dev/null
@@ -1,43 +0,0 @@
-%h3.page-title New file
-%hr
-.file-editor
-  = form_tag(project_new_tree_path(@project, @id), method: :put, class: 'form-horizontal form-new-file') do
-    .form-group.commit_message-group
-      = label_tag 'file_name', class: 'control-label' do
-        File name
-      .col-sm-10
-        .input-group
-          %span.input-group-addon
-            = @path[-1] == "/" ? @path : @path + "/"
-          = text_field_tag 'file_name', params[:file_name], placeholder: "sample.rb", required: true, class: 'form-control'
-          %span.input-group-addon
-            on
-            %span= @ref
-
-    .form-group.commit_message-group
-      = label_tag :encoding, class: "control-label" do
-        Encoding
-      .col-sm-10
-        = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'form-control'
-    .file-holder
-      .file-title
-        %i.fa.fa-file
-      .file-content.code
-        %pre#editor= params[:content]
-
-    = render 'shared/commit_message_container', params: params,
-             placeholder: 'Add new file'
-    = hidden_field_tag 'content', '', id: 'file-content'
-    = render 'projects/commit_button', ref: @ref,
-              cancel_path: project_tree_path(@project, @id)
-
-:javascript
-  ace.config.set("modePath", gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}/ace-src-noconflict")
-  var editor = ace.edit("editor");
-
-  disableButtonIfAnyEmptyField($('.form-new-file'), '.form-control', '.btn-create')
-
-  $(".js-commit-button").click(function(){
-    $("#file-content").val(editor.getValue());
-    $(".file-editor form").submit();
-  });
diff --git a/app/views/projects/no_repo.html.haml b/app/views/projects/no_repo.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..720957e8336a1cc4ec51c05fdc0dce7ef7e1eeda
--- /dev/null
+++ b/app/views/projects/no_repo.html.haml
@@ -0,0 +1,22 @@
+%h2
+  %i.fa.fa-warning
+  No repository
+
+%p.slead
+  The repository for this project does not exist.
+  %br
+  This means you can not push code until you create an empty repository or import existing one.
+%hr
+
+.no-repo-actions
+  = link_to namespace_project_repository_path(@project.namespace, @project), method: :post, class: 'btn btn-primary' do
+    Create empty bare repository
+
+  %strong.prepend-left-10.append-right-10 or
+
+  = link_to new_namespace_project_import_path(@project.namespace, @project), class: 'btn' do
+    Import repository
+
+- if can? current_user, :remove_project, @project
+  .prepend-top-20
+    = link_to 'Remove project', project_path(@project), data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right"
diff --git a/app/views/projects/notes/_discussion.html.haml b/app/views/projects/notes/_discussion.html.haml
index f4c6fad2fed0c3e8a089620801743f10e49aa903..3561ca49f8179c2c30a375a00c0c9a513412ecda 100644
--- a/app/views/projects/notes/_discussion.html.haml
+++ b/app/views/projects/notes/_discussion.html.haml
@@ -2,7 +2,8 @@
 .timeline-entry
   .timeline-entry-inner
     .timeline-icon
-      = image_tag avatar_icon(note.author_email), class: "avatar s40"
+      = link_to user_path(note.author) do
+        = image_tag avatar_icon(note.author_email), class: "avatar s40"
     .timeline-content
       - if note.for_merge_request?
         - if note.outdated?
diff --git a/app/views/projects/notes/_edit_form.html.haml b/app/views/projects/notes/_edit_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..acb3991d2946a523d3d8e8b88ce48e4f6cbef87a
--- /dev/null
+++ b/app/views/projects/notes/_edit_form.html.haml
@@ -0,0 +1,15 @@
+.note-edit-form
+  = form_for note, url: namespace_project_note_path(@project.namespace, @project, note), method: :put, remote: true, authenticity_token: true do |f|
+    = note_target_fields(note)
+    = render layout: 'projects/md_preview', locals: { preview_class: "note-text" } do
+      = render 'projects/zen', f: f, attr: :note,
+        classes: 'note_text js-note-text'
+
+      .comment-hints.clearfix
+        .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }}
+        .pull-right Attach files by dragging &amp; dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }.
+
+    .note-form-actions
+      .buttons
+        = f.submit 'Save Comment', class: "btn btn-primary btn-save btn-grouped js-comment-button"
+        = link_to  'Cancel', "#", class: "btn btn-cancel note-edit-cancel"
\ No newline at end of file
diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml
index c68b3817e79601f8dd6c085bd5b246c59c4e6d59..be96c302143cba44cf1c97163d98128d74672b53 100644
--- a/app/views/projects/notes/_form.html.haml
+++ b/app/views/projects/notes/_form.html.haml
@@ -1,27 +1,18 @@
-= form_for [@project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form common-note-form gfm-form" }, authenticity_token: true do |f|
-  = note_target_fields
+= form_for [@project.namespace.becomes(Namespace), @project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form common-note-form gfm-form" }, authenticity_token: true do |f|
+  = note_target_fields(@note)
   = f.hidden_field :commit_id
   = f.hidden_field :line_code
   = f.hidden_field :noteable_id
   = f.hidden_field :noteable_type
 
-  %ul.nav.nav-tabs
-    %li.active
-      = link_to '#note-write-holder', class: 'js-note-write-button' do
-        Write
-    %li
-      = link_to '#note-preview-holder', class: 'js-note-preview-button', data: { url: preview_project_notes_path(@project) } do
-        Preview
-  %div
-    .note-write-holder
-      = render 'projects/zen', f: f, attr: :note,
-                               classes: 'note_text js-note-text'
-      .light.clearfix
-        .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }}
-        .pull-right Attach images (JPG, PNG, GIF) by dragging &amp; dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }.
+  = render layout: 'projects/md_preview', locals: { preview_class: "note-text" } do
+    = render 'projects/zen', f: f, attr: :note,
+      classes: 'note_text js-note-text'
+
+    .comment-hints.clearfix
+      .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }}
+      .pull-right Attach files by dragging &amp; dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }.
 
-    .note-preview-holder.hide
-      .js-note-preview
 
   .note-form-actions
     .buttons
@@ -29,13 +20,5 @@
       = yield(:note_actions)
       %a.btn.grouped.js-close-discussion-note-form Cancel
 
-    .note-form-option
-      %a.choose-btn.btn.js-choose-note-attachment-button
-        %i.fa.fa-paperclip
-        %span Choose File ...
-      &nbsp;
-      %span.file_name.js-attachment-filename File name...
-      = f.file_field :attachment, class: "js-note-attachment-input hidden"
-
 :javascript
-  window.project_image_path_upload = "#{upload_image_project_path @project}";
+  window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index a25c5e207fb174960f962f24c9692b99acacbe62..71bdf5c8f2a0ad1168792de3a5b02779928fc84b 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -1,7 +1,11 @@
-%li.timeline-entry{ id: dom_id(note), class: dom_class(note), data: { discussion: note.discussion_id } }
+%li.timeline-entry{ id: dom_id(note), class: [dom_class(note), "note-row-#{note.id}", ('system-note' if note.system)], data: { discussion: note.discussion_id } }
   .timeline-entry-inner
     .timeline-icon
-      = image_tag avatar_icon(note.author_email), class: "avatar s40"
+      - if note.system
+        %span.fa.fa-circle
+      - else
+        = link_to user_path(note.author) do
+          = image_tag avatar_icon(note.author_email), class: "avatar s40"
     .timeline-content
       .note-header
         .note-actions
@@ -14,56 +18,54 @@
               %i.fa.fa-pencil-square-o
               Edit
             &nbsp;
-            = link_to project_note_path(@project, note), title: "Remove comment", method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: "danger js-note-delete" do
+            = link_to namespace_project_note_path(@project.namespace, @project, note), title: "Remove comment", method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: "danger js-note-delete" do
               %i.fa.fa-trash-o.cred
               Remove
+        - if note.system
+          = link_to user_path(note.author) do
+            = image_tag avatar_icon(note.author_email), class: "avatar s16"
         = link_to_member(@project, note.author, avatar: false)
+        %span.author-username
+          = '@' + note.author.username
         %span.note-last-update
           = note_timestamp(note)
 
-        - if note.upvote?
-          %span.vote.upvote.label.label-success
-            %i.fa.fa-thumbs-up
-            \+1
-        - if note.downvote?
-          %span.vote.downvote.label.label-danger
-            %i.fa.fa-thumbs-down
-            \-1
+        - if note.superceded?(@notes)
+          - if note.upvote?
+            %span.vote.upvote.label.label-gray.strikethrough
+              %i.fa.fa-thumbs-up
+              \+1
+          - if note.downvote?
+            %span.vote.downvote.label.label-gray.strikethrough
+              %i.fa.fa-thumbs-down
+              \-1
+        - else
+          - if note.upvote?
+            %span.vote.upvote.label.label-success
+              %i.fa.fa-thumbs-up
+              \+1
+          - if note.downvote?
+            %span.vote.downvote.label.label-danger
+              %i.fa.fa-thumbs-down
+              \-1
 
 
       .note-body
         .note-text
           = preserve do
             = markdown(note.note, {no_header_anchors: true})
-
-        .note-edit-form
-          = form_for note, url: project_note_path(@project, note), method: :put, remote: true, authenticity_token: true do |f|
-            = f.text_area :note, class: 'note_text js-note-text js-gfm-input turn-on'
-
-            .form-actions.clearfix
-              = f.submit 'Save changes', class: "btn btn-primary btn-save js-comment-button"
-
-              .note-form-option
-                %a.choose-btn.btn.js-choose-note-attachment-button
-                  %i.fa.fa-paperclip
-                  %span Choose File ...
-                &nbsp;
-                %span.file_name.js-attachment-filename File name...
-                = f.file_field :attachment, class: "js-note-attachment-input hidden"
-
-              = link_to  'Cancel', "#", class: "btn btn-cancel note-edit-cancel"
-
+        = render 'projects/notes/edit_form', note: note
 
       - if note.attachment.url
         .note-attachment
           - if note.attachment.image?
-            = link_to note.attachment.secure_url, target: '_blank' do
-              = image_tag note.attachment.secure_url, class: 'note-image-attach'
+            = link_to note.attachment.url, target: '_blank' do
+              = image_tag note.attachment.url, class: 'note-image-attach'
           .attachment
-            = link_to note.attachment.secure_url, target: "_blank" do
+            = link_to note.attachment.url, target: "_blank" do
               %i.fa.fa-paperclip
               = note.attachment_identifier
-              = link_to delete_attachment_project_note_path(@project, note),
+              = link_to delete_attachment_namespace_project_note_path(@project.namespace, @project, note),
                 title: "Delete this attachment", method: :delete, remote: true, data: { confirm: 'Are you sure you want to remove the attachment?' }, class: "danger js-note-attachment-delete" do
                 %i.fa.fa-trash-o.cred
       .clear
diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml
index 04ee17a40a0e6a17dd5904ffdea05c89afcce052..813e37276bdd8ec5fda2bad1f678a64069bedb25 100644
--- a/app/views/projects/notes/_notes_with_form.html.haml
+++ b/app/views/projects/notes/_notes_with_form.html.haml
@@ -7,4 +7,4 @@
   = render "projects/notes/form"
 
 :javascript
-  new Notes("#{project_notes_path(target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i})
+  new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i})
diff --git a/app/views/projects/notes/discussions/_active.html.haml b/app/views/projects/notes/discussions/_active.html.haml
index 52c06ec172d879e3fd45c9a9f75af014113e6700..7c6f72431730a42361fa2225df776aaed3e4bf68 100644
--- a/app/views/projects/notes/discussions/_active.html.haml
+++ b/app/views/projects/notes/discussions/_active.html.haml
@@ -8,7 +8,7 @@
     %div
       = link_to_member(@project, note.author, avatar: false)
       started a discussion
-      = link_to diffs_project_merge_request_path(note.project, note.noteable, anchor: note.line_code) do
+      = link_to diffs_namespace_project_merge_request_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code) do
         %strong on the diff
     .last-update.hide.js-toggle-content
       - last_note = discussion_notes.last
diff --git a/app/views/projects/notes/discussions/_commit.html.haml b/app/views/projects/notes/discussions/_commit.html.haml
index 94f16a5f02e78947fa6435100c4bafdf9ed23d3a..62609cfc1c8858d395a2e91b61c0921aaf0d7606 100644
--- a/app/views/projects/notes/discussions/_commit.html.haml
+++ b/app/views/projects/notes/discussions/_commit.html.haml
@@ -8,7 +8,7 @@
     %div
       = link_to_member(@project, note.author, avatar: false)
       started a discussion on commit
-      = link_to(note.noteable.short_id, project_commit_path(note.project, note.noteable), class: 'monospace')
+      = link_to(note.noteable.short_id, namespace_project_commit_path(note.project.namespace, note.project, note.noteable), class: 'monospace')
     .last-update.hide.js-toggle-content
       - last_note = discussion_notes.last
       last updated by
diff --git a/app/views/projects/notes/discussions/_diff.html.haml b/app/views/projects/notes/discussions/_diff.html.haml
index b4d1cce7980dd866121f7653ee53a7d5e6904fa0..711aa39101b865a3c1008ba8b89c40b1d68f74e4 100644
--- a/app/views/projects/notes/discussions/_diff.html.haml
+++ b/app/views/projects/notes/discussions/_diff.html.haml
@@ -2,13 +2,13 @@
 - if diff
   .diff-file
     .diff-header
-      - if diff.deleted_file
-        %span= diff.old_path
-      - else
-        %span= diff.new_path
-        - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
-          %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
-      %br/
+      %span
+        - if diff.deleted_file
+          = diff.old_path
+        - else
+          = diff.new_path
+          - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
+            %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
     .diff-content
       %table
         - note.truncated_diff_lines.each do |line|
@@ -19,8 +19,10 @@
               %td.new_line= "..."
               %td.line_content.matched= line.text
             - else
-              %td.old_line= raw(line.type == "new" ? "&nbsp;" : line.old_pos)
-              %td.new_line= raw(line.type == "old" ? "&nbsp;" : line.new_pos)
+              %td.old_line{class: line.type == "new" ? "new" : "old"}
+                = 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)
 
               - if line_code == note.line_code
diff --git a/app/views/projects/project_members/_group_members.html.haml b/app/views/projects/project_members/_group_members.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..43e92437cf577e64163efd308ca0526e86c3f1ac
--- /dev/null
+++ b/app/views/projects/project_members/_group_members.html.haml
@@ -0,0 +1,16 @@
+.panel.panel-default
+  .panel-heading
+    %strong #{@group.name}
+    group members
+    %small
+      (#{members.count})
+    .panel-head-actions
+      = link_to group_group_members_path(@group), class: 'btn btn-sm' do
+        %i.fa.fa-pencil-square-o
+        Edit group members
+  %ul.well-list
+    - members.each do |member|
+      = render 'groups/group_members/group_member', member: member, show_controls: false
+    - if members.count > 20
+      %li
+        and #{members.count - 20} more. For full list visit #{link_to 'group members page', group_group_members_path(@group)}
diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..5daae2708e6a42caaba7cbb43e7a5f69db56ddf5
--- /dev/null
+++ b/app/views/projects/project_members/_new_project_member.html.haml
@@ -0,0 +1,15 @@
+= form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project), html: { class: 'form-horizontal users-project-form' } do |f|
+  .form-group
+    = f.label :user_ids, "People", class: 'control-label'
+    .col-sm-10= users_select_tag(:user_ids, multiple: true, class: 'input-large', scope: :all)
+
+  .form-group
+    = f.label :access_level, "Project Access", class: 'control-label'
+    .col-sm-10
+      = select_tag :access_level, options_for_select(ProjectMember.access_roles, @project_member.access_level), class: "project-access-select select2"
+      .help-block
+        Read more about role permissions
+        %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
+
+  .form-actions
+    = f.submit 'Add users to project', class: "btn btn-create"
diff --git a/app/views/projects/project_members/_project_member.html.haml b/app/views/projects/project_members/_project_member.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..a07d07623340fd62000138be7cea09bb96753405
--- /dev/null
+++ b/app/views/projects/project_members/_project_member.html.haml
@@ -0,0 +1,37 @@
+- user = member.user
+- return unless user
+
+%li{class: "#{dom_class(member)} js-toggle-container project_member_row access-#{member.human_access.downcase}", id: dom_id(member)}
+  %span.list-item-name
+    = image_tag avatar_icon(user.email, 16), class: "avatar s16"
+    %strong= user.name
+    %span.cgray= user.username
+    - if user == current_user
+      %span.label.label-success It's you
+    - if user.blocked?
+      %label.label.label-danger
+        %strong Blocked
+
+  - if current_user_can_admin_project
+    - unless @project.personal? && user == current_user
+      .pull-right
+        %strong= member.human_access
+        = button_tag class: "btn-xs btn js-toggle-button",
+                     title: 'Edit access level', type: 'button' do
+          %i.fa.fa-pencil-square-o
+
+        &nbsp;
+        - if current_user == user
+          = link_to leave_namespace_project_project_members_path(@project.namespace, @project), data: { confirm: "Leave project?"}, method: :delete, class: "btn-xs btn btn-remove", title: 'Leave project' do
+            %i.fa.fa-minus.fa-inverse
+        - else
+          = link_to namespace_project_project_member_path(@project.namespace, @project, user), data: { confirm: remove_from_project_team_message(@project, user) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from team' do
+            %i.fa.fa-minus.fa-inverse
+
+    .edit-member.hide.js-toggle-content
+      %br
+      = form_for member, as: :project_member, url: namespace_project_project_member_path(@project.namespace, @project, member.user), remote: true do |f|
+        .prepend-top-10
+          = f.select :access_level, options_for_select(ProjectMember.access_roles, member.access_level), {}, class: 'form-control'
+        .prepend-top-10
+          = f.submit 'Save', class: 'btn btn-save'
diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..615c425e59ae2967a6ba90f5d7ff6ad8bd83103d
--- /dev/null
+++ b/app/views/projects/project_members/_team.html.haml
@@ -0,0 +1,11 @@
+- can_admin_project = can?(current_user, :admin_project, @project)
+
+.panel.panel-default.prepend-top-20
+  .panel-heading
+    %strong #{@project.name}
+    project members
+    %small
+      (#{members.count})
+  %ul.well-list
+    - members.each do |project_member|
+      = render 'project_member', member: project_member, current_user_can_admin_project: can_admin_project
diff --git a/app/views/projects/team_members/import.html.haml b/app/views/projects/project_members/import.html.haml
similarity index 66%
rename from app/views/projects/team_members/import.html.haml
rename to app/views/projects/project_members/import.html.haml
index d1f46c61b2e7d869fcce287a8fce9cf3ab3d6610..293754cd0c0fa180a5f80dec6fdb78738d88306a 100644
--- a/app/views/projects/team_members/import.html.haml
+++ b/app/views/projects/project_members/import.html.haml
@@ -3,12 +3,12 @@
 %p.light
   Only project members will be imported. Group members will be skipped.
 %hr
-= form_tag apply_import_project_team_members_path(@project), method: 'post', class: 'form-horizontal' do
+= form_tag apply_import_namespace_project_project_members_path(@project.namespace, @project), method: 'post', class: 'form-horizontal' do
   .form-group
     = label_tag :source_project_id, "Project", class: 'control-label'
     .col-sm-10= select_tag(:source_project_id, options_from_collection_for_select(current_user.authorized_projects, :id, :name_with_namespace), prompt: "Select project", class: "select2 lg", required: true)
 
   .form-actions
     = button_tag 'Import project members', class: "btn btn-create"
-    = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
+    = link_to "Cancel", namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-cancel"
 
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..36a6f6a15547d9d05737d5ff08f475a198531dae
--- /dev/null
+++ b/app/views/projects/project_members/index.html.haml
@@ -0,0 +1,35 @@
+%h3.page-title
+  Users with access to this project
+
+%p.light
+  Read more about project permissions
+  %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
+
+%hr
+
+.clearfix.js-toggle-container
+  = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form'  do
+    .form-group
+      = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input input-mn-300' }
+    = button_tag 'Search', class: 'btn'
+
+  - if can?(current_user, :admin_project_member, @project)
+    %span.pull-right
+      = button_tag class: 'btn btn-new btn-grouped js-toggle-button', type: 'button' do
+        Add members
+        %i.fa.fa-chevron-down
+      = link_to import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-grouped", title: "Import members from another project" do
+        Import members
+
+    .js-toggle-content.hide.new-group-member-holder
+      = render "new_project_member"
+
+= render "team", members: @project_members
+
+- if @group
+  = render "group_members", members: @group_members
+
+:coffeescript
+  $('form.member-search-form').on 'submit', (event) ->
+    event.preventDefault()
+    Turbolinks.visit @.action + '?' + $(@).serialize()
diff --git a/app/views/projects/project_members/update.js.haml b/app/views/projects/project_members/update.js.haml
new file mode 100644
index 0000000000000000000000000000000000000000..811b1858821c93518116a449322dc0b161954f77
--- /dev/null
+++ b/app/views/projects/project_members/update.js.haml
@@ -0,0 +1,3 @@
+- can_admin_project = can?(current_user, :admin_project, @project)
+:plain
+  $("##{dom_id(@project_member)}").replaceWith('#{escape_javascript(render("project_member", member: @project_member, current_user_can_admin_project: can_admin_project))}');
diff --git a/app/views/projects/protected_branches/_branches_list.html.haml b/app/views/projects/protected_branches/_branches_list.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..bb49f4de8736ce2422f605b09c67824ac4ef0040
--- /dev/null
+++ b/app/views/projects/protected_branches/_branches_list.html.haml
@@ -0,0 +1,34 @@
+- unless @branches.empty?
+  %br
+  %h4 Already Protected:
+  %table.table.protected-branches-list
+    %thead
+      %tr.no-border
+        %th Branch
+        %th Developers can push
+        %th Last commit
+        %th
+
+    %tbody
+      - @branches.each do |branch|
+        - @url = namespace_project_protected_branch_path(@project.namespace, @project, branch)
+        %tr
+          %td
+            = link_to namespace_project_commits_path(@project.namespace, @project, branch.name) do
+              %strong= branch.name
+              - if @project.root_ref?(branch.name)
+                %span.label.label-info default
+            %td
+              = check_box_tag "developers_can_push", branch.id, branch.developers_can_push, "data-url" => @url
+            %td
+              - if commit = branch.commit
+                = link_to namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id' do
+                  = commit.short_id
+                &middot;
+                #{time_ago_with_tooltip(commit.committed_date)}
+              - else
+                (branch was removed from repository)
+            %td
+              .pull-right
+                - if can? current_user, :admin_project, @project
+                  = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-remove btn-sm"
diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml
index 227a2f9a0619e4a7983f4d442ad7da80571e65d7..a3464c0e5e183d623abb99c5372b588349c9aee3 100644
--- a/app/views/projects/protected_branches/index.html.haml
+++ b/app/views/projects/protected_branches/index.html.haml
@@ -2,7 +2,7 @@
 %p.light Keep stable branches secure and force developers to use Merge Requests
 %hr
 
-.bs-callout.bs-callout-info
+.well.append-bottom-20
   %p Protected branches are designed to
   %ul
     %li prevent pushes from everybody except #{link_to "masters", help_page_path("permissions", "permissions"), class: "vlink"}
@@ -11,7 +11,7 @@
   %p Read more about #{link_to "project permissions", help_page_path("permissions", "permissions"), class: "underlined-link"}
 
 - if can? current_user, :admin_project, @project
-  = form_for [@project, @protected_branch], html: { class: 'form-horizontal' } do |f|
+  = form_for [@project.namespace.becomes(Namespace), @project, @protected_branch], html: { class: 'form-horizontal' } do |f|
     -if @protected_branch.errors.any?
       .alert.alert-danger
         %ul
@@ -22,29 +22,14 @@
       = f.label :name, "Branch", class: 'control-label'
       .col-sm-10
         = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "select2"})
+    .form-group
+      .col-sm-offset-2.col-sm-10
+        .checkbox
+          = f.label :developers_can_push do
+            = f.check_box :developers_can_push
+            %strong Developers can push
+          .help-block Allow developers to push to this branch
     .form-actions
       = f.submit 'Protect', class: "btn-create btn"
-- unless @branches.empty?
-  %h5 Already Protected:
-  %ul.bordered-list.protected-branches-list
-    - @branches.each do |branch|
-      %li
-        %h4
-          = link_to project_commits_path(@project, branch.name) do
-            %strong= branch.name
-            - if @project.root_ref?(branch.name)
-              %span.label.label-info default
-            %span.label.label-success
-              %i.fa.fa-lock
-          .pull-right
-            - if can? current_user, :admin_project, @project
-              = link_to 'Unprotect', [@project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-remove btn-small"
+= render 'branches_list'
 
-        - if commit = branch.commit
-          = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do
-            = commit.short_id
-          %span.light
-            = gfm escape_once(truncate(commit.title, length: 40))
-          #{time_ago_with_tooltip(commit.committed_date)}
-        - else
-          (branch was removed from repository)
diff --git a/app/views/projects/refs/logs_tree.js.haml b/app/views/projects/refs/logs_tree.js.haml
index 948a21aa8165594307907fbeb795f3685fe0b5c8..49ce6c0888ea0d8cb996b2ccc3952f1394e45956 100644
--- a/app/views/projects/refs/logs_tree.js.haml
+++ b/app/views/projects/refs/logs_tree.js.haml
@@ -11,9 +11,9 @@
 - if @logs.present?
   :plain
     var current_url = location.href.replace(/\/?$/, '/');
-    var log_url = '#{project_tree_url(@project, tree_join(@ref, @path || '/'))}'.replace(/\/?$/, '/');
+    var log_url = '#{namespace_project_tree_url(@project.namespace, @project, tree_join(@ref, @path || '/'))}'.replace(/\/?$/, '/');
     if(current_url == log_url) {
       // Load 10 more commit log for each file in tree
       // if we still on the same page
-      ajaxGet('#{logs_file_project_ref_path(@project, @ref, @path || '/', offset: (@offset +  @limit))}');
+      ajaxGet('#{logs_file_namespace_project_ref_path(@project.namespace, @project, @ref, @path || '/', offset: (@offset +  @limit))}');
     }
diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml
index ce69adeb48cd8751038fe3c7cf9ce17ddf4ed6c6..1ba7a1f206020ed9f4910fbf024287a203757947 100644
--- a/app/views/projects/repositories/_download_archive.html.haml
+++ b/app/views/projects/repositories/_download_archive.html.haml
@@ -3,35 +3,35 @@
 - split_button = split_button || false
 - if split_button == true
   %span.btn-group{class: btn_class}
-    = link_to archive_project_repository_path(@project, ref: ref, format: 'zip'), class: 'btn', rel: 'nofollow' do
+    = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn btn-sm', rel: 'nofollow' do
       %i.fa.fa-download
       %span Download zip
-    %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' }
+    %a.btn-sm.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' }
       %span.caret
       %span.sr-only
         Select Archive Format
     %ul.dropdown-menu{ role: 'menu' }
       %li
-        = link_to archive_project_repository_path(@project, ref: ref, format: 'zip'), rel: 'nofollow' do
+        = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), rel: 'nofollow' do
           %i.fa.fa-download
           %span Download zip
       %li
-        = link_to archive_project_repository_path(@project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do
+        = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do
           %i.fa.fa-download
           %span Download tar.gz
       %li
-        = link_to archive_project_repository_path(@project, ref: ref, format: 'tar.bz2'), rel: 'nofollow' do
+        = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar.bz2'), rel: 'nofollow' do
           %i.fa.fa-download
           %span Download tar.bz2
       %li
-        = link_to archive_project_repository_path(@project, ref: ref, format: 'tar'), rel: 'nofollow' do
+        = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar'), rel: 'nofollow' do
           %i.fa.fa-download
           %span Download tar
 - else
   %span.btn-group{class: btn_class}
-    = link_to archive_project_repository_path(@project, ref: ref, format: 'zip'), class: 'btn', rel: 'nofollow' do
+    = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn', rel: 'nofollow' do
       %i.fa.fa-download
       %span zip
-    = link_to archive_project_repository_path(@project, ref: ref, format: 'tar.gz'), class: 'btn', rel: 'nofollow' do
+    = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar.gz'), class: 'btn', rel: 'nofollow' do
       %i.fa.fa-download
       %span tar.gz
diff --git a/app/views/projects/repositories/_feed.html.haml b/app/views/projects/repositories/_feed.html.haml
index c77ffff43fe02df137a9b432996b9538cfa4dc86..f3526ad0747a8dbe31117f5e0dd7308efc9c3db1 100644
--- a/app/views/projects/repositories/_feed.html.haml
+++ b/app/views/projects/repositories/_feed.html.haml
@@ -1,7 +1,7 @@
 - commit = update
 %tr
   %td
-    = link_to project_commits_path(@project, commit.head.name) do
+    = link_to namespace_project_commits_path(@project.namespace, @project, commit.head.name) do
       %strong
         = commit.head.name
       - if @project.root_ref?(commit.head.name)
@@ -9,7 +9,7 @@
 
   %td
     %div
-      = link_to project_commits_path(@project, commit.id) do
+      = link_to namespace_project_commits_path(@project.namespace, @project, commit.id) do
         %code= commit.short_id
       = image_tag avatar_icon(commit.author_email), class: "", width: 16, alt: ''
       = gfm escape_once(truncate(commit.title, length: 40))
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index 1151f22c7e8e78076fba96fd25754c9412b0c01d..ce6b7a0737a8c0fa344687710d8f2d2f0cae0666 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -5,12 +5,12 @@
 %p= @service.description
 
 .back-link
-  = link_to project_services_path(@project) do
+  = link_to namespace_project_services_path(@project.namespace, @project) do
     &larr; to services
 
 %hr
 
-= form_for(@service, as: :service, url: project_service_path(@project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |f|
+= form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |f|
   - if @service.errors.any?
     .alert.alert-danger
       %ul
@@ -18,24 +18,72 @@
           %li= msg
 
   - if @service.help.present?
-    .bs-callout
-      = @service.help
+    .well
+      = preserve do
+        = markdown @service.help
 
   .form-group
     = f.label :active, "Active", class: "control-label"
     .col-sm-10
       = f.check_box :active
 
+  - if @service.supported_events.length > 1
+    .form-group
+      = f.label :url, "Trigger", class: 'control-label'
+      .col-sm-10
+        - if @service.supported_events.include?("push")
+          %div
+            = f.check_box :push_events, class: 'pull-left'
+            .prepend-left-20
+              = f.label :push_events, class: 'list-label' do
+                %strong Push events
+              %p.light
+                This url will be triggered by a push to the repository
+        - if @service.supported_events.include?("tag_push")
+          %div
+            = f.check_box :tag_push_events, class: 'pull-left'
+            .prepend-left-20
+              = f.label :tag_push_events, class: 'list-label' do
+                %strong Tag push events
+              %p.light
+                This url will be triggered when a new tag is pushed to the repository
+        - if @service.supported_events.include?("note")
+          %div
+            = f.check_box :note_events, class: 'pull-left'
+            .prepend-left-20
+              = f.label :note_events, class: 'list-label' do
+                %strong Comments
+              %p.light
+                This url will be triggered when someone adds a comment
+        - if @service.supported_events.include?("issue")
+          %div
+            = f.check_box :issues_events, class: 'pull-left'
+            .prepend-left-20
+              = f.label :issues_events, class: 'list-label' do
+                %strong Issues events
+              %p.light
+                This url will be triggered when an issue is created
+        - if @service.supported_events.include?("merge_request")
+          %div
+            = f.check_box :merge_requests_events, class: 'pull-left'
+            .prepend-left-20
+              = f.label :merge_requests_events, class: 'list-label' do
+                %strong Merge Request events
+              %p.light
+                This url will be triggered when a merge request is created
+
   - @service.fields.each do |field|
     - name = field[:name]
-    - value = @service.send(name) unless field[:type] == 'password'
+    - title = field[:title] || name.humanize
+    - value = service_field_value(field[:type], @service.send(name))
     - type = field[:type]
     - placeholder = field[:placeholder]
     - choices = field[:choices]
     - default_choice = field[:default_choice]
+    - help = field[:help]
 
     .form-group
-      = f.label name, class: "control-label"
+      = f.label name, title, class: "control-label"
       .col-sm-10
         - if type == 'text'
           = f.text_field name, class: "form-control", placeholder: placeholder
@@ -46,10 +94,13 @@
         - elsif type == 'select'
           = f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" }
         - elsif type == 'password'
-          = f.password_field name, class: 'form-control'
+          = f.password_field name, placeholder: value, class: 'form-control'
+        - if help
+          %span.help-block= help
 
   .form-actions
     = f.submit 'Save', class: 'btn btn-save'
     &nbsp;
-    - if @service.valid? && @service.activated? && @service.can_test?
-      = link_to 'Test settings', test_project_service_path(@project, @service.to_param), class: 'btn'
+    - if @service.valid? && @service.activated?
+      - disabled = @service.can_test? ? '':'disabled'
+      = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}"
diff --git a/app/views/projects/services/index.html.haml b/app/views/projects/services/index.html.haml
index 7271dd830ca76f2e9b73cce73dbd10ff5170c31c..0d3ccb6bb839e7306e5b9409fee7e309d11eea3e 100644
--- a/app/views/projects/services/index.html.haml
+++ b/app/views/projects/services/index.html.haml
@@ -1,13 +1,22 @@
 %h3.page-title Project services
 %p.light Project services allow you to integrate GitLab with other applications
-%hr
 
-%ul.bordered-list
+%table.table
+  %thead
+    %tr
+      %th
+      %th Service
+      %th Description
+      %th Last edit
   - @services.sort_by(&:title).each do |service|
-    %li
-      %h4
-        = link_to edit_project_service_path(@project, service.to_param) do
-          = service.title
-        .pull-right
-          = boolean_to_icon service.activated?
-      %p= service.description
+    %tr
+      %td
+        = boolean_to_icon service.activated?
+      %td
+        = link_to edit_namespace_project_service_path(@project.namespace, @project, service.to_param) do
+          %strong= service.title
+      %td
+        = service.description
+      %td.light
+        = time_ago_in_words service.updated_at
+        ago
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 9b06ebe95a4d2b2840c440e28721ae2a932171de..85113ffa7e23385c33103c12560d1b7d8b6432da 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -1,3 +1,7 @@
+- if current_user && can?(current_user, :download_code, @project)
+  = render 'shared/no_ssh'
+  = render 'shared/no_password'
+
 = render "home_panel"
 
 - readme = @repository.readme
@@ -11,20 +15,22 @@
         Readme
   .project-home-links
     - unless @project.empty_repo?
-      = link_to pluralize(number_with_delimiter(@repository.commit_count), 'commit'), project_commits_path(@project, @ref || @repository.root_ref)
-      = link_to pluralize(number_with_delimiter(@repository.branch_names.count), 'branch'), project_branches_path(@project)
-      = link_to pluralize(number_with_delimiter(@repository.tag_names.count), 'tag'), project_tags_path(@project)
+      = link_to pluralize(number_with_delimiter(@repository.commit_count), 'commit'), namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref)
+      = link_to pluralize(number_with_delimiter(@repository.branch_names.count), 'branch'), namespace_project_branches_path(@project.namespace, @project)
+      = link_to pluralize(number_with_delimiter(@repository.tag_names.count), 'tag'), namespace_project_tags_path(@project.namespace, @project)
       %span.light.prepend-left-20= repository_size
 
 .tab-content
   .tab-pane.active#tab-activity
     .row
+      = link_to '#aside', class: 'show-aside' do
+        %i.fa.fa-angle-left
       %section.col-md-9
         = render "events/event_last_push", event: @last_push
         = render 'shared/event_filter'
         .content_list
         = spinner
-      %aside.col-md-3.project-side.hidden-sm.hidden-xs
+      %aside.col-md-3.project-side
         .clearfix
           - if @project.archived?
             .alert.alert-warning
@@ -34,50 +40,68 @@
               %p Repository is read-only
 
           - if @project.forked_from_project
-            .alert.alert-success
+            .well
               %i.fa.fa-code-fork.project-fork-icon
               Forked from:
               %br
               = link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project)
 
           - unless @project.empty_repo?
-            = link_to project_compare_index_path(@project, from: @repository.root_ref, to: @ref || @repository.root_ref), class: 'btn btn-block' do
+            = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref), class: 'btn btn-block' do
               Compare code
 
-            - if @repository.version
-              - version = @repository.version
-              = link_to project_blob_path(@project, tree_join(@repository.root_ref, version.name)), class: 'btn btn-block' do
+            - if version = @repository.version
+              - detail_url = changelog_url(@project) || version_url(@project)
+              = link_to detail_url, class: 'btn btn-block' do
                 Version:
                 %span.count
                   = @repository.blob_by_oid(version.id).data
+            - elsif @repository.changelog
+              = link_to changelog_url(@project), class: 'btn btn-block' do
+                View changelog
 
-        .prepend-top-10
+            - if @repository.contribution_guide
+              = link_to contribution_guide_url(@project), class: 'btn btn-block' do
+                View contribution guide
+
+            - if @repository.license
+              = link_to license_url(@project), class: 'btn btn-block' do
+                View license
+
+        .prepend-top-10.append-bottom-10
           %p
             %span.light Created on
             #{@project.created_at.stamp('Aug 22, 2013')}
           %p
-            %span.light Owned by
+            %span.light Owned by #{@project.group ? "the" : nil}
             - if @project.group
               #{link_to @project.group.name, @project.group} group
             - else
               #{link_to @project.owner_name, @project.owner}
 
+        - unless @project.empty_repo?
+          - if can? current_user, :download_code, @project
+            %hr
+            .prepend-top-10.append-bottom-10
+              = render 'projects/repositories/download_archive', split_button: true
+
+        .prepend-top-10
           - @project.ci_services.each do |ci_service|
             - if ci_service.active? && ci_service.respond_to?(:builds_path)
+              %hr
               - if ci_service.respond_to?(:status_img_path)
-                = link_to ci_service.builds_path do
+                = link_to ci_service.builds_path, :'data-no-turbolink' => 'data-no-turbolink' do
                   = image_tag ci_service.status_img_path, alt: "build status"
               - else
                 %span.light CI provided by
-                = link_to ci_service.title, ci_service.builds_path
+                = link_to ci_service.title, ci_service.builds_path, :'data-no-turbolink' => 'data-no-turbolink'
 
   - if readme
     .tab-pane#tab-readme
       %article.readme-holder#README
-        = link_to project_blob_path(@project, tree_join(@repository.root_ref, readme.name)) do
+        = link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)) do
           %h4.readme-file-title
             %i.fa.fa-file
             = readme.name
         .wiki
           = render_readme(readme)
-
diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml
index f6a5bf9e4ff74d508e454d18d81c41565a7eb255..2d4d5d030ab3ec37c7601b4dc9d114bfec25621f 100644
--- a/app/views/projects/snippets/edit.html.haml
+++ b/app/views/projects/snippets/edit.html.haml
@@ -1,4 +1,4 @@
 %h3.page-title
   Edit snippet
 %hr
-= render "shared/snippets/form", url: project_snippet_path(@project, @snippet)
+= render "shared/snippets/form", url: namespace_project_snippet_path(@project.namespace, @project, @snippet)
diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml
index e60f9a44322d2ade2e2f0f8d4ef0e1d60fd6c168..e2d8ec673a17fe3f2e6ced456fbf3d9b5da3ba22 100644
--- a/app/views/projects/snippets/index.html.haml
+++ b/app/views/projects/snippets/index.html.haml
@@ -1,7 +1,7 @@
 %h3.page-title
   Snippets
   - if can? current_user, :write_project_snippet, @project
-    = link_to new_project_snippet_path(@project), class: "btn btn-new pull-right", title: "New Snippet" do
+    = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new pull-right", title: "New Snippet" do
       Add new snippet
 
 %p.light
diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml
index 10f684b63162650109bf1d747a4d5cc8e66ace7e..bb659dba0cf1cb21504f6796f835193055565305 100644
--- a/app/views/projects/snippets/new.html.haml
+++ b/app/views/projects/snippets/new.html.haml
@@ -1,4 +1,4 @@
 %h3.page-title
   New snippet
 %hr
-= render "shared/snippets/form", url: project_snippets_path(@project, @snippet)
+= render "shared/snippets/form", url: namespace_project_snippets_path(@project.namespace, @project, @snippet)
diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml
index ada0d30c49643e37012d20d4fc5bd5c13c47d57d..d19689a1056213a16988e15c975c09e4c2e4d888 100644
--- a/app/views/projects/snippets/show.html.haml
+++ b/app/views/projects/snippets/show.html.haml
@@ -2,7 +2,7 @@
   = @snippet.title
 
   .pull-right
-    = link_to new_project_snippet_path(@project), class: "btn btn-new", title: "New Snippet" do
+    = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new", title: "New Snippet" do
       Add new snippet
 
 %hr
@@ -17,21 +17,21 @@
         = @snippet.author_name
 
   .back-link
-    = link_to project_snippets_path(@project) do
+    = link_to namespace_project_snippets_path(@project.namespace, @project) do
       &larr; project snippets
 
 .file-holder
   .file-title
     %i.fa.fa-file
-    %span.file_name
+    %strong
       = @snippet.file_name
-    .options
+    .file-actions
       .btn-group
         - if can?(current_user, :modify_project_snippet, @snippet)
-          = link_to "edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-small", title: 'Edit Snippet'
-        = link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn btn-small", target: "_blank"
+          = link_to "edit", edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", title: 'Edit Snippet'
+        = link_to "raw", raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank"
       - if can?(current_user, :admin_project_snippet, @snippet)
-        = link_to "remove", project_snippet_path(@project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-small btn-remove", title: 'Delete Snippet'
+        = link_to "remove", namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-sm btn-remove", title: 'Delete Snippet'
   = render 'shared/snippets/blob'
 
 %div#notes= render "projects/notes/notes_with_form"
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index f93c1b4211fd5c9693e2ff63c127b846dd9ec1e7..f22308e54b04e48c56b48904ae80cb9ef27d0eec 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -1,17 +1,17 @@
 - commit = @repository.commit(tag.target)
 %li
   %h4
-    = link_to project_commits_path(@project, tag.name), class: "" do
+    = link_to namespace_project_commits_path(@project.namespace, @project, tag.name), class: "" do
       %i.fa.fa-tag
       = tag.name
     - if tag.message.present?
       &nbsp;
-      = tag.message
+      = strip_gpg_signature(tag.message)
     .pull-right
       - if can? current_user, :download_code, @project
-        = render 'projects/repositories/download_archive', ref: tag.name, btn_class: 'btn-grouped btn-group-small'
+        = render 'projects/repositories/download_archive', ref: tag.name, btn_class: 'btn-grouped btn-group-sm'
       - if can?(current_user, :admin_project, @project)
-        = link_to project_tag_path(@project, tag.name), class: 'btn btn-small btn-remove remove-row grouped', method: :delete, data: { confirm: 'Removed tag cannot be restored. Are you sure?'}, remote: true do
+        = link_to namespace_project_tag_path(@project.namespace, @project, tag.name), class: 'btn btn-sm btn-remove remove-row grouped', method: :delete, data: { confirm: 'Removed tag cannot be restored. Are you sure?'}, remote: true do
           %i.fa.fa-trash-o
 
   - if commit
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index ac74e3b6d3642c699f52aef8acc138bff0209c28..f1bc2bc9a2b23aa8cfc5526a610b7b4c59bb0c6f 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -4,7 +4,7 @@
   Git Tags
   - if can? current_user, :push_code, @project
     .pull-right
-      = link_to new_project_tag_path(@project), class: 'btn btn-create new-tag-btn' do
+      = link_to new_namespace_project_tag_path(@project.namespace, @project), class: 'btn btn-create new-tag-btn' do
         %i.fa.fa-add-sign
         New tag
 
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index ad7ff8d3db8c2b7f50bdd3b11c8f5b300a402c6c..655044438d50a412085d3e9e2ee351fefebb8ccb 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -5,7 +5,7 @@
 %h3.page-title
   %i.fa.fa-code-fork
   New tag
-= form_tag project_tags_path, method: :post, class: "form-horizontal" do
+= form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal" do
   .form-group
     = label_tag :tag_name, 'Name for new tag', class: 'control-label'
     .col-sm-10
@@ -22,9 +22,10 @@
       .light (Optional) Entering a message will create an annotated tag.
   .form-actions
     = button_tag 'Create tag', class: 'btn btn-create', tabindex: 3
-    = link_to 'Cancel', project_tags_path(@project), class: 'btn btn-cancel'
+    = link_to 'Cancel', namespace_project_tags_path(@project.namespace, @project), class: 'btn btn-cancel'
 
 :javascript
+  disableButtonIfAnyEmptyField($("#new-tag-form"), ".form-control", ".btn-create");
   var availableTags = #{@project.repository.ref_names.to_json};
 
   $("#ref").autocomplete({
diff --git a/app/views/projects/team_members/_form.html.haml b/app/views/projects/team_members/_form.html.haml
deleted file mode 100644
index 2bf61fa12bb1c26c17b62f7c5f6aea33573aeeb9..0000000000000000000000000000000000000000
--- a/app/views/projects/team_members/_form.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-%h3.page-title
-  New project member(s)
-
-= form_for @user_project_relation, as: :project_member, url: project_team_members_path(@project), html: { class: "form-horizontal users-project-form" } do |f|
-  -if @user_project_relation.errors.any?
-    .alert.alert-danger
-      %ul
-        - @user_project_relation.errors.full_messages.each do |msg|
-          %li= msg
-
-  %p 1. Choose people you want in the project
-  .form-group
-    = f.label :user_ids, "People", class: 'control-label'
-    .col-sm-10
-      = users_select_tag(:user_ids, multiple: true)
-
-  %p 2. Set access level for them
-  .form-group
-    = f.label :access_level, "Project Access", class: 'control-label'
-    .col-sm-10= select_tag :access_level, options_for_select(Gitlab::Access.options, @user_project_relation.access_level), class: "project-access-select select2"
-
-  .form-actions
-    = f.submit 'Add users', class: "btn btn-create"
-    = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
diff --git a/app/views/projects/team_members/_group_members.html.haml b/app/views/projects/team_members/_group_members.html.haml
deleted file mode 100644
index df3c914fdea7c2712d31a0d8f92c4bee583028f7..0000000000000000000000000000000000000000
--- a/app/views/projects/team_members/_group_members.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-- group_users_count = @group.group_members.count
-.panel.panel-default
-  .panel-heading
-    %strong #{@group.name}
-    group members (#{group_users_count})
-    .pull-right
-      = link_to members_group_path(@group), class: 'btn btn-small' do
-        %i.fa.fa-pencil-square-o
-  %ul.well-list
-    - @group.group_members.order('access_level DESC').limit(20).each do |member|
-      = render 'groups/group_members/group_member', member: member, show_controls: false
-    - if group_users_count > 20
-      %li
-        and #{group_users_count - 20} more. For full list visit #{link_to 'group members page', members_group_path(@group)}
diff --git a/app/views/projects/team_members/_team.html.haml b/app/views/projects/team_members/_team.html.haml
deleted file mode 100644
index 0e5b8176132a91ad02c981f9e4e0c9cf8024b9fa..0000000000000000000000000000000000000000
--- a/app/views/projects/team_members/_team.html.haml
+++ /dev/null
@@ -1,9 +0,0 @@
-.team-table
-  - can_admin_project = (can? current_user, :admin_project, @project)
-  .panel.panel-default
-    .panel-heading
-      %strong #{@project.name}
-      project members (#{members.count})
-    %ul.well-list
-      - members.each do |team_member|
-        = render 'team_member', member: team_member, current_user_can_admin_project: can_admin_project
diff --git a/app/views/projects/team_members/_team_member.html.haml b/app/views/projects/team_members/_team_member.html.haml
deleted file mode 100644
index 7a9c0939ba04ebb560610bcec97e85c5860205f0..0000000000000000000000000000000000000000
--- a/app/views/projects/team_members/_team_member.html.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-- user = member.user
-%li{id: dom_id(user), class: "team_member_row access-#{member.human_access.downcase}"}
-  .pull-right
-    - if current_user_can_admin_project
-      - unless @project.personal? && user == current_user
-        .pull-left
-          = form_for(member, as: :project_member, url: project_team_member_path(@project, member.user)) do |f|
-            = f.select :access_level, options_for_select(ProjectMember.access_roles, member.access_level), {}, class: "trigger-submit"
-          &nbsp;
-        = link_to project_team_member_path(@project, user), data: { confirm: remove_from_project_team_message(@project, user)}, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from team' do
-          %i.fa.fa-minus.fa-inverse
-  = image_tag avatar_icon(user.email, 32), class: "avatar s32"
-  %p
-    %strong= user.name
-  %span.cgray= user.username
-
-
diff --git a/app/views/projects/team_members/index.html.haml b/app/views/projects/team_members/index.html.haml
deleted file mode 100644
index ecb7c689e8ab9d882339ade2ee076ce369799597..0000000000000000000000000000000000000000
--- a/app/views/projects/team_members/index.html.haml
+++ /dev/null
@@ -1,16 +0,0 @@
-%h3.page-title
-  Users with access to this project
-
-  - if can? current_user, :admin_team_member, @project
-    %span.pull-right
-      = link_to new_project_team_member_path(@project), class: "btn btn-new btn-grouped", title: "New project member" do
-        New project member
-      = link_to import_project_team_members_path(@project), class: "btn btn-grouped", title: "Import members from another project" do
-        Import members
-
-%p.light
-  Read more about project permissions
-  %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
-= render "team", members: @project_members
-- if @group
-  = render "group_members"
diff --git a/app/views/projects/team_members/new.html.haml b/app/views/projects/team_members/new.html.haml
deleted file mode 100644
index b1bc3ba0eba684a146b503fa89225bda4614e840..0000000000000000000000000000000000000000
--- a/app/views/projects/team_members/new.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-= render "form"
diff --git a/app/views/projects/team_members/update.js.haml b/app/views/projects/team_members/update.js.haml
deleted file mode 100644
index c68fe9574a2526a4fb136c22bd2d1428919aad4b..0000000000000000000000000000000000000000
--- a/app/views/projects/team_members/update.js.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-- if @user_project_relation.valid?
-  :plain
-    $("##{dom_id(@user_project_relation)}").effect("highlight", {color: "#529214"}, 1000);;
-- else
-  :plain
-    $("##{dom_id(@user_project_relation)}").effect("highlight", {color: "#D12F19"}, 1000);;
diff --git a/app/views/projects/transfer.js.haml b/app/views/projects/transfer.js.haml
index 10b0de98c041494e71a612aa79396214566b29f9..17b9fecfeb162f8f3ac88523a7fbe336c4d46516 100644
--- a/app/views/projects/transfer.js.haml
+++ b/app/views/projects/transfer.js.haml
@@ -1,7 +1,2 @@
-- if @project.errors[:namespace_id].present?
-  :plain
-    $("#tab-transfer .errors-holder").replaceWith(errorMessage('#{escape_javascript(@project.errors[:namespace_id].first)}'));
-    $("#tab-transfer .form-actions input").removeAttr('disabled').removeClass('disabled');
-- else
-  :plain
-    location.href = "#{edit_project_path(@project)}";
+:plain
+    location.href = "#{edit_namespace_project_path(@project.namespace, @project)}";
diff --git a/app/views/projects/tree/_blob_item.html.haml b/app/views/projects/tree/_blob_item.html.haml
index 393ef0e24bd725416472b16d22fc4d620f3e2117..02ecbade219250ceaf038830c7f9da2361a5baba 100644
--- a/app/views/projects/tree/_blob_item.html.haml
+++ b/app/views/projects/tree/_blob_item.html.haml
@@ -1,8 +1,8 @@
 %tr{ class: "tree-item #{tree_hex_class(blob_item)}" }
   %td.tree-item-file-name
-    = tree_icon(type)
+    = tree_icon(type, blob_item.mode, blob_item.name)
     %span.str-truncated
-      = link_to blob_item.name, project_blob_path(@project, tree_join(@id || @commit.id, blob_item.name))
+      = link_to blob_item.name, namespace_project_blob_path(@project.namespace, @project, tree_join(@id || @commit.id, blob_item.name))
   %td.tree_time_ago.cgray
     = render 'spinner'
   %td.hidden-xs.tree_commit
diff --git a/app/views/projects/tree/_submodule_item.html.haml b/app/views/projects/tree/_submodule_item.html.haml
index 46e9be4af83bd73a08616d61cfe5b9d7503450d7..2b5f671c09ec5e4a1e268ecaa20f1578119c650d 100644
--- a/app/views/projects/tree/_submodule_item.html.haml
+++ b/app/views/projects/tree/_submodule_item.html.haml
@@ -1,14 +1,6 @@
-- tree, commit = submodule_links(submodule_item)
 %tr{ class: "tree-item" }
   %td.tree-item-file-name
-    %i.fa.fa-archive
-    %span
-      = link_to truncate(submodule_item.name, length: 40), tree
-    @
-    %span.monospace
-      - if commit.nil?
-        #{truncate_sha(submodule_item.id)}
-      - else
-        = link_to "#{truncate_sha(submodule_item.id)}", commit
+    %i.fa.fa-archive.fa-fw
+    = submodule_link(submodule_item, @ref)
   %td
   %td.hidden-xs
diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml
index 1159fcadffd9aa775c32c21ca2640816dbd9ba7d..9f43a1288aa5bcd429569a60c5267a1124b0930c 100644
--- a/app/views/projects/tree/_tree.html.haml
+++ b/app/views/projects/tree/_tree.html.haml
@@ -1,18 +1,20 @@
 %ul.breadcrumb.repo-breadcrumb
   %li
-    = link_to project_tree_path(@project, @ref) do
+    = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
       = @project.path
   - tree_breadcrumbs(tree, 6) do |title, path|
     %li
       - if path
-        = link_to truncate(title, length: 40), project_tree_path(@project, path)
+        = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path)
       - else
         = link_to title, '#'
   - if current_user && can_push_branch?(@project, @ref)
     %li
-      = link_to project_new_tree_path(@project, @id), title: 'New file', id: 'new-file-link' do
-        %small
-          %i.fa.fa-plus
+      = link_to project_new_tree_path(@project, @id), class: 'btn btn-small btn-xs', title: 'Create New file', id: 'new-file-link' do
+        Create        
+      = | 
+      = button_tag class: 'btn btn-small btn-xs', 'data-toggle' => 'modal', title: 'Upload New file', 'data-target' => '#modal-upload-tree' do
+        Upload	
 
 %div#tree-content-holder.tree-content-holder
   %table#tree-slider{class: "table_#{@hex_path} tree-table" }
@@ -27,15 +29,15 @@
             %i.fa.fa-angle-right
             &nbsp;
             %small.light
-              = link_to @commit.short_id, project_commit_path(@project, @commit)
+              = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit)
               &ndash;
               = truncate(@commit.title, length: 50)
-          = link_to 'History', project_commits_path(@project, @id), class: 'pull-right'
+          = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), class: 'pull-right'
 
     - if @path.present?
       %tr.tree-item
         %td.tree-item-file-name
-          = link_to "..", project_tree_path(@project, up_dir_path(tree)), class: 'prepend-left-10'
+          = link_to "..", namespace_project_tree_path(@project.namespace, @project, up_dir_path), class: 'prepend-left-10'
         %td
         %td.hidden-xs
 
@@ -44,8 +46,10 @@
   - if tree.readme
     = render "projects/tree/readme", readme: tree.readme
 
+
 %div.tree_progress
 
+
 :javascript
   // Load last commit log for each file in tree
   $('#tree-slider').waitForImages(function() {
diff --git a/app/views/projects/tree/_tree_commit_column.html.haml b/app/views/projects/tree/_tree_commit_column.html.haml
index bd50dd4d9a2d8e6681b3799dd5f353718d407da2..50521264a611c386a9813fb6767d9dca1b4e7f54 100644
--- a/app/views/projects/tree/_tree_commit_column.html.haml
+++ b/app/views/projects/tree/_tree_commit_column.html.haml
@@ -1,3 +1,3 @@
 %span.str-truncated
   %span.tree_author= commit_author_link(commit, avatar: true, size: 16)
-  = link_to_gfm commit.title, project_commit_path(@project, commit.id), class: "tree-commit-link"
+  = link_to_gfm commit.title, namespace_project_commit_path(@project.namespace, @project, commit.id), class: "tree-commit-link"
diff --git a/app/views/projects/tree/_tree_item.html.haml b/app/views/projects/tree/_tree_item.html.haml
index f8cecf9be1f14daba52a4c2b708e8410031e4213..e87138bf9800bd7d4349d4b450a6dfb3af741353 100644
--- a/app/views/projects/tree/_tree_item.html.haml
+++ b/app/views/projects/tree/_tree_item.html.haml
@@ -1,8 +1,9 @@
 %tr{ class: "tree-item #{tree_hex_class(tree_item)}" }
   %td.tree-item-file-name
-    = tree_icon(type)
+    = tree_icon(type, tree_item.mode, tree_item.name)
     %span.str-truncated
-      = link_to tree_item.name, project_tree_path(@project, tree_join(@id || @commit.id, tree_item.name))
+      - path = flatten_tree(tree_item)
+      = link_to path, namespace_project_tree_path(@project.namespace, @project, tree_join(@id || @commit.id, path))
   %td.tree_time_ago.cgray
     = render 'spinner'
   %td.hidden-xs.tree_commit
diff --git a/app/views/projects/tree/_upload.html.haml b/app/views/projects/tree/_upload.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..99ee6595010285a803093b4a6fd23a6920f98f53
--- /dev/null
+++ b/app/views/projects/tree/_upload.html.haml
@@ -0,0 +1,35 @@
+#modal-upload-tree.modal.hide
+  .modal-dialog
+    .modal-content
+      .modal-header
+        %a.close{href: "#", "data-dismiss" => "modal"} ×
+        %h3.page-title Upload 
+        %p.light
+          From branch
+          %strong= @ref
+      .modal-body
+        = form_tag project_new_tree_path(@project, @id), method: :put, class: 'form-horizontal', :multipart => true , :onChange => 'checkFile()' do
+          %br
+          .form-group
+            .col-sm-2
+            .col-sm-10
+              = file_field_tag :file_upload, :id => "file", :class => "file_up"
+          %br
+          = render 'shared/commit_message_container', params: params,
+                  placeholder: 'Upload this file because...'
+          .form-group
+            .col-sm-2
+            .col-sm-10
+              = button_tag 'Upload file', class: 'btn btn-small btn-primary'
+              = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
+:javascript 
+  function checkFile(){
+    str=document.getElementById('file').value; 
+    if(str.length < 1){
+      alert('Please select file!');
+    }
+  }
+  disableButtonIfAnyEmptyField( '#commit_message')
+
+
+
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index fc4616da6ec626bc35d107242ec7ec6824fd8bed..1cff71018e4a1c9c06c9acf9e5331cb26af48e3d 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -3,7 +3,16 @@
 
 - if can? current_user, :download_code, @project
   .tree-download-holder
-    = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'btn-group-small pull-right hidden-xs hidden-sm', split_button: true
+    = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'btn-group-sm pull-right hidden-xs hidden-sm', split_button: true
+
+- if allowed_tree_edit?
+  = render 'projects/tree/upload'
+
+- if allowed_tree_edit?
+  = render 'projects/tree/upload'
 
 #tree-holder.tree-holder.clearfix
   = render "tree", tree: @tree
+
+
+
diff --git a/app/views/projects/update.js.haml b/app/views/projects/update.js.haml
index cbb21f2b9fb03229e6a95b623bfd0e2f8803e078..4f3f4cab8d5c7b8df6afbfc79d7715fcd963ca4c 100644
--- a/app/views/projects/update.js.haml
+++ b/app/views/projects/update.js.haml
@@ -1,6 +1,6 @@
 - if @project.valid?
   :plain
-    location.href = "#{edit_project_path(@project)}";
+    location.href = "#{edit_namespace_project_path(@project.namespace, @project)}";
 - else
   :plain
     $(".project-edit-errors").html("#{escape_javascript(render('errors'))}");
diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml
index f37c086716d04b88e26354e579d86016427fdb81..9fbfa0b1aebcc1adba1eb1dfc6c06d06534ca945 100644
--- a/app/views/projects/wikis/_form.html.haml
+++ b/app/views/projects/wikis/_form.html.haml
@@ -1,4 +1,4 @@
-= form_for [@project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal wiki-form gfm-form' } do |f|
+= form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal wiki-form gfm-form' } do |f|
   -if @page.errors.any?
     #error_explanation
       .alert.alert-danger
@@ -19,13 +19,15 @@
         %code [Link Title](page-slug)
         \.
 
-  .form-group
+  .form-group.wiki-content
     = f.label :content, class: 'control-label'
     .col-sm-10
-      = render 'projects/zen', f: f, attr: :content, classes: 'description form-control'
-      .col-sm-12.hint
-        .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}
-        .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
+      = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do
+        = render 'projects/zen', f: f, attr: :content, classes: 'description form-control'
+        .col-sm-12.hint
+          .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}
+          .pull-right Attach files by dragging &amp; dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
+
       .clearfix
       .error-alert
   .form-group
@@ -35,11 +37,10 @@
   .form-actions
     - if @page && @page.persisted?
       = f.submit 'Save changes', class: "btn-save btn"
-      = link_to "Cancel", project_wiki_path(@project, @page), class: "btn btn-cancel"
+      = link_to "Cancel", namespace_project_wiki_path(@project.namespace, @project, @page), class: "btn btn-cancel"
     - else
       = f.submit 'Create page', class: "btn-create btn"
-      = link_to "Cancel", project_wiki_path(@project, :home), class: "btn btn-cancel"
+      = link_to "Cancel", namespace_project_wiki_path(@project.namespace, @project, :home), class: "btn btn-cancel"
 
 :javascript
-  window.project_image_path_upload = "#{upload_image_project_path @project}";
-
+  window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
diff --git a/app/views/projects/wikis/_main_links.html.haml b/app/views/projects/wikis/_main_links.html.haml
index 30410bc95e0b7bf87402acad2782ec8672cd3b0f..633214a4e869f9d091a47b2968298b5bfa046c4c 100644
--- a/app/views/projects/wikis/_main_links.html.haml
+++ b/app/views/projects/wikis/_main_links.html.haml
@@ -1,8 +1,8 @@
 %span.pull-right
   - if (@page && @page.persisted?)
-    = link_to history_project_wiki_path(@project, @page), class: "btn btn-grouped" do
+    = link_to history_namespace_project_wiki_path(@project.namespace, @project, @page), class: "btn btn-grouped" do
       Page History
     - if can?(current_user, :write_wiki, @project)
-      = link_to edit_project_wiki_path(@project, @page), class: "btn btn-grouped" do
+      = link_to edit_namespace_project_wiki_path(@project.namespace, @project, @page), class: "btn btn-grouped" do
         %i.fa.fa-pencil-square-o
         Edit
diff --git a/app/views/projects/wikis/_nav.html.haml b/app/views/projects/wikis/_nav.html.haml
index 90539fde583a2394754227159e930253e84733a7..693c3facb3286c1f8e9805d2e37fcfe578ee6448 100644
--- a/app/views/projects/wikis/_nav.html.haml
+++ b/app/views/projects/wikis/_nav.html.haml
@@ -1,12 +1,12 @@
 %ul.nav.nav-tabs
   = nav_link(html_options: {class: params[:id] == 'home' ? 'active' : '' }) do
-    = link_to 'Home', project_wiki_path(@project, :home)
+    = link_to 'Home', namespace_project_wiki_path(@project.namespace, @project, :home)
 
   = nav_link(path: 'wikis#pages') do
-    = link_to 'Pages', pages_project_wikis_path(@project)
+    = link_to 'Pages', pages_namespace_project_wikis_path(@project.namespace, @project)
 
   = nav_link(path: 'wikis#git_access') do
-    = link_to git_access_project_wikis_path(@project) do
+    = link_to git_access_namespace_project_wikis_path(@project.namespace, @project) do
       %i.fa.fa-download
       Git Access
 
diff --git a/app/views/projects/wikis/_new.html.haml b/app/views/projects/wikis/_new.html.haml
index 1ce292a02dfbd0f611cd1c3bf8bc491b05998cc7..6834969de8b44e3a77b57b5f05fc6758d44e23d3 100644
--- a/app/views/projects/wikis/_new.html.haml
+++ b/app/views/projects/wikis/_new.html.haml
@@ -7,7 +7,7 @@
       .modal-body
         = label_tag :new_wiki_path do
           %span Page slug
-        = text_field_tag :new_wiki_path, nil, placeholder: 'how-to-setup', class: 'form-control', required: true, :'data-wikis-path' => project_wikis_path(@project)
+        = text_field_tag :new_wiki_path, nil, placeholder: 'how-to-setup', class: 'form-control', required: true, :'data-wikis-path' => namespace_project_wikis_path(@project.namespace, @project)
         %p.hint
           Please don't use spaces.
       .modal-footer
diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml
index 5347caf000a4e3e1248edede24a1c6e2211ada6a..566850cb78d3487b10593cc71ae2aa8e41c3d203 100644
--- a/app/views/projects/wikis/edit.html.haml
+++ b/app/views/projects/wikis/edit.html.haml
@@ -9,5 +9,5 @@
 
 .pull-right
   - if @page.persisted? && can?(current_user, :admin_wiki, @project)
-    = link_to project_wiki_path(@project, @page), data: { confirm: "Are you sure you want to delete this page?"}, method: :delete, class: "btn btn-small btn-remove" do
+    = link_to namespace_project_wiki_path(@project.namespace, @project, @page), data: { confirm: "Are you sure you want to delete this page?"}, method: :delete, class: "btn btn-sm btn-remove" do
       Delete this page
diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml
index ef4b8f74714eaadd00457523b80acfa43982fd33..91291f753f772e66b579fa0c97cecfcfb8a69aab 100644
--- a/app/views/projects/wikis/history.html.haml
+++ b/app/views/projects/wikis/history.html.haml
@@ -1,7 +1,7 @@
 = render 'nav'
 %h3.page-title
   %span.light History for
-  = link_to @page.title, project_wiki_path(@project, @page)
+  = link_to @page.title, namespace_project_wiki_path(@project.namespace, @project, @page)
 
 %table.table
   %thead
@@ -12,18 +12,19 @@
       %th Last updated
       %th Format
   %tbody
-    - @page.versions.each do |version|
+    - @page.versions.each_with_index do |version, index|
       - commit = version
       %tr
         %td
-          = link_to project_wiki_path(@project, @page, version_id: commit.id) do
+          = link_to project_wiki_path_with_version(@project, @page,
+                                                   commit.id, index == 0) do
             = truncate_sha(commit.id)
         %td
           = commit.author.name
         %td
           = commit.message
         %td
-          #{time_ago_with_tooltip(version.date)}
+          #{time_ago_with_tooltip(version.authored_date)}
         %td
           %strong
             = @page.page.wiki.page(@page.page.name, commit.id).try(:format)
diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml
index 264b48ec36c057fdb2d4667e9e9173583917c6a5..ee233d9086f99d02406169cf9881d7dec7cd40ba 100644
--- a/app/views/projects/wikis/pages.html.haml
+++ b/app/views/projects/wikis/pages.html.haml
@@ -5,7 +5,7 @@
   - @wiki_pages.each do |wiki_page|
     %li
       %h4
-        = link_to wiki_page.title, project_wiki_path(@project, wiki_page)
+        = link_to wiki_page.title, namespace_project_wiki_path(@project.namespace, @project, wiki_page)
         %small (#{wiki_page.format})
         .pull-right
           %small Last edited #{time_ago_with_tooltip(wiki_page.commit.authored_date)}
diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml
index ede4fef9e24a696ef017c961d228792d0080759c..a6263e93f678e515a11429df7755a25772b0af66 100644
--- a/app/views/projects/wikis/show.html.haml
+++ b/app/views/projects/wikis/show.html.haml
@@ -5,7 +5,7 @@
 - if @page.historical?
   .warning_message
     This is an old version of this page.
-    You can view the #{link_to "most recent version", project_wiki_path(@project, @page)} or browse the #{link_to "history", history_project_wiki_path(@project, @page)}.
+    You can view the #{link_to "most recent version", namespace_project_wiki_path(@project.namespace, @project, @page)} or browse the #{link_to "history", history_namespace_project_wiki_path(@project.namespace, @project, @page)}.
 
 %hr
 
diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml
index eca69ce50b1f55840c83e487fe1b03375a404769..ffc145497abe08dbd90335d997b3cc7272d7a0d8 100644
--- a/app/views/search/_filter.html.haml
+++ b/app/views/search/_filter.html.haml
@@ -1,5 +1,5 @@
 .dropdown.inline
-  %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
+  %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'}
     %i.fa.fa-tags
     %span.light Group:
     - if @group.present?
@@ -17,7 +17,7 @@
           = group.name
 
 .dropdown.inline.prepend-left-10.project-filter
-  %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
+  %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'}
     %i.fa.fa-tags
     %span.light Project:
     - if @project.present?
diff --git a/app/views/search/_project_filter.html.haml b/app/views/search/_project_filter.html.haml
index c201b3d6c472f7b831d0a1987b345975c9e673cb..ad933502a282d928dd92c93c9f604b1f480936bd 100644
--- a/app/views/search/_project_filter.html.haml
+++ b/app/views/search/_project_filter.html.haml
@@ -25,6 +25,7 @@
         = @search_results.notes_count
   %li{class: ("active" if @scope == 'wiki_blobs')}
     = link_to search_filter_path(scope: 'wiki_blobs') do
+      %i.fa.fa-book
       Wiki
       .pull-right
         = @search_results.wiki_blobs_count
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index 58bcff9dbe33258891795ea9b42d85ca3feacf44..796dd752a4c8db68a17e067080dd7a97c3c2a79a 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -2,7 +2,7 @@
   #{@search_results.total_count} results found
   - unless @show_snippets
     - if @project
-      for #{link_to @project.name_with_namespace, @project}
+      for #{link_to @project.name_with_namespace, [@project.namespace.becomes(Namespace), @project]}
     - elsif @group
       for #{link_to @group.name, @group}
 
diff --git a/app/views/search/results/_blob.html.haml b/app/views/search/results/_blob.html.haml
index b46b4832e19a51567fe0badbbe0e80f7cff504d6..84e9be82c444e2596cc2c95472ed282a9e5dd18f 100644
--- a/app/views/search/results/_blob.html.haml
+++ b/app/views/search/results/_blob.html.haml
@@ -1,9 +1,9 @@
 .blob-result
   .file-holder
     .file-title
-      = link_to project_blob_path(@project, tree_join(blob.ref, blob.filename), :anchor => "L" + blob.startline.to_s) do
+      = link_to namespace_project_blob_path(@project.namespace, @project, tree_join(blob.ref, blob.filename), :anchor => "L" + blob.startline.to_s) do
         %i.fa.fa-file
         %strong
           = blob.filename
     .file-content.code.term
-      = render 'shared/file_hljs', blob: blob, first_line_number: blob.startline
+      = render 'shared/file_highlight', blob: blob, first_line_number: blob.startline, user_color_scheme_class: 'white'
diff --git a/app/views/search/results/_issue.html.haml b/app/views/search/results/_issue.html.haml
index 7868f958261cabe3072a5cbb0eda1695af104542..ce8ddff955690ea4895580cdb23945e75fd8bd7d 100644
--- a/app/views/search/results/_issue.html.haml
+++ b/app/views/search/results/_issue.html.haml
@@ -1,6 +1,6 @@
 .search-result-row
   %h4
-    = link_to [issue.project, issue] do
+    = link_to [issue.project.namespace.becomes(Namespace), issue.project, issue] do
       %span.term.str-truncated= issue.title
     .pull-right ##{issue.iid}
   - if issue.description.present?
diff --git a/app/views/search/results/_merge_request.html.haml b/app/views/search/results/_merge_request.html.haml
index 56b185283bd0bbda7866aae688e2af9e698669a2..2efa616d6644e453a53415d6fcf8fbdac5eb4c33 100644
--- a/app/views/search/results/_merge_request.html.haml
+++ b/app/views/search/results/_merge_request.html.haml
@@ -1,6 +1,6 @@
 .search-result-row
   %h4
-    = link_to [merge_request.target_project, merge_request] do
+    = link_to [merge_request.target_project.namespace.becomes(Namespace), merge_request.target_project, merge_request] do
       %span.term.str-truncated= merge_request.title
     .pull-right ##{merge_request.iid}
   - if merge_request.description.present?
diff --git a/app/views/search/results/_note.html.haml b/app/views/search/results/_note.html.haml
index a44a4542df50842d0d19a4e7caa0317107ec5da7..5fcba2b7e93b22938d73635dad5295ceb476329b 100644
--- a/app/views/search/results/_note.html.haml
+++ b/app/views/search/results/_note.html.haml
@@ -9,7 +9,7 @@
       = link_to project do
         = project.name_with_namespace
       &middot;
-      = link_to project_commit_path(project, note.commit_id, anchor: dom_id(note)) do
+      = link_to namespace_project_commit_path(project.namespace, project, note.commit_id, anchor: dom_id(note)) do
         Commit #{truncate_sha(note.commit_id)}
     - else
       = link_to project do
@@ -17,7 +17,7 @@
       &middot;
       %span #{note.noteable_type.titleize} ##{note.noteable.iid}
       &middot;
-      = link_to [project, note.noteable, anchor: dom_id(note)]  do
+      = link_to [project.namespace.becomes(Namespace), project, note.noteable, anchor: dom_id(note)]  do
         = note.noteable.title
 
   .note-search-result
diff --git a/app/views/search/results/_project.html.haml b/app/views/search/results/_project.html.haml
index 301b65eca2964e78294a1943e64f2a2f77e02275..195cf06c8ea73fa1b208d7f7556ddef491985ae8 100644
--- a/app/views/search/results/_project.html.haml
+++ b/app/views/search/results/_project.html.haml
@@ -1,6 +1,6 @@
 .search-result-row
   %h4
-    = link_to project do
+    = link_to [project.namespace.becomes(Namespace), project] do
       %span.term= project.name_with_namespace
   - if project.description.present?
     %span.light.term= project.description
diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml
index 6fc2cdf6362c4a991cb2f28b05e4315d017c1766..8af393777f0c32d4dde8597c762967769d1ae366 100644
--- a/app/views/search/results/_snippet_blob.html.haml
+++ b/app/views/search/results/_snippet_blob.html.haml
@@ -13,12 +13,6 @@
       .file-title
         %i.fa.fa-file
         %strong= snippet_blob[:snippet_object].file_name
-        %span.options
-          .btn-group.tree-btn-group.pull-right
-            - if snippet_blob[:snippet_object].author == current_user
-              = link_to "Edit", edit_snippet_path(snippet_blob[:snippet_object]), class: "btn btn-tiny", title: 'Edit Snippet'
-              = link_to "Delete", snippet_path(snippet_blob[:snippet_object]), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-tiny", title: 'Delete Snippet'
-            = link_to "Raw", raw_snippet_path(snippet_blob[:snippet_object]), class: "btn btn-tiny", target: "_blank"
       - if gitlab_markdown?(snippet_blob[:snippet_object].file_name)
         .file-content.wiki
           - snippet_blob[:snippet_chunks].each do |snippet|
diff --git a/app/views/search/results/_snippet_title.html.haml b/app/views/search/results/_snippet_title.html.haml
index f7e5ee5e20e67f0e13d62509dd2cdf510791f7ac..c414acb6a11118080b000133a372f6df57984bc9 100644
--- a/app/views/search/results/_snippet_title.html.haml
+++ b/app/views/search/results/_snippet_title.html.haml
@@ -11,7 +11,7 @@
 
   %small.pull-right.cgray
     - if snippet_title.project_id?
-      = link_to snippet_title.project.name_with_namespace, project_path(snippet_title.project)
+      = link_to snippet_title.project.name_with_namespace, namespace_project_path(snippet_title.project.namespace, snippet_title.project)
 
   .snippet-info
     = "##{snippet_title.id}"
diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml
index e361074b6a0bf14439c24e7548bc5a3f2a77d0ae..f9c5810e3d057962ec92eb8f913e3b7b2c93b4ed 100644
--- a/app/views/search/results/_wiki_blob.html.haml
+++ b/app/views/search/results/_wiki_blob.html.haml
@@ -1,9 +1,9 @@
 .blob-result
   .file-holder
     .file-title
-      = link_to project_wiki_path(@project, wiki_blob.filename) do
+      = link_to namespace_project_wiki_path(@project.namespace, @project, wiki_blob.filename) do
         %i.fa.fa-file
         %strong
           = wiki_blob.filename
     .file-content.code.term
-      = render 'shared/file_hljs', blob: wiki_blob, first_line_number: wiki_blob.startline
+      = render 'shared/file_highlight', blob: wiki_blob, first_line_number: wiki_blob.startline, user_color_scheme_class: 'white'
diff --git a/app/views/shared/_choose_group_avatar_button.html.haml b/app/views/shared/_choose_group_avatar_button.html.haml
index f32c2d388a7b6446c07437665127ad01e5fbf99a..000532b1c9a8f8ae71a271345c35eb28bd36f34b 100644
--- a/app/views/shared/_choose_group_avatar_button.html.haml
+++ b/app/views/shared/_choose_group_avatar_button.html.haml
@@ -1,7 +1,7 @@
-%a.choose-btn.btn.btn-small.js-choose-group-avatar-button
+%a.choose-btn.btn.btn-sm.js-choose-group-avatar-button
   %i.fa.fa-paperclip
   %span Choose File ...
 &nbsp;
 %span.file_name.js-avatar-filename File name...
 = f.file_field :avatar, class: 'js-group-avatar-input hidden'
-.light The maximum file size allowed is 100KB.
+.light The maximum file size allowed is 200KB.
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index 1cc6043f56bb73a9dba9d6491cbd061d0342e892..a1121750ca349e0b25ba94fdf77a228385660789 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -1,8 +1,20 @@
 - project = project || @project
 .git-clone-holder.input-group
   .input-group-btn
-    %button{class: "btn #{ 'active' if default_clone_protocol == 'ssh' }", :"data-clone" => project.ssh_url_to_repo} SSH
-    %button{class: "btn #{ 'active' if default_clone_protocol == 'http' }", :"data-clone" => project.http_url_to_repo}= gitlab_config.protocol.upcase
+    %button{ |
+      class: "btn #{ 'active' if default_clone_protocol == 'ssh' }#{ ' has_tooltip' if current_user && current_user.require_ssh_key? }", |
+      :"data-clone" => project.ssh_url_to_repo, |
+      :"data-title" => "Add an SSH key to your profile<br> to pull or push via SSH",
+      :"data-html" => "true",
+      :"data-container" => "body"}
+      SSH
+    %button{ |
+      class: "btn #{ 'active' if default_clone_protocol == 'http' }#{ ' has_tooltip' if current_user && current_user.require_password? }", |
+      :"data-clone" => project.http_url_to_repo, |
+      :"data-title" => "Set a password on your account<br> to pull or push via #{gitlab_config.protocol.upcase}",
+      :"data-html" => "true",
+      :"data-container" => "body"}
+      = gitlab_config.protocol.upcase
   = text_field_tag :project_clone, default_url_to_repo(project), class: "one_click_select form-control", readonly: true
   - if project.kind_of?(Project)
     .input-group-addon
diff --git a/app/views/shared/_commit_message_replace_container.html.haml b/app/views/shared/_commit_message_replace_container.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..99097b884755c34f461faa7bc307e13e0d73c092
--- /dev/null
+++ b/app/views/shared/_commit_message_replace_container.html.haml
@@ -0,0 +1,14 @@
+.form-group.commit_message-group
+  = label_tag 'commit_message_replace', class: 'control-label' do
+    Commit message
+  .col-sm-10
+    .commit-message-replace-container
+      .max-width-marker
+      = text_area_tag 'commit_message_replace',
+          (params[:commit_message_replace] || local_assigns[:text]),
+          class: 'form-control', placeholder: local_assigns[:placeholder],
+          required: true, rows: (local_assigns[:rows] || 3)
+    - if local_assigns[:hint]
+      %p.hint
+        Try to keep the first line under 52 characters
+        and the others under 72.
diff --git a/app/views/shared/_event_filter.html.haml b/app/views/shared/_event_filter.html.haml
index ee0b57fbe5afc2f3a7d9eb71cc51e044bfdf1368..d07a9e2b92468860f9b77d3345b27dc6fff5e97c 100644
--- a/app/views/shared/_event_filter.html.haml
+++ b/app/views/shared/_event_filter.html.haml
@@ -1,5 +1,19 @@
-.event_filter
+%ul.nav.nav-pills.event_filter
   = event_filter_link EventFilter.push, 'Push events'
   = event_filter_link EventFilter.merged, 'Merge events'
   = event_filter_link EventFilter.comments, 'Comments'
   = event_filter_link EventFilter.team, 'Team'
+
+  - if current_user
+    - if current_controller?(:dashboard)
+      %li.pull-right
+        = link_to dashboard_path(:atom, { private_token: current_user.private_token }), class: 'rss-btn' do
+          %i.fa.fa-rss
+          News Feed
+
+    - if current_controller?(:groups)
+      %li.pull-right
+        = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed", class: 'rss-btn' do
+          %i.fa.fa-rss
+          News Feed
+%hr
diff --git a/app/views/shared/_file_hljs.html.haml b/app/views/shared/_file_highlight.html.haml
similarity index 66%
rename from app/views/shared/_file_hljs.html.haml
rename to app/views/shared/_file_highlight.html.haml
index 444c948b0267e95f38d13df48792e5006a9a84e7..fba69dd0f3fb2974adb6d3ad2e9e2b9002f785b2 100644
--- a/app/views/shared/_file_hljs.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -1,4 +1,4 @@
-%div.highlighted-data{class: user_color_scheme_class}
+.file-content.code{class: user_color_scheme_class}
   .line-numbers
     - if blob.data.present?
       - blob.data.lines.to_a.size.times do |index|
@@ -7,7 +7,5 @@
         = link_to "#L#{i}", id: "L#{i}", rel: "#L#{i}" do
           %i.fa.fa-link
           = i
-  .highlight
-    %pre
-      %code{ class: highlightjs_class(blob.name) }
-        #{blob.data}
+  :preserve
+    #{highlight(blob.name, blob.data)}
diff --git a/app/views/shared/_filter.html.haml b/app/views/shared/_filter.html.haml
deleted file mode 100644
index d366dd97a71b4a4cce80977f18e219d1e2ba12e3..0000000000000000000000000000000000000000
--- a/app/views/shared/_filter.html.haml
+++ /dev/null
@@ -1,50 +0,0 @@
-.side-filters
-  = form_tag filter_path(entity), method: 'get' do
-    - if current_user
-      %fieldset.scope-filter
-        %ul.nav.nav-pills.nav-stacked
-          %li{class: ("active" if params[:scope] == 'assigned-to-me')}
-            = link_to filter_path(entity, scope: 'assigned-to-me') do
-              Assigned to me
-              %span.pull-right
-                = assigned_entities_count(current_user, entity, @group)
-          %li{class: ("active" if params[:scope] == 'authored')}
-            = link_to filter_path(entity, scope: 'authored') do
-              Created by me
-              %span.pull-right
-                = authored_entities_count(current_user, entity, @group)
-          %li{class: ("active" if params[:scope] == 'all')}
-            = link_to filter_path(entity, scope: 'all') do
-              Everyone's
-              %span.pull-right
-                = authorized_entities_count(current_user, entity, @group)
-
-    %fieldset.status-filter
-      %legend State
-      %ul.nav.nav-pills
-        %li{class: ("active" if params[:state] == 'opened')}
-          = link_to filter_path(entity, state: 'opened') do
-            Open
-        %li{class: ("active" if params[:state] == 'closed')}
-          = link_to filter_path(entity, state: 'closed') do
-            Closed
-        %li{class: ("active" if params[:state] == 'all')}
-          = link_to filter_path(entity, state: 'all') do
-            All
-
-    %fieldset
-      %legend Projects
-      %ul.nav.nav-pills.nav-stacked.nav-small
-        - @projects.each do |project|
-          - unless entities_per_project(project, entity).zero?
-            %li{class: ("active" if params[:project_id] == project.id.to_s)}
-              = link_to filter_path(entity, project_id: project.id) do
-                = project.name_with_namespace
-                %small.pull-right= entities_per_project(project, entity)
-
-    %fieldset
-      - if params[:state].present? || params[:project_id].present?
-        = link_to filter_path(entity, state: nil, project_id: nil), class: 'pull-right cgray' do
-          %i.fa.fa-times
-          %strong Clear filter
-
diff --git a/app/views/shared/_group_form.html.haml b/app/views/shared/_group_form.html.haml
index 93294e4250541d4e4fd13e4873b69b33424bd794..c0a9923348e72b49d8d1bd6d18f177fd06d2ea5b 100644
--- a/app/views/shared/_group_form.html.haml
+++ b/app/views/shared/_group_form.html.haml
@@ -1,9 +1,26 @@
+- if @group.persisted?
+  .form-group
+    = f.label :name, class: 'control-label' do
+      Group name
+    .col-sm-10
+      = f.text_field :name, placeholder: 'open-source', class: 'form-control'
+
 .form-group
-  = f.label :name, class: 'control-label' do
-    Group name
+  = f.label :path, class: 'control-label' do
+    Group path
   .col-sm-10
-    = f.text_field :name, placeholder: 'Example Group', class: 'form-control',
-        autofocus: local_assigns[:autofocus] || false
+    .input-group
+      .input-group-addon
+        = root_url
+      = f.text_field :path, placeholder: 'open-source', class: 'form-control',
+          autofocus: local_assigns[:autofocus] || false
+    - if @group.persisted?
+      .alert.alert-warning.prepend-top-10
+        %ul
+          %li Changing group path can have unintended side effects.
+          %li Renaming group path will rename directory for all related projects
+          %li It will change web url for access group and group projects.
+          %li It will change the git path to repositories under this group.
 
 .form-group.group-description-holder
   = f.label :description, 'Details', class: 'control-label'
diff --git a/app/views/shared/_issuable_filter.html.haml b/app/views/shared/_issuable_filter.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f169733f2e96ac1da31c522c64d690710147dd0d
--- /dev/null
+++ b/app/views/shared/_issuable_filter.html.haml
@@ -0,0 +1,58 @@
+.issues-filters
+  .issues-state-filters
+    %ul.nav.nav-tabs
+      %li{class: ("active" if params[:state] == 'opened')}
+        = link_to page_filter_path(state: 'opened') do
+          %i.fa.fa-exclamation-circle
+          Open
+      %li{class: ("active" if params[:state] == 'closed')}
+        = link_to page_filter_path(state: 'closed') do
+          %i.fa.fa-check-circle
+          Closed
+      %li{class: ("active" if params[:state] == 'all')}
+        = link_to page_filter_path(state: 'all') do
+          %i.fa.fa-compass
+          All
+
+  .issues-details-filters
+    = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_id, :label_name]), method: :get, class: 'filter-form' do
+      - if controller.controller_name == 'issues'
+        .check-all-holder
+          = check_box_tag "check_all_issues", nil, false,
+            class: "check_all_issues left",
+            disabled: !can?(current_user, :modify_issue, @project)
+      .issues-other-filters
+        .filter-item.inline
+          = users_select_tag(:assignee_id, selected: params[:assignee_id],
+            placeholder: 'Assignee', class: 'trigger-submit', any_user: true, null_user: true)
+
+        .filter-item.inline
+          = users_select_tag(:author_id, selected: params[:author_id],
+            placeholder: 'Author', class: 'trigger-submit', any_user: true)
+
+        .filter-item.inline.milestone-filter
+          = select_tag('milestone_id', projects_milestones_options, class: "select2 trigger-submit", prompt: 'Milestone')
+
+        - if @project
+          .filter-item.inline.labels-filter
+            = select_tag('label_name', project_labels_options(@project), class: "select2 trigger-submit", prompt: 'Label')
+
+        .pull-right
+          = render 'shared/sort_dropdown'
+
+    - if controller.controller_name == 'issues'
+      .issues_bulk_update.hide
+        = form_tag bulk_update_namespace_project_issues_path(@project.namespace, @project), method: :post  do
+          = select_tag('update[state_event]', options_for_select([['Open', 'reopen'], ['Closed', 'close']]), prompt: "Status", class: 'form-control')
+          = users_select_tag('update[assignee_id]', placeholder: 'Assignee', null_user: true)
+          = select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone")
+          = hidden_field_tag 'update[issues_ids]', []
+          = hidden_field_tag :state_event, params[:state_event]
+          = button_tag "Update issues", class: "btn update_selected_issues btn-save"
+
+:coffeescript
+  new UsersSelect()
+
+  $('form.filter-form').on 'submit', (event) ->
+    event.preventDefault()
+    Turbolinks.visit @.action + '&' + $(@).serialize()
diff --git a/app/views/shared/_issuable_search_form.html.haml b/app/views/shared/_issuable_search_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..639d203dcd69007e543e4d433301685a1796dd0c
--- /dev/null
+++ b/app/views/shared/_issuable_search_form.html.haml
@@ -0,0 +1,9 @@
+= form_tag(path, method: :get, id: "issue_search_form", class: 'pull-left issue-search-form') do
+  .append-right-10.hidden-xs.hidden-sm
+    = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by title or description', class: 'form-control issue_search search-text-input input-mn-300' }
+    = hidden_field_tag :state, params['state']
+    = hidden_field_tag :scope, params['scope']
+    = hidden_field_tag :assignee_id, params['assignee_id']
+    = hidden_field_tag :author_id, params['author_id']
+    = hidden_field_tag :milestone_id, params['milestone_id']
+    = hidden_field_tag :label_id, params['label_id']
diff --git a/app/views/shared/_issues.html.haml b/app/views/shared/_issues.html.haml
index e976f897dc9b48b6e935d0b52d9a60061e0bd99c..0dbb6a04393720ada519a3b81d158f1a6e7f6b27 100644
--- a/app/views/shared/_issues.html.haml
+++ b/app/views/shared/_issues.html.haml
@@ -4,7 +4,7 @@
       - project = group[0]
       .panel-heading
         = link_to_project project
-        = link_to 'show all', project_issues_path(project), class: 'pull-right'
+        = link_to 'show all', namespace_project_issues_path(project.namespace, project), class: 'pull-right'
 
       %ul.well-list.issues-list
         - group[1].each do |issue|
diff --git a/app/views/shared/_merge_requests.html.haml b/app/views/shared/_merge_requests.html.haml
index 39a1ee38f8e0371bb043d044425ef7f940948bf1..c02c5af008a35deffb3599f5c40ac886827e6744 100644
--- a/app/views/shared/_merge_requests.html.haml
+++ b/app/views/shared/_merge_requests.html.haml
@@ -4,7 +4,7 @@
       - project = group[0]
       .panel-heading
         = link_to_project project
-        = link_to 'show all', project_merge_requests_path(project), class: 'pull-right'
+        = link_to 'show all', namespace_project_merge_requests_path(project.namespace, project), class: 'pull-right'
       %ul.well-list.mr-list
         - group[1].each do |merge_request|
           = render 'projects/merge_requests/merge_request', merge_request: merge_request
diff --git a/app/views/shared/_milestones_filter.html.haml b/app/views/shared/_milestones_filter.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f685ae7726c62090cb6d495e18b24ba44edee478
--- /dev/null
+++ b/app/views/shared/_milestones_filter.html.haml
@@ -0,0 +1,14 @@
+.milestones-filters.append-bottom-10
+  %ul.nav.nav-tabs
+    %li{class: ("active" if params[:state].blank? || params[:state] == 'opened')}
+      = link_to milestones_filter_path(state: 'opened') do
+        %i.fa.fa-exclamation-circle
+        Open
+    %li{class: ("active" if params[:state] == 'closed')}
+      = link_to milestones_filter_path(state: 'closed') do
+        %i.fa.fa-check-circle
+        Closed
+    %li{class: ("active" if params[:state] == 'all')}
+      = link_to milestones_filter_path(state: 'all') do
+        %i.fa.fa-compass
+        All
diff --git a/app/views/shared/_no_password.html.haml b/app/views/shared/_no_password.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..a43bf33751a9365520535d0e569e4842528541d6
--- /dev/null
+++ b/app/views/shared/_no_password.html.haml
@@ -0,0 +1,8 @@
+- if cookies[:hide_no_password_message].blank? && !current_user.hide_no_password && current_user.require_password?
+  .no-password-message.alert.alert-warning.hidden-xs
+    You won't be able to pull or push project code via #{gitlab_config.protocol.upcase} until you #{link_to 'set a password', edit_profile_password_path} on your account
+
+    .pull-right
+      = link_to "Don't show again", profile_path(user: {hide_no_password: true}), method: :put
+      |
+      = link_to 'Remind later', '#', class: 'hide-no-password-message'
diff --git a/app/views/shared/_no_ssh.html.haml b/app/views/shared/_no_ssh.html.haml
index e70eb4d01b99e7d6b6fb6dfa2194ba9432ea9af0..089179e677aee39c0b6d91b7859d8e4a9afb149b 100644
--- a/app/views/shared/_no_ssh.html.haml
+++ b/app/views/shared/_no_ssh.html.haml
@@ -1,14 +1,8 @@
-- if cookies[:hide_no_ssh_message].blank? && current_user.require_ssh_key? && !current_user.hide_no_ssh_key
-  .no-ssh-key-message
-    .container
-      You won't be able to pull or push project code via SSH until you #{link_to 'add an SSH key', new_profile_key_path} to your profile
-      .pull-right.hidden-xs
-        = link_to "Don't show again", profile_path(user: {hide_no_ssh_key: true}), method: :put, class: 'hide-no-ssh-message', remote: true
-        |
-        = link_to 'Remind later', '#', class: 'hide-no-ssh-message'
-      .links-xs.visible-xs
-        = link_to "Add key", new_profile_key_path
-        |
-        = link_to "Don't show again", profile_path(user: {hide_no_ssh_key: true}), method: :put, class: 'hide-no-ssh-message', remote: true
-        |
-        = link_to 'Later', '#', class: 'hide-no-ssh-message'
+- if cookies[:hide_no_ssh_message].blank? && !current_user.hide_no_ssh_key && current_user.require_ssh_key?
+  .no-ssh-key-message.alert.alert-warning.hidden-xs
+    You won't be able to pull or push project code via SSH until you #{link_to 'add an SSH key', new_profile_key_path, class: 'alert-link'} to your profile
+
+    .pull-right
+      = link_to "Don't show again", profile_path(user: {hide_no_ssh_key: true}), method: :put, class: 'alert-link'
+      |
+      = link_to 'Remind later', '#', class: 'hide-no-ssh-message alert-link'
diff --git a/app/views/shared/_outdated_browser.html.haml b/app/views/shared/_outdated_browser.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..0eba1fe075f35762dbe37f0bae29c77dbfe02db7
--- /dev/null
+++ b/app/views/shared/_outdated_browser.html.haml
@@ -0,0 +1,8 @@
+- if outdated_browser?
+  - link = "https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/requirements.md#supported-web-browsers"
+  .browser-alert
+    GitLab may not work properly because you are using an outdated web browser.
+    %br
+    Please install a
+    = link_to 'supported web browser', link
+    for a better experience.
diff --git a/app/views/shared/_project.html.haml b/app/views/shared/_project.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..8746970c239a269c3bc8723da4b8ff78be887959
--- /dev/null
+++ b/app/views/shared/_project.html.haml
@@ -0,0 +1,21 @@
+= cache [project, controller.controller_name, controller.action_name] do
+  = link_to project_path(project), class: dom_class(project) do
+    - if avatar
+      .dash-project-avatar
+        = project_icon(project, alt: '', class: 'avatar project-avatar s40')
+    .dash-project-access-icon
+      = visibility_level_icon(project.visibility_level)
+    %span.str-truncated
+      %span.namespace-name
+        - if project.namespace
+          = project.namespace.human_name
+          \/
+      %span.project-name.filter-title
+        = project.name
+    - if stars
+      %span.pull-right.light
+        %i.fa.fa-star
+        = project.star_count
+    - else
+      %span.arrow
+        %i.fa.fa-angle-right
diff --git a/app/views/shared/_project_filter.html.haml b/app/views/shared/_project_filter.html.haml
deleted file mode 100644
index ea6a49e1501e38b6b3dddb2d6223bcb3034f0a9a..0000000000000000000000000000000000000000
--- a/app/views/shared/_project_filter.html.haml
+++ /dev/null
@@ -1,64 +0,0 @@
-.side-filters
-  = form_tag project_entities_path, method: 'get' do
-    - if current_user
-      %fieldset
-        %ul.nav.nav-pills.nav-stacked
-          %li{class: ("active" if params[:scope] == 'all')}
-            = link_to project_filter_path(scope: 'all') do
-              Everyone's
-              %span.pull-right
-                = authorized_entities_count(current_user, entity, @project)
-          %li{class: ("active" if params[:scope] == 'assigned-to-me')}
-            = link_to project_filter_path(scope: 'assigned-to-me') do
-              Assigned to me
-              %span.pull-right
-                = assigned_entities_count(current_user, entity, @project)
-          %li{class: ("active" if params[:scope] == 'created-by-me')}
-            = link_to project_filter_path(scope: 'created-by-me') do
-              Created by me
-              %span.pull-right
-                = authored_entities_count(current_user, entity, @project)
-
-    %fieldset
-      %legend State
-      %ul.nav.nav-pills
-        %li{class: ("active" if params[:state] == 'opened')}
-          = link_to project_filter_path(state: 'opened') do
-            Open
-        %li{class: ("active" if params[:state] == 'closed')}
-          = link_to project_filter_path(state: 'closed') do
-            Closed
-        %li{class: ("active" if params[:state] == 'all')}
-          = link_to project_filter_path(state: 'all') do
-            All
-
-    - if defined?(labels)
-      %fieldset
-        %legend
-          Labels
-          %small.pull-right
-            = link_to project_labels_path(@project), class: 'light' do
-              %i.fa.fa-pencil-square-o
-        %ul.nav.nav-pills.nav-stacked.nav-small.labels-filter
-          - @project.labels.order_by_name.each do |label|
-            %li{class: label_filter_class(label.name)}
-              = link_to labels_filter_path(label.name) do
-                = render_colored_label(label)
-                - if selected_label?(label.name)
-                  .pull-right
-                    %i.fa.fa-times
-
-        - if @project.labels.empty?
-          .light-well
-            Create first label at
-            = link_to 'labels page', project_labels_path(@project)
-            %br
-            or #{link_to 'generate', generate_project_labels_path(@project, redirect: redirect), method: :post} default set of labels
-
-    %fieldset
-      - if %w(state scope milestone_id assignee_id label_name).select { |k| params[k].present? }.any?
-        = link_to project_entities_path, class: 'cgray pull-right' do
-          %i.fa.fa-times
-          %strong Clear filter
-
-
diff --git a/app/views/shared/_projects_list.html.haml b/app/views/shared/_projects_list.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..4c58092af44ca17c60a75dd231dc87e5556bd179
--- /dev/null
+++ b/app/views/shared/_projects_list.html.haml
@@ -0,0 +1,17 @@
+- projects_limit = 20 unless local_assigns[:projects_limit]
+- avatar = true unless local_assigns[:avatar] == false
+- stars = false unless local_assigns[:stars] == true
+%ul.well-list.projects-list
+  - projects.each_with_index do |project, i|
+    %li{class: (i >= projects_limit) ? 'project-row hide' : 'project-row'}
+      = render "shared/project", project: project, avatar: avatar, stars: stars
+  - if projects.blank?
+    %li
+      .nothing-here-block There are no projects here.
+  - if projects.count > projects_limit
+    %li.bottom
+      %span.light
+        #{projects_limit} of #{pluralize(projects.count, 'project')} displayed.
+      %span
+        = link_to '#', class: 'js-expand' do
+          Show all
diff --git a/app/views/shared/_promo.html.haml b/app/views/shared/_promo.html.haml
index 3400c345c4c4008688c4056b55a989e04683705d..3596aabe309d14fc23ea7015fd834436e0d5443c 100644
--- a/app/views/shared/_promo.html.haml
+++ b/app/views/shared/_promo.html.haml
@@ -1,5 +1,5 @@
 .gitlab-promo
   = link_to 'Homepage', promo_url
   = link_to "Blog", promo_url + '/blog/'
-  = link_to "@gitlabhq", "https://twitter.com/gitlabhq"
+  = link_to "@gitlab", "https://twitter.com/gitlab"
   = link_to "Requests", "http://feedback.gitlab.com/"
diff --git a/app/views/shared/_ref_switcher.html.haml b/app/views/shared/_ref_switcher.html.haml
index 4d9534f49b1e3b2599d58007a5c07dfbf1656a17..eb2e1919e190541aae8b412ccab832b25dbfe79e 100644
--- a/app/views/shared/_ref_switcher.html.haml
+++ b/app/views/shared/_ref_switcher.html.haml
@@ -1,4 +1,4 @@
-= form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
+= form_tag switch_namespace_project_refs_path(@project.namespace, @project), method: :get, class: "project-refs-form" do
   = select_tag "ref", grouped_options_refs, class: "project-refs-select select2 select2-sm"
   = hidden_field_tag :destination, destination
   - if defined?(path)
diff --git a/app/views/shared/_sort_dropdown.html.haml b/app/views/shared/_sort_dropdown.html.haml
index 7b37b39780e50596097a9a74135039693e27ef65..af3d35de325d7465360f5764f600d5e2aa7b307c 100644
--- a/app/views/shared/_sort_dropdown.html.haml
+++ b/app/views/shared/_sort_dropdown.html.haml
@@ -1,22 +1,22 @@
 .dropdown.inline.prepend-left-10
-  %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
+  %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
     %span.light sort:
     - if @sort.present?
-      = @sort
+      = sort_options_hash[@sort]
     - else
-      Newest
+      = sort_title_recently_created
     %b.caret
-  %ul.dropdown-menu
+  %ul.dropdown-menu.dropdown-menu-align-right
     %li
-      = link_to project_filter_path(sort: 'newest') do
-        Newest
-      = link_to project_filter_path(sort: 'oldest') do
-        Oldest
-      = link_to project_filter_path(sort: 'recently_updated') do
-        Recently updated
-      = link_to project_filter_path(sort: 'last_updated') do
-        Last updated
-      = link_to project_filter_path(sort: 'milestone_due_soon') do
-        Milestone due soon
-      = link_to project_filter_path(sort: 'milestone_due_later') do
-        Milestone due later
+      = link_to page_filter_path(sort: sort_value_recently_created) do
+        = sort_title_recently_created
+      = link_to page_filter_path(sort: sort_value_oldest_created) do
+        = sort_title_oldest_created
+      = link_to page_filter_path(sort: sort_value_recently_updated) do
+        = sort_title_recently_updated
+      = link_to page_filter_path(sort: sort_value_oldest_updated) do
+        = sort_title_oldest_updated
+      = link_to page_filter_path(sort: sort_value_milestone_soon) do
+        = sort_title_milestone_soon
+      = link_to page_filter_path(sort: sort_value_milestone_later) do
+        = sort_title_milestone_later
diff --git a/app/views/shared/snippets/_blob.html.haml b/app/views/shared/snippets/_blob.html.haml
index 8cec6168ab83eeb07f6c0f0efa4a56da4641e378..30458793fd13e04ec7538cb3ded4ef91cc92dde0 100644
--- a/app/views/shared/snippets/_blob.html.haml
+++ b/app/views/shared/snippets/_blob.html.haml
@@ -8,7 +8,7 @@
       = render_markup(@snippet.file_name, @snippet.data)
   - else
     .file-content.code
-      = render 'shared/file_hljs', blob: @snippet
+      = render 'shared/file_highlight', blob: @snippet
 - else
   .file-content.code
     .nothing-here-block Empty file
diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml
index f729f129e45f45e9b57c512047ed3ed9dda20e64..4e0663ea2080b087a3226124394d2fddf324925a 100644
--- a/app/views/shared/snippets/_form.html.haml
+++ b/app/views/shared/snippets/_form.html.haml
@@ -30,7 +30,7 @@
         = f.submit 'Save', class: "btn-save btn"
 
       - if @snippet.respond_to?(:project)
-        = link_to "Cancel", project_snippets_path(@project), class: "btn btn-cancel"
+        = link_to "Cancel", namespace_project_snippets_path(@project.namespace, @project), class: "btn btn-cancel"
       - else
         = link_to "Cancel", snippets_path(@project), class: "btn btn-cancel"
 
diff --git a/app/views/snippets/_snippet.html.haml b/app/views/snippets/_snippet.html.haml
index c584dd8dfb671e16e9e2c902d783c31770cde683..5bb28664349416608c23b1c75db98a4ee406f63e 100644
--- a/app/views/snippets/_snippet.html.haml
+++ b/app/views/snippets/_snippet.html.haml
@@ -11,7 +11,7 @@
 
   %small.pull-right.cgray
     - if snippet.project_id?
-      = link_to snippet.project.name_with_namespace, project_path(snippet.project)
+      = link_to snippet.project.name_with_namespace, namespace_project_path(snippet.project.namespace, snippet.project)
 
   .snippet-info
     = "##{snippet.id}"
diff --git a/app/views/snippets/current_user_index.html.haml b/app/views/snippets/current_user_index.html.haml
index b2b7ea4df0ef97d8e0b0277aa8488905f7d0cca9..0df5ade500db382bb0e31ec111f6ff37204cc6e5 100644
--- a/app/views/snippets/current_user_index.html.haml
+++ b/app/views/snippets/current_user_index.html.haml
@@ -1,5 +1,5 @@
 %h3.page-title
-  My Snippets
+  Your Snippets
   .pull-right
     = link_to new_snippet_path, class: "btn btn-new btn-grouped", title: "New Snippet" do
       Add new snippet
diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml
index 0d71c41e2e7c502ae1a9624cece58eb28407d33b..5cd8ae26cf9c518bb647ab9876f96d8b815cade1 100644
--- a/app/views/snippets/index.html.haml
+++ b/app/views/snippets/index.html.haml
@@ -2,12 +2,12 @@
   Public snippets
 
   .pull-right
-    
+
     - if current_user
       = link_to new_snippet_path, class: "btn btn-new btn-grouped", title: "New Snippet" do
         Add new snippet
       = link_to user_snippets_path(current_user), class: "btn btn-grouped"  do
-        My snippets
+        Your snippets
 
 %p.light
   Public snippets created by you and other users are listed here
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index f5bc543de10a08ae19d44d79dd5ae45971bee731..55a990c94ed70320a492210777ed7008689789e5 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -23,7 +23,7 @@
   .back-link
     - if @snippet.author == current_user
       = link_to user_snippets_path(current_user) do
-        &larr; my snippets
+        &larr; your snippets
     - else
       = link_to snippets_path do
         &larr; discover snippets
@@ -31,13 +31,13 @@
 .file-holder
   .file-title
     %i.fa.fa-file
-    %span.file_name
+    %strong
       = @snippet.file_name
-    .options
+    .file-actions
       .btn-group
         - if can?(current_user, :modify_personal_snippet, @snippet)
-          = link_to "edit", edit_snippet_path(@snippet), class: "btn btn-small", title: 'Edit Snippet'
-        = link_to "raw", raw_snippet_path(@snippet), class: "btn btn-small", target: "_blank"
+          = link_to "edit", edit_snippet_path(@snippet), class: "btn btn-sm", title: 'Edit Snippet'
+        = link_to "raw", raw_snippet_path(@snippet), class: "btn btn-sm", target: "_blank"
       - if can?(current_user, :admin_personal_snippet, @snippet)
-        = link_to "remove", snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-small btn-remove", title: 'Delete Snippet'
+        = link_to "remove", snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-sm btn-remove", title: 'Delete Snippet'
   = render 'shared/snippets/blob'
diff --git a/app/views/snippets/user_index.html.haml b/app/views/snippets/user_index.html.haml
index 67f3a68aa22a614e127f85e6700469212bfb7ee5..df524cd18b0cb46b01612a3c6976605dccc336ba 100644
--- a/app/views/snippets/user_index.html.haml
+++ b/app/views/snippets/user_index.html.haml
@@ -5,7 +5,7 @@
     \/
     Snippets
   - if current_user
-    = link_to new_snippet_path, class: "btn btn-small add_new pull-right", title: "New Snippet" do
+    = link_to new_snippet_path, class: "btn btn-sm add_new pull-right", title: "New Snippet" do
       Add new snippet
 
 %hr
diff --git a/app/views/users/_groups.html.haml b/app/views/users/_groups.html.haml
index ea008c2dede73bc3a0a836c9557e57eb45ab5de7..f360fbb3d5d94159871f64e52cf0b9dae86a4886 100644
--- a/app/views/users/_groups.html.haml
+++ b/app/views/users/_groups.html.haml
@@ -1,3 +1,4 @@
-- groups.each do |group|
-  = link_to group, class: 'profile-groups-avatars', :title => group.name do
-    - image_tag group_icon(group.path)
+.clearfix
+  - groups.each do |group|
+    = link_to group, class: 'profile-groups-avatars inline', title: group.name do
+      = image_tag group_icon(group), class: 'avatar group-avatar s40'
diff --git a/app/views/users/_profile.html.haml b/app/views/users/_profile.html.haml
index 3b44959baad85de205a8e5af1445ae9e06b57678..bca71444956a9b4ad591ff60bb0f059b3ec2b9b9 100644
--- a/app/views/users/_profile.html.haml
+++ b/app/views/users/_profile.html.haml
@@ -12,7 +12,7 @@
     - unless user.linkedin.blank?
       %li
         %span.light LinkedIn:
-        %strong= user.linkedin
+        %strong= link_to user.linkedin, "http://www.linkedin.com/in/#{user.linkedin}"
     - unless user.twitter.blank?
       %li
         %span.light Twitter:
@@ -21,7 +21,7 @@
       %li
         %span.light Website:
         %strong= link_to user.short_website_url, user.full_website_url
-    - unless user.bio.blank?
+    - unless user.location.blank?
       %li
-        %span.light Bio:
-        %span= user.bio
+        %span.light Location:
+        %strong= user.location
diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml
index 1d38f8e8ab8b0838fe723b793feac72d8a1af8e3..b7383d5594e10d8b82b6d961751182a7ed954055 100644
--- a/app/views/users/_projects.html.haml
+++ b/app/views/users/_projects.html.haml
@@ -1,6 +1,13 @@
-.panel.panel-default
-  .panel-heading Personal projects
-  %ul.well-list
-    - projects.each do |project|
-      %li
-        = link_to_project project
+- if @contributed_projects.present?
+  .panel.panel-default.contributed-projects
+    .panel-heading Projects contributed to
+    = render 'shared/projects_list',
+      projects: @contributed_projects.sort_by(&:star_count).reverse,
+      projects_limit: 5, stars: true, avatar: false
+
+- if @projects.present?
+  .panel.panel-default
+    .panel-heading Personal projects
+    = render 'shared/projects_list',
+      projects: @projects.sort_by(&:star_count).reverse,
+      projects_limit: 10, stars: true, avatar: false
diff --git a/app/views/users/calendar.html.haml b/app/views/users/calendar.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..922b0c6cebf1cb1425ec056195bc15025cf434d2
--- /dev/null
+++ b/app/views/users/calendar.html.haml
@@ -0,0 +1,12 @@
+%h4
+  Contributions calendar
+  .pull-right
+    %small Issues, merge requests and push events
+#cal-heatmap.calendar
+  :javascript
+    new Calendar(
+      #{@timestamps.to_json},
+      #{@starting_year},
+      #{@starting_month},
+      '#{user_calendar_activities_path}'
+    );
diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..027a93a75fcd9ba317e1dc0b44c9e1b3035b1321
--- /dev/null
+++ b/app/views/users/calendar_activities.html.haml
@@ -0,0 +1,23 @@
+%h4.prepend-top-20
+  %span.light Contributions for
+  %strong #{@calendar_date.to_s(:short)}
+
+%ul.bordered-list
+  - @events.sort_by(&:created_at).each do |event|
+    %li
+      %span.light
+        %i.fa.fa-clock-o
+        = event.created_at.to_s(:time)
+      - if event.push?
+        #{event.action_name} #{event.ref_type} #{event.ref_name}
+      - else
+        = event_action_name(event)
+        - if event.target
+          %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target]
+
+      at
+      %strong
+        - if event.project
+          = link_to_project event.project
+        - else
+          = event.project_name
diff --git a/app/views/users/show.atom.builder b/app/views/users/show.atom.builder
new file mode 100644
index 0000000000000000000000000000000000000000..8fe30b23635fd58e414485a3a3510c36b135effe
--- /dev/null
+++ b/app/views/users/show.atom.builder
@@ -0,0 +1,12 @@
+xml.instruct!
+xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
+  xml.title   "Activity feed for #{@user.name}"
+  xml.link    href: user_url(@user, :atom), rel: "self", type: "application/atom+xml"
+  xml.link    href: user_url(@user), rel: "alternate", type: "text/html"
+  xml.id      projects_url
+  xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
+
+  @events.each do |event|
+    event_to_atom(xml, event)
+  end
+end
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index cb49c030af223ca3c308120596bc534d60d3e362..5e1d65e2ed836fc1a9fa042c7906fab860beeb33 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -1,26 +1,50 @@
 .row
-  .col-md-8
-    %h3.page-title
-      = image_tag avatar_icon(@user.email, 90), class: "avatar s90", alt: ''
-      = @user.name
-      - if @user == current_user
-        .pull-right
-          = link_to profile_path, class: 'btn' do
-            %i.fa.fa-pencil-square-o
-            Edit Profile settings
-      %br
-      %span.user-show-username #{@user.username}
-      %br
-      %small member since #{@user.created_at.stamp("Nov 12, 2031")}
+  = link_to '#aside', class: 'show-aside' do
+    %i.fa.fa-angle-left
+  %section.col-md-8
+    .header-with-avatar
+      = image_tag avatar_icon(@user.email, 90), class: "avatar avatar-tile s90", alt: ''
+      %h3
+        = @user.name
+        - if @user == current_user
+          .pull-right
+            = link_to profile_path, class: 'btn btn-sm' do
+              %i.fa.fa-pencil-square-o
+              Edit Profile settings
+      .username
+        @#{@user.username}
+      .description
+        - if @user.bio.present?
+          = @user.bio
+
     .clearfix
 
     - if @groups.any?
-      %h4 Groups:
-      = render 'groups', groups: @groups
+      .prepend-top-20
+        %h4 Groups
+        = render 'groups', groups: @groups
+        %hr
+
+    .hidden-xs
+      .user-calendar
+        %h4.center.light
+          %i.fa.fa-spinner.fa-spin
+      .user-calendar-activities
       %hr
-    %h4 User Activity:
-    = render @events
-  .col-md-4
+    %h4
+      User Activity
+
+      - if current_user
+        %span.rss-icon.pull-right
+          = link_to user_path(@user, :atom, { private_token: current_user.private_token }) do
+            %strong
+              %i.fa.fa-rss
+
+    .content_list
+    = spinner
+  %aside.col-md-4
     = render 'profile', user: @user
-    - if @projects.present?
-      = render 'projects', projects: @projects
+    = render 'projects'
+
+:coffeescript
+  $(".user-calendar").load("#{user_calendar_path}")
diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml
index 788d9065a7b43c26062b408a4aba9b65884395ee..36ea67420641ee8af1d63bf450107dc4e56f00ba 100644
--- a/app/views/votes/_votes_block.html.haml
+++ b/app/views/votes/_votes_block.html.haml
@@ -1,6 +1,10 @@
 .votes.votes-block
-  .progress
-    .progress-bar.progress-bar-success{style: "width: #{votable.upvotes_in_percent}%;"}
-    .progress-bar.progress-bar-danger{style: "width: #{votable.downvotes_in_percent}%;"}
-  .upvotes= "#{votable.upvotes} up"
-  .downvotes= "#{votable.downvotes} down"
+  .btn-group
+    - unless votable.upvotes.zero?
+      .btn.btn-sm.disabled.cgreen
+        %i.fa.fa-thumbs-up
+        = votable.upvotes
+    - unless votable.downvotes.zero?
+      .btn.btn-sm.disabled.cred
+        %i.fa.fa-thumbs-down
+        = votable.downvotes
diff --git a/app/views/votes/_votes_inline.html.haml b/app/views/votes/_votes_inline.html.haml
index ee80547483020630cd2edf93a4e423846c99295d..2cb3ae04e1a83b670b824993ee5a59e1dcf29684 100644
--- a/app/views/votes/_votes_inline.html.haml
+++ b/app/views/votes/_votes_inline.html.haml
@@ -1,9 +1,9 @@
 .votes.votes-inline
   - unless votable.upvotes.zero?
-    .upvotes
+    %span.upvotes.cgreen
       + #{votable.upvotes}
     - unless votable.downvotes.zero?
       \/
   - unless votable.downvotes.zero?
-    .downvotes
+    %span.downvotes.cred
       \- #{votable.downvotes}
diff --git a/app/workers/auto_merge_worker.rb b/app/workers/auto_merge_worker.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a6dd73eee5f81c8cff509d63b2294c0b05ae26a0
--- /dev/null
+++ b/app/workers/auto_merge_worker.rb
@@ -0,0 +1,13 @@
+class AutoMergeWorker
+  include Sidekiq::Worker
+
+  sidekiq_options queue: :default
+
+  def perform(merge_request_id, current_user_id, params)
+    params = params.with_indifferent_access
+    current_user = User.find(current_user_id)
+    merge_request = MergeRequest.find(merge_request_id)
+    merge_request.should_remove_source_branch = params[:should_remove_source_branch]
+    merge_request.automerge!(current_user, params[:commit_message])
+  end
+end
diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb
index e3f6f3a6aefa46056bed0b98351c73942da61889..1d21addece6df43d48a79a6c0e5d478c47e06ef3 100644
--- a/app/workers/emails_on_push_worker.rb
+++ b/app/workers/emails_on_push_worker.rb
@@ -1,25 +1,58 @@
 class EmailsOnPushWorker
   include Sidekiq::Worker
 
-  def perform(project_id, recipients, push_data)
+  def perform(project_id, recipients, push_data, options = {})
+    options.symbolize_keys!
+    options.reverse_merge!(
+      send_from_committer_email:  false, 
+      disable_diffs:              false
+    )
+    send_from_committer_email = options[:send_from_committer_email]
+    disable_diffs = options[:disable_diffs]
+
     project = Project.find(project_id)
     before_sha = push_data["before"]
     after_sha = push_data["after"]
-    branch = push_data["ref"]
+    ref = push_data["ref"]
     author_id = push_data["user_id"]
 
-    if before_sha =~ /^000000/ || after_sha =~ /^000000/
-      # skip if new branch was pushed or branch was removed
-      return true
-    end
+    action = 
+      if Gitlab::Git.blank_ref?(before_sha)
+        :create 
+      elsif Gitlab::Git.blank_ref?(after_sha)
+        :delete
+      else
+        :push
+      end
+
+    compare = nil
+    reverse_compare = false
+    if action == :push
+      compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha)
 
-    compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha)
+      return false if compare.same
 
-    # Do not send emails if git compare failed
-    return false unless compare && compare.commits.present?
+      if compare.commits.empty?
+        compare = Gitlab::Git::Compare.new(project.repository.raw_repository, after_sha, before_sha)
+
+        reverse_compare = true
+
+        return false if compare.commits.empty?
+      end
+    end
 
     recipients.split(" ").each do |recipient|
-      Notify.repository_push_email(project_id, recipient, author_id, branch, compare).deliver
+      Notify.repository_push_email(
+        project_id, 
+        recipient, 
+        author_id:                  author_id, 
+        ref:                        ref, 
+        action:                     action,
+        compare:                    compare, 
+        reverse_compare:            reverse_compare,
+        send_from_committer_email:  send_from_committer_email,
+        disable_diffs:              disable_diffs
+      ).deliver
     end
   ensure
     compare = nil
diff --git a/app/workers/irker_worker.rb b/app/workers/irker_worker.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8b50f423984f8f452b0c8ada50d6250143a6d7fb
--- /dev/null
+++ b/app/workers/irker_worker.rb
@@ -0,0 +1,169 @@
+require 'json'
+require 'socket'
+
+class IrkerWorker
+  include Sidekiq::Worker
+
+  def perform(project_id, chans, colors, push_data, settings)
+    project = Project.find(project_id)
+
+    # Get config parameters
+    return false unless init_perform settings, chans, colors
+
+    repo_name = push_data['repository']['name']
+    committer = push_data['user_name']
+    branch = push_data['ref'].gsub(%r'refs/[^/]*/', '')
+
+    if @colors
+      repo_name = "\x0304#{repo_name}\x0f"
+      branch = "\x0305#{branch}\x0f"
+    end
+
+    # Firsts messages are for branch creation/deletion
+    send_branch_updates push_data, project, repo_name, committer, branch
+
+    # Next messages are for commits
+    send_commits push_data, project, repo_name, committer, branch
+
+    close_connection
+    true
+  end
+
+  private
+
+  def init_perform(set, chans, colors)
+    @colors = colors
+    @channels = chans
+    start_connection set['server_ip'], set['server_port']
+  end
+
+  def start_connection(irker_server, irker_port)
+    begin
+      @socket = TCPSocket.new irker_server, irker_port
+    rescue Errno::ECONNREFUSED => e
+      logger.fatal "Can't connect to Irker daemon: #{e}"
+      return false
+    end
+    true
+  end
+
+  def sendtoirker(privmsg)
+    to_send = { to: @channels, privmsg: privmsg }
+    @socket.puts JSON.dump(to_send)
+  end
+
+  def close_connection
+    @socket.close
+  end
+
+  def send_branch_updates(push_data, project, repo_name, committer, branch)
+    if Gitlab::Git.blank_ref?(push_data['before'])
+      send_new_branch project, repo_name, committer, branch
+    elsif Gitlab::Git.blank_ref?(push_data['after'])
+      send_del_branch repo_name, committer, branch
+    end
+  end
+
+  def send_new_branch(project, repo_name, committer, branch)
+    repo_path = project.path_with_namespace
+    newbranch = "#{Gitlab.config.gitlab.url}/#{repo_path}/branches"
+    newbranch = "\x0302\x1f#{newbranch}\x0f" if @colors
+
+    privmsg = "[#{repo_name}] #{committer} has created a new branch "
+    privmsg += "#{branch}: #{newbranch}"
+    sendtoirker privmsg
+  end
+
+  def send_del_branch(repo_name, committer, branch)
+    privmsg = "[#{repo_name}] #{committer} has deleted the branch #{branch}"
+    sendtoirker privmsg
+  end
+
+  def send_commits(push_data, project, repo_name, committer, branch)
+    return if push_data['total_commits_count'] == 0
+
+    # Next message is for number of commit pushed, if any
+    if Gitlab::Git.blank_ref?(push_data['before'])
+      # Tweak on push_data["before"] in order to have a nice compare URL
+      push_data['before'] = before_on_new_branch push_data, project
+    end
+
+    send_commits_count(push_data, project, repo_name, committer, branch)
+
+    # One message per commit, limited by 3 messages (same limit as the
+    # github irc hook)
+    commits = push_data['commits'].first(3)
+    commits.each do |hook_attrs|
+      send_one_commit project, hook_attrs, repo_name, branch
+    end
+  end
+
+  def before_on_new_branch(push_data, project)
+    commit = commit_from_id project, push_data['commits'][0]['id']
+    parents = commit.parents
+    # Return old value if there's no new one
+    return push_data['before'] if parents.empty?
+    # Or return the first parent-commit
+    parents[0].id
+  end
+
+  def send_commits_count(data, project, repo, committer, branch)
+    url = compare_url data, project.path_with_namespace
+    commits = colorize_commits data['total_commits_count']
+
+    new_commits = 'new commit'
+    new_commits += 's' if data['total_commits_count'] > 1
+
+    sendtoirker "[#{repo}] #{committer} pushed #{commits} #{new_commits} " \
+                "to #{branch}: #{url}"
+  end
+
+  def compare_url(data, repo_path)
+    sha1 = Commit::truncate_sha(data['before'])
+    sha2 = Commit::truncate_sha(data['after'])
+    compare_url = "#{Gitlab.config.gitlab.url}/#{repo_path}/compare"
+    compare_url += "/#{sha1}...#{sha2}"
+    colorize_url compare_url
+  end
+
+  def send_one_commit(project, hook_attrs, repo_name, branch)
+    commit = commit_from_id project, hook_attrs['id']
+    sha = colorize_sha Commit::truncate_sha(hook_attrs['id'])
+    author = hook_attrs['author']['name']
+    files = colorize_nb_files(files_count commit)
+    title = commit.title
+
+    sendtoirker "#{repo_name}/#{branch} #{sha} #{author} (#{files}): #{title}"
+  end
+
+  def commit_from_id(project, id)
+    commit = Gitlab::Git::Commit.find(project.repository, id)
+    Commit.new(commit)
+  end
+
+  def files_count(commit)
+    files = "#{commit.diffs.count} file"
+    files += 's' if commit.diffs.count > 1
+    files
+  end
+
+  def colorize_sha(sha)
+    sha = "\x0314#{sha}\x0f" if @colors
+    sha
+  end
+
+  def colorize_nb_files(nb_files)
+    nb_files = "\x0312#{nb_files}\x0f" if @colors
+    nb_files
+  end
+
+  def colorize_url(url)
+    url = "\x0302\x1f#{url}\x0f" if @colors
+    url
+  end
+
+  def colorize_commits(commits)
+    commits = "\x02#{commits}\x0f" if @colors
+    commits
+  end
+end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 1406cba2db3210f4c9cb4d6b6e7b80e912f6bd7b..0c3ee6ba4ffa5a3c76a892c1e1e69919c88e43b2 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -21,7 +21,9 @@ class PostReceive
       return false
     end
 
-    changes = changes.lines if changes.kind_of?(String)
+    changes = Base64.decode64(changes) unless changes.include?(" ")
+    changes = utf8_encode_changes(changes)
+    changes = changes.lines
 
     changes.each do |change|
       oldrev, newrev, ref = change.strip.split(' ')
@@ -33,7 +35,7 @@ class PostReceive
         return false
       end
 
-      if tag?(ref)
+      if Gitlab::Git.tag_ref?(ref)
         GitTagPushService.new.execute(project, @user, oldrev, newrev, ref)
       else
         GitPushService.new.execute(project, @user, oldrev, newrev, ref)
@@ -41,13 +43,20 @@ class PostReceive
     end
   end
 
-  def log(message)
-    Gitlab::GitLogger.error("POST-RECEIVE: #{message}")
-  end
+  def utf8_encode_changes(changes)
+    changes = changes.dup
+    
+    changes.force_encoding("UTF-8")
+    return changes if changes.valid_encoding?
 
-  private
+    # Convert non-UTF-8 branch/tag names to UTF-8 so they can be dumped as JSON.
+    detection = CharlockHolmes::EncodingDetector.detect(changes)
+    return changes unless detection && detection[:encoding]
 
-  def tag?(ref)
-    !!(/refs\/tags\/(.*)/.match(ref))
+    CharlockHolmes::Converter.convert(changes, detection[:encoding], 'UTF-8')
+  end
+
+  def log(message)
+    Gitlab::GitLogger.error("POST-RECEIVE: #{message}")
   end
 end
diff --git a/app/workers/project_service_worker.rb b/app/workers/project_service_worker.rb
new file mode 100644
index 0000000000000000000000000000000000000000..64d39c4d3f7ef436cb4ee49e2a2d4d9a5a5ee72a
--- /dev/null
+++ b/app/workers/project_service_worker.rb
@@ -0,0 +1,10 @@
+class ProjectServiceWorker
+  include Sidekiq::Worker
+
+  sidekiq_options queue: :project_web_hook
+
+  def perform(hook_id, data)
+    data = data.with_indifferent_access
+    Service.find(hook_id).execute(data)
+  end
+end
diff --git a/app/workers/project_web_hook_worker.rb b/app/workers/project_web_hook_worker.rb
index 9f9b9b1df5f672249af8397439d2c3eccc2f25c2..73085c046bd6ab50ab3183a7178ab196939f3ad9 100644
--- a/app/workers/project_web_hook_worker.rb
+++ b/app/workers/project_web_hook_worker.rb
@@ -4,6 +4,7 @@ class ProjectWebHookWorker
   sidekiq_options queue: :project_web_hook
 
   def perform(hook_id, data)
-    WebHook.find(hook_id).execute data
+    data = data.with_indifferent_access
+    WebHook.find(hook_id).execute(data)
   end
 end
diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb
index 01586150cd2c2974b0db6a473a0f6c8276dc6be7..437640d2305d1a65c9fc6038b62fd4546108a838 100644
--- a/app/workers/repository_import_worker.rb
+++ b/app/workers/repository_import_worker.rb
@@ -6,17 +6,27 @@ class RepositoryImportWorker
 
   def perform(project_id)
     project = Project.find(project_id)
-    result = gitlab_shell.send(:import_repository,
+
+    import_result = gitlab_shell.send(:import_repository,
                                project.path_with_namespace,
                                project.import_url)
+    return project.import_fail unless import_result
+
+    data_import_result =  if project.import_type == 'github'
+                            Gitlab::GithubImport::Importer.new(project).execute
+                          elsif project.import_type == 'gitlab'
+                            Gitlab::GitlabImport::Importer.new(project).execute
+                          elsif project.import_type == 'bitbucket'
+                            Gitlab::BitbucketImport::Importer.new(project).execute
+                          else
+                            true
+                          end
+    return project.import_fail unless data_import_result
 
-    if result
-      project.import_finish
-      project.save
-      project.satellite.create unless project.satellite.exists?
-      project.update_repository_size
-    else
-      project.import_fail
-    end
+    project.import_finish
+    project.save
+    project.satellite.create unless project.satellite.exists?
+    project.update_repository_size
+    Gitlab::BitbucketImport::KeyDeleter.new(project).execute if project.import_type == 'bitbucket'
   end
 end
diff --git a/bin/guard b/bin/guard
new file mode 100755
index 0000000000000000000000000000000000000000..0c1a532bd01d7e797faaba230577d39c57f31208
--- /dev/null
+++ b/bin/guard
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+#
+# This file was generated by Bundler.
+#
+# The application 'guard' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'pathname'
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
+  Pathname.new(__FILE__).realpath)
+
+require 'rubygems'
+require 'bundler/setup'
+
+load Gem.bin_path('guard', 'guard')
diff --git a/bin/pkgr_before_precompile.sh b/bin/pkgr_before_precompile.sh
index 283abb6a0cd28d5c90f152b6f2dc137a034e4fd7..5a2007f4ab0ba511d3b3d6e9cf987709811387a1 100755
--- a/bin/pkgr_before_precompile.sh
+++ b/bin/pkgr_before_precompile.sh
@@ -18,6 +18,3 @@ rm config/resque.yml
 
 # Set default unicorn.rb file
 echo "" > config/unicorn.rb
-
-# Required for assets precompilation
-sudo service postgresql start
diff --git a/bin/rspec b/bin/rspec
index 41e37089ac299c889b86e4cfdf9d0b94151677af..20060ebd79c0ec217596c425ddc66ea58b4a02d1 100755
--- a/bin/rspec
+++ b/bin/rspec
@@ -4,4 +4,4 @@ begin
 rescue LoadError
 end
 require 'bundler/setup'
-load Gem.bin_path('rspec', 'rspec')
+load Gem.bin_path('rspec-core', 'rspec')
diff --git a/config/application.rb b/config/application.rb
index 44a5d68d1268c67dd9538844f73f72e9acc7b9c7..fa399533e523cf81a9a77b779d5ecfac2f4697e9 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -12,11 +12,11 @@ module Gitlab
     # -- all .rb files in that directory are automatically loaded.
 
     # Custom directories with classes and modules you want to be autoloadable.
-    config.autoload_paths += %W(#{config.root}/lib
-                                #{config.root}/app/models/hooks
-                                #{config.root}/app/models/concerns
-                                #{config.root}/app/models/project_services
-                                #{config.root}/app/models/members)
+    config.autoload_paths.push(*%W(#{config.root}/lib
+                                   #{config.root}/app/models/hooks
+                                   #{config.root}/app/models/concerns
+                                   #{config.root}/app/models/project_services
+                                   #{config.root}/app/models/members))
 
     # Only load the plugins named here, in the order given (default is alphabetical).
     # :all can be used as a placeholder for all plugins not explicitly named.
@@ -31,7 +31,7 @@ module Gitlab
     config.encoding = "utf-8"
 
     # Configure sensitive parameters which will be filtered from the log file.
-    config.filter_parameters += [:password]
+    config.filter_parameters.push(:password, :password_confirmation, :private_token)
 
     # Enable escaping HTML in JSON.
     config.active_support.escape_html_entities_in_json = true
@@ -50,6 +50,8 @@ module Gitlab
     # Version of your assets, change this if you want to expire all your assets
     config.assets.version = '1.0'
 
+    config.action_view.sanitized_allowed_protocols = %w(smb)
+
     # Relative url support
     # Uncomment and customize the last line to run in a non-root path
     # WARNING: We recommend creating a FQDN to host GitLab in a root path instead of this.
@@ -70,7 +72,10 @@ module Gitlab
     config.middleware.use Rack::Cors do
       allow do
         origins '*'
-        resource '/api/*', headers: :any, methods: [:get, :post, :options, :put, :delete]
+        resource '/api/*',
+          headers: :any,
+          methods: [:get, :post, :options, :put, :delete],
+          expose: ['Link']
       end
     end
 
@@ -92,5 +97,8 @@ module Gitlab
 
     redis_config_hash[:namespace] = 'cache:gitlab'
     config.cache_store = :redis_store, redis_config_hash
+
+    # This is needed for gitlab-shell
+    ENV['GITLAB_PATH_OUTSIDE_HOOK'] = ENV['PATH']
   end
 end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 78bf543402b5396358facf90a23566ef0625215b..3316ece387398bf8188c9a5fb0aee12315483f50 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -11,8 +11,9 @@ Gitlab::Application.configure do
   # Disable Rails's static asset server (Apache or nginx will already do this)
   config.serve_static_assets = false
 
-  # Compress JavaScripts and CSS
-  config.assets.compress = true
+  # Compress JavaScripts and CSS.
+  config.assets.js_compressor = :uglifier
+  # config.assets.css_compressor = :sass
 
   # Don't fallback to assets pipeline if a precompiled asset is missed
   config.assets.compile = true
@@ -74,7 +75,6 @@ Gitlab::Application.configure do
   config.action_mailer.raise_delivery_errors = true
 
   config.eager_load = true
-  config.assets.js_compressor = :uglifier
 
   config.allow_concurrency = false
 end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 25b082b98da894911c20eb72c2e0ef10de41f3d4..2d5e7addcd3ebe1b6d3dc5661e962c6790415370 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -5,7 +5,7 @@ Gitlab::Application.configure do
   # test suite. You never need to work with it otherwise. Remember that
   # your test database is "scratch space" for the test suite and is wiped
   # and recreated between test runs. Don't rely on the data there!
-  config.cache_classes = true
+  config.cache_classes = false
 
   # Configure static asset server for tests with Cache-Control for performance
   config.serve_static_assets = true
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index bb0ffae0b708049abbb297712c47594f8999b4eb..3f1ca34a667d8f945829d28baa43fafb398fae05 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -2,6 +2,11 @@
 # GitLab application config file  #
 # # # # # # # # # # # # # # # # # #
 #
+###########################  NOTE  #####################################
+# This file should not receive new settings. All configuration options #
+# are being moved to ApplicationSetting model!                         #
+########################################################################
+#
 # How to use:
 # 1. Copy file as gitlab.yml
 # 2. Update gitlab -> host with your fully qualified domain name
@@ -35,7 +40,7 @@ production: &base
 
     ## Date & Time settings
     # Uncomment and customize if you want to change the default time zone of GitLab application.
-    # To see all available zones, run `bundle exec rake time:zones:all`
+    # To see all available zones, run `bundle exec rake time:zones:all RAILS_ENV=production`
     # time_zone: 'UTC'
 
     ## Email settings
@@ -43,11 +48,10 @@ production: &base
     # email_enabled: true
     # Email address used in the "From" field in mails sent by GitLab
     email_from: example@example.com
+    email_display_name: GitLab
 
-    # Email server smtp settings are in [a separate file](initializers/smtp_settings.rb.sample).
+    # Email server smtp settings are in config/initializers/smtp_settings.rb.sample
 
-    ## User settings
-    default_projects_limit: 10
     # default_can_create_group: false  # default: true
     # username_changing_enabled: false # default: true - User can change her username/namespace
     ## Default theme
@@ -58,26 +62,12 @@ production: &base
     ##   COLOR  = 5
     # default_theme: 2 # default: 2
 
-    ## Users can create accounts
-    # This also allows normal users to sign up for accounts themselves
-    # default: false - By default GitLab administrators must create all new accounts
-    # signup_enabled: true
-
-    ## Standard login settings
-    # The standard login can be disabled to force login via LDAP
-    # default: true - If set to false the standard login form won't be shown on the sign-in page
-    # signin_enabled: false
-
-    # Restrict setting visibility levels for non-admin users.
-    # The default is to allow all levels.
-    # restricted_visibility_levels: [ "public" ]
-
     ## Automatic issue closing
     # If a commit message matches this regular expression, all issues referenced from the matched text will be closed.
     # This happens when the commit is pushed or merged into the default branch of a project.
     # When not specified the default issue_closing_pattern as specified below will be used.
     # Tip: you can test your closing pattern at http://rubular.com
-    # issue_closing_pattern: '([Cc]lose[sd]|[Ff]ixe[sd]) #(\d+)'
+    # issue_closing_pattern: '((?:[Cc]los(?:e[sd]|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)'
 
     ## Default project features settings
     default_projects_features:
@@ -96,35 +86,6 @@ production: &base
     # The default is 'tmp/repositories' relative to the root of the Rails app.
     # repository_downloads_path: tmp/repositories
 
-  ## External issues trackers
-  issues_tracker:
-    # redmine:
-    #   title: "Redmine"
-    #   ## If not nil, link 'Issues' on project page will be replaced with this
-    #   ## Use placeholders:
-    #   ##  :project_id        - GitLab project identifier
-    #   ##  :issues_tracker_id - Project Name or Id in external issue tracker
-    #   project_url: "http://redmine.sample/projects/:issues_tracker_id"
-    #
-    #   ## If not nil, links from /#\d/ entities from commit messages will replaced with this
-    #   ## Use placeholders:
-    #   ##  :project_id        - GitLab project identifier
-    #   ##  :issues_tracker_id - Project Name or Id in external issue tracker
-    #   ##  :id                - Issue id (from commit messages)
-    #   issues_url: "http://redmine.sample/issues/:id"
-    #
-    #   ## If not nil, links to creating new issues will be replaced with this
-    #   ## Use placeholders:
-    #   ##  :project_id        - GitLab project identifier
-    #   ##  :issues_tracker_id - Project Name or Id in external issue tracker
-    #   new_issue_url: "http://redmine.sample/projects/:issues_tracker_id/issues/new"
-    #
-    # jira:
-    #   title: "Atlassian Jira"
-    #   project_url: "http://jira.sample/issues/?jql=project=:issues_tracker_id"
-    #   issues_url: "http://jira.sample/browse/:id"
-    #   new_issue_url: "http://jira.sample/secure/CreateIssue.jspa"
-
   ## Gravatar
   ## For Libravatar see: http://doc.gitlab.com/ce/customization/libravatar.html
   gravatar:
@@ -153,9 +114,9 @@ production: &base
         label: 'LDAP'
 
         host: '_your_ldap_server'
-        port: 636
+        port: 389
         uid: 'sAMAccountName'
-        method: 'ssl' # "tls" or "ssl" or "plain"
+        method: 'plain' # "tls" or "ssl" or "plain"
         bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
         password: '_the_password_of_the_bind_user'
 
@@ -219,14 +180,19 @@ production: &base
     # arguments, followed by optional 'args' which can be either a hash or an array.
     # Documentation for this is available at http://doc.gitlab.com/ce/integration/omniauth.html
     providers:
-      # - { name: 'google_oauth2', app_id: 'YOUR APP ID',
-      #     app_secret: 'YOUR APP SECRET',
+      # - { name: 'google_oauth2', app_id: 'YOUR_APP_ID',
+      #     app_secret: 'YOUR_APP_SECRET',
       #     args: { access_type: 'offline', approval_prompt: '' } }
-      # - { name: 'twitter', app_id: 'YOUR APP ID',
-      #     app_secret: 'YOUR APP SECRET'}
-      # - { name: 'github', app_id: 'YOUR APP ID',
-      #     app_secret: 'YOUR APP SECRET',
+      # - { name: 'twitter', app_id: 'YOUR_APP_ID',
+      #     app_secret: 'YOUR_APP_SECRET'}
+      # - { name: 'github', app_id: 'YOUR_APP_ID',
+      #     app_secret: 'YOUR_APP_SECRET',
       #     args: { scope: 'user:email' } }
+      # - { name: 'gitlab', app_id: 'YOUR_APP_ID',
+      #     app_secret: 'YOUR_APP_SECRET',
+      #     args: { scope: 'api' } }
+      # - { name: 'bitbucket', app_id: 'YOUR_APP_ID',
+      #     app_secret: 'YOUR_APP_SECRET'}
 
 
 
@@ -293,10 +259,22 @@ production: &base
     # piwik_url: '_your_piwik_url'
     # piwik_site_id: '_your_piwik_site_id'
 
-    ## Text under sign-in page (Markdown enabled)
-    # sign_in_text: |
-    #   ![Company Logo](http://www.companydomain.com/logo.png)
-    #   [Learn more about CompanyName](http://www.companydomain.com/)
+  rack_attack:
+    git_basic_auth:
+      # Rack Attack IP banning enabled
+      # enabled: true
+      #
+      # Whitelist requests from 127.0.0.1 for web proxies (NGINX/Apache) with incorrect headers
+      # ip_whitelist: ["127.0.0.1"]
+      #
+      # Limit the number of Git HTTP authentication attempts per IP
+      # maxretry: 10
+      #
+      # Reset the auth attempt counter per IP after 60 seconds
+      # findtime: 60
+      #
+      # Ban an IP for one hour (3600s) after too many auth attempts
+      # bantime: 3600
 
 development:
   <<: *base
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 27bb83784bab38955381647d98fcc6afdbc3ebf9..15c1ae9466f2cf33c43875212c48da031ee3f2b9 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -13,7 +13,11 @@ class Settings < Settingslogic
       if gitlab_shell.ssh_port != 22
         "ssh://#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:#{gitlab_shell.ssh_port}/"
       else
-        "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:"
+        if gitlab_shell.ssh_host.include? ':'
+          "[#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}]:"
+        else
+          "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}:"
+        end
       end
     end
 
@@ -87,6 +91,7 @@ Settings['issues_tracker']  ||= {}
 #
 Settings['gitlab'] ||= Settingslogic.new({})
 Settings.gitlab['default_projects_limit'] ||= 10
+Settings.gitlab['default_branch_protection'] ||= 2
 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
 Settings.gitlab['default_theme'] = Gitlab::Theme::MARS if Settings.gitlab['default_theme'].nil?
 Settings.gitlab['host']       ||= 'localhost'
@@ -97,6 +102,7 @@ Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || ''
 Settings.gitlab['protocol']   ||= Settings.gitlab.https ? "https" : "http"
 Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].nil?
 Settings.gitlab['email_from'] ||= "gitlab@#{Settings.gitlab.host}"
+Settings.gitlab['email_display_name'] ||= "GitLab"
 Settings.gitlab['url']        ||= Settings.send(:build_gitlab_url)
 Settings.gitlab['user']       ||= 'git'
 Settings.gitlab['user_home']  ||= begin
@@ -105,11 +111,12 @@ rescue ArgumentError # no user configured
   '/home/' + Settings.gitlab['user']
 end
 Settings.gitlab['time_zone']  ||= nil
-Settings.gitlab['signup_enabled'] ||= false
+Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil?
 Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil?
+Settings.gitlab['twitter_sharing_enabled'] ||= true if Settings.gitlab['twitter_sharing_enabled'].nil?
 Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
 Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
-Settings.gitlab['issue_closing_pattern'] = '([Cc]lose[sd]|[Ff]ixe[sd]) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
+Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)' if Settings.gitlab['issue_closing_pattern'].nil?
 Settings.gitlab['default_projects_features'] ||= {}
 Settings.gitlab['webhook_timeout'] ||= 10
 Settings.gitlab.default_projects_features['issues']         = true if Settings.gitlab.default_projects_features['issues'].nil?
@@ -148,7 +155,7 @@ Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_s
 Settings['backup'] ||= Settingslogic.new({})
 Settings.backup['keep_time']  ||= 0
 Settings.backup['path']         = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root)
-Settings.backup['upload'] ||= Settingslogic.new({'remote_directory' => nil, 'connection' => nil})
+Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil })
 # Convert upload connection settings to use symbol keys, to make Fog happy
 if Settings.backup['upload']['connection']
   Settings.backup['upload']['connection'] = Hash[Settings.backup['upload']['connection'].map { |k, v| [k.to_sym, v] }]
@@ -171,6 +178,17 @@ Settings.satellites['timeout'] ||= 30
 #
 Settings['extra'] ||= Settingslogic.new({})
 
+#
+# Rack::Attack settings
+#
+Settings['rack_attack'] ||= Settingslogic.new({})
+Settings.rack_attack['git_basic_auth'] ||= Settingslogic.new({})
+Settings.rack_attack.git_basic_auth['enabled'] = true if Settings.rack_attack.git_basic_auth['enabled'].nil?
+Settings.rack_attack.git_basic_auth['ip_whitelist'] ||= %w{127.0.0.1}
+Settings.rack_attack.git_basic_auth['maxretry'] ||= 10
+Settings.rack_attack.git_basic_auth['findtime'] ||= 1.minute
+Settings.rack_attack.git_basic_auth['bantime'] ||= 1.hour
+
 #
 # Testing settings
 #
diff --git a/config/initializers/4_sidekiq.rb b/config/initializers/4_sidekiq.rb
index 228b14cb5264f3cb78cbe44629d4be024e0c4318..3c930a43ad65f159f45c6a4eb85866564ddceb80 100644
--- a/config/initializers/4_sidekiq.rb
+++ b/config/initializers/4_sidekiq.rb
@@ -14,7 +14,9 @@ Sidekiq.configure_server do |config|
   }
 
   config.server_middleware do |chain|
-    chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger
+    chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger if ENV['SIDEKIQ_LOG_ARGUMENTS']
+    chain.add Gitlab::SidekiqMiddleware::MemoryKiller if ENV['SIDEKIQ_MAX_RSS']
+    Disable Sidekiq arguments logging by default
   end
 end
 
diff --git a/config/initializers/6_rack_profiler.rb b/config/initializers/6_rack_profiler.rb
index a7ee3c59822ea30fe44c47ca0ac211f5b465544b..b634028756925661e59683bd908b5140275504ef 100644
--- a/config/initializers/6_rack_profiler.rb
+++ b/config/initializers/6_rack_profiler.rb
@@ -3,4 +3,6 @@ if Rails.env == 'development'
 
   # initialization is skipped so trigger it
   Rack::MiniProfilerRails.initialize!(Rails.application)
+  Rack::MiniProfiler.config.position = 'right'
+  Rack::MiniProfiler.config.start_hidden = true
 end
diff --git a/config/initializers/7_omniauth.rb b/config/initializers/7_omniauth.rb
index 18759f0cfb0923bb97e4bc1013c8482f75e40875..8f6c5673103de9d4feea06b2b42be6aa37130120 100644
--- a/config/initializers/7_omniauth.rb
+++ b/config/initializers/7_omniauth.rb
@@ -9,4 +9,4 @@ if Gitlab::LDAP::Config.enabled?
     server = Gitlab.config.ldap.servers.values.first
     alias_method server['provider_name'], :ldap
   end
-end
\ No newline at end of file
+end
diff --git a/config/initializers/acts_as_taggable_on_patch.rb b/config/initializers/acts_as_taggable_on_patch.rb
deleted file mode 100644
index baa77fde392b45754d5d94bf17079d63124125ba..0000000000000000000000000000000000000000
--- a/config/initializers/acts_as_taggable_on_patch.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# This is a patch to address the issue in https://github.com/mbleigh/acts-as-taggable-on/issues/427 caused by
-# https://github.com/rails/rails/commit/31a43ebc107fbd50e7e62567e5208a05909ec76c
-# gem 'acts-as-taggable-on' has the fix included https://github.com/mbleigh/acts-as-taggable-on/commit/89bbed3864a9252276fb8dd7d535fce280454b90
-# but not in the currently used version of gem ('2.4.1')
-# With replacement of 'acts-as-taggable-on' gem this file will become obsolete
-
-module ActsAsTaggableOn::Taggable
-  module Core
-    module ClassMethods
-      def tagged_with(tags, options = {})
-        tag_list = ActsAsTaggableOn::TagList.from(tags)
-        empty_result = where("1 = 0")
-
-        return empty_result if tag_list.empty?
-
-        joins = []
-        conditions = []
-        having = []
-        select_clause = []
-
-        context = options.delete(:on)
-        owned_by = options.delete(:owned_by)
-        alias_base_name = undecorated_table_name.gsub('.','_')
-        quote = ActsAsTaggableOn::Tag.using_postgresql? ? '"' : ''
-
-        if options.delete(:exclude)
-          if options.delete(:wild)
-            tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ? ESCAPE '!'", "%#{escape_like(t)}%"]) }.join(" OR ")
-          else
-            tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ?", t]) }.join(" OR ")
-          end
-
-          conditions << "#{table_name}.#{primary_key} NOT IN (SELECT #{ActsAsTaggableOn::Tagging.table_name}.taggable_id FROM #{ActsAsTaggableOn::Tagging.table_name} JOIN #{ActsAsTaggableOn::Tag.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND (#{tags_conditions}) WHERE #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name, nil)})"
-
-          if owned_by
-            joins <<  "JOIN #{ActsAsTaggableOn::Tagging.table_name}" +
-                      "  ON #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
-                      " AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name, nil)}" +
-                      " AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_id = #{owned_by.id}" +
-                      " AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_type = #{quote_value(owned_by.class.base_class.to_s, nil)}"
-          end
-
-        elsif options.delete(:any)
-          # get tags, drop out if nothing returned (we need at least one)
-          tags = if options.delete(:wild)
-            ActsAsTaggableOn::Tag.named_like_any(tag_list)
-          else
-            ActsAsTaggableOn::Tag.named_any(tag_list)
-          end
-
-          return empty_result unless tags.length > 0
-
-          # setup taggings alias so we can chain, ex: items_locations_taggings_awesome_cool_123
-          # avoid ambiguous column name
-          taggings_context = context ? "_#{context}" : ''
-
-          taggings_alias   = adjust_taggings_alias(
-            "#{alias_base_name[0..4]}#{taggings_context[0..6]}_taggings_#{sha_prefix(tags.map(&:name).join('_'))}"
-          )
-
-          tagging_join  = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
-                          "  ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
-                          " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}"
-          tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
-
-          # don't need to sanitize sql, map all ids and join with OR logic
-          conditions << tags.map { |t| "#{taggings_alias}.tag_id = #{t.id}" }.join(" OR ")
-          select_clause = "DISTINCT #{table_name}.*" unless context and tag_types.one?
-
-          if owned_by
-              tagging_join << " AND " +
-                  sanitize_sql([
-                      "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
-                      owned_by.id,
-                      owned_by.class.base_class.to_s
-                  ])
-          end
-
-          joins << tagging_join
-        else
-          tags = ActsAsTaggableOn::Tag.named_any(tag_list)
-
-          return empty_result unless tags.length == tag_list.length
-
-          tags.each do |tag|
-            taggings_alias = adjust_taggings_alias("#{alias_base_name[0..11]}_taggings_#{sha_prefix(tag.name)}")
-            tagging_join  = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
-                            "  ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
-                            " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}" +
-                            " AND #{taggings_alias}.tag_id = #{tag.id}"
-
-            tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
-
-            if owned_by
-                tagging_join << " AND " +
-                  sanitize_sql([
-                    "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
-                    owned_by.id,
-                    owned_by.class.base_class.to_s
-                  ])
-            end
-
-            joins << tagging_join
-          end
-        end
-
-        taggings_alias, tags_alias = adjust_taggings_alias("#{alias_base_name}_taggings_group"), "#{alias_base_name}_tags_group"
-
-        if options.delete(:match_all)
-          joins << "LEFT OUTER JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
-                   "  ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
-                   " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}"
-
-
-          group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}"
-          group = group_columns
-          having = "COUNT(#{taggings_alias}.taggable_id) = #{tags.size}"
-        end
-
-        select(select_clause) \
-          .joins(joins.join(" ")) \
-          .where(conditions.join(" AND ")) \
-          .group(group) \
-          .having(having) \
-          .order(options[:order]) \
-          .readonly(false)
-      end
-    end
-  end
-end
diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb
index d0065b63e545ead2c3cf7d762b673f5ce495471a..bfb8656df552da088bf7848deaa77540945bead2 100644
--- a/config/initializers/carrierwave.rb
+++ b/config/initializers/carrierwave.rb
@@ -12,22 +12,30 @@ if File.exists?(aws_file)
       aws_secret_access_key: AWS_CONFIG['secret_access_key'], # required
       region: AWS_CONFIG['region'],                           # optional, defaults to 'us-east-1'
     }
-    config.fog_directory  = AWS_CONFIG['bucket']                    # required
-    config.fog_public     = false                                   # optional, defaults to true
-    config.fog_attributes = {'Cache-Control'=>'max-age=315576000'}  # optional, defaults to {}
-    config.fog_authenticated_url_expiration = 1 << 29               # optional time (in seconds) that authenticated urls will be valid.
-                                                                    # when fog_public is false and provider is AWS or Google, defaults to 600
+
+    # required
+    config.fog_directory = AWS_CONFIG['bucket']
+
+    # optional, defaults to true
+    config.fog_public = false
+
+    # optional, defaults to {}
+    config.fog_attributes = { 'Cache-Control'=>'max-age=315576000' }
+
+    # optional time (in seconds) that authenticated urls will be valid.
+    # when fog_public is false and provider is AWS or Google, defaults to 600
+    config.fog_authenticated_url_expiration = 1 << 29
   end
 
   # Mocking Fog requests, based on: https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Test-Fog-based-uploaders
   if Rails.env.test?
     Fog.mock!
     connection = ::Fog::Storage.new(
-        :aws_access_key_id      => AWS_CONFIG['access_key_id'],
-        :aws_secret_access_key  => AWS_CONFIG['secret_access_key'],
-        :provider               => 'AWS',
-        :region                 => AWS_CONFIG['region']
+        aws_access_key_id: AWS_CONFIG['access_key_id'],
+        aws_secret_access_key: AWS_CONFIG['secret_access_key'],
+        provider: 'AWS',
+        region: AWS_CONFIG['region']
       )
-    connection.directories.create(:key => AWS_CONFIG['bucket'])
+    connection.directories.create(key: AWS_CONFIG['bucket'])
   end
 end
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index c6eb3e510362bbf9b05e5f0a2a2c74f90d64e265..79abe3c695da44bc1fd840e7b87262ce217f82a2 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -145,7 +145,8 @@ Devise.setup do |config|
   # Time interval you can reset your password with a reset password key.
   # Don't put a too small interval or your users won't have the time to
   # change their passwords.
-  config.reset_password_within = 2.hours
+  # When someone else invites you to GitLab this time is also used so it should be pretty long.
+  config.reset_password_within = 2.days
 
   # ==> Configuration for :encryptable
   # Allow you to use another encryption algorithm besides bcrypt (default). You can use
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9da7ebf4290df3f7a04f44c96480018332ba536c
--- /dev/null
+++ b/config/initializers/doorkeeper.rb
@@ -0,0 +1,102 @@
+Doorkeeper.configure do
+  # Change the ORM that doorkeeper will use.
+  # Currently supported options are :active_record, :mongoid2, :mongoid3, :mongo_mapper
+  orm :active_record
+
+  # This block will be called to check whether the resource owner is authenticated or not.
+  resource_owner_authenticator do
+    # Put your resource owner authentication logic here.
+    # Example implementation:
+    current_user || redirect_to(new_user_session_url)
+  end
+
+  resource_owner_from_credentials do |routes|
+    u = User.find_by(email: params[:username])
+    u if u && u.valid_password?(params[:password])
+  end
+
+  # If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below.
+  # admin_authenticator do
+  #   # Put your admin authentication logic here.
+  #   # Example implementation:
+  #   Admin.find_by_id(session[:admin_id]) || redirect_to(new_admin_session_url)
+  # end
+
+  # Authorization Code expiration time (default 10 minutes).
+  # authorization_code_expires_in 10.minutes
+
+  # Access token expiration time (default 2 hours).
+  # If you want to disable expiration, set this to nil.
+  access_token_expires_in nil
+
+  # Reuse access token for the same resource owner within an application (disabled by default)
+  # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
+  # reuse_access_token
+
+  # Issue access tokens with refresh token (disabled by default)
+  use_refresh_token
+
+  # Forces the usage of the HTTPS protocol in non-native redirect uris (enabled
+  # by default in non-development environments). OAuth2 delegates security in
+  # communication to the HTTPS protocol so it is wise to keep this enabled.
+  #
+  force_ssl_in_redirect_uri false
+
+  # Provide support for an owner to be assigned to each registered application (disabled by default)
+  # Optional parameter confirmation: true (default false) if you want to enforce ownership of
+  # a registered application
+  # Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
+  enable_application_owner confirmation: false
+
+  # Define access token scopes for your provider
+  # For more information go to
+  # https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
+  default_scopes  :api
+  #optional_scopes :write, :update
+
+  # Change the way client credentials are retrieved from the request object.
+  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
+  # falls back to the `:client_id` and `:client_secret` params from the `params` object.
+  # Check out the wiki for more information on customization
+  # client_credentials :from_basic, :from_params
+
+  # Change the way access token is authenticated from the request object.
+  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
+  # falls back to the `:access_token` or `:bearer_token` params from the `params` object.
+  # Check out the wiki for more information on customization
+  access_token_methods :from_access_token_param, :from_bearer_authorization, :from_bearer_param
+
+  # Change the native redirect uri for client apps
+  # When clients register with the following redirect uri, they won't be redirected to any server and the authorization code will be displayed within the provider
+  # The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL
+  # (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
+  #
+  native_redirect_uri nil#'urn:ietf:wg:oauth:2.0:oob'
+
+  # Specify what grant flows are enabled in array of Strings. The valid
+  # strings and the flows they enable are:
+  #
+  # "authorization_code" => Authorization Code Grant Flow
+  # "implicit"           => Implicit Grant Flow
+  # "password"           => Resource Owner Password Credentials Grant Flow
+  # "client_credentials" => Client Credentials Grant Flow
+  #
+  # If not specified, Doorkeeper enables all the four grant flows.
+  #
+  # grant_flows %w(authorization_code implicit password client_credentials)
+
+  # Under some circumstances you might want to have applications auto-approved,
+  # so that the user skips the authorization step.
+  # For example if dealing with trusted a application.
+  # skip_authorization do |resource_owner, client|
+  #   client.superapp? or resource_owner.admin?
+  # end
+
+  # WWW-Authenticate Realm (default "Doorkeeper").
+  # realm "Doorkeeper"
+
+  # Allow dynamic query parameters (disabled by default)
+  # Some applications require dynamic query parameters on their request_uri
+  # set to true if you want this to be allowed
+  # wildcard_redirect_uri false
+end
diff --git a/config/initializers/gitlab_shell_secret_token.rb b/config/initializers/gitlab_shell_secret_token.rb
index 8d2b771e53590b3abb9133df0475133ba4e5bf7c..e7c9f0ba7c2b8025bcc520cc307c5e05edd3a01b 100644
--- a/config/initializers/gitlab_shell_secret_token.rb
+++ b/config/initializers/gitlab_shell_secret_token.rb
@@ -16,4 +16,4 @@ end
 
 if File.exist?(Gitlab.config.gitlab_shell.path) && !File.exist?(gitlab_shell_symlink)
   FileUtils.symlink(secret_file, gitlab_shell_symlink)
-end
\ No newline at end of file
+end
diff --git a/config/initializers/public_key.rb b/config/initializers/public_key.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e4f09a2d02058d36952d667b866e2ff603942d42
--- /dev/null
+++ b/config/initializers/public_key.rb
@@ -0,0 +1,2 @@
+path = File.expand_path("~/.ssh/bitbucket_rsa.pub")
+Gitlab::BitbucketImport.public_key = File.read(path) if File.exist?(path)
diff --git a/config/initializers/rack_attack_git_basic_auth.rb b/config/initializers/rack_attack_git_basic_auth.rb
new file mode 100644
index 0000000000000000000000000000000000000000..bbbfed6832923cb41e94d2defe0af74843bf77a4
--- /dev/null
+++ b/config/initializers/rack_attack_git_basic_auth.rb
@@ -0,0 +1,12 @@
+unless Rails.env.test?
+  # Tell the Rack::Attack Rack middleware to maintain an IP blacklist. We will
+  # update the blacklist from Grack::Auth#authenticate_user.
+  Rack::Attack.blacklist('Git HTTP Basic Auth') do |req|
+    Rack::Attack::Allow2Ban.filter(req.ip, Gitlab.config.rack_attack.git_basic_auth) do
+      # This block only gets run if the IP was not already banned.
+      # Return false, meaning that we do not see anything wrong with the
+      # request at this time
+      false
+    end
+  end
+end
diff --git a/config/initializers/redis-store-fix-expiry.rb b/config/initializers/redis-store-fix-expiry.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fce0a13533012e92babfbb1dca780ad3b84932ff
--- /dev/null
+++ b/config/initializers/redis-store-fix-expiry.rb
@@ -0,0 +1,44 @@
+# Monkey-patch Redis::Store to make 'setex' and 'expire' work with namespacing
+
+module Gitlab
+  class Redis
+    class Store
+      module Namespace
+        # Redis::Store#setex in redis-store 1.1.4 does not respect namespaces;
+        # this new method does.
+        def setex(key, expires_in, value, options=nil)
+          namespace(key) { |key| super(key, expires_in, value) }
+        end
+
+        # Redis::Store#expire in redis-store 1.1.4 does not respect namespaces;
+        # this new method does.
+        def expire(key, expires_in)
+          namespace(key) { |key| super(key, expires_in) }
+        end
+
+        private
+
+        # Our new definitions of #setex and #expire above assume that the
+        # #namespace method exists. Because we cannot be sure of that, we
+        # re-implement the #namespace method from Redis::Store::Namespace so
+        # that it is available for all Redis::Store instances, whether they use
+        # namespacing or not.
+        #
+        # Based on lib/redis/store/namespace.rb L49-51 (redis-store 1.1.4)
+        def namespace(key)
+          if @namespace
+            yield interpolate(key)
+          else
+            # This Redis::Store instance does not use a namespace so we should
+            # just pass through the key.
+            yield key
+          end
+        end
+      end
+    end
+  end
+end
+
+Redis::Store.class_eval do
+  include Gitlab::Redis::Store::Namespace
+end
diff --git a/config/initializers/smtp_settings.rb.sample b/config/initializers/smtp_settings.rb.sample
index 3711b03796e797c5dc76544b6cd9bf611b7af594..f0fe2fdfa43909e794854815b4c9c51b92d83b04 100644
--- a/config/initializers/smtp_settings.rb.sample
+++ b/config/initializers/smtp_settings.rb.sample
@@ -1,8 +1,11 @@
-# To enable smtp email delivery for your GitLab instance do next: 
+# To enable smtp email delivery for your GitLab instance do the following:
 # 1. Rename this file to smtp_settings.rb
 # 2. Edit settings inside this file
 # 3. Restart GitLab instance
 #
+# For full list of options and their values see http://api.rubyonrails.org/classes/ActionMailer/Base.html
+#
+
 if Rails.env.production?
   Gitlab::Application.config.action_mailer.delivery_method = :smtp
 
@@ -13,6 +16,7 @@ if Rails.env.production?
     password: "123456",
     domain: "gitlab.company.com",
     authentication: :login,
-    enable_starttls_auto: true
+    enable_starttls_auto: true,
+    openssl_verify_mode: 'peer' # See ActionMailer documentation for other possible options
   }
 end
diff --git a/config/initializers/static_files.rb b/config/initializers/static_files.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d9042c652bb401fa3e1cd473392ca0160747c8c9
--- /dev/null
+++ b/config/initializers/static_files.rb
@@ -0,0 +1,15 @@
+app = Rails.application
+
+if app.config.serve_static_assets
+  # The `ActionDispatch::Static` middleware intercepts requests for static files 
+  # by checking if they exist in the `/public` directory. 
+  # We're replacing it with our `Gitlab::Middleware::Static` that does the same,
+  # except ignoring `/uploads`, letting those go through to the GitLab Rails app.
+
+  app.config.middleware.swap(
+    ActionDispatch::Static, 
+    Gitlab::Middleware::Static, 
+    app.paths["public"].first, 
+    app.config.static_cache_control
+  )
+end
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index 1cbcde5b3da4e3549b9f35bebe85c0232a0fbdeb..f3db5b7476e1ab35221fe1e6cfd55d9be6c82492 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -23,8 +23,8 @@ en:
       timeout: 'Your session expired, please sign in again to continue.'
       inactive: 'Your account was not activated yet.'
     sessions:
-      signed_in: 'Signed in successfully.'
-      signed_out: 'Signed out successfully.'
+      signed_in: ''
+      signed_out: ''
     users_sessions:
       user:
         signed_in: 'Signed in successfully.'
@@ -57,4 +57,4 @@ en:
       reset_password_instructions:
         subject: 'Reset password instructions'
       unlock_instructions:
-        subject: 'Unlock Instructions'
+        subject: 'Unlock Instructions'
\ No newline at end of file
diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c5b6b75e7f6408f07c0b7cd387dfd0675f29341c
--- /dev/null
+++ b/config/locales/doorkeeper.en.yml
@@ -0,0 +1,73 @@
+en:
+  activerecord:
+    errors:
+      models:
+        application:
+          attributes:
+            redirect_uri:
+              fragment_present: 'cannot contain a fragment.'
+              invalid_uri: 'must be a valid URI.'
+              relative_uri: 'must be an absolute URI.'
+  mongoid:
+    errors:
+      models:
+        application:
+          attributes:
+            redirect_uri:
+              fragment_present: 'cannot contain a fragment.'
+              invalid_uri: 'must be a valid URI.'
+              relative_uri: 'must be an absolute URI.'
+  mongo_mapper:
+    errors:
+      models:
+        application:
+          attributes:
+            redirect_uri:
+              fragment_present: 'cannot contain a fragment.'
+              invalid_uri: 'must be a valid URI.'
+              relative_uri: 'must be an absolute URI.'
+  doorkeeper:
+    errors:
+      messages:
+        # Common error messages
+        invalid_request: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
+        invalid_redirect_uri: 'The redirect uri included is not valid.'
+        unauthorized_client: 'The client is not authorized to perform this request using this method.'
+        access_denied: 'The resource owner or authorization server denied the request.'
+        invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
+        server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
+        temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
+
+        #configuration error messages
+        credential_flow_not_configured: 'Resource Owner Password Credentials flow failed due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.'
+        resource_owner_authenticator_not_configured: 'Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being unconfiged.'
+
+        # Access grant errors
+        unsupported_response_type: 'The authorization server does not support this response type.'
+
+        # Access token errors
+        invalid_client: 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'
+        invalid_grant: 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'
+        unsupported_grant_type: 'The authorization grant type is not supported by the authorization server.'
+
+        # Password Access token errors
+        invalid_resource_owner: 'The provided resource owner credentials are not valid, or resource owner cannot be found'
+
+        invalid_token:
+          revoked: "The access token was revoked"
+          expired: "The access token expired"
+          unknown: "The access token is invalid"
+    scopes:
+      api: Access your API
+
+    flash:
+      applications:
+        create:
+          notice: 'Application created.'
+        destroy:
+          notice: 'Application deleted.'
+        update:
+          notice: 'Application updated.'
+      authorized_applications:
+        destroy:
+          notice: 'Application revoked.'
diff --git a/config/routes.rb b/config/routes.rb
index 2534153758bd9d7fc1a8c4bf5ec994bf8c92ac94..388858d2670ae582440b2b18762f0b7f431bf033 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,11 +2,20 @@ require 'sidekiq/web'
 require 'api/api'
 
 Gitlab::Application.routes.draw do
-  #
+  use_doorkeeper do
+    controllers applications: 'oauth/applications',
+                authorized_applications: 'oauth/authorized_applications',
+                authorizations: 'oauth/authorizations'
+  end
+
+  # Autocomplete
+  get '/autocomplete/users' => 'autocomplete#users'
+  get '/autocomplete/users/:id' => 'autocomplete#user'
+
+
   # Search
-  #
-  get 'search' => "search#show"
-  get 'search/autocomplete' => "search#autocomplete", as: :search_autocomplete
+  get 'search' => 'search#show'
+  get 'search/autocomplete' => 'search#autocomplete', as: :search_autocomplete
 
   # API
   API::API.logger Rails.logger
@@ -15,9 +24,9 @@ Gitlab::Application.routes.draw do
   # Get all keys of user
   get ':username.keys' => 'profiles/keys#get_keys' , constraints: { username: /.*/ }
 
-  constraint = lambda { |request| request.env["warden"].authenticate? and request.env['warden'].user.admin? }
+  constraint = lambda { |request| request.env['warden'].authenticate? and request.env['warden'].user.admin? }
   constraints constraint do
-    mount Sidekiq::Web, at: "/admin/sidekiq", as: :sidekiq
+    mount Sidekiq::Web, at: '/admin/sidekiq', as: :sidekiq
   end
 
   # Enable Grack support
@@ -28,26 +37,75 @@ Gitlab::Application.routes.draw do
     receive_pack: Gitlab.config.gitlab_shell.receive_pack
   }), at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\//.match(request.path_info) }, via: [:get, :post]
 
-  #
   # Help
-  #
-
   get 'help'                  => 'help#index'
   get 'help/:category/:file'  => 'help#show', as: :help_page
   get 'help/shortcuts'
+  get 'help/ui'               => 'help#ui'
 
   #
   # Global snippets
   #
   resources :snippets do
     member do
-      get "raw"
+      get 'raw'
+    end
+  end
+  get '/s/:username' => 'snippets#user_index', as: :user_snippets, constraints: { username: /.*/ }
+
+
+  #
+  # Import
+  #
+  namespace :import do
+    resource :github, only: [:create, :new], controller: :github do
+      get :status
+      get :callback
+      get :jobs
+    end
+
+    resource :gitlab, only: [:create, :new], controller: :gitlab do
+      get :status
+      get :callback
+      get :jobs
+    end
+
+    resource :bitbucket, only: [:create, :new], controller: :bitbucket do
+      get :status
+      get :callback
+      get :jobs
+    end
+
+    resource :gitorious, only: [:create, :new], controller: :gitorious do
+      get :status
+      get :callback
+      get :jobs
     end
   end
-  get "/s/:username" => "snippets#user_index", as: :user_snippets, constraints: { username: /.*/ }
 
   #
-  # Explroe area
+  # Uploads
+  #
+
+  scope path: :uploads do
+    # Note attachments and User/Group/Project avatars
+    get ":model/:mounted_as/:id/:filename",
+        to:           "uploads#show",
+        constraints:  { model: /note|user|group|project/, mounted_as: /avatar|attachment/, filename: /.+/ }
+
+    # Project markdown uploads
+    get ":namespace_id/:project_id/:secret/:filename",
+      to:           "projects/uploads#show",
+      constraints:  { namespace_id: /[a-zA-Z.0-9_\-]+/, project_id: /[a-zA-Z.0-9_\-]+/, filename: /.+/ }
+  end
+
+  # Redirect old note attachments path to new uploads path.
+  get "files/note/:id/:filename",
+    to:           redirect("uploads/note/attachment/%{id}/%{filename}"),
+    constraints:  { filename: /.+/ }
+
+  #
+  # Explore area
   #
   namespace :explore do
     resources :projects, only: [:index] do
@@ -58,23 +116,19 @@ Gitlab::Application.routes.draw do
     end
 
     resources :groups, only: [:index]
-    root to: "projects#trending"
+    root to: 'projects#trending'
   end
 
   # Compatibility with old routing
-  get 'public' => "explore/projects#index"
-  get 'public/projects' => "explore/projects#index"
-
-  #
-  # Attachments serving
-  #
-  get 'files/:type/:id/:filename' => 'files#download', constraints: { id: /\d+/, type: /[a-z]+/, filename:  /.+/ }
+  get 'public' => 'explore/projects#index'
+  get 'public/projects' => 'explore/projects#index'
 
   #
   # Admin Area
   #
   namespace :admin do
     resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
+      resources :keys, only: [:show, :destroy]
       member do
         put :team_update
         put :block
@@ -83,9 +137,11 @@ Gitlab::Application.routes.draw do
       end
     end
 
+    resources :applications
+
     resources :groups, constraints: { id: /[^\/]+/ } do
       member do
-        put :project_teams_update
+        put :members_update
       end
     end
 
@@ -97,13 +153,26 @@ Gitlab::Application.routes.draw do
     resource :logs, only: [:show]
     resource :background_jobs, controller: 'background_jobs', only: [:show]
 
-    resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show] do
-      member do
-        put :transfer
+    resources :namespaces, path: '/projects', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do
+      root to: 'projects#index', as: :projects
+
+      resources(:projects,
+                path: '/',
+                constraints: { id: /[a-zA-Z.0-9_\-]+/ },
+                only: [:index, :show]) do
+        root to: 'projects#show'
+
+        member do
+          put :transfer
+        end
       end
     end
 
-    root to: "dashboard#index"
+    resource :application_settings, only: [:show, :update] do
+      resources :services
+    end
+
+    root to: 'dashboard#index'
   end
 
   #
@@ -113,13 +182,18 @@ Gitlab::Application.routes.draw do
     member do
       get :history
       get :design
+      get :applications
 
       put :reset_private_token
       put :update_username
     end
 
     scope module: :profiles do
-      resource :account, only: [:show, :update]
+      resource :account, only: [:show, :update] do
+        member do
+          delete :unlink
+        end
+      end
       resource :notifications, only: [:show, :update]
       resource :password, only: [:new, :create, :edit, :update] do
         member do
@@ -128,43 +202,58 @@ Gitlab::Application.routes.draw do
       end
       resources :keys
       resources :emails, only: [:index, :create, :destroy]
-      resources :groups, only: [:index] do
-        member do
-          delete :leave
-        end
-      end
       resource :avatar, only: [:destroy]
     end
   end
 
-  match "/u/:username" => "users#show", as: :user, constraints: { username: /.*/ }, via: :get
+  get 'u/:username/calendar' => 'users#calendar', as: :user_calendar,
+      constraints: { username: /.*/ }
+
+  get 'u/:username/calendar_activities' => 'users#calendar_activities', as: :user_calendar_activities,
+      constraints: { username: /.*/ }
+
+  get '/u/:username' => 'users#show', as: :user,
+      constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
 
   #
   # Dashboard Area
   #
-  resource :dashboard, controller: "dashboard", only: [:show] do
+  resource :dashboard, controller: 'dashboard', only: [:show] do
     member do
-      get :projects
       get :issues
       get :merge_requests
     end
+
+    scope module: :dashboard do
+      resources :milestones, only: [:index, :show]
+
+      resources :groups, only: [:index]
+
+      resources :projects, only: [] do
+        collection do
+          get :starred
+        end
+      end
+    end
   end
 
   #
   # Groups Area
   #
-  resources :groups, constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}  do
+  resources :groups, constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }  do
     member do
       get :issues
       get :merge_requests
-      get :members
       get :projects
     end
 
     scope module: :groups do
-      resources :group_members, only: [:create, :update, :destroy]
+      resources :group_members, only: [:index, :create, :update, :destroy] do
+        delete :leave, on: :collection
+      end
+
       resource :avatar, only: [:destroy]
-      resources :milestones
+      resources :milestones, only: [:index, :show, :update]
     end
   end
 
@@ -173,170 +262,236 @@ Gitlab::Application.routes.draw do
   devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations , passwords: :passwords, sessions: :sessions, confirmations: :confirmations }
 
   devise_scope :user do
-    get "/users/auth/:provider/omniauth_error" => "omniauth_callbacks#omniauth_error", as: :omniauth_error
+    get '/users/auth/:provider/omniauth_error' => 'omniauth_callbacks#omniauth_error', as: :omniauth_error
   end
+
+  root to: "dashboard#show"
+
   #
   # Project Area
   #
-  resources :projects, constraints: { id: /[a-zA-Z.0-9_\-]+\/[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do
-    member do
-      put :transfer
-      post :fork
-      post :archive
-      post :unarchive
-      post :upload_image
-      post :toggle_star
-      get :autocomplete_sources
-      get :import
-      put :retry_import
-    end
-
-    scope module: :projects do
-      resources :blob, only: [:show, :destroy], constraints: { id: /.+/ } do
-        get :diff, on: :member
-      end
-      resources :raw,       only: [:show], constraints: {id: /.+/}
-      resources :tree,      only: [:show], constraints: {id: /.+/, format: /(html|js)/ }
-      resources :edit_tree, only: [:show, :update], constraints: { id: /.+/ }, path: 'edit' do
-        post :preview, on: :member
+  resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do
+    resources(:projects, constraints: { id: /[a-zA-Z.0-9_\-]+/ }, except:
+              [:new, :create, :index], path: "/") do
+      member do
+        put :transfer
+        post :archive
+        post :unarchive
+        post :toggle_star
+        post :markdown_preview
+        get :autocomplete_sources
       end
-      resources :new_tree,  only: [:show, :update], constraints: {id: /.+/}, path: 'new'
-      resources :commit,    only: [:show], constraints: {id: /[[:alnum:]]{6,40}/}
-      resources :commits,   only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}
-      resources :compare,   only: [:index, :create]
-      resources :blame,     only: [:show], constraints: {id: /.+/}
-      resources :network,   only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/}
-      resources :graphs,    only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/} do
-        member do
-          get :commits
+
+      scope module: :projects do
+        # Blob routes:
+        get '/new/*id', to: 'blob#new', constraints: { id: /.+/ }, as: 'new_blob'
+        post '/create/*id', to: 'blob#create', constraints: { id: /.+/ }, as: 'create_blob'
+        get '/edit/*id', to: 'blob#edit', constraints: { id: /.+/ }, as: 'edit_blob'
+        put '/update/*id', to: 'blob#update', constraints: { id: /.+/ }, as: 'update_blob'
+        post '/preview/*id', to: 'blob#preview', constraints: { id: /.+/ }, as: 'preview_blob'
+
+        scope do
+          get(
+            '/blob/*id/diff',
+            to: 'blob#diff',
+            constraints: { id: /.+/, format: false },
+            as: :blob_diff
+          )
+          get(
+            '/blob/*id',
+            to: 'blob#show',
+            constraints: { id: /.+/, format: false },
+            as: :blob
+          )
+          delete(
+            '/blob/*id',
+            to: 'blob#destroy',
+            constraints: { id: /.+/, format: false }
+          )
+        end
+
+        scope do
+          get(
+            '/raw/*id',
+            to: 'raw#show',
+            constraints: { id: /.+/, format: /(html|js)/ },
+            as: :raw
+          )
         end
-      end
 
-      match "/compare/:from...:to" => "compare#show", as: "compare", via: [:get, :post], constraints: {from: /.+/, to: /.+/}
+        scope do
+          get(
+            '/tree/*id',
+            to: 'tree#show',
+            constraints: { id: /.+/, format: /(html|js)/ },
+            as: :tree
+          )
+        end
+
+        scope do
+          get(
+            '/blame/*id',
+            to: 'blame#show',
+            constraints: { id: /.+/, format: /(html|js)/ },
+            as: :blame
+          )
+        end
+
+        scope do
+          get(
+            '/commits/*id',
+            to: 'commits#show',
+            constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ },
+            as: :commits
+          )
+        end
 
-        resources :snippets, constraints: {id: /\d+/} do
+        resource  :avatar, only: [:show, :destroy]
+        resources :commit, only: [:show], constraints: { id: /[[:alnum:]]{6,40}/ } do
+          get :branches, on: :member
+        end
+
+        resources :compare, only: [:index, :create]
+        resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }
+
+        resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do
           member do
-            get "raw"
+            get :commits
           end
         end
 
-      resources :wikis, only: [:show, :edit, :destroy, :create], constraints: {id: /[a-zA-Z.0-9_\-\/]+/} do
-        collection do
-          get :pages
-          put ':id' => 'wikis#update'
-          get :git_access
+        get '/compare/:from...:to' => 'compare#show', :as => 'compare',
+            :constraints => { from: /.+/, to: /.+/ }
+
+        resources :snippets, constraints: { id: /\d+/ } do
+          member do
+            get 'raw'
+          end
         end
 
-        member do
-          get "history"
+        resources :wikis, only: [:show, :edit, :destroy, :create], constraints: { id: /[a-zA-Z.0-9_\-\/]+/ } do
+          collection do
+            get :pages
+            put ':id' => 'wikis#update'
+            get :git_access
+          end
+
+          member do
+            get 'history'
+          end
         end
-      end
 
-      resource :repository, only: [:show] do
-        member do
-          get "archive", constraints: { format: Gitlab::Regex.archive_formats_regex }
+        resource :repository, only: [:show, :create] do
+          member do
+            get 'archive', constraints: { format: Gitlab::Regex.archive_formats_regex }
+          end
         end
-      end
 
-      resources :services, constraints: { id: /[^\/]+/ }, only: [:index, :edit, :update] do
-        member do
-          get :test
+        resources :services, constraints: { id: /[^\/]+/ }, only: [:index, :edit, :update] do
+          member do
+            get :test
+          end
         end
-      end
 
-      resources :deploy_keys, constraints: {id: /\d+/} do
-        member do
-          put :enable
-          put :disable
+        resources :deploy_keys, constraints: { id: /\d+/ } do
+          member do
+            put :enable
+            put :disable
+          end
         end
-      end
 
-      resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
-      resources :tags, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
-      resources :protected_branches, only: [:index, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
+        resource :fork, only: [:new, :create]
+        resource :import, only: [:new, :create, :show]
 
-      resources :refs, only: [] do
-        collection do
-          get "switch"
-        end
+        resources :refs, only: [] do
+          collection do
+            get 'switch'
+          end
 
-        member do
-          # tree viewer logs
-          get "logs_tree", constraints: { id: Gitlab::Regex.git_reference_regex }
-          get "logs_tree/:path" => "refs#logs_tree",
-            as: :logs_file,
-            constraints: {
-              id:   Gitlab::Regex.git_reference_regex,
+          member do
+            # tree viewer logs
+            get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex }
+            get 'logs_tree/:path' => 'refs#logs_tree', as: :logs_file, constraints: {
+              id: Gitlab::Regex.git_reference_regex,
               path: /.*/
             }
+          end
         end
-      end
 
-      resources :merge_requests, constraints: {id: /\d+/}, except: [:destroy] do
-        member do
-          get :diffs
-          post :automerge
-          get :automerge_check
-          get :ci_status
-        end
+        resources :merge_requests, constraints: { id: /\d+/ }, except: [:destroy] do
+          member do
+            get :diffs
+            post :automerge
+            get :automerge_check
+            get :ci_status
+            post :toggle_subscription
+          end
 
-        collection do
-          get :branch_from
-          get :branch_to
-          get :update_branches
+          collection do
+            get :branch_from
+            get :branch_to
+            get :update_branches
+          end
         end
-      end
 
-      resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do
-        member do
-          get :test
+        resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
+        resources :tags, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
+        resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
+
+        resources :hooks, only: [:index, :create, :destroy], constraints: { id: /\d+/ } do
+          member do
+            get :test
+          end
         end
-      end
 
-      resources :team, controller: 'team_members', only: [:index]
-      resources :milestones, except: [:destroy], constraints: {id: /\d+/} do
-        member do
-          put :sort_issues
-          put :sort_merge_requests
+        resources :milestones, except: [:destroy], constraints: { id: /\d+/ } do
+          member do
+            put :sort_issues
+            put :sort_merge_requests
+          end
         end
-      end
 
-      resources :labels, constraints: {id: /\d+/} do
-        collection do
-          post :generate
+        resources :labels, constraints: { id: /\d+/ } do
+          collection do
+            post :generate
+          end
         end
-      end
 
-      resources :issues, constraints: {id: /\d+/}, except: [:destroy] do
-        collection do
-          post  :bulk_update
+        resources :issues, constraints: { id: /\d+/ }, except: [:destroy] do
+          member do
+            post :toggle_subscription
+          end
+          collection do
+            post  :bulk_update
+          end
         end
-      end
 
-      resources :team_members, except: [:index, :edit], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ } do
-        collection do
-          delete :leave
+        resources :project_members, except: [:new, :edit], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ } do
+          collection do
+            delete :leave
 
-          # Used for import team
-          # from another project
-          get :import
-          post :apply_import
+            # Used for import team
+            # from another project
+            get :import
+            post :apply_import
+          end
         end
-      end
 
-      resources :notes, only: [:index, :create, :destroy, :update], constraints: {id: /\d+/} do
-        member do
-          delete :delete_attachment
+        resources :notes, only: [:index, :create, :destroy, :update], constraints: { id: /\d+/ } do
+          member do
+            delete :delete_attachment
+          end
         end
 
-        collection do
-          post :preview
+        resources :uploads, only: [:create] do
+          collection do
+            get ":secret/:filename", action: :show, as: :show, constraints: { filename: /.+/ }
+          end
         end
       end
+
     end
   end
 
-  get ':id' => "namespaces#show", constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}
-
-  root to: "dashboard#show"
+  get ':id' => 'namespaces#show', constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
 end
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index ea22744fd90c49eb4817f0c0ec8952b30df4b7ee..86a5512e761982b0cfa80edf6ed5a793dece593d 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -13,10 +13,10 @@
 #
 # ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
 
-# Use at least one worker per core if you're on a dedicated server,
-# more will usually help for _short_ waits on databases/caches.
-# The minimum is 2
-worker_processes 2
+# Read about unicorn workers here:
+# http://doc.gitlab.com/ee/install/requirements.html#unicorn-workers
+#
+worker_processes 3
 
 # Since Unicorn is never exposed to outside clients, it does not need to
 # run on the standard HTTP port (80), there is no reason to start Unicorn
@@ -37,10 +37,10 @@ listen "127.0.0.1:8080", :tcp_nopush => true
 
 # nuke workers after 30 seconds instead of 60 seconds (the default)
 #
-# NOTICE: git push over http depends on this value. 
-# If you want be able to push huge amount of data to git repository over http 
-# you will have to increase this value too. 
-# 
+# NOTICE: git push over http depends on this value.
+# If you want be able to push huge amount of data to git repository over http
+# you will have to increase this value too.
+#
 # Example of output if you try to push 1GB repo to GitLab over http.
 #   -> git push http://gitlab.... master
 #
diff --git a/db/fixtures/development/01_admin.rb b/db/fixtures/development/01_admin.rb
index 004d4cd64a135a2b1a776be2190e776166bc64f2..bba2fc4b186ea050f64b106928d22db3011d38ef 100644
--- a/db/fixtures/development/01_admin.rb
+++ b/db/fixtures/development/01_admin.rb
@@ -3,9 +3,9 @@ Gitlab::Seeder.quiet do
     s.id = 1
     s.name = 'Administrator'
     s.email = 'admin@example.com'
+    s.notification_email = 'admin@example.com'
     s.username = 'root'
     s.password = '5iveL!fe'
-    s.password_confirmation = '5iveL!fe'
     s.admin = true
     s.projects_limit = 100
     s.confirmed_at = DateTime.now
diff --git a/db/fixtures/development/05_users.rb b/db/fixtures/development/05_users.rb
index c263dd232aff567c190df99999bd71f12bc46bc9..24952a1f66167a2d324380de6791c34b9399535f 100644
--- a/db/fixtures/development/05_users.rb
+++ b/db/fixtures/development/05_users.rb
@@ -1,31 +1,31 @@
 Gitlab::Seeder.quiet do
   (2..20).each  do |i|
     begin
-      User.seed(:id, [{
-        id: i,
+      User.create!(
         username: Faker::Internet.user_name,
         name: Faker::Name.name,
         email: Faker::Internet.email,
-        confirmed_at: DateTime.now
-      }])
+        confirmed_at: DateTime.now,
+        password: '12345678'
+      )
+
       print '.'
-    rescue ActiveRecord::RecordNotSaved
+    rescue ActiveRecord::RecordInvalid
       print 'F'
     end
   end
 
   (1..5).each do |i|
     begin
-      User.seed(:id, [
-        id: i + 10,
+      User.create!(
         username: "user#{i}",
         name: "User #{i}",
         email: "user#{i}@example.com",
         confirmed_at: DateTime.now,
         password: '12345678'
-      ])
+      )
       print '.'
-    rescue ActiveRecord::RecordNotSaved
+    rescue ActiveRecord::RecordInvalid
       print 'F'
     end
   end
diff --git a/db/fixtures/production/001_admin.rb b/db/fixtures/production/001_admin.rb
index 0755ac714e11c217c395bf71d5f31cb0d0a94c55..8b560ee09e00251a28c05b13d9d972f0a0c23946 100644
--- a/db/fixtures/production/001_admin.rb
+++ b/db/fixtures/production/001_admin.rb
@@ -11,7 +11,6 @@ admin = User.create(
   name: "Administrator",
   username: 'root',
   password: password,
-  password_confirmation: password,
   password_expires_at: expire_time,
   theme_id: Gitlab::Theme::MARS
 
diff --git a/db/migrate/20140125162722_add_avatar_to_projects.rb b/db/migrate/20140125162722_add_avatar_to_projects.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9523ac722f2fa2144759e3cd268374eb1747e322
--- /dev/null
+++ b/db/migrate/20140125162722_add_avatar_to_projects.rb
@@ -0,0 +1,5 @@
+class AddAvatarToProjects < ActiveRecord::Migration
+  def change
+    add_column :projects, :avatar, :string
+  end
+end
diff --git a/db/migrate/20140907220153_serialize_service_properties.rb b/db/migrate/20140907220153_serialize_service_properties.rb
index bd75ab1eacb606b0a6d420588cfc98ad42a88d50..d45a10465be7ad8ef62a537b8c2128d67c91eb7b 100644
--- a/db/migrate/20140907220153_serialize_service_properties.rb
+++ b/db/migrate/20140907220153_serialize_service_properties.rb
@@ -1,6 +1,9 @@
 class SerializeServiceProperties < ActiveRecord::Migration
   def change
-    add_column :services, :properties, :text
+    unless column_exists?(:services, :properties)
+      add_column :services, :properties, :text
+    end
+
     Service.reset_column_information
 
     associations =
@@ -19,18 +22,21 @@ class SerializeServiceProperties < ActiveRecord::Migration
                                :api_version, :jira_issue_transition_id],
     }
 
-    Service.all.each do |service|
+    Service.find_each(batch_size: 500).each do |service|
       associations[service.type.to_sym].each do |attribute|
         service.send("#{attribute}=", service.attributes[attribute.to_s])
       end
-      service.save
+
+      service.save(validate: false)
     end
 
-    remove_column :services, :project_url, :string
-    remove_column :services, :subdomain, :string
-    remove_column :services, :room, :string
-    remove_column :services, :recipients, :text
-    remove_column :services, :api_key, :string
-    remove_column :services, :token, :string
+    if column_exists?(:services, :project_url)
+      remove_column :services, :project_url, :string
+      remove_column :services, :subdomain, :string
+      remove_column :services, :room, :string
+      remove_column :services, :recipients, :text
+      remove_column :services, :api_key, :string
+      remove_column :services, :token, :string
+    end
   end
 end
diff --git a/db/migrate/20141006143943_move_slack_service_to_webhook.rb b/db/migrate/20141006143943_move_slack_service_to_webhook.rb
index a8e07033a5d2d1ecaeda211f2e859e7905a4c912..5836cd6b8dba3fdfa9b7b0c782e915864c06e1ca 100644
--- a/db/migrate/20141006143943_move_slack_service_to_webhook.rb
+++ b/db/migrate/20141006143943_move_slack_service_to_webhook.rb
@@ -10,7 +10,7 @@ class MoveSlackServiceToWebhook < ActiveRecord::Migration
         slack_service.properties.delete('subdomain')
         # Room is configured on the Slack side
         slack_service.properties.delete('room')
-        slack_service.save
+        slack_service.save(validate: false)
       end
     end
   end
diff --git a/db/migrate/20141121133009_add_timestamps_to_members.rb b/db/migrate/20141121133009_add_timestamps_to_members.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ef6d4dedf32c95a69f85cc471def6bd66b392f36
--- /dev/null
+++ b/db/migrate/20141121133009_add_timestamps_to_members.rb
@@ -0,0 +1,15 @@
+# In 20140914145549_migrate_to_new_members_model.rb we forgot to set the
+# created_at and updated_at times for new records in the 'members' table. This
+# became a problem after commit c8e78d972a5a628870eefca0f2ccea0199c55bda which
+# was added in GitLab 7.5. With this migration we ensure that all rows in
+# 'members' have at least some created_at and updated_at timestamp.
+class AddTimestampsToMembers < ActiveRecord::Migration
+  def up
+    execute "UPDATE members SET created_at = NOW() WHERE created_at is NULL"
+    execute "UPDATE members SET updated_at = NOW() WHERE updated_at is NULL"
+  end
+
+  def down
+    # no change
+  end
+end
diff --git a/db/migrate/20141121161704_add_identity_table.rb b/db/migrate/20141121161704_add_identity_table.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a85b0426cec8b36e762a94767ff302876501296b
--- /dev/null
+++ b/db/migrate/20141121161704_add_identity_table.rb
@@ -0,0 +1,46 @@
+class AddIdentityTable < ActiveRecord::Migration
+  def up
+    create_table :identities do |t|
+      t.string :extern_uid
+      t.string :provider
+      t.references :user
+    end
+
+    add_index :identities, :user_id
+
+    execute <<eos
+INSERT INTO identities (provider, extern_uid, user_id)
+SELECT provider, extern_uid, id FROM users
+WHERE provider IS NOT NULL
+eos
+
+    if index_exists?(:users, ["extern_uid", "provider"])
+      remove_index :users, ["extern_uid", "provider"]
+    end
+
+    remove_column :users, :extern_uid
+    remove_column :users, :provider
+  end
+
+  def down
+    add_column :users, :extern_uid, :string
+    add_column :users, :provider, :string
+
+    if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
+      execute <<eos
+UPDATE users u
+SET provider = i.provider, extern_uid = i.extern_uid
+FROM identities i
+WHERE i.user_id = u.id
+eos
+      else
+        execute "UPDATE users u, identities i SET u.provider = i.provider, u.extern_uid = i.extern_uid WHERE u.id = i.user_id"
+      end
+
+    drop_table :identities
+
+    unless index_exists?(:users, ["extern_uid", "provider"])
+      add_index "users", ["extern_uid", "provider"], name: "index_users_on_extern_uid_and_provider", unique: true, using: :btree
+    end
+  end
+end
diff --git a/db/migrate/20141205134006_add_locked_at_to_merge_request.rb b/db/migrate/20141205134006_add_locked_at_to_merge_request.rb
new file mode 100644
index 0000000000000000000000000000000000000000..49651c44a82284c86289d2094d83a0421838e1e9
--- /dev/null
+++ b/db/migrate/20141205134006_add_locked_at_to_merge_request.rb
@@ -0,0 +1,5 @@
+class AddLockedAtToMergeRequest < ActiveRecord::Migration
+  def change
+    add_column :merge_requests, :locked_at, :datetime
+  end
+end
diff --git a/db/migrate/20141216155758_create_doorkeeper_tables.rb b/db/migrate/20141216155758_create_doorkeeper_tables.rb
new file mode 100644
index 0000000000000000000000000000000000000000..af5aa7d8b734be6a2d240074aefb0d26c54e4203
--- /dev/null
+++ b/db/migrate/20141216155758_create_doorkeeper_tables.rb
@@ -0,0 +1,42 @@
+class CreateDoorkeeperTables < ActiveRecord::Migration
+  def change
+    create_table :oauth_applications do |t|
+      t.string  :name,         null: false
+      t.string  :uid,          null: false
+      t.string  :secret,       null: false
+      t.text    :redirect_uri, null: false
+      t.string  :scopes,       null: false, default: ''
+      t.timestamps
+    end
+
+    add_index :oauth_applications, :uid, unique: true
+
+    create_table :oauth_access_grants do |t|
+      t.integer  :resource_owner_id, null: false
+      t.integer  :application_id,    null: false
+      t.string   :token,             null: false
+      t.integer  :expires_in,        null: false
+      t.text     :redirect_uri,      null: false
+      t.datetime :created_at,        null: false
+      t.datetime :revoked_at
+      t.string   :scopes
+    end
+
+    add_index :oauth_access_grants, :token, unique: true
+
+    create_table :oauth_access_tokens do |t|
+      t.integer  :resource_owner_id
+      t.integer  :application_id
+      t.string   :token,             null: false
+      t.string   :refresh_token
+      t.integer  :expires_in
+      t.datetime :revoked_at
+      t.datetime :created_at,        null: false
+      t.string   :scopes
+    end
+
+    add_index :oauth_access_tokens, :token, unique: true
+    add_index :oauth_access_tokens, :resource_owner_id
+    add_index :oauth_access_tokens, :refresh_token, unique: true
+  end
+end
diff --git a/db/migrate/20141217125223_add_owner_to_application.rb b/db/migrate/20141217125223_add_owner_to_application.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7d5e6d07d0f21ae50a08ceb958b2f9ddbb1dc8c5
--- /dev/null
+++ b/db/migrate/20141217125223_add_owner_to_application.rb
@@ -0,0 +1,7 @@
+class AddOwnerToApplication < ActiveRecord::Migration
+  def change
+    add_column :oauth_applications, :owner_id, :integer, null: true
+    add_column :oauth_applications, :owner_type, :string, null: true
+    add_index :oauth_applications, [:owner_id, :owner_type]
+  end
+end
\ No newline at end of file
diff --git a/db/migrate/20141223135007_add_import_data_to_project_table.rb b/db/migrate/20141223135007_add_import_data_to_project_table.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5db78f94cc978c3a06511aa76ff6ccd9339bf58a
--- /dev/null
+++ b/db/migrate/20141223135007_add_import_data_to_project_table.rb
@@ -0,0 +1,8 @@
+class AddImportDataToProjectTable < ActiveRecord::Migration
+  def change
+    add_column :projects, :import_type, :string
+    add_column :projects, :import_source, :string
+
+    add_column :users, :github_access_token, :string
+  end
+end
diff --git a/db/migrate/20141226080412_add_developers_can_push_to_protected_branches.rb b/db/migrate/20141226080412_add_developers_can_push_to_protected_branches.rb
new file mode 100644
index 0000000000000000000000000000000000000000..70e7272f7f3f8640de1240bfdeb7f4d09133529f
--- /dev/null
+++ b/db/migrate/20141226080412_add_developers_can_push_to_protected_branches.rb
@@ -0,0 +1,5 @@
+class AddDevelopersCanPushToProtectedBranches < ActiveRecord::Migration
+  def change
+    add_column :protected_branches, :developers_can_push, :boolean, default: false, null: false
+  end
+end
diff --git a/db/migrate/20150108073740_create_application_settings.rb b/db/migrate/20150108073740_create_application_settings.rb
new file mode 100644
index 0000000000000000000000000000000000000000..651e35fdf7a9eca8021f8c5cf4c6dd442f7058c1
--- /dev/null
+++ b/db/migrate/20150108073740_create_application_settings.rb
@@ -0,0 +1,13 @@
+class CreateApplicationSettings < ActiveRecord::Migration
+  def change
+    create_table :application_settings 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.timestamps
+    end
+  end
+end
diff --git a/db/migrate/20150116234544_add_home_page_url_for_application_settings.rb b/db/migrate/20150116234544_add_home_page_url_for_application_settings.rb
new file mode 100644
index 0000000000000000000000000000000000000000..aa179ce3a4d29ec0ff236cb74a4c219afb47701e
--- /dev/null
+++ b/db/migrate/20150116234544_add_home_page_url_for_application_settings.rb
@@ -0,0 +1,5 @@
+class AddHomePageUrlForApplicationSettings < ActiveRecord::Migration
+  def change
+    add_column :application_settings, :home_page_url, :string
+  end
+end
diff --git a/db/migrate/20150116234545_add_gitlab_access_token_to_user.rb b/db/migrate/20150116234545_add_gitlab_access_token_to_user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c28ba3197ac80a5caa7931aa55540367ec3429d0
--- /dev/null
+++ b/db/migrate/20150116234545_add_gitlab_access_token_to_user.rb
@@ -0,0 +1,5 @@
+class AddGitlabAccessTokenToUser < ActiveRecord::Migration
+  def change
+    add_column :users, :gitlab_access_token, :string
+  end
+end
diff --git a/db/migrate/20150125163100_add_default_branch_protection_setting.rb b/db/migrate/20150125163100_add_default_branch_protection_setting.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5020daf55f3df10ce2f8e79decd331ebdd168751
--- /dev/null
+++ b/db/migrate/20150125163100_add_default_branch_protection_setting.rb
@@ -0,0 +1,5 @@
+class AddDefaultBranchProtectionSetting < ActiveRecord::Migration
+  def change
+    add_column :application_settings, :default_branch_protection, :integer, :default => 2
+  end
+end
diff --git a/db/migrate/20150205211843_add_timestamps_to_identities.rb b/db/migrate/20150205211843_add_timestamps_to_identities.rb
new file mode 100644
index 0000000000000000000000000000000000000000..77cddbfec3b2b9af2c44df09031a193e13ee46ca
--- /dev/null
+++ b/db/migrate/20150205211843_add_timestamps_to_identities.rb
@@ -0,0 +1,5 @@
+class AddTimestampsToIdentities < ActiveRecord::Migration
+  def change
+    add_timestamps(:identities)
+  end
+end
diff --git a/db/migrate/20150206181414_add_index_to_created_at.rb b/db/migrate/20150206181414_add_index_to_created_at.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fc624fca60dd8acc3c3960832cfccd84a53cf289
--- /dev/null
+++ b/db/migrate/20150206181414_add_index_to_created_at.rb
@@ -0,0 +1,16 @@
+class AddIndexToCreatedAt < ActiveRecord::Migration
+  def change
+    add_index "users", [:created_at, :id]
+    add_index "members", [:created_at, :id]
+    add_index "projects", [:created_at, :id]
+    add_index "issues", [:created_at, :id]
+    add_index "merge_requests", [:created_at, :id]
+    add_index "milestones", [:created_at, :id]
+    add_index "namespaces", [:created_at, :id]
+    add_index "notes", [:created_at, :id]
+    add_index "identities", [:created_at, :id]
+    add_index "keys", [:created_at, :id]
+    add_index "web_hooks", [:created_at, :id]
+    add_index "snippets", [:created_at, :id]
+  end
+end
diff --git a/db/migrate/20150206222854_add_notification_email_to_user.rb b/db/migrate/20150206222854_add_notification_email_to_user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ab80f7e582f3022d75e3c0e6f734f44bc73293a2
--- /dev/null
+++ b/db/migrate/20150206222854_add_notification_email_to_user.rb
@@ -0,0 +1,11 @@
+class AddNotificationEmailToUser < ActiveRecord::Migration
+  def up
+    add_column :users, :notification_email, :string
+
+    execute "UPDATE users SET notification_email = email"
+  end
+
+  def down
+    remove_column :users, :notification_email
+  end
+end
diff --git a/db/migrate/20150209222013_add_missing_index.rb b/db/migrate/20150209222013_add_missing_index.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a816c2e9e8ca11e9754b371e809339b19138544d
--- /dev/null
+++ b/db/migrate/20150209222013_add_missing_index.rb
@@ -0,0 +1,5 @@
+class AddMissingIndex < ActiveRecord::Migration
+  def change
+    add_index "services", [:created_at, :id]
+  end
+end
diff --git a/db/migrate/20150211172122_add_template_to_service.rb b/db/migrate/20150211172122_add_template_to_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b1bfbc45ee9ab36c5f48a69d16e868e6f3c7ca56
--- /dev/null
+++ b/db/migrate/20150211172122_add_template_to_service.rb
@@ -0,0 +1,5 @@
+class AddTemplateToService < ActiveRecord::Migration
+  def change
+    add_column :services, :template, :boolean, default: false
+  end
+end
diff --git a/db/migrate/20150211174341_allow_null_in_services_project_id.rb b/db/migrate/20150211174341_allow_null_in_services_project_id.rb
new file mode 100644
index 0000000000000000000000000000000000000000..68f0281279159537ca2cbb2990e967fd3d3d7277
--- /dev/null
+++ b/db/migrate/20150211174341_allow_null_in_services_project_id.rb
@@ -0,0 +1,5 @@
+class AllowNullInServicesProjectId < ActiveRecord::Migration
+  def change
+    change_column :services, :project_id, :integer, null: true
+  end
+end
diff --git a/db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb b/db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a0439172391f07f26e4f08ee1e4ff027ad40d571
--- /dev/null
+++ b/db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb
@@ -0,0 +1,5 @@
+class AddTwitterSharingEnabledToApplicationSettings < ActiveRecord::Migration
+  def change
+    add_column :application_settings, :twitter_sharing_enabled, :boolean, default: true
+  end
+end
diff --git a/db/migrate/20150213114800_add_hide_no_password_to_user.rb b/db/migrate/20150213114800_add_hide_no_password_to_user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..685f08442762183f53bad4ec097324aec9b04971
--- /dev/null
+++ b/db/migrate/20150213114800_add_hide_no_password_to_user.rb
@@ -0,0 +1,5 @@
+class AddHideNoPasswordToUser < ActiveRecord::Migration
+  def change
+    add_column :users, :hide_no_password, :boolean, default: false
+  end
+end
diff --git a/db/migrate/20150213121042_add_password_automatically_set_to_user.rb b/db/migrate/20150213121042_add_password_automatically_set_to_user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c3c7c1ffc77d8f10e4c1e6fd3b2f2018c1c31d8d
--- /dev/null
+++ b/db/migrate/20150213121042_add_password_automatically_set_to_user.rb
@@ -0,0 +1,5 @@
+class AddPasswordAutomaticallySetToUser < ActiveRecord::Migration
+  def change
+    add_column :users, :password_automatically_set, :boolean, default: false
+  end
+end
diff --git a/db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb b/db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..23ac1b399ec4007dc91ff6ab893015979ecbb1cb
--- /dev/null
+++ b/db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb
@@ -0,0 +1,6 @@
+class AddBitbucketAccessTokenAndSecretToUser < ActiveRecord::Migration
+  def change
+    add_column :users, :bitbucket_access_token, :string
+    add_column :users, :bitbucket_access_token_secret, :string
+  end
+end
diff --git a/db/migrate/20150219004514_add_events_to_services.rb b/db/migrate/20150219004514_add_events_to_services.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cf73a0174f4f6d7992729bc79b08f7952285aedb
--- /dev/null
+++ b/db/migrate/20150219004514_add_events_to_services.rb
@@ -0,0 +1,8 @@
+class AddEventsToServices < ActiveRecord::Migration
+  def change
+    add_column :services, :push_events, :boolean, :default => true
+    add_column :services, :issues_events, :boolean, :default => true
+    add_column :services, :merge_requests_events, :boolean, :default => true
+    add_column :services, :tag_push_events, :boolean, :default => true
+  end
+end
diff --git a/db/migrate/20150223022001_set_missing_last_activity_at.rb b/db/migrate/20150223022001_set_missing_last_activity_at.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3f6d4d83474f639fa4fdfa102576051b020c76f4
--- /dev/null
+++ b/db/migrate/20150223022001_set_missing_last_activity_at.rb
@@ -0,0 +1,8 @@
+class SetMissingLastActivityAt < ActiveRecord::Migration
+  def up
+    execute "UPDATE projects SET last_activity_at = updated_at WHERE last_activity_at IS NULL"
+  end
+
+  def down
+  end
+end
diff --git a/db/migrate/20150225065047_add_note_events_to_services.rb b/db/migrate/20150225065047_add_note_events_to_services.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d54ba9e482f846fb8170227a0fd80197e9438b0f
--- /dev/null
+++ b/db/migrate/20150225065047_add_note_events_to_services.rb
@@ -0,0 +1,5 @@
+class AddNoteEventsToServices < ActiveRecord::Migration
+  def change
+    add_column :services, :note_events, :boolean, default: true, null: false
+  end
+end
diff --git a/db/migrate/20150301014758_add_restricted_visibility_levels_to_application_settings.rb b/db/migrate/20150301014758_add_restricted_visibility_levels_to_application_settings.rb
new file mode 100644
index 0000000000000000000000000000000000000000..494c3033bfff79c57151b773fe72abb2a8195860
--- /dev/null
+++ b/db/migrate/20150301014758_add_restricted_visibility_levels_to_application_settings.rb
@@ -0,0 +1,5 @@
+class AddRestrictedVisibilityLevelsToApplicationSettings < ActiveRecord::Migration
+  def change
+    add_column :application_settings, :restricted_visibility_levels, :text
+  end
+end
diff --git a/db/migrate/20150306023106_fix_namespace_duplication.rb b/db/migrate/20150306023106_fix_namespace_duplication.rb
new file mode 100644
index 0000000000000000000000000000000000000000..334e5574559e361a717b5d6ad6951ce0efd554d2
--- /dev/null
+++ b/db/migrate/20150306023106_fix_namespace_duplication.rb
@@ -0,0 +1,21 @@
+class FixNamespaceDuplication < ActiveRecord::Migration
+  def up
+    #fixes path duplication
+    select_all('SELECT MAX(id) max, COUNT(id) cnt, path FROM namespaces GROUP BY path HAVING COUNT(id) > 1').each do |nms|
+      bad_nms_ids = select_all("SELECT id FROM namespaces WHERE path = '#{nms['path']}' AND id <> #{nms['max']}").map{|x| x["id"]}
+      execute("UPDATE projects SET namespace_id = #{nms["max"]} WHERE namespace_id IN(#{bad_nms_ids.join(', ')})")
+      execute("DELETE FROM namespaces WHERE id IN(#{bad_nms_ids.join(', ')})")
+    end
+
+    #fixes name duplication
+    select_all('SELECT MAX(id) max, COUNT(id) cnt, name FROM namespaces GROUP BY name HAVING COUNT(id) > 1').each do |nms|
+      bad_nms_ids = select_all("SELECT id FROM namespaces WHERE name = '#{nms['name']}' AND id <> #{nms['max']}").map{|x| x["id"]}
+      execute("UPDATE projects SET namespace_id = #{nms["max"]} WHERE namespace_id IN(#{bad_nms_ids.join(', ')})")
+      execute("DELETE FROM namespaces WHERE id IN(#{bad_nms_ids.join(', ')})")
+    end
+  end
+
+  def down
+    # not implemented
+  end
+end
diff --git a/db/migrate/20150306023112_add_unique_index_to_namespace.rb b/db/migrate/20150306023112_add_unique_index_to_namespace.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6472138e3eff92e0b9fda45f40644bab4acc441b
--- /dev/null
+++ b/db/migrate/20150306023112_add_unique_index_to_namespace.rb
@@ -0,0 +1,9 @@
+class AddUniqueIndexToNamespace < ActiveRecord::Migration
+  def change
+    remove_index :namespaces, column: :name if index_exists?(:namespaces, :name)
+    remove_index :namespaces, column: :path if index_exists?(:namespaces, :path)
+
+    add_index :namespaces, :name, unique: true
+    add_index :namespaces, :path, unique: true
+  end
+end
diff --git a/db/migrate/20150313012111_create_subscriptions_table.rb b/db/migrate/20150313012111_create_subscriptions_table.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a1d4d9dedc57048388dfe1a3109c7fc6c09ace7e
--- /dev/null
+++ b/db/migrate/20150313012111_create_subscriptions_table.rb
@@ -0,0 +1,16 @@
+class CreateSubscriptionsTable < ActiveRecord::Migration
+  def change
+    create_table :subscriptions do |t|
+      t.integer :user_id
+      t.references :subscribable, polymorphic: true
+      t.boolean :subscribed
+      
+      t.timestamps
+    end
+
+    add_index :subscriptions, 
+              [:subscribable_id, :subscribable_type, :user_id],
+              unique: true,
+              name: 'subscriptions_user_id_and_ref_fields'
+  end
+end
diff --git a/db/migrate/20150320234437_add_location_to_user.rb b/db/migrate/20150320234437_add_location_to_user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..32731d37d7558c4a01a3577372ea9ea8463f11d2
--- /dev/null
+++ b/db/migrate/20150320234437_add_location_to_user.rb
@@ -0,0 +1,5 @@
+class AddLocationToUser < ActiveRecord::Migration
+  def change
+    add_column :users, :location, :string
+  end
+end
diff --git a/db/migrate/20150324155957_set_incorrect_assignee_id_to_null.rb b/db/migrate/20150324155957_set_incorrect_assignee_id_to_null.rb
new file mode 100644
index 0000000000000000000000000000000000000000..42dc8173e46ee315b46d68c8a2ed3a040427956e
--- /dev/null
+++ b/db/migrate/20150324155957_set_incorrect_assignee_id_to_null.rb
@@ -0,0 +1,6 @@
+class SetIncorrectAssigneeIdToNull < ActiveRecord::Migration
+  def up
+    execute "UPDATE issues SET assignee_id = NULL WHERE assignee_id = -1"
+    execute "UPDATE merge_requests SET assignee_id = NULL WHERE assignee_id = -1"
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 8ddebc5132a2b4fef9633636508d20448b97909c..b841206c6cb314955a2fffd72a3c646b20cc93db 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,11 +11,26 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20141007100818) do
+ActiveRecord::Schema.define(version: 20150324155957) do
+    Add missing timestamps to the 'members' table
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
 
+  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
+    t.boolean  "twitter_sharing_enabled",      default: true
+    t.text     "restricted_visibility_levels"
+  end
+
   create_table "broadcast_messages", force: true do |t|
     t.text     "message",    null: false
     t.datetime "starts_at"
@@ -74,6 +89,17 @@ ActiveRecord::Schema.define(version: 20141007100818) do
 
   add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
 
+  create_table "identities", force: true do |t|
+    t.string   "extern_uid"
+    t.string   "provider"
+    t.integer  "user_id"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
+  add_index "identities", ["created_at", "id"], name: "index_identities_on_created_at_and_id", using: :btree
+  add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree
+
   create_table "issues", force: true do |t|
     t.string   "title"
     t.integer  "assignee_id"
@@ -91,6 +117,7 @@ ActiveRecord::Schema.define(version: 20141007100818) do
 
   add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree
   add_index "issues", ["author_id"], name: "index_issues_on_author_id", using: :btree
+  add_index "issues", ["created_at", "id"], name: "index_issues_on_created_at_and_id", using: :btree
   add_index "issues", ["created_at"], name: "index_issues_on_created_at", using: :btree
   add_index "issues", ["milestone_id"], name: "index_issues_on_milestone_id", using: :btree
   add_index "issues", ["project_id", "iid"], name: "index_issues_on_project_id_and_iid", unique: true, using: :btree
@@ -107,6 +134,7 @@ ActiveRecord::Schema.define(version: 20141007100818) do
     t.string   "fingerprint"
   end
 
+  add_index "keys", ["created_at", "id"], name: "index_keys_on_created_at_and_id", using: :btree
   add_index "keys", ["user_id"], name: "index_keys_on_user_id", using: :btree
 
   create_table "label_links", force: true do |t|
@@ -142,6 +170,7 @@ ActiveRecord::Schema.define(version: 20141007100818) do
   end
 
   add_index "members", ["access_level"], name: "index_members_on_access_level", using: :btree
+  add_index "members", ["created_at", "id"], name: "index_members_on_created_at_and_id", using: :btree
   add_index "members", ["source_id", "source_type"], name: "index_members_on_source_id_and_source_type", using: :btree
   add_index "members", ["type"], name: "index_members_on_type", using: :btree
   add_index "members", ["user_id"], name: "index_members_on_user_id", using: :btree
@@ -173,10 +202,12 @@ ActiveRecord::Schema.define(version: 20141007100818) do
     t.integer  "iid"
     t.text     "description"
     t.integer  "position",          default: 0
+    t.datetime "locked_at"
   end
 
   add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree
   add_index "merge_requests", ["author_id"], name: "index_merge_requests_on_author_id", using: :btree
+  add_index "merge_requests", ["created_at", "id"], name: "index_merge_requests_on_created_at_and_id", using: :btree
   add_index "merge_requests", ["created_at"], name: "index_merge_requests_on_created_at", using: :btree
   add_index "merge_requests", ["milestone_id"], name: "index_merge_requests_on_milestone_id", using: :btree
   add_index "merge_requests", ["source_branch"], name: "index_merge_requests_on_source_branch", using: :btree
@@ -196,6 +227,7 @@ ActiveRecord::Schema.define(version: 20141007100818) do
     t.integer  "iid"
   end
 
+  add_index "milestones", ["created_at", "id"], name: "index_milestones_on_created_at_and_id", using: :btree
   add_index "milestones", ["due_date"], name: "index_milestones_on_due_date", using: :btree
   add_index "milestones", ["project_id", "iid"], name: "index_milestones_on_project_id_and_iid", unique: true, using: :btree
   add_index "milestones", ["project_id"], name: "index_milestones_on_project_id", using: :btree
@@ -211,9 +243,10 @@ ActiveRecord::Schema.define(version: 20141007100818) do
     t.string   "avatar"
   end
 
-  add_index "namespaces", ["name"], name: "index_namespaces_on_name", using: :btree
+  add_index "namespaces", ["created_at", "id"], name: "index_namespaces_on_created_at_and_id", using: :btree
+  add_index "namespaces", ["name"], name: "index_namespaces_on_name", unique: true, using: :btree
   add_index "namespaces", ["owner_id"], name: "index_namespaces_on_owner_id", using: :btree
-  add_index "namespaces", ["path"], name: "index_namespaces_on_path", using: :btree
+  add_index "namespaces", ["path"], name: "index_namespaces_on_path", unique: true, using: :btree
   add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree
 
   create_table "notes", force: true do |t|
@@ -233,6 +266,7 @@ ActiveRecord::Schema.define(version: 20141007100818) do
 
   add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree
   add_index "notes", ["commit_id"], name: "index_notes_on_commit_id", using: :btree
+  add_index "notes", ["created_at", "id"], name: "index_notes_on_created_at_and_id", using: :btree
   add_index "notes", ["created_at"], name: "index_notes_on_created_at", using: :btree
   add_index "notes", ["noteable_id", "noteable_type"], name: "index_notes_on_noteable_id_and_noteable_type", using: :btree
   add_index "notes", ["noteable_type"], name: "index_notes_on_noteable_type", using: :btree
@@ -240,6 +274,49 @@ ActiveRecord::Schema.define(version: 20141007100818) do
   add_index "notes", ["project_id"], name: "index_notes_on_project_id", using: :btree
   add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", using: :btree
 
+  create_table "oauth_access_grants", force: true do |t|
+    t.integer  "resource_owner_id", null: false
+    t.integer  "application_id",    null: false
+    t.string   "token",             null: false
+    t.integer  "expires_in",        null: false
+    t.text     "redirect_uri",      null: false
+    t.datetime "created_at",        null: false
+    t.datetime "revoked_at"
+    t.string   "scopes"
+  end
+
+  add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true, using: :btree
+
+  create_table "oauth_access_tokens", force: true do |t|
+    t.integer  "resource_owner_id"
+    t.integer  "application_id"
+    t.string   "token",             null: false
+    t.string   "refresh_token"
+    t.integer  "expires_in"
+    t.datetime "revoked_at"
+    t.datetime "created_at",        null: false
+    t.string   "scopes"
+  end
+
+  add_index "oauth_access_tokens", ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true, using: :btree
+  add_index "oauth_access_tokens", ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id", using: :btree
+  add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true, using: :btree
+
+  create_table "oauth_applications", force: true do |t|
+    t.string   "name",                      null: false
+    t.string   "uid",                       null: false
+    t.string   "secret",                    null: false
+    t.text     "redirect_uri",              null: false
+    t.string   "scopes",       default: "", null: false
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.integer  "owner_id"
+    t.string   "owner_type"
+  end
+
+  add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type", using: :btree
+  add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree
+
   create_table "projects", force: true do |t|
     t.string   "name"
     t.string   "path"
@@ -259,21 +336,26 @@ ActiveRecord::Schema.define(version: 20141007100818) do
     t.string   "import_url"
     t.integer  "visibility_level",       default: 0,        null: false
     t.boolean  "archived",               default: false,    null: false
+    t.string   "avatar"
     t.string   "import_status"
     t.float    "repository_size",        default: 0.0
     t.integer  "star_count",             default: 0,        null: false
+    t.string   "import_type"
+    t.string   "import_source"
   end
 
+  add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree
   add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
   add_index "projects", ["last_activity_at"], name: "index_projects_on_last_activity_at", using: :btree
   add_index "projects", ["namespace_id"], name: "index_projects_on_namespace_id", using: :btree
   add_index "projects", ["star_count"], name: "index_projects_on_star_count", using: :btree
 
   create_table "protected_branches", force: true do |t|
-    t.integer  "project_id", null: false
-    t.string   "name",       null: false
+    t.integer  "project_id",                          null: false
+    t.string   "name",                                null: false
     t.datetime "created_at"
     t.datetime "updated_at"
+    t.boolean  "developers_can_push", default: false, null: false
   end
 
   add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree
@@ -281,13 +363,20 @@ ActiveRecord::Schema.define(version: 20141007100818) do
   create_table "services", force: true do |t|
     t.string   "type"
     t.string   "title"
-    t.integer  "project_id",                 null: false
+    t.integer  "project_id"
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.boolean  "active",     default: false, null: false
+    t.boolean  "active",                default: false, null: false
     t.text     "properties"
+    t.boolean  "template",              default: false
+    t.boolean  "push_events",           default: true
+    t.boolean  "issues_events",         default: true
+    t.boolean  "merge_requests_events", default: true
+    t.boolean  "tag_push_events",       default: true
+    t.boolean  "note_events",           default: true,  null: false
   end
 
+  add_index "services", ["created_at", "id"], name: "index_services_on_created_at_and_id", using: :btree
   add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree
 
   create_table "snippets", force: true do |t|
@@ -304,11 +393,23 @@ ActiveRecord::Schema.define(version: 20141007100818) do
   end
 
   add_index "snippets", ["author_id"], name: "index_snippets_on_author_id", using: :btree
+  add_index "snippets", ["created_at", "id"], name: "index_snippets_on_created_at_and_id", using: :btree
   add_index "snippets", ["created_at"], name: "index_snippets_on_created_at", using: :btree
   add_index "snippets", ["expires_at"], name: "index_snippets_on_expires_at", using: :btree
   add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree
   add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree
 
+  create_table "subscriptions", force: true do |t|
+    t.integer  "user_id"
+    t.integer  "subscribable_id"
+    t.string   "subscribable_type"
+    t.boolean  "subscribed"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
+  add_index "subscriptions", ["subscribable_id", "subscribable_type", "user_id"], name: "subscriptions_user_id_and_ref_fields", unique: true, using: :btree
+
   create_table "taggings", force: true do |t|
     t.integer  "tag_id"
     t.integer  "taggable_id"
@@ -327,12 +428,12 @@ ActiveRecord::Schema.define(version: 20141007100818) do
   end
 
   create_table "users", force: true do |t|
-    t.string   "email",                    default: "",    null: false
-    t.string   "encrypted_password",       default: "",    null: false
+    t.string   "email",                         default: "",    null: false
+    t.string   "encrypted_password",            default: "",    null: false
     t.string   "reset_password_token"
     t.datetime "reset_password_sent_at"
     t.datetime "remember_created_at"
-    t.integer  "sign_in_count",            default: 0
+    t.integer  "sign_in_count",                 default: 0
     t.datetime "current_sign_in_at"
     t.datetime "last_sign_in_at"
     t.string   "current_sign_in_ip"
@@ -340,24 +441,22 @@ ActiveRecord::Schema.define(version: 20141007100818) do
     t.datetime "created_at"
     t.datetime "updated_at"
     t.string   "name"
-    t.boolean  "admin",                    default: false, null: false
-    t.integer  "projects_limit",           default: 10
-    t.string   "skype",                    default: "",    null: false
-    t.string   "linkedin",                 default: "",    null: false
-    t.string   "twitter",                  default: "",    null: false
+    t.boolean  "admin",                         default: false, null: false
+    t.integer  "projects_limit",                default: 10
+    t.string   "skype",                         default: "",    null: false
+    t.string   "linkedin",                      default: "",    null: false
+    t.string   "twitter",                       default: "",    null: false
     t.string   "authentication_token"
-    t.integer  "theme_id",                 default: 1,     null: false
+    t.integer  "theme_id",                      default: 1,     null: false
     t.string   "bio"
-    t.integer  "failed_attempts",          default: 0
+    t.integer  "failed_attempts",               default: 0
     t.datetime "locked_at"
-    t.string   "extern_uid"
-    t.string   "provider"
     t.string   "username"
-    t.boolean  "can_create_group",         default: true,  null: false
-    t.boolean  "can_create_team",          default: true,  null: false
+    t.boolean  "can_create_group",              default: true,  null: false
+    t.boolean  "can_create_team",               default: true,  null: false
     t.string   "state"
-    t.integer  "color_scheme_id",          default: 1,     null: false
-    t.integer  "notification_level",       default: 1,     null: false
+    t.integer  "color_scheme_id",               default: 1,     null: false
+    t.integer  "notification_level",            default: 1,     null: false
     t.datetime "password_expires_at"
     t.integer  "created_by_id"
     t.string   "avatar"
@@ -365,17 +464,25 @@ ActiveRecord::Schema.define(version: 20141007100818) do
     t.datetime "confirmed_at"
     t.datetime "confirmation_sent_at"
     t.string   "unconfirmed_email"
-    t.boolean  "hide_no_ssh_key",          default: false
-    t.string   "website_url",              default: "",    null: false
+    t.boolean  "hide_no_ssh_key",               default: false
+    t.string   "website_url",                   default: "",    null: false
     t.datetime "last_credential_check_at"
+    t.string   "github_access_token"
+    t.string   "gitlab_access_token"
+    t.string   "notification_email"
+    t.boolean  "hide_no_password",              default: false
+    t.boolean  "password_automatically_set",    default: false
+    t.string   "bitbucket_access_token"
+    t.string   "bitbucket_access_token_secret"
+    t.string   "location"
   end
 
   add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
   add_index "users", ["authentication_token"], name: "index_users_on_authentication_token", unique: true, using: :btree
   add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
+  add_index "users", ["created_at", "id"], name: "index_users_on_created_at_and_id", using: :btree
   add_index "users", ["current_sign_in_at"], name: "index_users_on_current_sign_in_at", using: :btree
   add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
-  add_index "users", ["extern_uid", "provider"], name: "index_users_on_extern_uid_and_provider", unique: true, using: :btree
   add_index "users", ["name"], name: "index_users_on_name", using: :btree
   add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
   add_index "users", ["username"], name: "index_users_on_username", using: :btree
@@ -404,6 +511,7 @@ ActiveRecord::Schema.define(version: 20141007100818) do
     t.boolean  "tag_push_events",       default: false
   end
 
+  add_index "web_hooks", ["created_at", "id"], name: "index_web_hooks_on_created_at_and_id", using: :btree
   add_index "web_hooks", ["project_id"], name: "index_web_hooks_on_project_id", using: :btree
 
 end
diff --git a/doc/README.md b/doc/README.md
index b9aa12f767581e097fe7c6c5ee50c7adf8a10aee..4e00dceac2bffbd6c67319da54921dcce81d524d 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -2,27 +2,30 @@
 
 ## User documentation
 
-- [API](api/README.md) Explore how you can access GitLab via a simple and powerful API.
-- [Markdown](markdown/markdown.md) Learn what you can do with GitLab's advanced formatting system.
+- [API](api/README.md) Automate GitLab via a simple and powerful API.
+- [Markdown](markdown/markdown.md) GitLab's advanced formatting system.
 - [Permissions](permissions/permissions.md) Learn what each role in a project (guest/reporter/developer/master/owner) can do.
-- [Project Services](project_services/project_services.md) Explore how project services can integrate a project with external services, such as for CI.
-- [Public access](public_access/public_access.md) Learn how you can allow public and internal access to a project.
+- [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat.
+- [Public access](public_access/public_access.md) Learn how you can allow public and internal access to projects.
 - [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects.
 - [Web hooks](web_hooks/web_hooks.md) Let GitLab notify you when new code has been pushed to your project.
-- [Workflow](workflow/README.md) Learn how to use Git and GitLab together.
+- [Workflow](workflow/README.md) Using GitLab functionality and importing projects from GitHub and SVN.
+- [GitLab as OAuth2 authentication service provider](integration/oauth_provider.md). It allows you to login to other applications from GitLab.
 
 ## Administrator documentation
 
-- [Install](install/README.md) Requirements, directory structures and manual installation.
+- [Install](install/README.md) Requirements, directory structures and installation from source.
 - [Integration](integration/README.md) How to integrate with systems such as JIRA, Redmine, LDAP and Twitter.
-- [Raketasks](raketasks/README.md) Explore what GitLab has in store for you to make administration easier.
+- [Raketasks](raketasks/README.md) Backups, maintenance, automatic web hook setup and the importing of projects.
 - [Custom git hooks](hooks/custom_hooks.md) Custom git hooks (on the filesystem) for when web hooks aren't enough.
-- [System hooks](system_hooks/system_hooks.md) Let GitLab notify you when certain management tasks need to be carried out.
+- [System hooks](system_hooks/system_hooks.md) Notifications when users, projects and keys are changed.
 - [Security](security/README.md) Learn what you can do to further secure your GitLab instance.
 - [Update](update/README.md) Update guides to upgrade your installation.
 - [Welcome message](customization/welcome_message.md) Add a custom welcome message to the sign-in page.
 - [Issue closing](customization/issue_closing.md) Customize how to close an issue from commit messages.
 - [Libravatar](customization/libravatar.md) Use Libravatar for user avatars.
+- [Operations](operations/README.md) Keeping GitLab up and running
+- [Log system](logs/logs.md) Log system
 
 ## Contributor documentation
 
diff --git a/doc/api/README.md b/doc/api/README.md
index ffe250df3ff1e8ada04ce112ba1f26e121252976..dec530d0b812022be099d3023f279de0b3e850dc 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -22,6 +22,7 @@
 ## Clients
 
 Find API Clients for GitLab [on our website](https://about.gitlab.com/applications/#api-clients).
+You can use [GitLab as an OAuth2 client](oauth2.md) to make API calls.
 
 ## Introduction
 
@@ -51,6 +52,24 @@ curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" "http://example.com/api/v3/p
 
 The API uses JSON to serialize data. You don't need to specify `.json` at the end of API URL.
 
+## Authentication with OAuth2 token
+
+Instead of the private_token you can transmit the OAuth2 access token as a header or as a parameter.
+
+### OAuth2 token (as a parameter)
+
+```
+curl https://localhost:3000/api/v3/user?access_token=OAUTH-TOKEN
+```
+
+###  OAuth2 token (as a header)
+
+```
+curl -H "Authorization: Bearer OAUTH-TOKEN" https://localhost:3000/api/v3/user
+```
+
+Read more about [GitLab as an OAuth2 client](oauth2.md).
+
 ## Status codes
 
 The API is designed to return different status codes according to context and action. In this way if a request results in an error the caller is able to get insight into what went wrong, e.g. status code `400 Bad Request` is returned if a required attribute is missing from the request. The following list gives an overview of how the API functions generally behave.
@@ -79,7 +98,7 @@ Return values:
 
 ## Sudo
 
-All API requests support performing an api call as if you were another user, if your private token is for an administration account. You need to pass  `sudo` parameter by url or header with an id or username of the user you want to perform the operation as. If passed as header, the header name must be "SUDO" (capitals).
+All API requests support performing an api call as if you were another user, if your private token is for an administration account. You need to pass  `sudo` parameter by URL or header with an id or username of the user you want to perform the operation as. If passed as header, the header name must be "SUDO" (capitals).
 
 If a non administrative `private_token` is provided then an error message will be returned with status code 403:
 
@@ -124,7 +143,7 @@ When listing resources you can pass the following parameters:
 - `page` (default: `1`) - page number
 - `per_page` (default: `20`, max: `100`) - number of items to list per page
 
-[Link headers](http://www.w3.org/wiki/LinkHeader) are send back with each response. These have `rel` prev/next/first/last and contain the relevant URL. Please use these instead of generating your own urls.
+[Link headers](http://www.w3.org/wiki/LinkHeader) are send back with each response. These have `rel` prev/next/first/last and contain the relevant URL. Please use these instead of generating your own URLs.
 
 ## id vs iid
 
diff --git a/doc/api/branches.md b/doc/api/branches.md
index 319f0b47386c24053c098e1b41b143784fdb851d..6a9c10c85206d9ee3f0820332abcbd45782c5a60 100644
--- a/doc/api/branches.md
+++ b/doc/api/branches.md
@@ -15,27 +15,20 @@ Parameters:
 ```json
 [
   {
-    "name": "master",
     "commit": {
+      "author_email": "john@example.com",
+      "author_name": "John Smith",
+      "authored_date": "2012-06-27T05:51:39-07:00",
+      "committed_date": "2012-06-28T03:44:20-07:00",
+      "committer_email": "john@example.com",
+      "committer_name": "John Smith",
       "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
-      "parents": [
-        {
-          "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
-        }
-      ],
-      "tree": "46e82de44b1061621357f24c05515327f2795a95",
       "message": "add projects API",
-      "author": {
-        "name": "John Smith",
-        "email": "john@example.com"
-      },
-      "committer": {
-        "name": "John Smith",
-        "email": "john@example.com"
-      },
-      "authored_date": "2012-06-27T05:51:39-07:00",
-      "committed_date": "2012-06-28T03:44:20-07:00"
+      "parent_ids": [
+        "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+      ]
     },
+    "name": "master",
     "protected": true
   }
 ]
@@ -56,27 +49,20 @@ Parameters:
 
 ```json
 {
-  "name": "master",
   "commit": {
+    "author_email": "john@example.com",
+    "author_name": "John Smith",
+    "authored_date": "2012-06-27T05:51:39-07:00",
+    "committed_date": "2012-06-28T03:44:20-07:00",
+    "committer_email": "john@example.com",
+    "committer_name": "John Smith",
     "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
-    "parents": [
-      {
-        "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
-      }
-    ],
-    "tree": "46e82de44b1061621357f24c05515327f2795a95",
     "message": "add projects API",
-    "author": {
-      "name": "John Smith",
-      "email": "john@example.com"
-    },
-    "committer": {
-      "name": "John Smith",
-      "email": "john@example.com"
-    },
-    "authored_date": "2012-06-27T05:51:39-07:00",
-    "committed_date": "2012-06-28T03:44:20-07:00"
+    "parent_ids": [
+      "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+    ]
   },
+  "name": "master",
   "protected": true
 }
 ```
@@ -97,27 +83,20 @@ Parameters:
 
 ```json
 {
-  "name": "master",
   "commit": {
+    "author_email": "john@example.com",
+    "author_name": "John Smith",
+    "authored_date": "2012-06-27T05:51:39-07:00",
+    "committed_date": "2012-06-28T03:44:20-07:00",
+    "committer_email": "john@example.com",
+    "committer_name": "John Smith",
     "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
-    "parents": [
-      {
-        "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
-      }
-    ],
-    "tree": "46e82de44b1061621357f24c05515327f2795a95",
     "message": "add projects API",
-    "author": {
-      "name": "John Smith",
-      "email": "john@example.com"
-    },
-    "committer": {
-      "name": "John Smith",
-      "email": "john@example.com"
-    },
-    "authored_date": "2012-06-27T05:51:39-07:00",
-    "committed_date": "2012-06-28T03:44:20-07:00"
+    "parent_ids": [
+      "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+    ]
   },
+  "name": "master",
   "protected": true
 }
 ```
@@ -138,27 +117,20 @@ Parameters:
 
 ```json
 {
-  "name": "master",
   "commit": {
+    "author_email": "john@example.com",
+    "author_name": "John Smith",
+    "authored_date": "2012-06-27T05:51:39-07:00",
+    "committed_date": "2012-06-28T03:44:20-07:00",
+    "committer_email": "john@example.com",
+    "committer_name": "John Smith",
     "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
-    "parents": [
-      {
-        "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
-      }
-    ],
-    "tree": "46e82de44b1061621357f24c05515327f2795a95",
     "message": "add projects API",
-    "author": {
-      "name": "John Smith",
-      "email": "john@example.com"
-    },
-    "committer": {
-      "name": "John Smith",
-      "email": "john@example.com"
-    },
-    "authored_date": "2012-06-27T05:51:39-07:00",
-    "committed_date": "2012-06-28T03:44:20-07:00"
+    "parent_ids": [
+      "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+    ]
   },
+  "name": "master",
   "protected": false
 }
 ```
@@ -177,21 +149,20 @@ Parameters:
 
 ```json
 {
-  "name": "my-new-branch",
   "commit": {
-    "id": "8848c0e90327a0b70f1865b843fb2fbfb9345e57",
-    "message": "Merge pull request #54 from brightbox/use_fog_brightbox_module\n\nUpdate to use fog-brightbox module",
-    "parent_ids": [
-      "fff449e0bf453576f16c91d6544f00a2664009d8",
-      "f93a93626fec20fd659f4ed3ab2e64019b6169ae"
-    ],
-    "authored_date": "2014-02-20T19:54:55+02:00",
-    "author_name": "john smith",
     "author_email": "john@example.com",
-    "committed_date": "2014-02-20T19:54:55+02:00",
-    "committer_name": "john smith",
-    "committer_email": "john@example.com"
+    "author_name": "John Smith",
+    "authored_date": "2012-06-27T05:51:39-07:00",
+    "committed_date": "2012-06-28T03:44:20-07:00",
+    "committer_email": "john@example.com",
+    "committer_name": "John Smith",
+    "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+    "message": "add projects API",
+    "parent_ids": [
+      "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+    ]
   },
+  "name": "master",
   "protected": false
 }
 ```
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 6b379b02d28f18d7f4be115216aea2f841d46749..b5a4b05ccaf2cd0cdd9487d8f2d6be698e6d84c8 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -14,11 +14,13 @@ GET /groups
     "id": 1,
     "name": "Foobar Group",
     "path": "foo-bar",
-    "owner_id": 18
+    "description": "An interesting group"
   }
 ]
 ```
 
+You can search for groups by name or path, see below.
+
 ## Details of a group
 
 Get all details of a group.
@@ -29,7 +31,7 @@ GET /groups/:id
 
 Parameters:
 
-- `id` (required) - The ID of a group
+- `id` (required) - The ID or path of a group
 
 ## New group
 
@@ -43,6 +45,7 @@ Parameters:
 
 - `name` (required) - The name of the group
 - `path` (required) - The path of the group
+- `description` (optional) - The group's description
 
 ## Transfer project to group
 
@@ -54,7 +57,7 @@ POST  /groups/:id/projects/:project_id
 
 Parameters:
 
-- `id` (required) - The ID of a group
+- `id` (required) - The ID or path of a group
 - `project_id` (required) - The ID of a project
 
 ## Remove group
@@ -67,7 +70,26 @@ DELETE /groups/:id
 
 Parameters:
 
-- `id` (required) - The ID of a user group
+- `id` (required) - The ID or path of a user group
+
+## Search for group
+
+Get all groups that match your string in their name or path.
+
+```
+GET /groups?search=foobar
+```
+
+```json
+[
+  {
+    "id": 1,
+    "name": "Foobar Group",
+    "path": "foo-bar",
+    "description": "An interesting group"
+  }
+]
+```
 
 ## Group members
 
@@ -124,10 +146,24 @@ POST /groups/:id/members
 
 Parameters:
 
-- `id` (required) - The ID of a group
+- `id` (required) - The ID or path of a group
 - `user_id` (required) - The ID of a user to add
 - `access_level` (required) - Project access level
 
+### Edit group team member
+
+Updates a group team member to a specified access level.
+
+```
+PUT /groups/:id/members/:user_id
+```
+
+Parameters:
+
+- `id` (required) - The ID of a group
+- `user_id` (required) - The ID of a group member
+- `access_level` (required) - Project access level
+
 ### Remove user team member
 
 Removes user from user team.
@@ -138,5 +174,5 @@ DELETE /groups/:id/members/:user_id
 
 Parameters:
 
-- `id` (required) - The ID of a user group
+- `id` (required) - The ID or path of a user group
 - `user_id` (required) - The ID of a group member
diff --git a/doc/api/issues.md b/doc/api/issues.md
index ceeb683a6bfab231c5ba242202560a69ef402827..a7dd8b74c35a3f6799c732663d2798ead68db0ba 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -18,6 +18,8 @@ Parameters:
 
 - `state` (optional) - Return `all` issues or just those that are `opened` or `closed`
 - `labels` (optional) - Comma-separated list of label names
+- `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
+- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
 
 ```json
 [
@@ -56,7 +58,7 @@ Parameters:
       "title": "v1.0",
       "description": "",
       "due_date": "2012-07-20",
-      "state": "reopenend",
+      "state": "reopened",
       "updated_at": "2012-07-04T13:42:48Z",
       "created_at": "2012-07-04T13:42:48Z"
     },
@@ -105,6 +107,8 @@ Parameters:
 - `state` (optional) - Return `all` issues or just those that are `opened` or `closed`
 - `labels` (optional) - Comma-separated list of label names
 - `milestone` (optional) - Milestone title
+- `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
+- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
 
 ## Single issue
 
@@ -204,7 +208,7 @@ If an error occurs, an error number and a message explaining the reason is retur
 
 ## Delete existing issue (**Deprecated**)
 
-The function is deprecated and returns a `405 Method Not Allowed` error if called. An issue gets now closed and is done by calling `PUT /projects/:id/issues/:issue_id` with parameter `closed` set to 1.
+The function is deprecated and returns a `405 Method Not Allowed` error if called. An issue gets now closed and is done by calling `PUT /projects/:id/issues/:issue_id` with parameter `state_event` set to `close`.
 
 ```
 DELETE /projects/:id/issues/:issue_id
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 14884e53915ab4efebcb23ca6ba877aee24137ec..6a272539e45fb7db43877b74652fe24dbffcb0ed 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -2,7 +2,9 @@
 
 ## List merge requests
 
-Get all merge requests for this project. The `state` parameter can be used to get only merge requests with a given state (`opened`, `closed`, or `merged`) or all of them (`all`). The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests.
+Get all merge requests for this project. 
+The `state` parameter can be used to get only merge requests with a given state (`opened`, `closed`, or `merged`) or all of them (`all`). 
+The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests.
 
 ```
 GET /projects/:id/merge_requests
@@ -14,8 +16,8 @@ Parameters:
 
 - `id` (required) - The ID of a project
 - `state` (optional) - Return `all` requests or just those that are `merged`, `opened` or `closed`
-- `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields
-- `sort` (optional) - Return requests sorted in `asc` or `desc` order
+- `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
+- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
 
 ```json
 [
@@ -94,6 +96,76 @@ Parameters:
 }
 ```
 
+## Get single MR changes
+
+Shows information about the merge request including its files and changes
+
+```
+GET /projects/:id/merge_request/:merge_request_id/changes
+```
+
+Parameters:
+
+- `id` (required) - The ID of a project
+- `merge_request_id` (required) - The ID of MR
+
+```json
+{
+  "id": 21,
+  "iid": 1,
+  "project_id": 4,
+  "title": "Blanditiis beatae suscipit hic assumenda et molestias nisi asperiores repellat et.",
+  "description": "Qui voluptatibus placeat ipsa alias quasi. Deleniti rem ut sint. Optio velit qui distinctio.",
+  "state": "reopened",
+  "created_at": "2015-02-02T19:49:39.159Z",
+  "updated_at": "2015-02-02T20:08:49.959Z",
+  "target_branch": "secret_token",
+  "source_branch": "version-1-9",
+  "upvotes": 0,
+  "downvotes": 0,
+  "author": {
+    "name": "Chad Hamill",
+    "username": "jarrett",
+    "id": 5,
+    "state": "active",
+    "avatar_url": "http://www.gravatar.com/avatar/b95567800f828948baf5f4160ebb2473?s=40&d=identicon"
+  },
+  "assignee": {
+    "name": "Administrator",
+    "username": "root",
+    "id": 1,
+    "state": "active",
+    "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40&d=identicon"
+  },
+  "source_project_id": 4,
+  "target_project_id": 4,
+  "labels": [ ],
+  "milestone": {
+    "id": 5,
+    "iid": 1,
+    "project_id": 4,
+    "title": "v2.0",
+    "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
+    "state": "closed",
+    "created_at": "2015-02-02T19:49:26.013Z",
+    "updated_at": "2015-02-02T19:49:26.013Z",
+    "due_date": null
+  },
+  "files": [
+    {
+    "old_path": "VERSION",
+    "new_path": "VERSION",
+    "a_mode": "100644",
+    "b_mode": "100644",
+    "diff": "--- a/VERSION\ +++ b/VERSION\ @@ -1 +1 @@\ -1.9.7\ +1.9.8",
+    "new_file": false,
+    "renamed_file": false,
+    "deleted_file": false
+    }
+  ]
+}
+```
+
 ## Create MR
 
 Creates a new merge request.
@@ -109,6 +181,7 @@ Parameters:
 - `target_branch` (required)     - The target branch
 - `assignee_id` (optional)       - Assignee user ID
 - `title` (required)             - Title of MR
+- `description` (optional)       - Description of MR
 - `target_project_id` (optional) - The target project (numeric id)
 
 ```json
@@ -160,6 +233,7 @@ Parameters:
 - `target_branch`               - The target branch
 - `assignee_id`                 - Assignee user ID
 - `title`                       - Title of MR
+- `description`                 - Description of MR
 - `state_event`                 - New state (close|reopen|merge)
 
 ```json
@@ -169,6 +243,7 @@ Parameters:
   "source_branch": "test1",
   "project_id": 3,
   "title": "test1",
+  "description": "description1",
   "state": "opened",
   "upvotes": 0,
   "downvotes": 0,
@@ -300,7 +375,7 @@ Parameters:
     }
   },
   {
-    "note": "_Status changed to closed_",
+    "note": "Status changed to closed",
     "author": {
       "id": 11,
       "username": "admin",
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index 2f525327504cf2f3a070a387b1d8f8347a9feaf1..d48b3bcce8aa3fe83ea93db902957e3ac9056d65 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -72,3 +72,16 @@ Parameters:
 - `description` (optional) - The description of a milestone
 - `due_date` (optional) - The due date of the milestone
 - `state_event` (optional) - The state event of the milestone (close|activate)
+
+## Get all issues assigned to a single milestone
+
+Gets all issues assigned to a single project milestone.
+
+```
+GET /projects/:id/milestones/:milestone_id/issues
+```
+
+Parameters:
+
+- `id` (required) - The ID of a project
+- `milestone_id` (required) - The ID of a project milestone
diff --git a/doc/api/notes.md b/doc/api/notes.md
index b5256ac803e488fc071fab2aeb81b75683deba1a..ee2f9fa0eac7192ebe6f8d7b4fa7cc46d039d254 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -21,7 +21,7 @@ Parameters:
 [
   {
     "id": 302,
-    "body": "_Status changed to closed_",
+    "body": "Status changed to closed",
     "attachment": null,
     "author": {
       "id": 1,
@@ -78,6 +78,21 @@ Parameters:
 - `issue_id` (required) - The ID of an issue
 - `body` (required) - The content of a note
 
+### Modify existing issue note
+
+Modify existing note of an issue.
+
+```
+PUT /projects/:id/issues/:issue_id/notes/:note_id
+```
+
+Parameters:
+
+- `id` (required) - The ID of a project
+- `issue_id` (required) - The ID of an issue
+- `note_id` (required) - The ID of a note
+- `body` (required) - The content of a note
+
 ## Snippets
 
 ### List all snippet notes
@@ -137,7 +152,22 @@ POST /projects/:id/snippets/:snippet_id/notes
 Parameters:
 
 - `id` (required) - The ID of a project
-- `snippet_id` (required) - The ID of an snippet
+- `snippet_id` (required) - The ID of a snippet
+- `body` (required) - The content of a note
+
+### Modify existing snippet note
+
+Modify existing note of a snippet.
+
+```
+PUT /projects/:id/snippets/:snippet_id/notes/:note_id
+```
+
+Parameters:
+
+- `id` (required) - The ID of a project
+- `snippet_id` (required) - The ID of a snippet
+- `note_id` (required) - The ID of a note
 - `body` (required) - The content of a note
 
 ## Merge Requests
@@ -199,3 +229,18 @@ Parameters:
 - `id` (required) - The ID of a project
 - `merge_request_id` (required) - The ID of a merge request
 - `body` (required) - The content of a note
+
+### Modify existing merge request note
+
+Modify existing note of a merge request.
+
+```
+PUT /projects/:id/merge_requests/:merge_request_id/notes/:note_id
+```
+
+Parameters:
+
+- `id` (required) - The ID of a project
+- `merge_request_id` (required) - The ID of a merge request
+- `note_id` (required) - The ID of a note
+- `body` (required) - The content of a note
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
new file mode 100644
index 0000000000000000000000000000000000000000..d416a826f797f68d6e5324f8a562d85fa4813326
--- /dev/null
+++ b/doc/api/oauth2.md
@@ -0,0 +1,102 @@
+# GitLab as an OAuth2 client
+
+This document is about using other OAuth authentication service providers to sign into GitLab.
+If you want GitLab to be an OAuth authentication service provider to sign into other services please see the [Oauth2 provider documentation](../integration/oauth_provider.md).
+
+OAuth2 is a protocol that enables us to authenticate a user without requiring them to give their password. 
+
+Before using the OAuth2 you should create an application in user's account. Each application gets a unique App ID and App Secret parameters. You should not share these.
+
+This functionality is based on [doorkeeper gem](https://github.com/doorkeeper-gem/doorkeeper)
+
+## Web Application Flow
+
+This flow is using for authentication from third-party web sites and is probably used the most. 
+It basically consists of an exchange of an authorization token for an access token. For more detailed info, check out the [RFC spec here](http://tools.ietf.org/html/rfc6749#section-4.1)
+
+This flow consists from 3 steps.
+
+### 1. Registering the client
+
+Create an application in user's account profile.
+
+### 2. Requesting authorization
+
+To request the authorization token, you should visit the `/oauth/authorize` endpoint. You can do that by visiting manually the URL:
+
+```
+http://localhost:3000/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code
+```
+
+Where REDIRECT_URI is the URL in your app where users will be sent after authorization. 	
+
+### 3. Requesting the access token
+
+To request the access token, you should use the returned code and exchange it for an access token. To do that you can use any HTTP client. In this case, I used rest-client:
+
+```
+parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=AUTHORIZATION_CODE&redirect_uri=REDIRECT_URI'
+RestClient.post 'http://localhost:3000/oauth/token', parameters
+
+# The response will be
+{
+ "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
+ "token_type": "bearer", 
+ "expires_in": 7200,
+ "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1"
+}
+```
+
+You can now make requests to the API with the access token returned.
+
+###  Use the access token to access the API
+
+The access token allows you to make requests to the API on a behalf of a user.
+
+```
+GET https://localhost:3000/api/v3/user?access_token=OAUTH-TOKEN
+```
+
+Or you can put the token to the Authorization header:
+
+```
+curl -H "Authorization: Bearer OAUTH-TOKEN" https://localhost:3000/api/v3/user
+```
+
+## Resource Owner Password Credentials
+
+In this flow, a token is requested in exchange for the resource owner credentials (username and password). 
+The credentials should only be used when there is a high degree of trust between the resource owner and the client (e.g. the
+client is part of the device operating system or a highly privileged application), and when other authorization grant types are not
+available (such as an authorization code).
+
+Even though this grant type requires direct client access to the resource owner credentials, the resource owner credentials are used
+for a single request and are exchanged for an access token.  This grant type can eliminate the need for the client to store the
+resource owner credentials for future use, by exchanging the credentials with a long-lived access token or refresh token.
+You can do POST request to `/oauth/token` with parameters:
+
+```
+{
+  "grant_type"    : "password",
+  "username"      : "user@example.com",
+  "password"      : "sekret"
+}
+```
+
+Then, you'll receive the access token back in the response:
+
+```
+{
+  "access_token": "1f0af717251950dbd4d73154fdf0a474a5c5119adad999683f5b450c460726aa",
+  "token_type": "bearer",
+  "expires_in": 7200
+}
+```
+
+For testing you can use the oauth2 ruby gem:
+
+```
+client = OAuth2::Client.new('the_client_id', 'the_client_secret', :site => "http://example.com")
+access_token = client.password.get_token('user@example.com', 'sekret')
+puts access_token.token
+```
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 0055e2e476f9334713bb12ede2662ceeab782232..7fe244477dbe20d33d1715f3d4d2b7bff7523a00 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -1,5 +1,23 @@
 # Projects
 
+
+### Project visibility level
+
+Project in GitLab has be either private, internal or public.
+You can determine it by `visibility_level` field in project. 
+
+Constants for project visibility levels are next:
+
+* Private. `visibility_level` is `0`. 
+  Project access must be granted explicitly for each user.
+
+* Internal. `visibility_level` is `10`.
+  The project can be cloned by any logged in user.
+ 
+* Public. `visibility_level` is `20`.
+  The project can be cloned without any authentication.
+
+
 ## List projects
 
 Get a list of projects accessible by the authenticated user.
@@ -11,6 +29,9 @@ GET /projects
 Parameters:
 
 - `archived` (optional) - if passed, limit by archived status
+- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
+- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
+- `search` (optional) - Return list of authorized projects according to a search criteria
 
 ```json
 [
@@ -47,7 +68,8 @@ Parameters:
       "path": "diaspora",
       "updated_at": "2013-09-30T13: 46: 02Z"
     },
-    "archived": false
+    "archived": false,
+    "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png"
   },
   {
     "id": 6,
@@ -82,7 +104,8 @@ Parameters:
       "path": "brightbox",
       "updated_at": "2013-09-30T13:46:02Z"
     },
-    "archived": false
+    "archived": false,
+    "avatar_url": null
   }
 ]
 ```
@@ -95,6 +118,13 @@ Get a list of projects which are owned by the authenticated user.
 GET /projects/owned
 ```
 
+Parameters:
+
+- `archived` (optional) - if passed, limit by archived status
+- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
+- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
+- `search` (optional) - Return list of authorized projects according to a search criteria
+
 ### List ALL projects
 
 Get a list of all GitLab projects (admin only).
@@ -103,6 +133,13 @@ Get a list of all GitLab projects (admin only).
 GET /projects/all
 ```
 
+Parameters:
+
+- `archived` (optional) - if passed, limit by archived status
+- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
+- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
+- `search` (optional) - Return list of authorized projects according to a search criteria
+
 ### Get single project
 
 Get a specific project, identified by project ID or NAMESPACE/PROJECT_NAME, which is owned by the authenticated user.
@@ -160,7 +197,8 @@ Parameters:
       "notification_level": 3
     }
   },
-  "archived": false
+  "archived": false,
+  "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png"
 }
 ```
 
@@ -284,6 +322,31 @@ Parameters:
 - `visibility_level` (optional)
 - `import_url` (optional)
 
+### Edit project
+
+Updates an existing project
+
+```
+PUT /projects/:id
+```
+
+Parameters:
+
+- `id` (required) - The ID of a project
+- `name` (optional) - project name
+- `path` (optional) - repository name for project
+- `description` (optional) - short project description
+- `default_branch` (optional)
+- `issues_enabled` (optional)
+- `merge_requests_enabled` (optional)
+- `wiki_enabled` (optional)
+- `snippets_enabled` (optional)
+- `public` (optional) - if `true` same as setting visibility_level = 20
+- `visibility_level` (optional)
+
+On success, method returns 200 with the updated project. If parameters are 
+invalid, 400 is returned.
+
 ### Fork project
 
 Forks a project into the user namespace of the authenticated user.
@@ -513,7 +576,7 @@ Parameters:
         }
       ],
       "tree": "c68537c6534a02cc2b176ca1549f4ffa190b58ee",
-      "message": "give caolan credit where it's due (up top)",
+      "message": "give Caolan credit where it's due (up top)",
       "author": {
         "name": "Jeremy Ashkenas",
         "email": "jashkenas@example.com"
@@ -628,6 +691,8 @@ GET /projects/search/:query
 
 Parameters:
 
--   query (required) - A string contained in the project name
--   per_page (optional) - number of projects to return per page
--   page (optional) - the page to retrieve
+- `query` (required) - A string contained in the project name
+- `per_page` (optional) - number of projects to return per page
+- `page` (optional) - the page to retrieve
+- `order_by` (optional) - Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields
+- `sort` (optional) - Return requests sorted in `asc` or `desc` order
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 8acf85d21c81a927470831f3df9257e630776fd6..331674538028b4d4cbc5d85dad52ccce25fad98f 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -15,24 +15,21 @@ Parameters:
 ```json
 [
   {
-    "name": "v1.0.0",
     "commit": {
+      "author_name": "John Smith",
+      "author_email": "john@example.com",
+      "authored_date": "2012-05-28T04:42:42-07:00",
+      "committed_date": "2012-05-28T04:42:42-07:00",
+      "committer_name": "Jack Smith",
+      "committer_email": "jack@example.com",
       "id": "2695effb5807a22ff3d138d593fd856244e155e7",
-      "parents": [],
-      "tree": "38017f2f189336fe4497e9d230c5bb1bf873f08d",
       "message": "Initial commit",
-      "author": {
-        "name": "John Smith",
-        "email": "john@example.com"
-      },
-      "committer": {
-        "name": "Jack Smith",
-        "email": "jack@example.com"
-      },
-      "authored_date": "2012-05-28T04:42:42-07:00",
-      "committed_date": "2012-05-28T04:42:42-07:00"
+      "parents_ids": [
+        "2a4b78934375d7f53875269ffd4f45fd83a84ebe"
+      ]
     },
-    "protected": null
+    "name": "v1.0.0",
+    "message": null
   }
 ]
 ```
@@ -53,23 +50,23 @@ Parameters:
 - `message` (optional) - Creates annotated tag.
 
 ```json
-[
-  {
-    "name": "v1.0.0",
-    "message": "Release 1.0.0",
-    "commit": {
-      "id": "2695effb5807a22ff3d138d593fd856244e155e7",
-      "parents": [],
-      "message": "Initial commit",
-      "authored_date": "2012-05-28T04:42:42-07:00",
-      "author_name": "John Smith",
-      "author email": "john@example.com",
-      "committer_name": "Jack Smith",
-      "committed_date": "2012-05-28T04:42:42-07:00",
-      "committer_email": "jack@example.com"
-    },
-  }
-]
+{
+  "commit": {
+    "author_name": "John Smith",
+    "author_email": "john@example.com",
+    "authored_date": "2012-05-28T04:42:42-07:00",
+    "committed_date": "2012-05-28T04:42:42-07:00",
+    "committer_name": "Jack Smith",
+    "committer_email": "jack@example.com",
+    "id": "2695effb5807a22ff3d138d593fd856244e155e7",
+    "message": "Initial commit",
+    "parents_ids": [
+      "2a4b78934375d7f53875269ffd4f45fd83a84ebe"
+    ]
+  },
+  "name": "v1.0.0",
+  "message": null
+}
 ```
 The message will be `nil` when creating a lightweight tag otherwise
 it will contain the annotation.
diff --git a/doc/api/services.md b/doc/api/services.md
index ab9f9c00c67ae9bd62b6f91aa2e09d23d3fe2e1a..cbf767d1b251a773520f158229bdb1e21e0c7e22 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -13,7 +13,7 @@ PUT /projects/:id/services/gitlab-ci
 Parameters:
 
 - `token` (required) - CI project token
-- `project_url` (required) - CI project url
+- `project_url` (required) - CI project URL
 
 ### Delete GitLab CI service
 
@@ -23,23 +23,23 @@ Delete GitLab CI service settings for a project.
 DELETE /projects/:id/services/gitlab-ci
 ```
 
-## Hipchat
+## HipChat
 
-### Edit Hipchat service
+### Edit HipChat service
 
-Set Hipchat service for project.
+Set HipChat service for project.
 
 ```
 PUT /projects/:id/services/hipchat
 ```
 Parameters:
 
-- `token` (required) - Hipchat token
-- `room` (required) - Hipchat room name
+- `token` (required) - HipChat token
+- `room` (required) - HipChat room name
 
-### Delete Hipchat service
+### Delete HipChat service
 
-Delete Hipchat service for a project.
+Delete HipChat service for a project.
 
 ```
 DELETE /projects/:id/services/hipchat
diff --git a/doc/api/users.md b/doc/api/users.md
index 20e0d68977e97238dd3ccdc7115431f7a2500892..a8b7685b503c463e9e573a25c3cb90fb801b87b3 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -170,6 +170,7 @@ Parameters:
 - `bio` (optional)              - User's biography
 - `admin` (optional)            - User is admin - true or false (default)
 - `can_create_group` (optional) - User can create groups - true or false
+- `confirm` (optional)          - Require confirmation - true (default) or false
 
 ## User modification
 
@@ -260,12 +261,14 @@ GET /user/keys
   {
     "id": 1,
     "title": "Public key",
-    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+    "created_at": "2014-08-01T14:47:39.080Z"
   },
   {
     "id": 3,
     "title": "Another Public key",
-    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+    "created_at": "2014-08-01T14:47:39.080Z"
   }
 ]
 ```
@@ -302,7 +305,8 @@ Parameters:
 {
   "id": 1,
   "title": "Public key",
-  "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+  "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+  "created_at": "2014-08-01T14:47:39.080Z"
 }
 ```
 
@@ -319,6 +323,31 @@ Parameters:
 - `title` (required) - new SSH Key's title
 - `key` (required)   - new SSH key
 
+```json
+{
+  "created_at": "2015-01-21T17:44:33.512Z",
+  "key": "ssh-dss AAAAB3NzaC1kc3MAAACBAMLrhYgI3atfrSD6KDas1b/3n6R/HP+bLaHHX6oh+L1vg31mdUqK0Ac/NjZoQunavoyzqdPYhFz9zzOezCrZKjuJDS3NRK9rspvjgM0xYR4d47oNZbdZbwkI4cTv/gcMlquRy0OvpfIvJtjtaJWMwTLtM5VhRusRuUlpH99UUVeXAAAAFQCVyX+92hBEjInEKL0v13c/egDCTQAAAIEAvFdWGq0ccOPbw4f/F8LpZqvWDydAcpXHV3thwb7WkFfppvm4SZte0zds1FJ+Hr8Xzzc5zMHe6J4Nlay/rP4ewmIW7iFKNBEYb/yWa+ceLrs+TfR672TaAgO6o7iSRofEq5YLdwgrwkMmIawa21FrZ2D9SPao/IwvENzk/xcHu7YAAACAQFXQH6HQnxOrw4dqf0NqeKy1tfIPxYYUZhPJfo9O0AmBW2S36pD2l14kS89fvz6Y1g8gN/FwFnRncMzlLY/hX70FSc/3hKBSbH6C6j8hwlgFKfizav21eS358JJz93leOakJZnGb8XlWvz1UJbwCsnR2VEY8Dz90uIk1l/UqHkA= loic@call",
+  "title": "ABC",
+  "id": 4
+}
+```
+
+Will return created key with status `201 Created` on success. If an
+error occurs a `400 Bad Request` is returned with a message explaining the error:
+
+```json
+{
+  "message": {
+    "fingerprint": [
+      "has already been taken"
+    ],
+    "key": [
+      "has already been taken"
+    ]
+  }
+}
+```
+
 ## Add SSH key for user
 
 Create new key owned by specified user. Available only for admin
diff --git a/doc/customization/libravatar.md b/doc/customization/libravatar.md
index 4dffd3027a9f30b88671511505ac93e243b26f5d..ee57fdc65906a7e46ef68a54d3f7924d99768d9d 100644
--- a/doc/customization/libravatar.md
+++ b/doc/customization/libravatar.md
@@ -16,7 +16,7 @@ the configuration options as follows:
 ```yml
   gravatar:
     enabled: true
-    # gravatar urls: possible placeholders: %{hash} %{size} %{email}
+    # gravatar URLs: possible placeholders: %{hash} %{size} %{email}
     plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
 ```
 
@@ -25,14 +25,14 @@ the configuration options as follows:
 ```yml
   gravatar:
     enabled: true
-    # gravatar urls: possible placeholders: %{hash} %{size} %{email}
+    # gravatar URLs: possible placeholders: %{hash} %{size} %{email}
     ssl_url: "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
 ```
 
 ## Self-hosted
 
-If you are [running your own libravatar service](http://wiki.libravatar.org/running_your_own/) the url will be different in the configuration
-but the important part is to provide the same placeholders so GitLab can parse the url correctly.
+If you are [running your own libravatar service](http://wiki.libravatar.org/running_your_own/) the URL will be different in the configuration
+but the important part is to provide the same placeholders so GitLab can parse the URL correctly.
 
 For example, you host a service on `http://libravatar.example.com` the `plain_url` you need to supply in `gitlab.yml` is
 
@@ -65,5 +65,5 @@ Run `sudo gitlab-ctl reconfigure` for changes to take effect.
 
 [Libravatar supports different sets](http://wiki.libravatar.org/api/) of `missing images` for emails not found on the Libravatar service.
 
-In order to use a different set other than `identicon`, replace `&d=identicon` portion of the url with another supported set.
-For example, you can use `retro` set in which case url would look like: `plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"`
+In order to use a different set other than `identicon`, replace `&d=identicon` portion of the URL with another supported set.
+For example, you can use `retro` set in which case the URL would look like: `plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"`
diff --git a/doc/development/README.md b/doc/development/README.md
index 20db6662aca8093c1135ef2c2c627684e5bc6498..62881781145a1b1bc4cc0dd001cb4cc9736b1f46 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -4,3 +4,6 @@
 - [Shell commands](shell_commands.md) in the GitLab codebase
 - [Rake tasks](rake_tasks.md) for development
 - [CI setup](ci_setup.md) for testing GitLab
+- [Sidekiq debugging](sidekiq_debugging.md)
+- [UI guide](ui_guide.md) for building GitLab with existing css styles and elements
+Disable Sidekiq arguments logging by default
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index c4813d22eaa168e14f8b5258d9bfcfa96add0aba..541af487bb1fc71f34367ce0258408d77f790b62 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -8,6 +8,38 @@ EE releases are available not long after CE releases. To obtain the GitLab EE th
 
 Both EE and CE require an add-on component called gitlab-shell. It is obtained from the [gitlab-shell repository](https://gitlab.com/gitlab-org/gitlab-shell/tree/master). New versions are usually tags but staying on the master branch will give you the latest stable version. New releases are generally around the same time as GitLab CE releases with exception for informal security updates deemed critical.
 
+## Physical office analogy
+
+You can imagine GitLab as a physical office.
+
+**The repositories** are the goods GitLab handling.
+They can be stored in a warehouse.
+This can be either a hard disk, or something more complex, such as a NFS filesystem;
+
+**Nginx** acts like the front-desk.
+Users come to Nginx and request actions to be done by workers in the office;
+
+**The database** is a series of metal file cabinets with information on:
+ - The goods in the warehouse (metadata, issues, merge requests etc);
+ - The users coming to the front desk (permissions)
+
+**Redis** is a communication board with “cubby holes” that can contain tasks for office workers;
+
+**Sidekiq** is a worker that primarily handles sending out emails.
+It takes tasks from the Redis communication board;
+
+**A Unicorn worker** is a worker that handles quick/mundane tasks.
+They work with the communication board (Redis).
+Their job description:
+ - check permissions by checking the user session stored in a Redis “cubby hole”;
+ - make tasks for Sidekiq;
+ - fetch stuff from the warehouse or move things around in there;
+
+**Gitlab-shell** is a third kind of worker that takes orders from a fax machine (SSH) instead of the front desk (HTTP).
+Gitlab-shell communicates with Sidekiq via the “communication board” (Redis), and asks quick questions of the Unicorn workers either directly or via the front desk.
+
+**GitLab Enterprise Edition (the application)** is the collection of processes and business practices that the office is run by.
+
 ## System Layout
 
 When referring to ~git in the pictures it means the home directory of the git user which is typically /home/git.
@@ -22,7 +54,7 @@ To serve repositories over SSH there's an add-on application called gitlab-shell
 
 ![GitLab Diagram Overview](gitlab_diagram_overview.png)
 
-A typical install of GitLab will be on Ubuntu Linux or RHEL/CentOS. It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incoming jobs.
+A typical install of GitLab will be on GNU/Linux. It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incoming jobs.
 
 The GitLab web app uses MySQL or PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. It also keeps default branch and hook information with the bare repository. `/home/git/gitlab-satellites` keeps checked out repositories when performing actions such as a merge request, editing files in the web interface, etc.
 
@@ -38,7 +70,7 @@ To summarize here's the [directory structure of the `git` user home directory](.
 
     ps aux | grep '^git'
 
-GitLab has several components to operate. As a system user (i.e. any user that is not the `git` user) it requires a persistent database (MySQL/PostreSQL) and redis database. It also uses Apache httpd or nginx to proxypass Unicorn. As the `git` user it starts Sidekiq and Unicorn (a simple ruby HTTP server running on port `8080` by default). Under the GitLab user there are normally 4 processes: `unicorn_rails master` (1 process), `unicorn_rails worker` (2 processes), `sidekiq` (1 process).
+GitLab has several components to operate. As a system user (i.e. any user that is not the `git` user) it requires a persistent database (MySQL/PostreSQL) and redis database. It also uses Apache httpd or Nginx to proxypass Unicorn. As the `git` user it starts Sidekiq and Unicorn (a simple ruby HTTP server running on port `8080` by default). Under the GitLab user there are normally 4 processes: `unicorn_rails master` (1 process), `unicorn_rails worker` (2 processes), `sidekiq` (1 process).
 
 ### Repository access
 
@@ -114,13 +146,13 @@ nginx
 
 Apache httpd
 
-- [Explanation of apache logs](http://httpd.apache.org/docs/2.2/logs.html).
+- [Explanation of Apache logs](http://httpd.apache.org/docs/2.2/logs.html).
 - `/var/log/apache2/` contains error and output logs (on Ubuntu).
 - `/var/log/httpd/` contains error and output logs (on RHEL).
 
 redis
 
-- `/var/log/redis/redis.log` there are also logrotated logs there.
+- `/var/log/redis/redis.log` there are also log-rotated logs there.
 
 PostgreSQL
 
diff --git a/doc/development/ci_setup.md b/doc/development/ci_setup.md
index ee16aedafe7563459502fa895ff1cda5f3089120..f9b488681820db5041dc5bd1678697eaf0ac981d 100644
--- a/doc/development/ci_setup.md
+++ b/doc/development/ci_setup.md
@@ -26,7 +26,7 @@ We use [these build scripts](https://gitlab.com/gitlab-org/gitlab-ci/blob/master
 # Build configuration on [Semaphore](https://semaphoreapp.com/gitlabhq/gitlabhq/) for testing the [GitHub.com repo](https://github.com/gitlabhq/gitlabhq)
 
 - Language: Ruby
-- Ruby verion: 2.1.2
+- Ruby version: 2.1.2
 - database.yml: pg
 
 Build commands
@@ -37,7 +37,10 @@ bundle install --deployment --path vendor/bundle (Setup)
 cp config/gitlab.yml.example config/gitlab.yml (Setup)
 bundle exec rake db:create (Setup)
 bundle exec rake spinach (Thread #1)
-bundle exec rake spec (Thread #2)
+bundle exec rake spec (thread #2)
+bundle exec rake rubocop (thread #3)
+bundle exec rake brakeman (thread #4)
+bundle exec rake jasmine:ci (thread #5)
 ```
 
 Use rubygems mirror.
diff --git a/doc/development/omnibus.md b/doc/development/omnibus.md
new file mode 100644
index 0000000000000000000000000000000000000000..0ba354d28a2fcdd60003326bff03ac9910ce6261
--- /dev/null
+++ b/doc/development/omnibus.md
@@ -0,0 +1,32 @@
+# What you should know about omnibus packages
+
+Most users install GitLab using our omnibus packages. As a developer it can be
+good to know how the omnibus packages differ from what you have on your laptop
+when you are coding.
+
+## Files are owned by root by default
+
+All the files in the Rails tree (`app/`, `config/` etc.) are owned by 'root' in
+omnibus installations. This makes the installation simpler and it provides
+extra security. The omnibus reconfigure script contains commands that give
+write access to the 'git' user only where needed.
+
+For example, the 'git' user is allowed to write in the `log/` directory, in
+`public/uploads`, and they are allowed to rewrite the `db/schema.rb` file.
+
+In other cases, the reconfigure script tricks GitLab into not trying to write a
+file. For instance, GitLab will generate a `.secret` file if it cannot find one
+and write it to the Rails root. In the omnibus packages, reconfigure writes the
+`.secret` file first, so that GitLab never tries to write it.
+
+## Code, data and logs are in separate directories
+
+The omnibus design separates code (read-only, under `/opt/gitlab`) from data
+(read/write, under `/var/opt/gitlab`) and logs (read/write, under
+`/var/log/gitlab`). To make this happen the reconfigure script sets custom
+paths where it can in GitLab config files, and where there are no path
+settings, it uses symlinks.
+
+For example, `config/gitlab.yml` is treated as data so that file is a symlink.
+The same goes for `public/uploads`. The `log/` directory is replaced by omnibus
+with a symlink to `/var/log/gitlab/gitlab-rails`.
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index 6d9ac161e91ec55ca6221005c08c7099eda07f08..53f8095cb13555b47abf7708bf46e2670c514f25 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -1,6 +1,6 @@
 # Rake tasks for developers
 
-## Setup db with developer seeds:
+## Setup db with developer seeds
 
 Note that if your db user does not have advanced privileges you must create the db manually before running this command.
 
@@ -8,6 +8,10 @@ Note that if your db user does not have advanced privileges you must create the
 bundle exec rake setup
 ```
 
+The `setup` task is a alias for `gitlab:setup`.
+This tasks calls `db:setup` to create the database, calls `add_limits_mysql` that adds limits to the database schema in case of a MySQL database and fianlly it calls `db:seed_fu` to seed the database.
+Note: `db:setup` calls `db:seed` but this does nothing.
+
 ## Run tests
 
 This runs all test suites present in GitLab.
diff --git a/doc/development/shell_commands.md b/doc/development/shell_commands.md
index 23c8365c340f8f3fc7b8032bc069a5edf5397636..821027f43fa391ab66266d080e8ac96c2eb29006 100644
--- a/doc/development/shell_commands.md
+++ b/doc/development/shell_commands.md
@@ -1,5 +1,8 @@
 # Guidelines for shell commands in the GitLab codebase
 
+This document contains guidelines for working with processes and files in the GitLab codebase.
+These guidelines are meant to make your code more reliable _and_ secure.
+
 ## References
 
 - [Google Ruby Security Reviewer's Guide](https://code.google.com/p/ruby-security/wiki/Guide)
@@ -105,7 +108,72 @@ In other repositories, such as gitlab-shell you can also use `IO.popen`.
 
 ```ruby
 # Safe IO.popen example
-logs = IO.popen(%W(git log), chdir: repo_dir).read
+logs = IO.popen(%W(git log), chdir: repo_dir) { |p| p.read }
 ```
 
 Note that unlike `Gitlab::Popen.popen`, `IO.popen` does not capture standard error.
+
+## Avoid user input at the start of path strings
+
+Various methods for opening and reading files in Ruby can be used to read the
+standard output of a process instead of a file.  The following two commands do
+roughly the same:
+
+```
+`touch /tmp/pawned-by-backticks`
+File.read('|touch /tmp/pawned-by-file-read')
+```
+
+The key is to open a 'file' whose name starts with a `|`.
+Affected methods include Kernel#open, File::read, File::open, IO::open and IO::read.
+
+You can protect against this behavior of 'open' and 'read' by ensuring that an
+attacker cannot control the start of the filename string you are opening.  For
+instance, the following is sufficient to protect against accidentally starting
+a shell command with `|`:
+
+```
+# we assume repo_path is not controlled by the attacker (user)
+path = File.join(repo_path, user_input)
+# path cannot start with '|' now.
+File.read(path)
+```
+
+If you have to use user input a relative path, prefix `./` to the path.
+
+Prefixing user-supplied paths also offers extra protection against paths
+starting with `-` (see the discussion about using `--` above).
+
+## Guard against path traversal
+
+Path traversal is a security where the program (GitLab) tries to restrict user
+access to a certain directory on disk, but the user manages to open a file
+outside that directory by taking advantage of the `../` path notation.
+
+```
+# Suppose the user gave us a path and they are trying to trick us
+user_input = '../other-repo.git/other-file'
+
+# We look up the repo path somewhere
+repo_path = 'repositories/user-repo.git'
+
+# The intention of the code below is to open a file under repo_path, but
+# because the user used '..' she can 'break out' into
+# 'repositories/other-repo.git'
+full_path = File.join(repo_path, user_input)
+File.open(full_path) do # Oops!
+```
+
+A good way to protect against this is to compare the full path with its
+'absolute path' according to Ruby's `File.absolute_path`.
+
+```
+full_path = File.join(repo_path, user_input)
+if full_path != File.absolute_path(full_path)
+  raise "Invalid path: #{full_path.inspect}"
+end
+
+File.open(full_path) do # Etc.
+```
+
+A check like this could have avoided CVE-2013-4583.
diff --git a/doc/development/sidekiq_debugging.md b/doc/development/sidekiq_debugging.md
new file mode 100644
index 0000000000000000000000000000000000000000..cea11e5f126601e31c1886de25792f2b77461150
--- /dev/null
+++ b/doc/development/sidekiq_debugging.md
@@ -0,0 +1,14 @@
+# Sidekiq debugging
+
+## Log arguments to Sidekiq jobs
+
+If you want to see what arguments are being passed to Sidekiq jobs you can set
+the SIDEKIQ_LOG_ARGUMENTS environment variable.
+
+```
+SIDEKIQ_LOG_ARGUMENTS=1 bundle exec foreman start
+```
+
+It is not recommend to enable this setting in production because some Sidekiq
+jobs (such as sending a password reset email) take secret arguments (for
+example the password reset token).
diff --git a/doc/development/ui_guide.md b/doc/development/ui_guide.md
new file mode 100644
index 0000000000000000000000000000000000000000..2f01defc11d8a7b474c02f825314b6c0fc7c9d0a
--- /dev/null
+++ b/doc/development/ui_guide.md
@@ -0,0 +1,12 @@
+# UI Guide for building GitLab 
+
+## Best practices for creating new pages in GitLab
+
+TODO: write some best practices when develop GitLab features.
+
+## GitLab UI development kit
+
+We created a page inside GitLab where you can check commonly used html and css elements.
+
+When you run GitLab instance locally - just visit http://localhost:3000/help/ui page to see UI examples 
+you can use during GitLab development.
diff --git a/doc/hooks/custom_hooks.md b/doc/hooks/custom_hooks.md
index 00867ead80d3086c9bc229a4c6cdaade10618fbd..f7d4f3de68b3cccf22ddf656cd5d35e2d774894c 100644
--- a/doc/hooks/custom_hooks.md
+++ b/doc/hooks/custom_hooks.md
@@ -24,7 +24,7 @@ set up a custom hook.
 
 1. Pick a project that needs a custom git hook.
 1. On the GitLab server, navigate to the project's repository directory.
-For a manual install the path is usually 
+For an installation from source the path is usually
 `/home/git/repositories/<group>/<project>.git`. For Omnibus installs the path is
 usually `/var/opt/gitlab/git-data/repositories/<group>/<project>.git`.
 1. Create a new directory in this location called `custom_hooks`.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 459a21ae8214c10f6d492a2c318879277188e70e..d6208bb079716e87f1ca4dc20b2f5733cf918ec7 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -1,14 +1,14 @@
-# Installation
+# Installation from source
 
 ## Consider the Omnibus package installation
 
-Since a manual installation is a lot of work and error prone we strongly recommend the fast and reliable [Omnibus package installation](https://about.gitlab.com/downloads/) (deb/rpm).
+Since an installation from source is a lot of work and error prone we strongly recommend the fast and reliable [Omnibus package installation](https://about.gitlab.com/downloads/) (deb/rpm).
 
 ## Select Version to Install
 
-Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install. In most cases this should be the highest numbered stable branch (example shown below).
-
-![Select latest branch](https://i.imgur.com/Lrdxk1k.png)
+Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the tag (version) of GitLab you would like to install.
+In most cases this should be the highest numbered production tag (without rc in it).
+You can select the tag in the version dropdown in the top left corner of GitLab (below the menu bar).
 
 If the highest number stable branch is unclear please check the [GitLab Blog](https://about.gitlab.com/blog/) for installation guide links by version.
 
@@ -22,7 +22,9 @@ This is the official installation guide to set up a production server. To set up
 
 The following steps have been known to work. Please **use caution when you deviate** from this guide. Make sure you don't violate any assumptions GitLab makes about its environment. For example many people run into permission problems because they changed the location of directories or run services as the wrong user.
 
-If you find a bug/error in this guide please **submit a merge request** following the [contributing guide](../../CONTRIBUTING.md).
+If you find a bug/error in this guide please **submit a merge request**
+following the
+[contributing guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md).
 
 ## Overview
 
@@ -54,7 +56,7 @@ up-to-date and install it.
 
 Install the required packages (needed to compile Ruby and native extensions to Ruby gems):
 
-    sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server redis-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils pkg-config cmake
+    sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server redis-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils pkg-config cmake libkrb5-dev nodejs
 
 Make sure you have the right version of Git installed
 
@@ -101,8 +103,8 @@ Remove the old Ruby 1.8 if present
 Download Ruby and compile it:
 
     mkdir /tmp/ruby && cd /tmp/ruby
-    curl -L --progress ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
-    cd ruby-2.1.2
+    curl -L --progress http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.5.tar.gz | tar xz
+    cd ruby-2.1.5
     ./configure --disable-install-rdoc
     make
     sudo make install
@@ -139,7 +141,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
 
     # Try connecting to the new database with the new user
     sudo -u git -H psql -d gitlabhq_production
-    
+
     # Quit the database session
     gitlabhq_production> \q
 
@@ -181,9 +183,9 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
 ### Clone the Source
 
     # Clone GitLab repository
-    sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-4-stable gitlab
+    sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-9-stable gitlab
 
-**Note:** You can change `7-4-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+**Note:** You can change `7-9-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
 
 ### Configure It
 
@@ -278,7 +280,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
 GitLab Shell is an SSH access and repository management software developed specially for GitLab.
 
     # Run the installation task for gitlab-shell (replace `REDIS_URL` if needed):
-    sudo -u git -H bundle exec rake gitlab:shell:install[v2.0.1] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production
+    sudo -u git -H bundle exec rake gitlab:shell:install[v2.6.0] REDIS_URL=unix:/var/run/redis/redis.sock RAILS_ENV=production
 
     # By default, the gitlab-shell config is generated from your main GitLab config.
     # You can review (and modify) the gitlab-shell config as follows:
@@ -294,9 +296,9 @@ GitLab Shell is an SSH access and repository management software developed speci
 
     # When done you see 'Administrator account created:'
 
-**Note:** You can set the Administrator password by supplying it in environmental variable `GITLAB_ROOT_PASSWORD`, eg.:
+**Note:** You can set the Administrator/root password by supplying it in environmental variable `GITLAB_ROOT_PASSWORD` as seen below. If you don't set the password (and it is set to the default one) please wait with exposing GitLab to the public internet until the installation is done and you've logged into the server the first time. During the first login you'll be forced to change the default password.
 
-    sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=newpassword
+    sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword
 
 ### Install Init Script
 
@@ -383,15 +385,17 @@ NOTE: Supply `SANITIZE=true` environment variable to `gitlab:check` to omit proj
 
 ### Initial Login
 
-Visit YOUR_SERVER in your web browser for your first GitLab login. The setup has created an admin account for you. You can use it to log in:
+Visit YOUR_SERVER in your web browser for your first GitLab login. The setup has created a default admin account for you. You can use it to log in:
 
     root
     5iveL!fe
 
-**Important Note:** Please go over to your profile page and immediately change the password, so nobody can access your GitLab by using this login information later on.
+**Important Note:** On login you'll be prompted to change the password.
 
 **Enjoy!**
 
+You can use `sudo service gitlab start` and `sudo service gitlab stop` to start and stop GitLab.
+
 ## Advanced Setup Tips
 
 ### Using HTTPS
@@ -455,4 +459,4 @@ You can configure LDAP authentication in `config/gitlab.yml`. Please restart Git
 
 ### Using Custom Omniauth Providers
 
-See the [omniauth integration document](doc/integration/omniauth.md)
+See the [omniauth integration document](../integration/omniauth.md)
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index fd59ac8a0734c71e32d765dba1fdb5dc3e677eae..7a3216dd2d2b517064b27a40d5a127174286c8b0 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -7,7 +7,7 @@
 - Ubuntu
 - Debian
 - CentOS
-- RedHat Enterprise Linux (please use the CentOS packages and instructions)
+- Red Hat Enterprise Linux (please use the CentOS packages and instructions)
 - Scientific Linux (please use the CentOS packages and instructions)
 - Oracle Linux (please use the CentOS packages and instructions)
 
@@ -22,7 +22,7 @@ For the installations options please see [the installation page on the GitLab we
 - FreeBSD
 
 On the above unsupported distributions is still possible to install GitLab yourself.
-Please see the [manual installation guide](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) and the [unofficial installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) on the public wiki for more information.
+Please see the [installation from source guide](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) and the [unofficial installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) on the public wiki for more information.
 
 ### Non-Unix operating systems such as Windows
 
@@ -38,6 +38,16 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/) but GitLab
 
 ## Hardware requirements
 
+### Storage
+
+The necessary hard drive space largely depends on the size of the repos you want to store in GitLab but as a *rule of thumb* you should have at least twice as much free space as all your repos combined take up. You need twice the storage because [GitLab satellites](structure.md) contain an extra copy of each repo.
+
+If you want to be flexible about growing your hard drive space in the future consider mounting it using LVM so you can add more hard drives when you need them.
+
+Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume.
+
+If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab.
+
 ### CPU
 
 - 1 core works supports up to 100 users but the application can be a bit slower due to having all workers and background jobs running on the same core
@@ -50,6 +60,10 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/) but GitLab
 
 ### Memory
 
+You need at least 2GB of addressable memory (RAM + swap) to install and use GitLab!
+With less memory GitLab will give strange errors during the reconfigure run and 500 errors during usage.
+
+- 512MB RAM + 1.5GB of swap is the absolute minimum but we strongly **advise against** this amount of memory. See the unicorn worker section below for more advise.
 - 1GB RAM + 1GB swap supports up to 100 users
 - **2GB RAM** is the **recommended** memory size and supports up to 500 users
 - 4GB RAM supports up to 2,000 users
@@ -60,15 +74,19 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/) but GitLab
 
 Notice: The 25 workers of Sidekiq will show up as separate processes in your process overview (such as top or htop) but they share the same RAM allocation since Sidekiq is a multithreaded application.
 
-### Storage
+## Unicorn Workers
 
-The necessary hard drive space largely depends on the size of the repos you want to store in GitLab but as a *rule of thumb* you should have at least twice as much free space as all your repos combined take up. You need twice the storage because [GitLab satellites](structure.md) contain an extra copy of each repo.
+It's possible to increase the amount of unicorn workers and this will usually help for to reduce the response time of the applications and increase the ability to handle parallel requests.
 
-If you want to be flexible about growing your hard drive space in the future consider mounting it using LVM so you can add more hard drives when you need them.
+For most instances we recommend using: CPU cores + 1 = unicorn workers.
+So for a machine with 2 cores, 3 unicorn workers is ideal.
 
-Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume.
+For all machines that have 1GB and up we recommend a minimum of three unicorn workers.
+If you have a 512MB machine with a magnetic (non-SSD) swap drive we recommend to configure only one Unicorn worker to prevent excessive swapping.
+With one Unicorn worker only git over ssh access will work because the git over HTTP access requires two running workers (one worker to receive the user request and one worker for the authorization check).
+If you have a 512MB machine with a SSD drive you can use two Unicorn workers, this will allow HTTP access although it will be slow due to swapping.
 
-If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab.
+To change the Unicorn workers when you have the Omnibus package please see [the Unicorn settings in the Omnibus GitLab documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.md#unicorn-settings).
 
 ## Database
 
@@ -88,4 +106,4 @@ On a very active server (10,000 active users) the Sidekiq process can use 1GB+ o
 - Firefox (Latest released version and [latest ESR version](https://www.mozilla.org/en-US/firefox/organizations/))
 - Safari 7+ (known problem: required fields in html5 do not work)
 - Opera (Latest released version)
-- IE 10+
+- IE 10+
\ No newline at end of file
diff --git a/doc/integration/README.md b/doc/integration/README.md
index 357ed0383146ac1b9a03b713788bce2906c0b37d..286bd34a0bd57360c5376ef8ad3b700c397de125 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -6,14 +6,16 @@ See the documentation below for details on how to configure these services.
 
 - [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc.
 - [LDAP](ldap.md) Set up sign in via LDAP
-- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, and Google via OAuth.
+- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab, and Google via OAuth.
 - [Slack](slack.md) Integrate with the Slack chat service
+- [OAuth2 provider](oauth_provider.md) OAuth2 application creation
+- [Gmail](gitlab_buttons_in_gmail.md) Adds GitLab actions to messages
 
-Jenkins support is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jenkins.html).
+GitLab Enterprise Edition contains [advanced JIRA support](http://doc.gitlab.com/ee/integration/jira.html) and [advanced Jenkins support](http://doc.gitlab.com/ee/integration/jenkins.html).
 
 ## Project services
 
-Integration with services such as Campfire, Flowdock, Gemnasium, HipChat, PivotalTracker and Slack are available in the from of a Project Service.
+Integration with services such as Campfire, Flowdock, Gemnasium, HipChat, Pivotal Tracker, and Slack are available in the form of a Project Service.
 You can find these within GitLab in the Services page under Project Settings if you are at least a master on the project.
 Project Services are a bit like plugins in that they allow a lot of freedom in adding functionality to GitLab, for example there is also a service that can send an email every time someone pushes new commits.
 Because GitLab is open source we can ship with the code and tests for all plugins.
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
new file mode 100644
index 0000000000000000000000000000000000000000..d82e1f8b41ba02c89e8155099628b5fad30c144c
--- /dev/null
+++ b/doc/integration/bitbucket.md
@@ -0,0 +1,122 @@
+# Integrate your server with Bitbucket
+
+Import projects from Bitbucket and login to your GitLab instance with your Bitbucket account.
+
+To enable the Bitbucket OmniAuth provider you must register your application with Bitbucket.
+Bitbucket will generate an application ID and secret key for you to use.
+
+1.  Sign in to Bitbucket.
+
+1.  Navigate to your individual user settings or a team's settings, depending on how you want the application registered. It does not matter if the application is registered as an individual or a team - that is entirely up to you.
+
+1.  Select "OAuth" in the left menu.
+
+1.  Select "Add consumer".
+
+1.  Provide the required details.
+    - Name: This can be anything. Consider something like "\<Organization\>'s GitLab" or "\<Your Name\>'s GitLab" or something else descriptive.
+    - Application description: Fill this in if you wish.
+    - URL: The URL to your GitLab installation. 'https://gitlab.company.com'
+1.  Select "Save".
+
+1.  You should now see a Key and Secret in the list of OAuth customers.
+    Keep this page open as you continue configuration.
+
+1.  On your GitLab server, open the configuration file.
+
+    For omnibus package:
+
+    ```sh
+      sudo editor /etc/gitlab/gitlab.rb
+    ```
+
+    For instalations from source:
+
+    ```sh
+      cd /home/git/gitlab
+
+      sudo -u git -H editor config/gitlab.yml
+    ```
+
+1.  See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+
+1.  Add the provider configuration:
+
+    For omnibus package:
+
+    ```ruby
+      gitlab_rails['omniauth_providers'] = [
+        {
+          "name" => "bitbucket",
+          "app_id" => "YOUR_KEY",
+          "app_secret" => "YOUR_APP_SECRET",
+          "url" => "https://bitbucket.org/"
+        }
+      ]
+    ```
+
+    For installation from source:
+
+    ```
+      - { name: 'bitbucket', app_id: 'YOUR_KEY',
+        app_secret: 'YOUR_APP_SECRET' }
+    ```
+
+1.  Change 'YOUR_APP_ID' to the key from the Bitbucket application page from step 7.
+
+1.  Change 'YOUR_APP_SECRET' to the secret from the Bitbucket application page from step 7.
+
+1.  Save the configuration file.
+
+1.  Restart GitLab for the changes to take effect.
+
+On the sign in page there should now be a Bitbucket icon below the regular sign in form.
+Click the icon to begin the authentication process. Bitbucket will ask the user to sign in and authorize the GitLab application.
+If everything goes well the user will be returned to GitLab and will be signed in.
+
+## Bitbucket project import
+
+To allow projects to be imported directly into GitLab, Bitbucket requires two extra setup steps compared to GitHub and GitLab.com.
+
+Bitbucket doesn't allow OAuth applications to clone repositories over HTTPS, and instead requires GitLab to use SSH and identify itself using your GitLab server's SSH key.
+
+### Step 1: Known hosts
+
+To allow GitLab to connect to Bitbucket over SSH, you need to add 'bitbucket.org' to your GitLab server's known SSH hosts. Take the following steps to do so:
+
+1. Manually connect to 'bitbucket.org' over SSH, while logged in as the `git` account that GitLab will use:
+
+    ```sh
+    ssh git@bitbucket.org
+    ```
+
+1.  Verify the RSA key fingerprint you'll see in the response matches the one in the [Bitbucket documentation](https://confluence.atlassian.com/display/BITBUCKET/Use+the+SSH+protocol+with+Bitbucket#UsetheSSHprotocolwithBitbucket-KnownhostorBitbucket'spublickeyfingerprints) (the specific IP address doesn't matter):
+
+    ```sh
+    The authenticity of host 'bitbucket.org (207.223.240.182)' can't be established.
+    RSA key fingerprint is 97:8c:1b:f2:6f:14:6b:5c:3b:ec:aa:46:46:74:7c:40.
+    Are you sure you want to continue connecting (yes/no)?
+    ```
+
+1. If the fingerprint matches, type `yes` to continue connecting and have 'bitbucket.org' be added to your known hosts.
+
+1. Your GitLab server is now able to connect to Bitbucket over SSH. Continue to step 2:
+
+### Step 2: Public key
+
+To be able to access repositories on Bitbucket, GitLab will automatically register your public key with Bitbucket as a deploy key for the repositories to be imported. Your public key needs to be at `~/.ssh/bitbucket_rsa.pub`, which will expand to `/home/git/.ssh/bitbucket_rsa.pub` in most configurations.
+
+If you have that file in place, you're all set and should see the "Import projects from Bitbucket" option enabled. If you don't, do the following:
+
+1. Create a new SSH key:
+
+    ```sh
+    sudo -u git -H ssh-keygen
+    ```
+
+    When asked `Enter file in which to save the key` specify the correct path, eg. `/home/git/.ssh/bitbucket_rsa`.
+    Make sure to use an **empty passphrase**.
+
+2. Restart GitLab to allow it to find the new public key.
+
+You should now see the "Import projects from Bitbucket" option on the New Project page enabled.
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index 87af94512ed3ee09ac17612e59460e5bf90af91b..96755707dee3d9e59c4f7c8b5cde373a092e9efb 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -1,13 +1,39 @@
 # External issue tracker
 
-GitLab has a great issue tracker but you can also use an external issue tracker such as JIRA, Bugzilla or Redmine. This is something that you can turn on per GitLab project. If for example you configure JIRA it provides the following functionality:
+GitLab has a great issue tracker but you can also use an external issue tracker such as Jira, Bugzilla or Redmine. You can configure issue trackers per GitLab project. For instance, if you configure Jira it allows you to do the following:
 
-- the 'Issues' link on the GitLab project pages takes you to the appropriate JIRA issue index;
-- 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.
+- the 'Issues' link on the GitLab project pages takes you to the appropriate Jira issue index;
+- clicking 'New issue' on the project dashboard creates a new Jira issue;
+- To reference Jira issue PROJECT-1234 in comments, use syntax PROJECT-1234. Commit messages get turned into HTML links to the corresponding Jira issue.
 
-![jira screenshot](jira-integration-points.png)
+![Jira screenshot](jira-integration-points.png)
 
-You can configure the integration in the gitlab.yml configuration file.
+GitLab Enterprise Edition contains [advanced JIRA support](http://doc.gitlab.com/ee/integration/jira.html).
+
+## Configuration
+
+### Project Service
+
+You can enable an external issue tracker per project. As an example, we will configure `Redmine` for project named gitlab-ci.
+
+Fill in the required details on the page:
+
+![redmine configuration](redmine_configuration.png)
+
+* `description` A name for the issue tracker (to differentiate between instances, for example).
+* `project_url` The URL to the project in Redmine which is being linked to this GitLab project.
+* `issues_url` The URL to the issue in Redmine project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the url. This id is used by GitLab as a placeholder to replace the issue number.
+* `new_issue_url` This is the URL to create a new issue in Redmine for the project linked to this GitLab project.
+
+### Service Template
+
+It is necessary to configure the external issue tracker per project, because project specific details are needed for the integration with GitLab.
+The admin can add a service template that sets a default for each project. This makes it much easier to configure individual projects.
+
+In GitLab Admin section, navigate to `Service Templates` and choose the service template you want to create:
+
+![redmine service template](redmine_service_template.png)
+
+After the template is created, the template details will be pre-filled on the project service page.
 
 Support to add your commits to the Jira ticket automatically is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jira.html).
diff --git a/doc/integration/github.md b/doc/integration/github.md
index 714593d8266d234c7d7e87ce06da10a3a75960ba..b64501c2aaab8ec3f32c91c70426c158f69a4955 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -1,6 +1,9 @@
-# GitHub OAuth2 OmniAuth Provider
+# Integrate your server with GitHub
 
-To enable the GitHub OmniAuth provider you must register your application with GitHub. GitHub will generate a client ID and secret key for you to use.
+Import projects from GitHub and login to your GitLab instance with your GitHub account.
+
+To enable the GitHub OmniAuth provider you must register your application with GitHub. 
+GitHub will generate an application ID and secret key for you to use.
 
 1.  Sign in to GitHub.
 
@@ -14,35 +17,63 @@ To enable the GitHub OmniAuth provider you must register your application with G
     - Application name: This can be anything. Consider something like "\<Organization\>'s GitLab" or "\<Your Name\>'s GitLab" or something else descriptive.
     - Homepage URL: The URL to your GitLab installation. 'https://gitlab.company.com'
     - Application description: Fill this in if you wish.
-    - Authorization callback URL: 'https://gitlab.company.com/users/auth/github/callback'
+    - Authorization callback URL: 'https://gitlab.company.com/'
 1.  Select "Register application".
 
-1.  You should now see a Client ID and Client Secret near the top right of the page (see screenshot). Keep this page open as you continue configuration. ![GitHub app](github_app.png)
+1.  You should now see a Client ID and Client Secret near the top right of the page (see screenshot). 
+    Keep this page open as you continue configuration.
+    ![GitHub app](github_app.png)
 
 1.  On your GitLab server, open the configuration file.
 
+    For omnibus package:
+
+    ```sh
+      sudo editor /etc/gitlab/gitlab.rb
+    ```
+
+    For instalations from source:
+
     ```sh
-    cd /home/git/gitlab
+      cd /home/git/gitlab
 
-    sudo -u git -H editor config/gitlab.yml
+      sudo -u git -H editor config/gitlab.yml
     ```
 
-1.  Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details.
+1.  See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+
+1.  Add the provider configuration:
+
+    For omnibus package:
+
+    ```ruby
+      gitlab_rails['omniauth_providers'] = [
+        {
+          "name" => "github",
+          "app_id" => "YOUR_APP_ID",
+          "app_secret" => "YOUR_APP_SECRET",
+          "url" => "https://github.com/",
+          "args" => { "scope" => "user:email" }
+        }
+      ]
+    ```
 
-1.  Under `providers:` uncomment (or add) lines that look like the following:
+    For installation from source:
 
     ```
-        - { name: 'github', app_id: 'YOUR APP ID',
-          app_secret: 'YOUR APP SECRET',
-          args: { scope: 'user:email' } }
+      - { name: 'github', app_id: 'YOUR_APP_ID',
+        app_secret: 'YOUR_APP_SECRET',
+        args: { scope: 'user:email' } }
     ```
 
-1.  Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7.
+1.  Change 'YOUR_APP_ID' to the client ID from the GitHub application page from step 7.
 
-1.  Change 'YOUR APP SECRET' to the client secret from the GitHub application page  from step 7.
+1.  Change 'YOUR_APP_SECRET' to the client secret from the GitHub application page  from step 7.
 
 1.  Save the configuration file.
 
 1.  Restart GitLab for the changes to take effect.
 
-On the sign in page there should now be a GitHub icon below the regular sign in form. Click the icon to begin the authentication process. GitHub will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in.
+On the sign in page there should now be a GitHub icon below the regular sign in form. 
+Click the icon to begin the authentication process. GitHub will ask the user to sign in and authorize the GitLab application. 
+If everything goes well the user will be returned to GitLab and will be signed in.
diff --git a/doc/integration/github_app.png b/doc/integration/github_app.png
index c0873b2e20d142779e3e2642a176bc2bdcd4899d..d890345ced917f2c78ae77dc39c2b66d1362e0d5 100644
Binary files a/doc/integration/github_app.png and b/doc/integration/github_app.png differ
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
new file mode 100644
index 0000000000000000000000000000000000000000..216f1f11a9b0c9b1d9c364305364f0f0216cab8a
--- /dev/null
+++ b/doc/integration/gitlab.md
@@ -0,0 +1,84 @@
+# Integrate your server with GitLab.com
+
+Import projects from GitLab.com and login to your GitLab instance with your GitLab.com account.
+
+To enable the GitLab.com OmniAuth provider you must register your application with GitLab.com. 
+GitLab.com will generate an application ID and secret key for you to use.
+
+1.  Sign in to GitLab.com
+
+1.  Navigate to your profile settings.
+
+1.  Select "Applications" in the left menu.
+
+1.  Select "New application".
+
+1.  Provide the required details.
+    - Name: This can be anything. Consider something like "\<Organization\>'s GitLab" or "\<Your Name\>'s GitLab" or something else descriptive.
+    - Redirect URI:
+
+    ```
+    http://your-gitlab.example.com/import/gitlab/callback
+    http://your-gitlab.example.com/users/auth/gitlab/callback
+    ```
+
+    The first link is required for the importer and second for the authorization.
+
+1.  Select "Submit".
+
+1.  You should now see a Client ID and Client Secret near the top right of the page (see screenshot). 
+    Keep this page open as you continue configuration. 
+    ![GitLab app](gitlab_app.png)
+
+1.  On your GitLab server, open the configuration file.
+
+    For omnibus package:
+
+    ```sh
+      sudo editor /etc/gitlab/gitlab.rb
+    ```
+
+    For instalations from source:
+
+    ```sh
+      cd /home/git/gitlab
+
+      sudo -u git -H editor config/gitlab.yml
+    ```
+
+1.  See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+
+1.  Add the provider configuration:
+
+    For omnibus package:
+
+    ```ruby
+      gitlab_rails['omniauth_providers'] = [
+        {
+          "name" => "gitlab",
+          "app_id" => "YOUR_APP_ID",
+          "app_secret" => "YOUR_APP_SECRET",
+          "args" => { "scope" => "api" }
+        }
+      ]
+    ```
+
+    For installations from source:
+
+    ```
+      - { name: 'gitlab', app_id: 'YOUR_APP_ID',
+        app_secret: 'YOUR_APP_SECRET',
+        args: { scope: 'api' } }
+    ```
+
+1.  Change 'YOUR_APP_ID' to the Application ID from the GitLab.com application page.
+
+1.  Change 'YOUR_APP_SECRET' to the secret from the GitLab.com application page.
+
+1.  Save the configuration file.
+
+1.  Restart GitLab for the changes to take effect.
+
+On the sign in page there should now be a GitLab.com icon below the regular sign in form. 
+Click the icon to begin the authentication process. GitLab.com will ask the user to sign in and authorize the GitLab application. 
+If everything goes well the user will be returned to your GitLab instance and will be signed in.
diff --git a/doc/integration/gitlab_app.png b/doc/integration/gitlab_app.png
new file mode 100644
index 0000000000000000000000000000000000000000..3f9391a821bcb2d625e4c8e4db10f1da66168240
Binary files /dev/null and b/doc/integration/gitlab_app.png differ
diff --git a/doc/integration/gitlab_buttons_in_gmail.md b/doc/integration/gitlab_buttons_in_gmail.md
index 5cfea5a90f88474741f6066d0076a42c00f51895..a9885cef1092ce710ffb7981dd7c810b11329903 100644
--- a/doc/integration/gitlab_buttons_in_gmail.md
+++ b/doc/integration/gitlab_buttons_in_gmail.md
@@ -1,4 +1,4 @@
-# GitLab buttons in gmail
+# GitLab buttons in Gmail
 
 GitLab supports [Google actions in email](https://developers.google.com/gmail/markup/actions/actions-overview).
 
@@ -9,3 +9,20 @@ If correctly setup, emails that require an action will be marked in Gmail.
 To get this functioning, you need to be registered with Google.
 [See how to register with google in this document.](https://developers.google.com/gmail/markup/registering-with-google)
 
+To aid the registering with google, GitLab offers a rake task that will send an email to google whitelisting email address from your GitLab server.
+
+To check what would be sent to the google email address, run the rake task:
+
+```bash
+bundle exec rake gitlab:mail_google_schema_whitelisting RAILS_ENV=production
+```
+
+**This will not send the email but give you the output of how the mail will look.**
+
+Copy the output of the rake task to [google email markup tester](https://www.google.com/webmasters/markup-tester/u/0/) and press "Validate".
+
+If you receive "No errors detected" message from the tester you can send the email using:
+
+```bash
+bundle exec rake gitlab:mail_google_schema_whitelisting RAILS_ENV=production SEND=true
+```
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 7a78aff8ea4160971ba41348aa5bababde52fbad..e1c14c7c94828f08b04254a7427f65b18b809a38 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -27,27 +27,50 @@ To enable the Google OAuth2 OmniAuth provider you must register your application
     - Authorized redirect URI: 'https://gitlab.example.com/users/auth/google_oauth2/callback'
 1. Under the heading "Client ID for web application" you should see a Client ID and Client secret (see screenshot). Keep this page open as you continue configuration. ![Google app](google_app.png)
 
-1. On your GitLab server, open the configuration file.
+1.  On your GitLab server, open the configuration file.
+
+    For omnibus package:
+
+    ```sh
+      sudo editor /etc/gitlab/gitlab.rb
+    ```
+
+    For instalations from source:
 
     ```sh
-    cd /home/git/gitlab
+      cd /home/git/gitlab
 
-    sudo -u git -H editor config/gitlab.yml
+      sudo -u git -H editor config/gitlab.yml
     ```
 
-1.  Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details.
+1.  See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+
+1.  Add the provider configuration:
+
+    For omnibus package:
+
+    ```ruby
+      gitlab_rails['omniauth_providers'] = [
+        {
+          "name" => "google_oauth2",
+          "app_id" => "YOUR_APP_ID",
+          "app_secret" => "YOUR_APP_SECRET",
+          "args" => { "access_type" => "offline", "approval_prompt" => '' }
+        }
+      ]
+    ```
 
-1.  Under `providers:` uncomment (or add) lines that look like the following:
+    For installations from source:
 
     ```
-           - { name: 'google_oauth2', app_id: 'YOUR APP ID',
-             app_secret: 'YOUR APP SECRET',
-             args: { access_type: 'offline', approval_prompt: '' } }
+     - { name: 'google_oauth2', app_id: 'YOUR_APP_ID',
+       app_secret: 'YOUR_APP_SECRET',
+       args: { access_type: 'offline', approval_prompt: '' } }
     ```
 
-1.  Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7.
+1.  Change 'YOUR_APP_ID' to the client ID from the Google Developer page from step 10.
 
-1.  Change 'YOUR APP SECRET' to the client secret from the GitHub application page  from step 7.
+1.  Change 'YOUR_APP_SECRET' to the client secret from the Google Developer page from step 10.
 
 1.  Save the configuration file.
 
diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md
index 56b0d826adbcdc44388aa71d5d7884c757b0bdbf..125ce31b5217061f1bf0cdd250a1e1942cdaa538 100644
--- a/doc/integration/ldap.md
+++ b/doc/integration/ldap.md
@@ -29,9 +29,9 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
   label: 'LDAP'
 
   host: '_your_ldap_server'
-  port: 636
+  port: 389
   uid: 'sAMAccountName'
-  method: 'ssl' # "tls" or "ssl" or "plain"
+  method: 'plain' # "tls" or "ssl" or "plain"
   bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
   password: '_the_password_of_the_bind_user'
 
@@ -76,6 +76,9 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
 EOS
 ```
 
+If you are getting 'Connection Refused' errors when trying to connect to the LDAP server please double-check the LDAP `port` and `method` settings used by GitLab.
+Common combinations are `method: 'plain'` and `port: 389`, OR `method: 'ssl'` and `port: 636`.
+
 If you are using a GitLab installation from source you can find the LDAP settings in `/home/git/gitlab/config/gitlab.yml`:
 
 ```
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
new file mode 100644
index 0000000000000000000000000000000000000000..192c321f7129941e44c68b23e8257c36e8da4ee2
--- /dev/null
+++ b/doc/integration/oauth_provider.md
@@ -0,0 +1,35 @@
+## GitLab as OAuth2 authentication service provider
+
+This document is about using GitLab as an OAuth authentication service provider to sign into other services.
+If you want to use other OAuth authentication service providers to sign into GitLab please see the [OAuth2 client documentation](../api/oauth2.md)
+
+OAuth2 provides client applications a 'secure delegated access' to server resources on behalf of a resource owner. Or you can allow users to sign in to your application with their GitLab.com account.
+In fact OAuth allows to issue access token to third-party clients by an authorization server, 
+with the approval of the resource owner, or end-user. 
+Mostly, OAuth2 is using for SSO (Single sign-on). But you can find a lot of different usages for this functionality. 
+For example, our feature 'GitLab Importer' is using OAuth protocol to give an access to repositories without sharing user credentials to GitLab.com account. 
+Also GitLab.com application can be used for authentication to your GitLab instance if needed [GitLab OmniAuth](gitlab.md).
+
+GitLab has two ways to add new OAuth2 application to an instance, you can add application as regular user and through admin area. So GitLab actually can have an instance-wide and a user-wide applications. There is no defferences between them except the different permission levels.
+
+### Adding application through profile
+Go to your profile section 'Application' and press button 'New Application'
+
+![applications](oauth_provider/user_wide_applications.png)
+
+After this you will see application form, where "Name" is arbitrary name, "Redirect URI" is URL in your app where users will be sent after authorization on GitLab.com.
+
+![application_form](oauth_provider/application_form.png)
+
+### Authorized application
+Every application you authorized will be shown in your "Authorized application" sections.
+
+![authorized_application](oauth_provider/authorized_application.png)
+
+At any time you can revoke access just clicking button "Revoke"
+
+### OAuth applications in admin area
+
+If you want to create application that does not belong to certain user you can create it from admin area 
+
+![admin_application](oauth_provider/admin_application.png)
\ No newline at end of file
diff --git a/doc/integration/oauth_provider/admin_application.png b/doc/integration/oauth_provider/admin_application.png
new file mode 100644
index 0000000000000000000000000000000000000000..a5f34512aa85236ac9ecc7d70129d8a3a3f1a71b
Binary files /dev/null and b/doc/integration/oauth_provider/admin_application.png differ
diff --git a/doc/integration/oauth_provider/application_form.png b/doc/integration/oauth_provider/application_form.png
new file mode 100644
index 0000000000000000000000000000000000000000..ae135db2627f24b24e4b4b1ba401ab78e2de0b09
Binary files /dev/null and b/doc/integration/oauth_provider/application_form.png differ
diff --git a/doc/integration/oauth_provider/authorized_application.png b/doc/integration/oauth_provider/authorized_application.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3ce05be9cc71cf965a8941313057f6d0851b085
Binary files /dev/null and b/doc/integration/oauth_provider/authorized_application.png differ
diff --git a/doc/integration/oauth_provider/user_wide_applications.png b/doc/integration/oauth_provider/user_wide_applications.png
new file mode 100644
index 0000000000000000000000000000000000000000..719e1974068eaf081fbaea3c0b397654a56f9379
Binary files /dev/null and b/doc/integration/oauth_provider/user_wide_applications.png differ
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 00adae58dfaef96d44f31f0024552e01a36bfe87..24f7b4bb4b407a2770f0d5735dea87a649ea1983 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -1,18 +1,47 @@
 # OmniAuth
 
-GitLab leverages OmniAuth to allow users to sign in using Twitter, GitHub, and other popular services. Configuring
+GitLab leverages OmniAuth to allow users to sign in using Twitter, GitHub, and other popular services.
 
-OmniAuth does not prevent standard GitLab authentication or LDAP (if configured) from continuing to work. Users can choose to sign in using any of the configured mechanisms.
+Configuring OmniAuth does not prevent standard GitLab authentication or LDAP (if configured) from continuing to work. Users can choose to sign in using any of the configured mechanisms.
 
 - [Initial OmniAuth Configuration](#initial-omniauth-configuration)
 - [Supported Providers](#supported-providers)
 - [Enable OmniAuth for an Existing User](#enable-omniauth-for-an-existing-user)
+- [OmniAuth configuration sample when using Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master#omniauth-google-twitter-github-login)
 
 ## Initial OmniAuth Configuration
 
-Before configuring individual OmniAuth providers there are a few global settings that need to be verified.
+Before configuring individual OmniAuth providers there are a few global settings that are in common for all providers that we need to consider.
 
-1.  Open the configuration file.
+- Omniauth needs to be enabled, see details below for example.
+- `allow_single_sign_on` defaults to `false`. If `false` users must be created manually or they will not be able to
+sign in via OmniAuth.
+- `block_auto_created_users` defaults to `true`. If `true` auto created users will be blocked by default and will
+have to be unblocked by an administrator before they are able to sign in.
+- **Note:** If you set `allow_single_sign_on` to `true` and `block_auto_created_users` to `false` please be aware
+that any user on the Internet will be able to successfully sign in to your GitLab without administrative approval.
+
+If you want to change these settings:
+
+* **For omnibus package**
+
+    Open the configuration file:
+
+    ```sh
+    sudo editor /etc/gitlab/gitlab.rb
+    ```
+
+    and change
+
+    ```
+    gitlab_rails['omniauth_enabled'] = true
+    gitlab_rails['omniauth_allow_single_sign_on'] = false
+    gitlab_rails['block_auto_created_users'] = true
+    ```
+
+* **For installations from source**
+
+    Open the configuration file:
 
     ```sh
     cd /home/git/gitlab
@@ -20,13 +49,13 @@ Before configuring individual OmniAuth providers there are a few global settings
     sudo -u git -H editor config/gitlab.yml
     ```
 
-1.  Find the section dealing with OmniAuth. The section will look similar to the following.
+    and change the following section
 
     ```
-      ## OmniAuth settings
+     ## OmniAuth settings
       omniauth:
         # Allow login via Twitter, Google, etc. using OmniAuth providers
-        enabled: false
+        enabled: true
 
         # CAUTION!
         # This allows users to login without having a user account first (default: false).
@@ -34,47 +63,15 @@ Before configuring individual OmniAuth providers there are a few global settings
         allow_single_sign_on: false
         # Locks down those users until they have been cleared by the admin (default: true).
         block_auto_created_users: true
-
-        ## Auth providers
-        # Uncomment the following lines and fill in the data of the auth provider you want to use
-        # If your favorite auth provider is not listed you can use others:
-        # see https://github.com/gitlabhq/gitlab-public-wiki/wiki/Custom-omniauth-provider-configurations
-        # The 'app_id' and 'app_secret' parameters are always passed as the first two
-        # arguments, followed by optional 'args' which can be either a hash or an array.
-        providers:
-        # - { name: 'google_oauth2', app_id: 'YOUR APP ID',
-        #     app_secret: 'YOUR APP SECRET',
-        #     args: { access_type: 'offline', approval_prompt: '' } }
-        # - { name: 'twitter', app_id: 'YOUR APP ID',
-        #     app_secret: 'YOUR APP SECRET'}
-        # - { name: 'github', app_id: 'YOUR APP ID',
-        #     app_secret: 'YOUR APP SECRET',
-        #     args: { scope: 'user:email' } }
-        # - {"name": 'shibboleth',
-        #     args: { shib_session_id_field: "HTTP_SHIB_SESSION_ID",
-        #     shib_application_id_field: "HTTP_SHIB_APPLICATION_ID",
-        #     uid_field: "HTTP_EPPN",
-        #     name_field: "HTTP_CN",
-        #     info_fields: {"email": "HTTP_MAIL" } } }
-
     ```
 
-1.  Change `enabled` to `true`.
-
-1.  Consider the next two configuration options: `allow_single_sign_on` and `block_auto_created_users`.
-
-    - `allow_single_sign_on` defaults to `false`. If `false` users must be created manually or they will not be able to
-    sign in via OmniAuth.
-    - `block_auto_created_users` defaults to `true`. If `true` auto created users will be blocked by default and will
-    have to be unblocked by an administrator before they are able to sign in.
-    - **Note:** If you set `allow_single_sign_on` to `true` and `block_auto_created_users` to `false` please be aware
-    that any user on the Internet will be able to successfully sign in to your GitLab without administrative approval.
-
-1.  Choose one or more of the Supported Providers below to continue configuration.
+Now we can choose one or more of the Supported Providers below to continue configuration.
 
 ## Supported Providers
 
 - [GitHub](github.md)
+- [Bitbucket](bitbucket.md)
+- [GitLab.com](gitlab.md)
 - [Google](google.md)
 - [Shibboleth](shibboleth.md)
 - [Twitter](twitter.md)
diff --git a/doc/integration/redmine_configuration.png b/doc/integration/redmine_configuration.png
new file mode 100644
index 0000000000000000000000000000000000000000..6b1453632293f010e2349a98270e99d5ac60c39d
Binary files /dev/null and b/doc/integration/redmine_configuration.png differ
diff --git a/doc/integration/redmine_service_template.png b/doc/integration/redmine_service_template.png
new file mode 100644
index 0000000000000000000000000000000000000000..1159eb5b9649f1efdd513e224931731bea99fbd3
Binary files /dev/null and b/doc/integration/redmine_service_template.png differ
diff --git a/doc/integration/shibboleth.md b/doc/integration/shibboleth.md
index 78317a5c0f26a58d381b0dfeeb9e2d56c5c3922a..6258e5f1030980980b9188cebb2d2c2031fc554a 100644
--- a/doc/integration/shibboleth.md
+++ b/doc/integration/shibboleth.md
@@ -2,19 +2,19 @@
 
 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:
 
-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.
 
-1. You can find Apache config in gitlab-reciepes (https://github.com/gitlabhq/gitlab-recipes/blob/master/web-server/apache/gitlab-ssl.conf)
+1. You can find Apache config in gitlab-recipes (https://github.com/gitlabhq/gitlab-recipes/blob/master/web-server/apache/gitlab-ssl.conf)
 
 Following changes are needed to enable shibboleth:
 
-protect omniauth-shibboleth callback url:
+protect omniauth-shibboleth callback URL:
 ```
   <Location /users/auth/shibboleth/callback>
     AuthType shibboleth
@@ -32,25 +32,25 @@ protect omniauth-shibboleth callback url:
     SetHandler shib
   </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
   RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
-  RewriteCond %{REQUEST_URI} !/Shibboleth.sso 
-  RewriteCond %{REQUEST_URI} !/shibboleth-sp 
+  RewriteCond %{REQUEST_URI} !/Shibboleth.sso
+  RewriteCond %{REQUEST_URI} !/shibboleth-sp
   RewriteRule .* http://127.0.0.1:8080%{REQUEST_URI} [P,QSA]
   RequestHeader set X_FORWARDED_PROTO 'https'
 ```
 
-1.  Edit /etc/gitlab/gitlab.rb configuration file, your shibboleth attributes should be in form of "HTTP_ATTRIBUTE" and you should addjust them to your need and environment. Add any other configuration you need. 
+1.  Edit /etc/gitlab/gitlab.rb configuration file, your shibboleth attributes should be in form of "HTTP_ATTRIBUTE" and you should addjust them to your need and environment. Add any other configuration you need.
 
-File it should look like this:
+File should look like this:
 ```
 external_url 'https://gitlab.example.com'
 gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
 
-# disable nginx
+# disable Nginx
 nginx['enable'] = false
 
 gitlab_rails['omniauth_allow_single_sign_on'] = true
@@ -70,7 +70,7 @@ gitlab_rails['omniauth_providers'] = [
 ]
 
 ```
-1. Save changes and reconfigure gitlab: 
+1. Save changes and reconfigure gitlab:
 ```
 sudo gitlab-ctl reconfigure
 ```
diff --git a/doc/integration/slack.md b/doc/integration/slack.md
index f2e73f272ef6758bc1d69a04a61bf276eb0b2183..2fd22c513ad4b84d1420baa2326611e067c3af29 100644
--- a/doc/integration/slack.md
+++ b/doc/integration/slack.md
@@ -35,7 +35,7 @@ After Slack is ready we need to setup GitLab. Here are the steps to achieve this
 1.  Fill in your Slack details
 
     - Mark it as active
-    - Paste in the webhook url you got from Slack
+    - Paste in the webhook URL you got from Slack
 
 Have fun :)
 
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index d1b52927d300fe4c290a5344e1ac8e8888ed2ade..fe9091ad9a8393640485a2d1291a3eb92562760f 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -13,7 +13,7 @@ To enable the Twitter OmniAuth provider you must register your application with
     something else descriptive.
     - Description: Create a description.
     - Website: The URL to your GitLab installation. 'https://gitlab.example.com'
-    - Callback URL: 'https://gitlab.example.com/users/auth/github/callback'
+    - Callback URL: 'https://gitlab.example.com/users/auth/twitter/callback'
     - Agree to the "Rules of the Road."
 
     ![Twitter App Details](twitter_app_details.png)
@@ -33,25 +33,46 @@ To enable the Twitter OmniAuth provider you must register your application with
 
 1.  On your GitLab server, open the configuration file.
 
+    For omnibus package:
+
+    ```sh
+      sudo editor /etc/gitlab/gitlab.rb
+    ```
+
+    For instalations from source:
+
     ```sh
-    cd /home/git/gitlab
+      cd /home/git/gitlab
 
-    sudo -u git -H editor config/gitlab.yml
+      sudo -u git -H editor config/gitlab.yml
     ```
 
-1.  Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration)
-for more details.
+1.  See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+
+1.  Add the provider configuration:
+
+    For omnibus package:
+
+    ```ruby
+      gitlab_rails['omniauth_providers'] = [
+        {
+          "name" => "twitter",
+          "app_id" => "YOUR_APP_ID",
+          "app_secret" => "YOUR_APP_SECRET"
+        }
+      ]
+    ```
 
-1.  Under `providers:` uncomment (or add) lines that look like the following:
+    For installations from source:
 
     ```
-       - { name: 'twitter', app_id: 'YOUR APP ID',
-         app_secret: 'YOUR APP SECRET' }
+      - { name: 'twitter', app_id: 'YOUR_APP_ID',
+        app_secret: 'YOUR_APP_SECRET' }
     ```
 
-1.  Change 'YOUR APP ID' to the API key from Twitter page in step 11.
+1.  Change 'YOUR_APP_ID' to the API key from Twitter page in step 11.
 
-1.  Change 'YOUR APP SECRET' to the API secret from the Twitter page in step 11.
+1.  Change 'YOUR_APP_SECRET' to the API secret from the Twitter page in step 11.
 
 1.  Save the configuration file.
 
diff --git a/doc/logs/logs.md b/doc/logs/logs.md
new file mode 100644
index 0000000000000000000000000000000000000000..ec0109a426f427a5ea92621d69bd46899b700f59
--- /dev/null
+++ b/doc/logs/logs.md
@@ -0,0 +1,102 @@
+## Log system
+GitLab has advanced log system so everything is logging and you can analize your instance using various system log files.
+In addition to system log files, GitLab Enterprise Edition comes with Audit Events. Find more about them [in Audit Events documentation](http://doc.gitlab.com/ee/administration/audit_events.html)
+
+System log files are typically plain text in a standard log file format. This guide talks about how to read and use these system log files.
+
+#### production.log
+This file lives in `/var/log/gitlab/gitlab-rails/production.log` for omnibus package or in `/home/git/gitlab/logs/production.log` for installations from the source.
+
+This file contains information about all performed requests. You can see url and type of request, IP address and what exactly parts of code were involved to service this particular request. Also you can see all SQL request that have been performed and how much time it took.
+This task is more useful for GitLab contributors and developers. Use part of this log file when you are going to report bug.
+
+```
+Started GET "/gitlabhq/yaml_db/tree/master" for 168.111.56.1 at 2015-02-12 19:34:53 +0200
+Processing by Projects::TreeController#show as HTML
+  Parameters: {"project_id"=>"gitlabhq/yaml_db", "id"=>"master"}
+
+  ... [CUT OUT]
+
+  amespaces"."created_at" DESC, "namespaces"."id" DESC LIMIT 1  [["id", 26]]
+  CACHE (0.0ms)  SELECT  "members".* FROM "members"  WHERE "members"."source_type" = 'Project' AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $1 AND "members"."source_type" = $2 AND "members"."user_id" = 1  ORDER BY "members"."created_at" DESC, "members"."id" DESC LIMIT 1  [["source_id", 18], ["source_type", "Project"]]
+  CACHE (0.0ms)  SELECT  "members".* FROM "members"  WHERE "members"."source_type" = 'Project' AND "members".
+   (1.4ms)  SELECT COUNT(*) FROM "merge_requests"  WHERE "merge_requests"."target_project_id" = $1 AND ("merge_requests"."state" IN ('opened','reopened'))  [["target_project_id", 18]]
+  Rendered layouts/nav/_project.html.haml (28.0ms)
+  Rendered layouts/_collapse_button.html.haml (0.2ms)
+  Rendered layouts/_flash.html.haml (0.1ms)
+  Rendered layouts/_page.html.haml (32.9ms)
+Completed 200 OK in 166ms (Views: 117.4ms | ActiveRecord: 27.2ms)
+```
+In this example we can see that server processed HTTP request with url `/gitlabhq/yaml_db/tree/master` from IP 168.111.56.1 at 2015-02-12 19:34:53 +0200. Also we can see that request was processed by Projects::TreeController.
+
+#### application.log
+This file lives in `/var/log/gitlab/gitlab-rails/application.log` for omnibus package or in `/home/git/gitlab/logs/application.log` for installations from the source.
+
+This log file helps you discover events happening in your instance such as user creation, project removing and so on.
+
+```
+October 06, 2014 11:56: User "Administrator" (admin@example.com) was created
+October 06, 2014 11:56: Documentcloud created a new project "Documentcloud / Underscore"
+October 06, 2014 11:56: Gitlab Org created a new project "Gitlab Org / Gitlab Ce"
+October 07, 2014 11:25: User "Claudie Hodkiewicz" (nasir_stehr@olson.co.uk)  was removed
+October 07, 2014 11:25: Project "project133" was removed
+```
+#### githost.log
+This file lives in `/var/log/gitlab/gitlab-rails/githost.log` for omnibus package or in `/home/git/gitlab/logs/githost.log` for installations from the source.
+
+The GitLab has to interact with git repositories but in some rare cases something can go wrong and in this case you will know what exactly happened. This log file contains all failed requests from GitLab to git repository. In majority of cases this file will be useful for developers only.
+```
+December 03, 2014 13:20 -> ERROR -> Command failed [1]: /usr/bin/git --git-dir=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq/.git --work-tree=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq merge --no-ff -mMerge branch 'feature_conflict' into 'feature' source/feature_conflict
+
+error: failed to push some refs to '/Users/vsizov/gitlab-development-kit/repositories/gitlabhq/gitlab_git.git'
+```
+
+#### satellites.log
+This file lives in `/var/log/gitlab/gitlab-rails/satellites.log` for omnibus package or in `/home/git/gitlab/logs/satellites.log` for installations from the source.
+
+In some cases GitLab should perform write actions to git repository, for example when it is needed to merge the merge request or edit a file with online editor. If something went wrong you can look into this file to find out what exactly happened.
+```
+October 07, 2014 11:36: Failed to create satellite for Chesley Weimann III / project1817
+October 07, 2014 11:36: PID: 1872: git clone /Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/repositories/conrad6841/gitlabhq.git /Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/conrad6841/gitlabhq
+October 07, 2014 11:36: PID: 1872: -> fatal: repository '/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/repositories/conrad6841/gitlabhq.git' does not exist
+```
+
+#### sidekiq.log
+This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for omnibus package or in `/home/git/gitlab/logs/sidekiq.log` for installations from the source.
+
+GitLab uses background jobs for processing tasks which can take a long time. All information about processing these jobs are writing down to this file.
+```
+2014-06-10T07:55:20Z 2037 TID-tm504 ERROR: /opt/bitnami/apps/discourse/htdocs/vendor/bundle/ruby/1.9.1/gems/redis-3.0.7/lib/redis/client.rb:228:in `read'
+2014-06-10T18:18:26Z 14299 TID-55uqo INFO: Booting Sidekiq 3.0.0 with redis options {:url=>"redis://localhost:6379/0", :namespace=>"sidekiq"}
+```
+
+#### gitlab-shell.log
+This file lives in `/var/log/gitlab/gitlab-shell/gitlab-shell.log` for omnibus package or in `/home/git/gitlab-shell/logs/sidekiq.log` for installations from the source.
+
+gitlab-shell is using by Gitlab for executing git commands and provide ssh access to git repositories.
+
+```
+I, [2015-02-13T06:17:00.671315 #9291]  INFO -- : Adding project root/example.git at </var/opt/gitlab/git-data/repositories/root/dcdcdcdcd.git>.
+I, [2015-02-13T06:17:00.679433 #9291]  INFO -- : Moving existing hooks directory and simlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git.
+```
+
+#### unicorn_stderr.log
+This file lives in `/var/log/gitlab/unicorn/unicorn_stderr.log` for omnibus package or in `/home/git/gitlab/logs/unicorn_stderr.log` for installations from the source.
+
+Unicorn is a high-performance forking Web server which is used for serving GitLab application. You can look at this log, for example, if your application does not respond. This log cantains all information about state of unicorn processes at any given time.
+
+```
+I, [2015-02-13T06:14:46.680381 #9047]  INFO -- : Refreshing Gem list
+I, [2015-02-13T06:14:56.931002 #9047]  INFO -- : listening on addr=127.0.0.1:8080 fd=12
+I, [2015-02-13T06:14:56.931381 #9047]  INFO -- : listening on addr=/var/opt/gitlab/gitlab-rails/sockets/gitlab.socket fd=13
+I, [2015-02-13T06:14:56.936638 #9047]  INFO -- : master process ready
+I, [2015-02-13T06:14:56.946504 #9092]  INFO -- : worker=0 spawned pid=9092
+I, [2015-02-13T06:14:56.946943 #9092]  INFO -- : worker=0 ready
+I, [2015-02-13T06:14:56.947892 #9094]  INFO -- : worker=1 spawned pid=9094
+I, [2015-02-13T06:14:56.948181 #9094]  INFO -- : worker=1 ready
+W, [2015-02-13T07:16:01.312916 #9094]  WARN -- : #<Unicorn::HttpServer:0x0000000208f618>: worker (pid: 9094) exceeds memory limit (320626688 bytes > 247066940 bytes)
+W, [2015-02-13T07:16:01.313000 #9094]  WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 9094) alive: 3621 sec (trial 1)
+I, [2015-02-13T07:16:01.530733 #9047]  INFO -- : reaped #<Process::Status: pid 9094 exit 0> worker=1
+I, [2015-02-13T07:16:01.534501 #13379]  INFO -- : worker=1 spawned pid=13379
+I, [2015-02-13T07:16:01.534848 #13379]  INFO -- : worker=1 ready
+```
diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md
index edb7a97550392475667d73adfd9f5bcc70d9f395..965d8fc313f5d0c9ce567fd796f9aacb3f6d558b 100644
--- a/doc/markdown/markdown.md
+++ b/doc/markdown/markdown.md
@@ -6,7 +6,7 @@
 
 * [Newlines](#newlines)
 * [Multiple underscores in words](#multiple-underscores-in-words)
-* [URL autolinking](#url-autolinking)
+* [URL auto-linking](#url-auto-linking)
 * [Code and Syntax Highlighting](#code-and-syntax-highlighting)
 * [Emoji](#emoji)
 * [Special GitLab references](#special-gitlab-references)
@@ -40,20 +40,21 @@ You can use GFM in
 - milestones
 - wiki pages
 
-You can also use other rich text files in GitLab. You might have to install a depency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information.
+You can also use other rich text files in GitLab. You might have to install a dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information.
 
 ## Newlines
 
 GFM honors the markdown specification in how [paragraphs and line breaks are handled](http://daringfireball.net/projects/markdown/syntax#p).
 
-A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines.:
+A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines.  
+Line-breaks, or softreturns, are rendered if you end a line with two or more spaces
 
-    Roses are red
+    Roses are red [followed by two or more spaces]  
     Violets are blue
 
     Sugar is sweet
 
-Roses are red
+Roses are red  
 Violets are blue
 
 Sugar is sweet
@@ -68,7 +69,7 @@ It is not reasonable to italicize just _part_ of a word, especially when you're
 perform_complicated_task
 do_this_and_do_that_and_another_thing
 
-## URL autolinking
+## URL auto-linking
 
 GFM will autolink standard URLs you copy and paste into your text. So if you want to link to a URL (instead of a textural link), you can simply put the URL in verbatim and it will be turned into a link to that URL.
 
@@ -140,25 +141,25 @@ But let's throw in a <b>tag</b>.
 
 ## Emoji
 
-	Sometimes you want to be a :ninja: and add some :glowing_star: to your :speech_balloon:. Well we have a gift for you:
+	Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you:
 
-	:high_voltage_sign: You can use emoji anywhere GFM is supported. :victory_hand:
+	:zap: You can use emoji anywhere GFM is supported. :v:
 
-	You can use it to point out a :bug: or warn about :speak_no_evil_monkey: patches. And if someone improves your really :snail: code, send them some :cake:. People will :heart: you for that.
+	You can use it to point out a :bug: or warn about :speak_no_evil: patches. And if someone improves your really :snail: code, send them some :birthday:. People will :heart: you for that.
 
-	If you are new to this, don't be :fearful_face:. You can easily join the emoji :family:. All you need to do is to look up on the supported codes.
+	If you are new to this, don't be :fearful:. You can easily join the emoji :family:. All you need to do is to look up on the supported codes.
 
-	Consult the [Emoji Cheat Sheet](https://www.dropbox.com/s/b9xaqb977s6d8w1/cheat_sheet.pdf) for a list of all supported emoji codes. :thumbsup:
+	Consult the [Emoji Cheat Sheet](http://emoji.codes) for a list of all supported emoji codes. :thumbsup:
 
-Sometimes you want to be a :ninja: and add some :glowing_star: to your :speech_balloon:. Well we have a gift for you:
+Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you:
 
-:high_voltage_sign: You can use emoji anywhere GFM is supported. :victory_hand:
+:zap: You can use emoji anywhere GFM is supported. :v:
 
-You can use it to point out a :bug: or warn about :speak_no_evil_monkey: patches. And if someone improves your really :snail: code, send them some :cake:. People will :heart: you for that.
+You can use it to point out a :bug: or warn about :speak_no_evil: patches. And if someone improves your really :snail: code, send them some :birthday:. People will :heart: you for that.
 
-If you are new to this, don't be :fearful_face:. You can easily join the emoji :family:. All you need to do is to look up on the supported codes.
+If you are new to this, don't be :fearful:. You can easily join the emoji :family:. All you need to do is to look up on the supported codes.
 
-Consult the [Emoji Cheat Sheet](https://www.dropbox.com/s/b9xaqb977s6d8w1/cheat_sheet.pdf) for a list of all supported emoji codes. :thumbsup:
+Consult the [Emoji Cheat Sheet](http://emoji.codes) for a list of all supported emoji codes. :thumbsup:
 
 ## Special GitLab References
 
@@ -170,7 +171,7 @@ GFM will turn that reference into a link so you can navigate between them easily
 
 GFM will recognize the following:
 
-- @foo : for team members
+- @foo : for specific team members or groups
 - @all : for the whole team
 - #123 : for issues
 - !123 : for merge requests
@@ -250,17 +251,17 @@ The IDs are generated from the content of the header according to the following
 For example:
 
 ```
-###### ..Ab_c-d. e [anchor](url) ![alt text](url)..
+###### ..Ab_c-d. e [anchor](URL) ![alt text](URL)..
 ```
 
 which renders as:
 
-###### ..Ab_c-d. e [anchor](url) ![alt text](url)..
+###### ..Ab_c-d. e [anchor](URL) ![alt text](URL)..
 
 will first be converted by step 1) into a string like:
 
 ```
-..Ab_c-d. e &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:
@@ -277,8 +278,8 @@ ab_c-d-e-anchor
 
 Note in particular how:
 
-- for markdown anchors `[text](url)`, only the `text` is used
-- markdown images `![alt](url)` are completely ignored
+- for markdown anchors `[text](URL)`, only the `text` is used
+- markdown images `![alt](URL)` are completely ignored
 
 ## Emphasis
 
@@ -420,6 +421,8 @@ Quote break.
 
 You can also use raw HTML in your Markdown, and it'll mostly work pretty well.
 
+Note that inline HTML is disabled in the default Gitlab configuration, although it is [possible](https://github.com/gitlabhq/gitlabhq/pull/8007/commits) for the system administrator to enable it.
+
 ```no-highlight
 <dl>
   <dt>Definition list</dt>
@@ -438,6 +441,8 @@ You can also use raw HTML in your Markdown, and it'll mostly work pretty well.
   <dd>Does *not* work **very** well. Use HTML <em>tags</em>.</dd>
 </dl>
 
+See the documentation for HTML::Pipeline's [SanitizationFilter](http://www.rubydoc.info/gems/html-pipeline/HTML/Pipeline/SanitizationFilter#WHITELIST-constant) class for the list of allowed HTML tags and attributes.  In addition to the default `SanitizationFilter` whitelist, GitLab allows the `class`, `id`, and `style` attributes.
+
 ## Horizontal Rule
 
 ```
@@ -483,6 +488,10 @@ This line is separated from the one above by two newlines, so it will be a *sepa
 
 This line is also a separate paragraph, but...
 This line is only separated by a single newline, so it's a separate line in the *same paragraph*.
+
+This line is also a separate paragraph, and...  
+This line is on its own line, because the previous line ends with two
+spaces.
 ```
 
 Here's a line for us to start with.
@@ -492,6 +501,10 @@ This line is separated from the one above by two newlines, so it will be a *sepa
 This line is also begins a separate paragraph, but...
 This line is only separated by a single newline, so it's a separate line in the *same paragraph*.
 
+This line is also a separate paragraph, and...  
+This line is on its own line, because the previous line ends with two
+spaces.
+
 ## Tables
 
 Tables aren't part of the core Markdown spec, but they are part of GFM and Markdown Here supports them.
diff --git a/doc/operations/README.md b/doc/operations/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f1456c6c8e2abae2faf7076078e8157a96b71765
--- /dev/null
+++ b/doc/operations/README.md
@@ -0,0 +1,4 @@
+# GitLab operations
+
+- [Sidekiq MemoryKiller](sidekiq_memory_killer.md)
+- [Cleaning up Redis sessions](cleaning_up_redis_sessions.md)
diff --git a/doc/operations/cleaning_up_redis_sessions.md b/doc/operations/cleaning_up_redis_sessions.md
new file mode 100644
index 0000000000000000000000000000000000000000..93521e976d51e05204c34addbedc8cb0e4c514ab
--- /dev/null
+++ b/doc/operations/cleaning_up_redis_sessions.md
@@ -0,0 +1,52 @@
+# Cleaning up stale Redis sessions
+
+Since version 6.2, GitLab stores web user sessions as key-value pairs in Redis.
+Prior to GitLab 7.3, user sessions did not automatically expire from Redis. If
+you have been running a large GitLab server (thousands of users) since before
+GitLab 7.3 we recommend cleaning up stale sessions to compact the Redis
+database after you upgrade to GitLab 7.3. You can also perform a cleanup while
+still running GitLab 7.2 or older, but in that case new stale sessions will
+start building up again after you clean up.
+
+In GitLab versions prior to 7.3.0, the session keys in Redis are 16-byte
+hexadecimal values such as '976aa289e2189b17d7ef525a6702ace9'. Starting with
+GitLab 7.3.0, the keys are
+prefixed with 'session:gitlab:', so they would look like
+'session:gitlab:976aa289e2189b17d7ef525a6702ace9'. Below we describe how to
+remove the keys in the old format.
+
+First we define a shell function with the proper Redis connection details.
+
+```
+rcli() {
+  # This example works for Omnibus installations of GitLab 7.3 or newer. For an
+  # installation from source you will have to change the socket path and the
+  # path to redis-cli.
+  sudo /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket "$@"
+}
+
+# test the new shell function; the response should be PONG
+rcli ping
+```
+
+Now we do a search to see if there are any session keys in the old format for
+us to clean up.
+
+```
+# returns the number of old-format session keys in Redis
+rcli keys '*' | grep '^[a-f0-9]\{32\}$' | wc -l
+```
+
+If the number is larger than zero, you can proceed to expire the keys from
+Redis. If the number is zero there is nothing to clean up.
+
+```
+# Tell Redis to expire each matched key after 600 seconds.
+rcli keys '*' | grep '^[a-f0-9]\{32\}$' | awk '{ print "expire", $0, 600 }' | rcli
+# This will print '(integer) 1' for each key that gets expired.
+```
+
+Over the next 15 minutes (10 minutes expiry time plus 5 minutes Redis
+background save interval) your Redis database will be compacted. If you are
+still using GitLab 7.2, users who are not clicking around in GitLab during the
+10 minute expiry window will be signed out of GitLab.
diff --git a/doc/operations/sidekiq_memory_killer.md b/doc/operations/sidekiq_memory_killer.md
new file mode 100644
index 0000000000000000000000000000000000000000..867b01b0d5ae746e2e3e459296ace116a9795f95
--- /dev/null
+++ b/doc/operations/sidekiq_memory_killer.md
@@ -0,0 +1,38 @@
+# Sidekiq MemoryKiller
+
+The GitLab Rails application code suffers from memory leaks. For web requests
+this problem is made manageable using
+[unicorn-worker-killer](https://github.com/kzk/unicorn-worker-killer) which
+restarts Unicorn worker processes in between requests when needed. The Sidekiq
+MemoryKiller applies the same approach to the Sidekiq processes used by GitLab
+to process background jobs.
+
+Unlike unicorn-worker-killer, which is enabled by default for all GitLab
+installations since GitLab 6.4, the Sidekiq MemoryKiller is enabled by default
+_only_ for Omnibus packages. The reason for this is that the MemoryKiller
+relies on Runit to restart Sidekiq after a memory-induced shutdown and GitLab
+installations from source do not all use Runit or an equivalent.
+
+With the default settings, the MemoryKiller will cause a Sidekiq restart no
+more often than once every 15 minutes, with the restart causing about one
+minute of delay for incoming background jobs.
+
+## Configuring the MemoryKiller
+
+The MemoryKiller is controlled using environment variables.
+
+- `SIDEKIQ_MEMORY_KILLER_MAX_RSS`: if this variable is set, and its value is
+  greater than 0, then after each Sidekiq job, the MemoryKiller will check the
+  RSS of the Sidekiq process that executed the job. If the RSS of the Sidekiq
+  process (expressed in kilobytes) exceeds SIDEKIQ_MEMORY_KILLER_MAX_RSS, a
+  delayed shutdown is triggered. The default value for Omnibus packages is set
+  [in the omnibus-gitlab
+  repository](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/attributes/default.rb).
+- `SIDEKIQ_MEMORY_KILLER_GRACE_TIME`: defaults 900 seconds (15 minutes). When
+  a shutdown is triggered, the Sidekiq process will keep working normally for
+  another 15 minutes.
+- `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT`: defaults to 30 seconds. When the grace
+  time has expired, the MemoryKiller tells Sidekiq to stop accepting new jobs.
+  Existing jobs get 30 seconds to finish. After that, the MemoryKiller tells
+  Sidekiq to shut down, and an external supervision mechanism (e.g. Runit) must
+  restart Sidekiq.
diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md
index d561868c8bb213e7db322a20cdbe26b6c63c9e44..8cfa7f9c876f35bd3c739dc9d518a2ad05ae42b1 100644
--- a/doc/permissions/permissions.md
+++ b/doc/permissions/permissions.md
@@ -8,7 +8,6 @@ If a user is a GitLab administrator they receive all permissions.
 
 ## Project
 
-
 | Action                                | Guest   | Reporter   | Developer   | Master   | Owner  |
 |---------------------------------------|---------|------------|-------------|----------|--------|
 | Create new issue                      | ✓       | ✓          | ✓           | ✓        | ✓      |
@@ -19,6 +18,7 @@ If a user is a GitLab administrator they receive all permissions.
 | Create new merge request              |         |            | ✓           | ✓        | ✓      |
 | Create new branches                   |         |            | ✓           | ✓        | ✓      |
 | Push to non-protected branches        |         |            | ✓           | ✓        | ✓      |
+| Force push to non-protected branches  |         |            | ✓           | ✓        | ✓      |
 | Remove non-protected branches         |         |            | ✓           | ✓        | ✓      |
 | Add tags                              |         |            | ✓           | ✓        | ✓      |
 | Write a wiki                          |         |            | ✓           | ✓        | ✓      |
@@ -28,6 +28,7 @@ If a user is a GitLab administrator they receive all permissions.
 | Add new team members                  |         |            |             | ✓        | ✓      |
 | Push to protected branches            |         |            |             | ✓        | ✓      |
 | Enable/disable branch protection      |         |            |             | ✓        | ✓      |
+| Turn on/off prot. branch push for devs|         |            |             | ✓        | ✓      |
 | Rewrite/remove git tags               |         |            |             | ✓        | ✓      |
 | Edit project                          |         |            |             | ✓        | ✓      |
 | Add deploy keys to project            |         |            |             | ✓        | ✓      |
@@ -35,9 +36,16 @@ If a user is a GitLab administrator they receive all permissions.
 | Switch visibility level               |         |            |             |          | ✓      |
 | Transfer project to another namespace |         |            |             |          | ✓      |
 | Remove project                        |         |            |             |          | ✓      |
+| Force push to protected branches      |         |            |             |          |        |
+| Remove protected branches             |         |            |             |          |        |
 
 ## Group
 
+In order for a group to appear as public and be browsable, it must contain at
+least one public project.
+
+Any user can remove themselves from a group, unless they are the last Owner of the group.
+
 | Action                  | Guest | Reporter | Developer | Master | Owner |
 |-------------------------|-------|----------|-----------|--------|-------|
 | Browse group            | ✓     | ✓        | ✓         | ✓      | ✓     |
@@ -45,5 +53,3 @@ If a user is a GitLab administrator they receive all permissions.
 | Create project in group |       |          |           | ✓      | ✓     |
 | Manage group members    |       |          |           |        | ✓     |
 | Remove group            |       |          |           |        | ✓     |
-
-Any user can remove himself from a group, unless he is the last Owner of the group.
diff --git a/doc/project_services/hipchat.md b/doc/project_services/hipchat.md
new file mode 100644
index 0000000000000000000000000000000000000000..021a93a288ff9de25dac5cda9cca1cef36a93795
--- /dev/null
+++ b/doc/project_services/hipchat.md
@@ -0,0 +1,54 @@
+# Atlassian HipChat
+
+GitLab provides a way to send HipChat notifications upon a number of events,
+such as when a user pushes code, creates a branch or tag, adds a comment, and
+creates a merge request.
+
+## Setup
+
+GitLab requires the use of a HipChat v2 API token to work. v1 tokens are
+not supported at this time. Note the differences between v1 and v2 tokens:
+
+HipChat v1 API (legacy) supports "API Auth Tokens" in the Group API menu. A v1
+token is allowed to send messages to *any* room.
+
+HipChat v2 API has tokens that are can be created using the Integrations tab
+in the Group or Room admin page. By design, these are lightweight tokens that
+allow GitLab to send messages only to *one* room.
+
+### Complete these steps in HipChat:
+
+1. Go to: https://admin.hipchat.com/admin
+1. Click on "Group Admin" -> "Integrations".
+1. Find "Build Your Own!" and click "Create".
+1. Select the desired room, name the integration "GitLab", and click "Create".
+1. In the "Send messages to this room by posting this URL" column, you should
+see a URL in the format:
+
+```
+    https://api.hipchat.com/v2/room/<room>/notification?auth_token=<token>
+```
+
+HipChat is now ready to accept messages from GitLab. Next, set up the HipChat
+service in GitLab.
+
+### Complete these steps in GitLab:
+
+1. Navigate to the project you want to configure for notifications.
+1. Select "Settings" in the top navigation.
+1. Select "Services" in the left navigation.
+1. Click "HipChat".
+1. Select the "Active" checkbox.
+1. Insert the `token` field from the URL into the `Token` field on the Web page.
+1. Insert the `room` field from the URL into the `Room` field on the Web page.
+1. Save or optionally click "Test Settings".
+
+## Troubleshooting
+
+If you do not see notifications, make sure you are using a HipChat v2 API
+token, not a v1 token.
+
+Note that the v2 token is tied to a specific room. If you want to be able to
+specify arbitrary rooms, you can create an API token for a specific user in
+HipChat under "Account settings" and "API access". Use the `XXX` value under
+`auth_token=XXX`.
diff --git a/doc/project_services/irker.md b/doc/project_services/irker.md
new file mode 100644
index 0000000000000000000000000000000000000000..780a45bca20fbc5d533ec17f358f077337192f34
--- /dev/null
+++ b/doc/project_services/irker.md
@@ -0,0 +1,46 @@
+# Irker IRC Gateway
+
+GitLab provides a way to push update messages to an Irker server. When
+configured, pushes to a project will trigger the service to send data directly
+to the Irker server.
+
+See the project homepage for further info: http://www.catb.org/esr/irker/
+
+## Needed setup
+
+You will first need an Irker daemon. You can download the Irker code from its
+gitorious repository on https://gitorious.org/irker: `git clone
+git@gitorious.org:irker/irker.git`. Once you have downloaded the code, you can
+run the python script named `irkerd`. This script is the gateway script, it acts
+both as an IRC client, for sending messages to an IRC server obviously, and as a
+TCP server, for receiving messages from the GitLab service.
+
+If the Irker server runs on the same machine, you are done. If not, you will
+need to follow the firsts steps of the next section.
+
+## Optional setup
+
+In the `app/models/project_services/irker_service.rb` file, you can modify some
+options in the `initialize_settings` method:
+- **server_ip** (defaults to `localhost`): the server IP address where the
+`irkerd` daemon runs;
+- **server_port** (defaults to `6659`): the server port of the `irkerd` daemon;
+- **max_channels** (defaults to `3`): the maximum number of recipients the
+client is authorized to join, per project;
+- **default_irc_uri** (no default) : if this option is set, it has to be in the
+format `irc[s]://domain.name` and will be prepend to each and every channel
+provided by the user which is not a full URI.
+
+If the Irker server and the GitLab application do not run on the same host, you
+will **need** to setup at least the **server_ip** option.
+
+## Note on Irker recipients
+
+Irker accepts channel names of the form `chan` and `#chan`, both for the
+`#chan` channel. If you want to send messages in query, you will need to add
+`,isnick` avec the channel name, in this form: `Aorimn,isnick`. In this latter
+case, `Aorimn` is treated as a nick and no more as a channel name.
+
+Irker can also join password-protected channels. Users need to append
+`?key=thesecretpassword` to the chan name.
+
diff --git a/doc/project_services/project_services.md b/doc/project_services/project_services.md
index 20a69a211dd664fa10c5f34b9f4df3637552531f..03937d20728f80821f63792fae2b1de8744cbd94 100644
--- a/doc/project_services/project_services.md
+++ b/doc/project_services/project_services.md
@@ -4,15 +4,17 @@ __Project integrations with external services for continuous integration and mor
 
 ## Services
 
-- Assemblia
-- [Atlassian Bamboo CI](bamboo.md) An Atlassian product for continous integration.
+- Assembla
+- [Atlassian Bamboo CI](bamboo.md) An Atlassian product for continuous integration.
 - Build box
 - Campfire
 - Emails on push
 - Flowdock
 - Gemnasium
 - GitLab CI
-- Hipchat
-- PivotalTracker
+- [HipChat](hipchat.md) An Atlassian product for private group chat and instant messaging.
+- [Irker](irker.md) An IRC gateway to receive messages on repository updates.
+- Pivotal Tracker
 - Pushover
 - Slack
+- TeamCity
diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md
index 4712c3870215d54d37ef4fcef98774b822512f6f..7c5a6c046399e41652a584e8f64a9e79433b4a3d 100644
--- a/doc/public_access/public_access.md
+++ b/doc/public_access/public_access.md
@@ -41,4 +41,4 @@ When visiting the public page of an user, you will only see listed projects whic
 
 ## Restricting the use of public or internal projects
 
-In [gitlab.yml](https://gitlab.com/gitlab-org/gitlab-ce/blob/dbd88d453b8e6c78a423fa7e692004b1db6ea069/config/gitlab.yml.example#L64) you can disable public projects or public and internal projects for the entire GitLab installation to prevent people making code public by accident.
+In [gitlab.yml](https://gitlab.com/gitlab-org/gitlab-ce/blob/dbd88d453b8e6c78a423fa7e692004b1db6ea069/config/gitlab.yml.example#L64) you can disable public projects or public and internal projects for the entire GitLab installation to prevent people making code public by accident.  The restricted visibility settings do not apply to admin users.
diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md
index 9e2f697bca69dfb66e2cbf6fe04141e4d1caec45..770b7a70fe0a43e99badbfa0ad145d5c9813019c 100644
--- a/doc/raketasks/README.md
+++ b/doc/raketasks/README.md
@@ -1,5 +1,8 @@
+# Rake tasks
+
 - [Backup restore](backup_restore.md)
 - [Cleanup](cleanup.md)
+- [Features](features.md)
 - [Maintenance](maintenance.md) and self-checks
 - [User management](user_management.md)
 - [Web hooks](web_hooks.md)
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index b4581e2a07a86f2411d1d56d34ee7857a388a746..99cdfff0ac63e0fe818ff50fbb90f128181bfdb0 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -13,8 +13,8 @@ You can only restore a backup to exactly the same version of GitLab that you cre
 # use this command if you've installed GitLab with the Omnibus package
 sudo gitlab-rake gitlab:backup:create
 
-# if you've installed GitLab from source or using the cookbook
-bundle exec rake gitlab:backup:create RAILS_ENV=production
+# if you've installed GitLab from source
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 Example output:
@@ -137,7 +137,7 @@ with the name of your bucket:
 Please be informed that a backup does not store your configuration files.
 If you use an Omnibus package please see the [instructions in the readme to backup your configuration](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#backup-and-restore-omnibus-gitlab-configuration).
 If you have a cookbook installation there should be a copy of your configuration in Chef.
-If you have a manual installation please consider backing up your gitlab.yml file and any SSL keys and certificates.
+If you have an installation from source, please consider backing up your `gitlab.yml` file, any SSL keys and certificates, and your [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
 
 ## Restore a previously created backup
 
@@ -147,7 +147,7 @@ You can only restore a backup to exactly the same version of GitLab that you cre
 # Omnibus package installation
 sudo gitlab-rake gitlab:backup:restore
 
-# installation from source or cookbook
+# installation from source
 bundle exec rake gitlab:backup:restore RAILS_ENV=production
 ```
 
@@ -192,7 +192,7 @@ Deleting tmp directories...[DONE]
 
 For Omnibus package installations, see https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#scheduling-a-backup .
 
-For installation from source or cookbook:
+For installation from source:
 ```
 cd /home/git/gitlab
 sudo -u git -H editor config/gitlab.yml # Enable keep_time in the backup section to automatically delete old backups
@@ -203,5 +203,31 @@ Add the following lines at the bottom:
 
 ```
 # Create a full backup of the GitLab repositories and SQL database every day at 4am
-0 4 * * * cd /home/git/gitlab && PATH=/usr/local/bin:/usr/bin:/bin bundle exec rake gitlab:backup:create RAILS_ENV=production
+0 4 * * * cd /home/git/gitlab && PATH=/usr/local/bin:/usr/bin:/bin bundle exec rake gitlab:backup:create RAILS_ENV=production CRON=1
 ```
+
+The `CRON=1` environment setting tells the backup script to suppress all progress output if there are no errors.
+This is recommended to reduce cron spam.
+
+## Alternative backup strategies
+
+If your GitLab server contains a lot of Git repository data you may find the GitLab backup script to be too slow.
+In this case you can consider using filesystem snapshots as part of your backup strategy.
+
+Example: Amazon EBS
+
+> A GitLab server using omnibus-gitlab hosted on Amazon AWS.
+> An EBS drive containing an ext4 filesystem is mounted at `/var/opt/gitlab`.
+> In this case you could make an application backup by taking an EBS snapshot.
+> The backup includes all repositories, uploads and Postgres data.
+
+Example: LVM snapshots + rsync
+
+> A GitLab server using omnibus-gitlab, with an LVM logical volume mounted at `/var/opt/gitlab`.
+> Replicating the `/var/opt/gitlab` directory using rsync would not be reliable because too many files would change while rsync is running.
+> Instead of rsync-ing `/var/opt/gitlab`, we create a temporary LVM snapshot, which we mount as a read-only filesystem at `/mnt/gitlab_backup`.
+> Now we can have a longer running rsync job which will create a consistent replica on the remote server.
+> 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.
+It is not uncommon however for a VM snapshot to require you to power down the server, so this approach is probably of limited practical use.
diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md
index 9e48f56c9514cb9189c0c56fcbdf4a8cb5650c90..96d67f7b5d664fa24eaa378adc189849db2a9cf8 100644
--- a/doc/raketasks/cleanup.md
+++ b/doc/raketasks/cleanup.md
@@ -8,7 +8,7 @@ Remove namespaces(dirs) from `/home/git/repositories` if they don't exist in Git
 # omnibus-gitlab
 sudo gitlab-rake gitlab:cleanup:dirs
 
-# installation from source or cookbook
+# installation from source
 bundle exec rake gitlab:cleanup:dirs RAILS_ENV=production
 ```
 
@@ -18,6 +18,6 @@ Remove repositories (global only for now) from `/home/git/repositories` if they
 # omnibus-gitlab
 sudo gitlab-rake gitlab:cleanup:repos
 
-# installation from source or cookbook
+# installation from source
 bundle exec rake gitlab:cleanup:repos RAILS_ENV=production
 ```
diff --git a/doc/raketasks/features.md b/doc/raketasks/features.md
index 99b3d5525b0e3fcc19ff507a3ade5e1016a4945a..f9a46193547459a0117c525cd70587013bd2f066 100644
--- a/doc/raketasks/features.md
+++ b/doc/raketasks/features.md
@@ -6,7 +6,7 @@ This command will enable the namespaces feature introduced in v4.0. It will move
 
 Note:
 
-- Because the **repository location will change**, you will need to **update all your git url's** to point to the new location.
+- Because the **repository location will change**, you will need to **update all your git URLs** to point to the new location.
 - Username can be changed at [Profile / Account](/profile/account)
 
 **Example:**
diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md
index bb229e8acbbcb7e277e93674e7b7ca0d374b3de9..8a38937062e003b658d54d081539f00029735543 100644
--- a/doc/raketasks/import.md
+++ b/doc/raketasks/import.md
@@ -13,15 +13,32 @@
 
 - For omnibus-gitlab, it is located at: `/var/opt/gitlab/git-data/repositories` by default, unless you changed
 it in the `/etc/gitlab/gitlab.rb` file.
-- For manual installations, it is usually located at: `/home/git/repositories` or you can see where
+- For installations from source, it is usually located at: `/home/git/repositories` or you can see where
 your repositories are located by looking at `config/gitlab.yml` under the `gitlab_shell => repos_path` entry.
 
+New folder needs to have git user ownership and read/write/execute access for git user and its group:
+
+```
+sudo -u git mkdir /var/opt/gitlab/git-data/repositories/new_group
+```
+
+If you are using an installation from source, replace `/var/opt/gitlab/git-data`
+with `/home/git`.
+
 ### Copy your bare repositories inside this newly created folder:
 
 ```
-$ cp -r /old/git/foo.git/ /home/git/repositories/new_group/
+sudo cp -r /old/git/foo.git /var/opt/gitlab/git-data/repositories/new_group/
+
+# Do this once when you are done copying git repositories
+sudo chown -R git:git /var/opt/gitlab/git-data/repositories/new_group/
 ```
 
+`foo.git` needs to be owned by the git user and git users group.
+
+If you are using an installation from source, replace `/var/opt/gitlab/git-data`
+with `/home/git`.
+
 ### Run the command below depending on your type of installation:
 
 #### Omnibus Installation
@@ -30,7 +47,7 @@ $ cp -r /old/git/foo.git/ /home/git/repositories/new_group/
 $ sudo gitlab-rake gitlab:import:repos
 ```
 
-#### Manual Installation
+#### Installation from source
 
 Before running this command you need to change the directory to where your GitLab installation is located:
 
diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md
index f6bd7565799e8ae818c1c2d36879732c4f6c6a76..41a994f3f68faba2016b34c6daa5628f0d2c7edf 100644
--- a/doc/raketasks/maintenance.md
+++ b/doc/raketasks/maintenance.md
@@ -8,7 +8,7 @@ This command gathers information about your GitLab installation and the System i
 # omnibus-gitlab
 sudo gitlab-rake gitlab:env:info
 
-# installation from source or cookbook
+# installation from source
 bundle exec rake gitlab:env:info RAILS_ENV=production
 ```
 
@@ -16,30 +16,31 @@ Example output:
 
 ```
 System information
-System:		Debian 6.0.7
-Current User:	git
-Using RVM:	no
-Ruby Version: 2.0.0-p481
-Gem Version:  1.8.23
-Bundler Version:1.3.5
-Rake Version:	10.0.4
+System:           Debian 7.8
+Current User:     git
+Using RVM:        no
+Ruby Version:     2.1.5p273
+Gem Version:      2.4.3
+Bundler Version:  1.7.6
+Rake Version:     10.3.2
+Sidekiq Version:  2.17.8
 
 GitLab information
-Version:	5.1.0.beta2
-Revision:	4da8b37
-Directory:	/home/git/gitlab
-DB Adapter:	mysql2
-URL:		http://example.com
-HTTP Clone URL:	http://example.com/some-project.git
-SSH Clone URL:	git@example.com:some-project.git
-Using LDAP:	no
-Using Omniauth:	no
+Version:          7.7.1
+Revision:         41ab9e1
+Directory:        /home/git/gitlab
+DB Adapter:       postgresql
+URL:              https://gitlab.example.com
+HTTP Clone URL:   https://gitlab.example.com/some-project.git
+SSH Clone URL:    git@gitlab.example.com:some-project.git
+Using LDAP:       no
+Using Omniauth:   no
 
 GitLab Shell
-Version:	1.2.0
-Repositories:	/home/git/repositories/
-Hooks:		/home/git/gitlab-shell/hooks/
-Git:		/usr/bin/git
+Version:          2.4.1
+Repositories:     /home/git/repositories/
+Hooks:            /home/git/gitlab-shell/hooks/
+Git:              /usr/bin/git
 ```
 
 ## Check GitLab configuration
@@ -59,7 +60,7 @@ You may also have a look at our [Trouble Shooting Guide](https://github.com/gitl
 # omnibus-gitlab
 sudo gitlab-rake gitlab:check
 
-# installation from source or cookbook
+# installation from source
 bundle exec rake gitlab:check RAILS_ENV=production
 ```
 
@@ -122,3 +123,56 @@ sudo -u git -H mkdir -p /home/git/gitlab-satellites
 sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production
 sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites
 ```
+
+## Rebuild authorized_keys file
+
+In some case it is necessary to rebuild the `authorized_keys` file.
+
+For Omnibus-packages:
+```
+sudo gitlab-rake gitlab:shell:setup
+```
+
+For installations from source:
+```
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production
+```
+
+```
+This will rebuild an authorized_keys file.
+You will lose any data stored in authorized_keys file.
+Do you want to continue (yes/no)? yes
+```
+
+## Clear redis cache
+
+If for some reason the dashboard shows wrong information you might want to 
+clear Redis' cache.
+
+For Omnibus-packages:
+```
+sudo gitlab-rake cache:clear
+```
+
+For installations from source:
+```
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+## Precompile the assets
+
+Sometimes during version upgrades you might end up with some wrong CSS or
+missing some icons. In that case, try to precompile the assets again.
+
+For Omnibus-packages:
+```
+sudo gitlab-rake assets:precompile
+```
+
+For installations from source:
+```
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+```
diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md
index 3c67753ad28bceae1818993579a4a52ac6dedd83..80b01ca4043c03d66b27c39d01275b4926fe13d4 100644
--- a/doc/raketasks/user_management.md
+++ b/doc/raketasks/user_management.md
@@ -6,7 +6,7 @@
 # omnibus-gitlab
 sudo gitlab-rake gitlab:import:user_to_projects[username@domain.tld]
 
-# installation from source or cookbook
+# installation from source
 bundle exec rake gitlab:import:user_to_projects[username@domain.tld] RAILS_ENV=production
 ```
 
@@ -20,7 +20,7 @@ Notes:
 # omnibus-gitlab
 sudo gitlab-rake gitlab:import:all_users_to_all_projects
 
-# installation from source or cookbook
+# installation from source
 bundle exec rake gitlab:import:all_users_to_all_projects RAILS_ENV=production
 ```
 
@@ -30,7 +30,7 @@ bundle exec rake gitlab:import:all_users_to_all_projects RAILS_ENV=production
 # omnibus-gitlab
 sudo gitlab-rake gitlab:import:user_to_groups[username@domain.tld]
 
-# installation from source or cookbook
+# installation from source
 bundle exec rake gitlab:import:user_to_groups[username@domain.tld] RAILS_ENV=production
 ```
 
@@ -44,6 +44,6 @@ Notes:
 # omnibus-gitlab
 sudo gitlab-rake gitlab:import:all_users_to_all_groups
 
-# installation from source or cookbook
+# installation from source
 bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production
 ```
diff --git a/doc/raketasks/web_hooks.md b/doc/raketasks/web_hooks.md
index e1a58835d889d6b9a159098326c694c63452013a..5a8b94af9b4bdd034bba760ec6ef53371f9e9c85 100644
--- a/doc/raketasks/web_hooks.md
+++ b/doc/raketasks/web_hooks.md
@@ -4,42 +4,42 @@
 
     # omnibus-gitlab
     sudo gitlab-rake gitlab:web_hook:add URL="http://example.com/hook"
-    # source installations or cookbook
+    # source installations
     bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" RAILS_ENV=production
 
 ## Add a web hook for projects in a given **NAMESPACE**:
 
     # omnibus-gitlab
     sudo gitlab-rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE=acme
-    # source installations or cookbook
+    # source installations
     bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE=acme RAILS_ENV=production
 
 ## Remove a web hook from **ALL** projects using:
 
     # omnibus-gitlab
     sudo gitlab-rake gitlab:web_hook:rm URL="http://example.com/hook"
-    # source installations or cookbook
+    # source installations
     bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" RAILS_ENV=production
 
 ## Remove a web hook from projects in a given **NAMESPACE**:
 
     # omnibus-gitlab
     sudo gitlab-rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE=acme
-    # source installations or cookbook
+    # source installations
     bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE=acme RAILS_ENV=production
 
 ## List **ALL** web hooks:
 
     # omnibus-gitlab
     sudo gitlab-rake gitlab:web_hook:list
-    # source installations or cookbook
+    # source installations
     bundle exec rake gitlab:web_hook:list RAILS_ENV=production
 
 ## List the web hooks from projects in a given **NAMESPACE**:
 
     # omnibus-gitlab
     sudo gitlab-rake gitlab:web_hook:list NAMESPACE=/
-    # source installations or cookbook
+    # source installations
     bundle exec rake gitlab:web_hook:list NAMESPACE=/ RAILS_ENV=production
 
 > Note: `/` is the global namespace.
diff --git a/doc/release/howto_rc1.md b/doc/release/howto_rc1.md
new file mode 100644
index 0000000000000000000000000000000000000000..07c703142d4d3dea5b5103f9e246f09a9080bfa5
--- /dev/null
+++ b/doc/release/howto_rc1.md
@@ -0,0 +1,55 @@
+# How to create RC1
+
+The RC1 release comes with the task to update the installation and upgrade docs. Be mindful that there might already be merge requests for this on GitLab or GitHub.
+
+### 1. Update the installation guide
+
+1. Check if it references the correct branch `x-x-stable` (doesn't exist yet, but that is okay)
+1. Check the [GitLab Shell version](/lib/tasks/gitlab/check.rake#L782)
+1. Check the [Git version](/lib/tasks/gitlab/check.rake#L794)
+1. There might be other changes. Ask around.
+
+### 2. Create update guides
+
+[Follow this guide](howto_update_guides.md) to create update guides.
+
+### 3. Code quality indicators
+
+Make sure the code quality indicators are green / good.
+
+- [![Build status](http://ci.gitlab.org/projects/1/status.png?ref=master)](http://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch)
+
+- [![Build Status](https://semaphoreapp.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/243338/badge.png)](https://semaphoreapp.com/gitlabhq/gitlabhq) (master branch)
+
+- [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq)
+
+- [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) this button can be yellow (small updates are available) but must not be red (a security fix or an important update is available)
+
+- [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq)
+
+### 4. Run release tool
+
+**Make sure EE `master` has latest changes from CE `master`**
+
+Get release tools
+
+```
+git clone git@dev.gitlab.org:gitlab/release-tools.git
+cd release-tools
+```
+
+Release candidate creates stable branch from master.
+So we need to sync master branch between all CE, EE and CI remotes.
+
+```
+bundle exec rake sync
+```
+
+Create release candidate and stable branch:
+
+```
+bundle exec rake release["x.x.0.rc1"]
+```
+
+Now developers can use master for merging new features.
+So you should use stable branch for future code changes related to release.
diff --git a/doc/release/howto_update_guides.md b/doc/release/howto_update_guides.md
new file mode 100644
index 0000000000000000000000000000000000000000..23d0959c33d590a4a15fa6ee2130184f7f88d176
--- /dev/null
+++ b/doc/release/howto_update_guides.md
@@ -0,0 +1,55 @@
+# Create update guides
+
+1. Create: CE update guide from previous version. Like `7.3-to-7.4.md`
+1. Create: CE to EE update guide in EE repository for latest version.
+1. Update: `6.x-or-7.x-to-7.x.md` to latest version.
+1. Create: CI update guide from previous version
+
+It's best to copy paste the previous guide and make changes where necessary.
+The typical steps are listed below with any points you should specifically look at.
+
+#### 0. Any major changes?
+
+List any major changes here, so the user is aware of them before starting to upgrade. For instance:
+
+- Database updates
+- Web server changes
+- File structure changes
+
+#### 1. Stop server
+
+#### 2. Make backup
+
+#### 3. Do users need to update dependencies like `git`?
+
+- Check if the [GitLab Shell version](/lib/tasks/gitlab/check.rake#L782) changed since the last release.
+
+- Check if the [Git version](/lib/tasks/gitlab/check.rake#L794) changed since the last release.
+
+#### 4. Get latest code
+
+#### 5. Does GitLab shell need to be updated?
+
+#### 6. Install libs, migrations, etc.
+
+#### 7. Any config files updated since last release?
+
+Check if any of these changed since last release:
+
+- [lib/support/nginx/gitlab](/lib/support/nginx/gitlab)
+- [lib/support/nginx/gitlab-ssl](/lib/support/nginx/gitlab-ssl)
+- <https://gitlab.com/gitlab-org/gitlab-shell/commits/master/config.yml.example>
+- [config/gitlab.yml.example](/config/gitlab.yml.example)
+- [config/unicorn.rb.example](/config/unicorn.rb.example)
+- [config/database.yml.mysql](/config/database.yml.mysql)
+- [config/database.yml.postgresql](/config/database.yml.postgresql)
+- [config/initializers/rack_attack.rb.example](/config/initializers/rack_attack.rb.example)
+- [config/resque.yml.example](/config/resque.yml.example)
+
+#### 8. Need to update init script?
+
+Check if the `init.d/gitlab` script changed since last release: [lib/support/init.d/gitlab](/lib/support/init.d/gitlab)
+
+#### 9. Start application
+
+#### 10. Check application status
diff --git a/doc/release/monthly.md b/doc/release/monthly.md
index c50bfc21f8fe5c92ac248d23bb01f5dc014ac257..cfe01896d8fac30905a7ea7cf301aa8df793d39e 100644
--- a/doc/release/monthly.md
+++ b/doc/release/monthly.md
@@ -1,204 +1,126 @@
 # Monthly Release
 
-NOTE: This is a guide for GitLab developers.
+NOTE: This is a guide used by the GitLab B.V. developers.
 
-# **7 workdays before release - Code Freeze & Release Manager**
+It starts 7 working days before the release.
+The release manager doesn't have to perform all the work but must ensure someone is assigned.
+The current release manager must schedule the appointment of the next release manager.
+The new release manager should create overall issue to track the progress.
 
-### **1. Stop merging in code, except for important bug fixes**
+## Release Manager
 
-### **2. Release Manager**
+A release manager is selected that coordinates all releases the coming month, including the patch releases for previous releases.
+The release manager has to make sure all the steps below are done and delegated where necessary.
+This person should also make sure this document is kept up to date and issues are created and updated.
 
-A release manager is selected that coordinates the entire release of this version. The release manager has to make sure all the steps below are done and delegated where necessary. This person should also make sure this document is kept up to date and issues are created and updated.
+## Take vacations into account
 
-### **3. Create an overall issue**
+The time is measured in weekdays to compensate for weekends.
+Do everything on time to prevent problems due to rush jobs or too little testing time.
+Make sure that you take into account any vacations of maintainers.
+If the release is falling behind immediately warn the team.
+
+## Create an overall issue and follow it
 
 Create issue for GitLab CE project(internal). Name it "Release x.x.x" for easier searching.
 Replace the dates with actual dates based on the number of workdays before the release.
+All steps from issue template are explained below
 
 ```
-Xth:
-
-* Update the changelog (#LINK)
-* Triage the omnibus-gitlab milestone
-
-Xth:
-
-* Merge CE in to EE (#LINK)
-* Close the omnibus-gitlab milestone
-
-Xth:
-
-* Create x.x.0.rc1 (#LINK)
-* Build package for GitLab.com (https://dev.gitlab.org/cookbooks/chef-repo/blob/master/doc/administration.md#build-a-package)
-
-Xth:
-
-* Update GitLab.com with rc1 (#LINK) (https://dev.gitlab.org/cookbooks/chef-repo/blob/master/doc/administration.md#deploy-the-package)
-* Regression issue and tweet about rc1 (#LINK)
-* Start blog post (#LINK)
-
-Xth:
-
-* Do QA and fix anything coming out of it (#LINK)
-
-22nd:
-
-* Release CE and EE (#LINK)
-
-Xth:
-
-* * Deploy to GitLab.com (#LINK)
-
-```
-
-### **4. Update changelog**
-
-Any changes not yet added to the changelog are added by lead developer and in that merge request the complete team is asked if there is anything missing.
+Xth: (7 working days before the 22nd)
 
-### **5. Take weekend and vacations into account**
+- [ ] Code freeze
+- [ ] Update the CE changelog (#LINK)
+- [ ] Update the EE changelog (#LINK)
+- [ ] Update the CI changelog (#LINK)
+- [ ] Triage the omnibus-gitlab milestone
 
-Ensure that there is enough time to incorporate the findings of the release candidate, etc.
+Xth: (6 working days before the 22nd)
 
-# **6 workdays before release- Merge the CE into EE**
+- [ ] Merge CE master in to EE master via merge request (#LINK)
+- [ ] Determine QA person and notify this person
+- [ ] Check the tasks in [how to rc1 guide](howto_rc1.md) and delegate tasks if necessary
+- [ ] Create CE, EE, CI RC1 versions (#LINK)
 
-Do this via a merge request.
+Xth: (5 working days before the 22nd)
 
-# **5 workdays before release - Create RC1**
+- [ ] Do QA and fix anything coming out of it (#LINK)
+- [ ] Close the omnibus-gitlab milestone
+- [ ] Prepare the blog post (#LINK)
 
-The RC1 release comes with the task to update the installation and upgrade docs. Be mindful that there might already be merge requests for this on GitLab or GitHub.
+Xth: (4 working days before the 22nd)
 
-### **1. Update the installation guide**
+- [ ] Update GitLab.com with rc1 (#LINK) (https://dev.gitlab.org/cookbooks/chef-repo/blob/master/doc/administration.md#deploy-the-package)
+- [ ] Update ci.gitLab.com with rc1 (#LINK) (https://dev.gitlab.org/cookbooks/chef-repo/blob/master/doc/administration.md#deploy-the-package)
+- [ ] Create regression issues (CE, CI) (#LINK)
+- [ ] Tweet about rc1 (#LINK)
 
-1. Check if it references the correct branch `x-x-stable` (doesn't exist yet, but that is okay)
-1. Check the [GitLab Shell version](/lib/tasks/gitlab/check.rake#L782)
-1. Check the [Git version](/lib/tasks/gitlab/check.rake#L794)
-1. There might be other changes. Ask around.
+Xth: (3 working days before the 22nd)
 
-### **2. Create update guides**
+- [ ] Merge CE stable branch into EE stable branch
 
-1. Create: CE update guide from previous version. Like `7.3-to-7.4.md`
-1. Create: CE to EE update guide in EE repository for latest version.
-1. Update: `6.x-or-7.x-to-7.x.md` to latest version.
+Xth: (2 working days before the 22nd)
 
-It's best to copy paste the previous guide and make changes where necessary.
-The typical steps are listed below with any points you should specifically look at.
+- [ ] Check that everyone is mentioned on the blog post (the reviewer should have done this one working day ago)
+- [ ] Check that MVP is added to the mvp page (source/mvp/index.html in www-gitlab-com)
 
-#### 0. Any major changes?
+Xth: (1 working day before the 22nd)
 
-List any major changes here, so the user is aware of them before starting to upgrade. For instance:
+- [ ] Create CE, EE, CI stable versions (#LINK)
+- [ ] Create Omnibus tags and build packages
+- [ ] Update GitLab.com with the stable version (#LINK)
+- [ ] Update ci.gitLab.com with the stable version (#LINK)
 
-- Database updates
-- Web server changes
-- File structure changes
-
-#### 1. Make backup
-
-#### 2. Stop server
-
-#### 3. Do users need to update dependencies like `git`?
-
-- Check if the [GitLab Shell version](/lib/tasks/gitlab/check.rake#L782) changed since the last release.
-
-- Check if the [Git version](/lib/tasks/gitlab/check.rake#L794) changed since the last release.
-
-#### 4. Get latest code
-
-#### 5. Does GitLab shell need to be updated?
-
-#### 6. Install libs, migrations, etc.
-
-#### 7. Any config files updated since last release?
-
-Check if any of these changed since last release:
-
-- [lib/support/nginx/gitlab](/lib/support/nginx/gitlab)
-- [lib/support/nginx/gitlab-ssl](/lib/support/nginx/gitlab-ssl)
-- <https://gitlab.com/gitlab-org/gitlab-shell/commits/master/config.yml.example>
-- [config/gitlab.yml.example](/config/gitlab.yml.example)
-- [config/unicorn.rb.example](/config/unicorn.rb.example)
-- [config/database.yml.mysql](/config/database.yml.mysql)
-- [config/database.yml.postgresql](/config/database.yml.postgresql)
-- [config/initializers/rack_attack.rb.example](/config/initializers/rack_attack.rb.example)
-- [config/resque.yml.example](/config/resque.yml.example)
+22nd:
 
-#### 8. Need to update init script?
+- [ ] Release CE, EE and CI (#LINK)
 
-Check if the `init.d/gitlab` script changed since last release: [lib/support/init.d/gitlab](/lib/support/init.d/gitlab)
+```
 
-#### 9. Start application
+- - -
 
-#### 10. Check application status
+## Code Freeze
 
-### **3. Code quality indicators**
+Stop merging code in master, except for important bug fixes
 
-Make sure the code quality indicators are green / good.
+## Update changelog
 
-- [![Build status](http://ci.gitlab.org/projects/1/status.png?ref=master)](http://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch)
+Any changes not yet added to the changelog are added by lead developer and in that merge request the complete team is
+asked if there is anything missing.
 
-- [![Build Status](https://semaphoreapp.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/243338/badge.png)](https://semaphoreapp.com/gitlabhq/gitlabhq) (master branch)
+There are three changelogs that need to be updated: CE, EE and CI.
 
-- [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq)
+## Create RC1 (CE, EE, CI)
 
-- [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) this button can be yellow (small updates are available) but must not be red (a security fix or an important update is available)
+[Follow this How-to guide](howto_rc1.md) to create RC1.
 
-- [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq)
+## Prepare CHANGELOG for next release
 
-### **4. Run release tool**
+Once the stable branches have been created, update the CHANGELOG in `master` with the upcoming version, usually X.X.X.pre.
 
-**Make sure EE `master` has latest changes from CE `master`**
+## QA
 
-Get release tools
-
-```
-git clone git@dev.gitlab.org:gitlab/release-tools.git
-cd release-tools
-```
-
-Release candidate creates stable branch from master. 
-So we need to sync master branch between all CE remotes. Also do same for EE.
-
-```
-bundle exec rake sync
-```
-
-Create release candidate and stable branch:
-
-```
-bundle exec rake release["x.x.0.rc1"]
-```
+Create issue on dev.gitlab.org `gitlab` repository, named "GitLab X.X QA" in order to keep track of the progress.
 
-Now developers can use master for merging new features.
-So you should use stable branch for future code chages related to release.
+Use the omnibus packages created for RC1 of Enterprise Edition using [this guide](https://dev.gitlab.org/gitlab/gitlab-ee/blob/master/doc/release/manual_testing.md).
 
+**NOTE** Upgrader can only be tested when tags are pushed to all repositories. Do not forget to confirm it is working before releasing. Note that in the issue.
 
-# **4 workdays before release - Release RC1**
+#### Fix anything coming out of the QA
 
-### **1. Determine QA person
+Create an issue with description of a problem, if it is quick fix fix it yourself otherwise contact the team for advice.
 
-Notify person of QA day.
+**NOTE** If there is a problem that cannot be fixed in a timely manner, reverting the feature is an option! If the feature is reverted,
+create an issue about it in order to discuss the next steps after the release.
 
-### **2. Update GitLab.com**
+## Update GitLab.com with RC1
 
-Merge the RC1 EE code into GitLab.com.
-Once the build is green, create a package.
+Use the omnibus EE packages created for RC1.
 If there are big database migrations consider testing them with the production db on a VM.
 Try to deploy in the morning.
 It is important to do this as soon as possible, so we can catch any errors before we release the full version.
 
-### **3. Prepare the blog post**
-
-- Start with a complete copy of the [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md) and fill it out.
-- Check the changelog of CE and EE for important changes.
-- Create a WIP MR for the blog post
-- Ask Dmitriy to add screenshots to the WIP MR.
-- Decide with team who will be the MVP user. 
-- Create WIP MR for adding MVP to MVP page on website
-- Add a note if there are security fixes: This release fixes an important security issue and we advise everyone to upgrade as soon as possible.
-- Create a merge request on [GitLab.com](https://gitlab.com/gitlab-com/www-gitlab-com/tree/master)
-- Assign to one reviewer who will fix spelling issues by editing the branch (can use the online editor)
-- After the reviewer is finished the whole team will be mentioned to give their suggestions via line comments
-
-### **4. Create a regressions issue**
+## Create a regressions issue
 
 On [the GitLab CE issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues/) create an issue titled "GitLab X.X regressions" add the following text:
 
@@ -207,41 +129,31 @@ Please do not raise issues directly in this issue but link to issues that might
 The decision to create a patch release or not is with the release manager who is assigned to this issue.
 The release manager will comment here about the plans for patch releases.
 
-Assign the issue to the release manager and /cc all the core-team members active on the issue tracker. If there are any known bugs in the release add them immediately.
+Assign the issue to the release manager and at mention all members of gitlab core team. If there are any known bugs in the release add them immediately.
 
-### **4. Tweet**
+## Tweet about RC1
 
 Tweet about the RC release:
 
 > GitLab x.x.0.rc1 is out. This release candidate is only suitable for testing. Please link regressions issues from LINK_TO_REGRESSION_ISSUE
 
-# **1 workdays before release - Preparation**
-
-### **1. Pre QA merge**
-
-Merge CE into EE before doing the QA.
+## Prepare the blog post
 
-### **2. QA**
+1. Start with a complete copy of the [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md) and fill it out.
+1. Make sure the blog post contains information about the GitLab CI release.
+1. Check the changelog of CE and EE for important changes.
+1. Also check the CI changelog
+1. Add a proposed tweet text to the blog post WIP MR description.
+1. Create a WIP MR for the blog post
+1. Ask Dmitriy (or a team member with OS X) to add screenshots to the WIP MR.
+1. Decide with core team who will be the MVP user.
+1. Create WIP MR for adding MVP to MVP page on website
+1. Add a note if there are security fixes: This release fixes an important security issue and we advise everyone to upgrade as soon as possible.
+1. Create a merge request on [GitLab.com](https://gitlab.com/gitlab-com/www-gitlab-com/tree/master)
+1. Assign to one reviewer who will fix spelling issues by editing the branch (either with a git client or by using the online editor)
+1. Comment to the reviewer: '@person Please mention the whole team as soon as you are done (3 workdays before release at the latest)'
 
-Create issue on dev.gitlab.org `gitlab` repository, named "GitLab X.X QA" in order to keep track of the progress.
-
-Use the omnibus packages of Enterprise Edition using [this guide](https://dev.gitlab.org/gitlab/gitlab-ee/blob/master/doc/release/manual_testing.md).
-
-**NOTE** Upgrader can only be tested when tags are pushed to all repositories. Do not forget to confirm it is working before releasing. Note that in the issue.
-
-### **3. Fix anything coming out of the QA**
-
-Create an issue with description of a problem, if it is quick fix fix it yourself otherwise contact the team for advice.
-
-**NOTE** If there is a problem that cannot be fixed in a timely manner, reverting the feature is an option! If the feature is reverted,
-create an issue about it in order to discuss the next steps after the release.
-
-# **22nd - Release CE and EE**
-
-**Make sure EE `x-x-stable-ee` has latest changes from CE `x-x-stable`**
-
-
-### **1. Release code**
+## Create CE, EE, CI stable versions
 
 Get release tools
 
@@ -256,47 +168,45 @@ Bump version, create release tag and push to remotes:
 bundle exec rake release["x.x.0"]
 ```
 
-
-### **2. Update installation.md**
+This will create correct version and tag and push to all CE, EE and CI remotes.
 
 Update [installation.md](/doc/install/installation.md) to the newest version in master.
 
 
-### **3. Build the Omnibus packages**
+## Create Omnibus tags and build packages
 
 Follow the [release doc in the Omnibus repository](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/release.md).
 This can happen before tagging because Omnibus uses tags in its own repo and SHA1's to refer to the GitLab codebase.
 
+## Update GitLab.com with the stable version
+
+- Deploy the package (should not need downtime because of the small difference with RC1)
+- Deploy the package for ci.gitlab.com
 
-### **4. Publish packages for new release**
+## Release CE, EE and CI
+
+__1. Publish packages for new release__
 
 Update `downloads/index.html` and `downloads/archive/index.html` in `www-gitlab-com` repository.
 
-### **5. Publish blog for new release**
+__2. Publish blog for new release__
 
+Doublecheck the everyone has been mentioned in the blog post.
 Merge the [blog merge request](#1-prepare-the-blog-post) in `www-gitlab-com` repository.
 
-### **6. Tweet to blog**
+__3. Tweet to blog__
 
 Send out a tweet to share the good news with the world.
 List the most important features and link to the blog post.
 
-Proposed tweet for CE "GitLab X.X is released! It brings *** <link-to-blogpost>"
-
-# **1 workday after release - Update GitLab.com**
+Proposed tweet "Release of GitLab X.X & CI Y.Y! FEATURE, FEATURE and FEATURE &lt;link-to-blog-post&gt; #gitlab"
 
-- Build a package for gitlab.com based on the official release instead of RC1
-- Deploy the package
+Consider creating a post on Hacker News.
 
-# **25th - Release GitLab CI**
+## Release new AMIs
 
-- Create the update guid `doc/x.x-to-x.x.md`.
-- Update CHANGELOG
-- Bump version
-- Create annotated tags `git tag -a vx.x.0 -m 'Version x.x.0' xxxxx`
-- Create stable branch `x-x-stable`
-- Create GitHub release post
-- Post to blog about release
-- Post to twitter
+[Follow this guide](https://dev.gitlab.org/gitlab/AMI/blob/master/README.md)
 
+## Create a WIP blogpost for the next release
 
+Create a WIP blogpost using [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md).
diff --git a/doc/release/patch.md b/doc/release/patch.md
index 6ed56427e9acaffc5d4a655effc0f54821556773..68156ae9c0e15946e5bd3e5de62fed7b503ae677 100644
--- a/doc/release/patch.md
+++ b/doc/release/patch.md
@@ -17,13 +17,16 @@ Otherwise include it in the monthly release and note there was a regression fix
 1. Create an issue on private GitLab development server
 1. Name the issue "Release X.X.X CE and X.X.X EE", this will make searching easier
 1. Fix the issue on a feature branch, do this on the private GitLab development server
+1. If it is a security issue, then assign it to the release manager and apply a 'security' label
 1. Consider creating and testing workarounds
 1. After the branch is merged into master, cherry pick the commit(s) into the current stable branch
 1. Make sure that the build has passed and all tests are passing
-1. In a separate commit in the stable branch update the CHANGELOG
+1. In a separate commit in the master branch update the CHANGELOG
 1. For EE, update the CHANGELOG-EE if it is EE specific fix. Otherwise, merge the stable CE branch and add to CHANGELOG-EE "Merge community edition changes for version X.X.X"
+1. Merge CE stable branch into EE stable branch
 
-### Bump version 
+
+### Bump version
 
 Get release tools
 
@@ -46,9 +49,10 @@ CE=false be rake release['x.x.x']
 
 ### Release
 
-1. Apply the patch to GitLab Cloud and the private GitLab development server
 1. [Build new packages with the latest version](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/release.md)
-1. Cherry-pick the changelog update back into master
-1. Create and publish a blog post
-1. Send tweets about the release from `@gitlabhq`, tweet should include the most important feature that the release is addressing and link to the blog post
+1. Apply the patch to GitLab.com and the private GitLab development server
+1. Apply the patch to ci.gitLab.com and the private GitLab CI development server
+1. Create and publish a blog post, see [patch release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/patch_release_blog_template.md)
+1. Send tweets about the release from `@gitlab`, tweet should include the most important feature that the release is addressing and link to the blog post
 1. Note in the 'GitLab X.X regressions' issue that the patch was published (CE only)
+1. [Create new AMIs](https://dev.gitlab.org/gitlab/AMI/blob/master/README.md)
diff --git a/doc/release/security.md b/doc/release/security.md
index 79d23c02ea4d51d2f87e3f05d2c7ea3b15c55513..60bcfbb6da5b9f94e680076b268d5d0685225bee 100644
--- a/doc/release/security.md
+++ b/doc/release/security.md
@@ -14,13 +14,17 @@ Please report suspected security vulnerabilities in private to <support@gitlab.c
 
 1. Verify that the issue can be reproduced
 1. Acknowledge the issue to the researcher that disclosed it
+1. Inform the release manager that there needs to be a security release
 1. Do the steps from [patch release document](doc/release/patch.md), starting with "Create an issue on private GitLab development server"
+1. The MR with the security fix should get a 'security' label and be assigned to the release manager
+1. Build the package for GitLab.com and do a deploy
+1. Build the package for ci.gitLab.com and do a deploy
+1. [Create new AMIs](https://dev.gitlab.org/gitlab/AMI/blob/master/README.md)
 1. Create feature branches for the blog post on GitLab.com and link them from the code branch
 1. Merge and publish the blog posts
 1. Send tweets about the release from `@gitlabhq`
-1. Send out an email to the 'GitLab Newsletter' mailing list on MailChimp (or the 'Subscribers' list if the security fix is for EE only)
 1. Send out an email to [the community google mailing list](https://groups.google.com/forum/#!forum/gitlabhq)
-1. Post a signed copy of our complete announcement to [oss-security](http://www.openwall.com/lists/oss-security/) and request a CVE number
+1. Post a signed copy of our complete announcement to [oss-security](http://www.openwall.com/lists/oss-security/) and request a CVE number. CVE is only needed for bugs that allow someone to own the server (Remote Code Execution) or access to code of projects they are not a member of.
 1. Add the security researcher to the [Security Researcher Acknowledgments list](http://about.gitlab.com/vulnerability-acknowledgements/)
 1. Thank the security researcher in an email for their cooperation
 1. Update the blog post and the CHANGELOG when we receive the CVE number
diff --git a/doc/security/README.md b/doc/security/README.md
index f88375f2afd5c4a1633a013acb21cb4f1801517e..49dfa6eec76e68791623652f4a7cfb2cc7c3edbf 100644
--- a/doc/security/README.md
+++ b/doc/security/README.md
@@ -2,4 +2,5 @@
 
 - [Password length limits](password_length_limits.md)
 - [Rack attack](rack_attack.md)
+- [Web Hooks and insecure internal web services](webhooks.md)
 - [Information exclusivity](information_exclusivity.md)
diff --git a/doc/security/information_exclusivity.md b/doc/security/information_exclusivity.md
index 127166ae2e7fac4f9fb16425998465ebc3efc33b..f8e7fc3fd0ec5f3b36a5c2791be7ebefe946f1e0 100644
--- a/doc/security/information_exclusivity.md
+++ b/doc/security/information_exclusivity.md
@@ -4,6 +4,6 @@ Git is a distributed version control system (DVCS).
 This means that everyone that works with the source code has a local copy of the complete repository.
 In GitLab every project member that is not a guest (so reporters, developers and masters) can clone the repository to get a local copy.
 After obtaining this local copy the user can upload the full repository anywhere, including another project under their control or another server.
-The consequense is that you can't build access controls that prevent the intentional sharing of source code by users that have access to the source code.
+The consequence is that you can't build access controls that prevent the intentional sharing of source code by users that have access to the source code.
 This is an inherent feature of a DVCS and all git management systems have this limitation.
 Obviously you can take steps to prevent unintentional sharing and information destruction, this is why only some people are allowed to invite others and nobody can force push a protected branch.
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
new file mode 100644
index 0000000000000000000000000000000000000000..1e9d33e87c314a3b9353a623b4806114b47c5939
--- /dev/null
+++ b/doc/security/webhooks.md
@@ -0,0 +1,13 @@
+# Web Hooks and insecure internal web services
+
+If you have non-GitLab web services running on your GitLab server or within its local network, these may be vulnerable to exploitation via Web Hooks.
+
+With [Web Hooks](../web_hooks/web_hooks.md), you and your project masters and owners can set up URLs to be triggered when specific things happen to projects. Normally, these requests are sent to external web services specifically set up for this purpose, that process the request and its attached data in some appropriate way. 
+
+Things get hairy, however, when a Web Hook is set up with a URL that doesn't point to an external, but to an internal service, that may do something completely unintended when the web hook is triggered and the POST request is sent.
+
+Because Web Hook requests are made by the GitLab server itself, these have complete access to everything running on the server (http://localhost:123) or within the server's local network (http://192.168.1.12:345), even if these services are otherwise protected and inaccessible from the outside world.
+
+If a web service does not require authentication, Web Hooks can be used to trigger destructive commands by getting the GitLab server to make POST requests to endpoints like "http://localhost:123/some-resource/delete". 
+
+To prevent this type of exploitation from happening, make sure that you are aware of every web service GitLab could potentially have access to, and that all of these are set up to require authentication for every potentially destructive command. Enabling authentication but leaving a default password is not enough.
\ No newline at end of file
diff --git a/doc/sidekiq_debugging.md b/doc/sidekiq_debugging.md
new file mode 100644
index 0000000000000000000000000000000000000000..cea11e5f126601e31c1886de25792f2b77461150
--- /dev/null
+++ b/doc/sidekiq_debugging.md
@@ -0,0 +1,14 @@
+# Sidekiq debugging
+
+## Log arguments to Sidekiq jobs
+
+If you want to see what arguments are being passed to Sidekiq jobs you can set
+the SIDEKIQ_LOG_ARGUMENTS environment variable.
+
+```
+SIDEKIQ_LOG_ARGUMENTS=1 bundle exec foreman start
+```
+
+It is not recommend to enable this setting in production because some Sidekiq
+jobs (such as sending a password reset email) take secret arguments (for
+example the password reset token).
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index c87fffd7d2ca1494354329097493bef13703f6fb..0acb15896d379d0ac80a7b555d178dd9507984dd 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -1,4 +1,73 @@
 # SSH
 
-- [Deploy keys](deploy_keys.md)
-- [SSH](ssh.md)
+## SSH keys
+
+An SSH key allows you to establish a secure connection between your
+computer and GitLab.
+
+Before generating an SSH key, check if your system already has one by
+running `cat ~/.ssh/id_rsa.pub`. If you see a long string starting with
+`ssh-rsa` or `ssh-dsa`, you can skip the ssh-keygen step.
+
+To generate a new SSH key, just open your terminal and use code below. The
+ssh-keygen command prompts you for a location and filename to store the key
+pair and for a password. When prompted for the location and filename, you
+can press enter to use the default.
+
+It is a best practice to use a password for an SSH key, but it is not
+required and you can skip creating a password by pressing enter. Note that
+the password you choose here can't be altered or retrieved.
+
+```bash
+ssh-keygen -t rsa -C "$your_email"
+```
+
+Use the code below to show your public key.
+
+```bash
+cat ~/.ssh/id_rsa.pub
+```
+
+Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your
+user profile. Please copy the complete key starting with `ssh-` and ending
+with your username and host.  
+
+Use code below to copy your public key to the clipboard. Depending on your
+OS you'll need to use a different command:
+
+**Windows:**
+```bash
+clip < ~/.ssh/id_rsa.pub
+```
+
+**Mac:**
+```bash
+pbcopy < ~/.ssh/id_rsa.pub
+```
+
+**GNU/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 project, or through
+a group. See `def accessible_deploy_keys` in `app/models/user.rb` for more
+information.
diff --git a/doc/ssh/deploy_keys.md b/doc/ssh/deploy_keys.md
deleted file mode 100644
index dcca8bdc61aa4f9d327d8943d2353f901384942a..0000000000000000000000000000000000000000
--- a/doc/ssh/deploy_keys.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Deploy keys
-
-Deploy keys allow read-only access one or multiple projects with a single SSH key.
-
-This is really useful for cloning repositories to your Continuous Integration (CI) server. By using a deploy keys you don't have to setup a dummy user account.
-
-If you are a project master or owner you can add a deploy key in the project settings under the section Deploy Keys. Press the 'New Deploy Key' button and upload a public ssh key. After this the machine that uses the corresponding private key has read-only access to the project.
-
-You can't add the same deploy key twice with the 'New Deploy Key' option. If you want to add the same key to another project please enable it in the list that says 'Deploy keys from projects available to you'. All the deploy keys of all the projects you have access to are available. This project access can happen through being a direct member of the project or through a group. See `def accessible_deploy_keys` in `app/models/user.rb` for more information.
diff --git a/doc/ssh/ssh.md b/doc/ssh/ssh.md
deleted file mode 100644
index d466c1bde720859c508853b97001025dd6b42a18..0000000000000000000000000000000000000000
--- a/doc/ssh/ssh.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# SSH keys
-
-SSH key allows you to establish a secure connection between your computer and GitLab
-
-Before generating an SSH key, check if your system already has one by running `cat ~/.ssh/id_rsa.pub` If your see a long string starting with `ssh-rsa` or `ssh-dsa`, you can skip the ssh-keygen step.
-
-To generate a new SSH key just open your terminal and use code below. The ssh-keygen command prompts you for a location and filename to store the key pair and for a password. When prompted for the location and filename you can press enter to use the default. 
-It is a best practice to use a password for an SSH key but it is not required and you can skip creating a password by pressing enter. 
-Note that the password you choose here can't be altered or retrieved.
-
-```bash
-ssh-keygen -t rsa -C "$your_email"
-```
-
-Use the code below to show your public key.
-
-```bash
-cat ~/.ssh/id_rsa.pub
-```
-
-Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your user profile. Please copy the complete key starting with `ssh-` and ending with your username and host.
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index 54e6e3a9e3fd4748c5781f3e3bc69e70c5d45a0d..f9b6d37d8405fdab0411353642b905331179396c 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -1,6 +1,6 @@
 # System hooks
 
-Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create` and `key_destroy`.
+Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create`, `key_destroy`, `group_create`, `group_destroy`, `user_add_to_group` and `user_remove_from_group`.
 
 System hooks can be used, e.g. for logging or changing information in a LDAP server.
 
@@ -15,8 +15,8 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
                 "name": "StoreCloud",
          "owner_email": "johnsmith@gmail.com",
           "owner_name": "John Smith",
-                "path": "stormcloud",
- "path_with_namespace": "jsmith/stormcloud",
+                "path": "storecloud",
+ "path_with_namespace": "jsmith/storecloud",
           "project_id": 74,
   "project_visibility": "private",
 }
@@ -50,6 +50,7 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
        "project_path": "storecloud",
          "user_email": "johnsmith@gmail.com",
           "user_name": "John Smith",
+            "user_id": 41,
  "project_visibility": "private",
 }
 ```
@@ -66,6 +67,7 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
        "project_path": "storecloud",
          "user_email": "johnsmith@gmail.com",
           "user_name": "John Smith",
+            "user_id": 41,
  "project_visibility": "private",
 }
 ```
@@ -117,3 +119,62 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser
             "id": 4
 }
 ```
+
+**Group created:**
+
+```json
+{
+   "created_at": "2012-07-21T07:30:54Z",
+   "event_name": "group_create",
+         "name": "StoreCloud",
+  "owner_email": "johnsmith@gmail.com",
+   "owner_name": "John Smith",
+         "path": "storecloud",
+     "group_id": 78
+}
+```
+
+**Group removed:**
+
+```json
+{
+   "created_at": "2012-07-21T07:30:54Z",
+   "event_name": "group_destroy",
+         "name": "StoreCloud",
+  "owner_email": "johnsmith@gmail.com",
+   "owner_name": "John Smith",
+         "path": "storecloud",
+     "group_id": 78
+}
+```
+
+**New Group Member:**
+
+```json
+{
+    "created_at": "2012-07-21T07:30:56Z",
+    "event_name": "user_add_to_group",
+  "group_access": "Master",
+      "group_id": 78,
+    "group_name": "StoreCloud",
+    "group_path": "storecloud",
+    "user_email": "johnsmith@gmail.com",
+     "user_name": "John Smith",
+       "user_id": 41
+}
+```
+**Group Member Removed:**
+
+```json
+{
+    "created_at": "2012-07-21T07:30:56Z",
+    "event_name": "user_remove_from_group",
+  "group_access": "Master",
+      "group_id": 78,
+    "group_name": "StoreCloud",
+    "group_path": "storecloud",
+    "user_email": "johnsmith@gmail.com",
+     "user_name": "John Smith",
+       "user_id": 41
+}
+```
diff --git a/doc/update/2.6-to-3.0.md b/doc/update/2.6-to-3.0.md
index 6aabbe095dc0c1c45f64546876fa8a3f4623198a..4827ef9501a112732c0eb5ac5726ceef7e72aabb 100644
--- a/doc/update/2.6-to-3.0.md
+++ b/doc/update/2.6-to-3.0.md
@@ -1,4 +1,5 @@
 # From 2.6 to 3.0
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/2.6-to-3.0.md) for the most up to date instructions.*
 
 ## 1. Stop server & resque
 
@@ -22,29 +23,29 @@ sudo -u gitlab bundle exec rake db:migrate RAILS_ENV=production
 # !!! Config should be replaced with a new one. Check it after replace
 cp config/gitlab.yml.example config/gitlab.yml
 
-# update gitolite hooks
+# update Gitolite hooks
 
-# GITOLITE v2:
+# Gitolite v2:
 sudo cp ./lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive
 sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive
 
-# GITOLITE v3:
+# Gitolite v3:
 sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
 sudo chown git:git /home/git/.gitolite/hooks/common/post-receive
 
 # set valid path to hooks in gitlab.yml in git_host section
 # like this
 git_host:
-  # gitolite 2
+  # Gitolite 2
   hooks_path: /home/git/share/gitolite/hooks
-  # gitolite 3
+  # Gitolite 3
   hooks_path: /home/git/.gitolite/hooks/
 
 
-# Make some changes to gitolite config
+# Make some changes to Gitolite config
 # For more information visit https://github.com/gitlabhq/gitlabhq/pull/1719
 
-# gitolite v2
+# Gitolite v2
 sudo -u git -H sed -i 's/\(GL_GITCONFIG_KEYS\s*=>*\s*\).\{2\}/\\1"\.\*"/g' /home/git/.gitolite.rc
 
 # gitlite v3
diff --git a/doc/update/2.9-to-3.0.md b/doc/update/2.9-to-3.0.md
index 8af86b0dc982714775a2e8f5a12432b5318050c4..f4a997a8c5e5676b2f33937e2331f52e06a98b8d 100644
--- a/doc/update/2.9-to-3.0.md
+++ b/doc/update/2.9-to-3.0.md
@@ -1,4 +1,5 @@
 # From 2.9 to 3.0
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/2.9-to-3.0.md) for the most up to date instructions.*
 
 ## 1. Stop server & resque
 
diff --git a/doc/update/3.0-to-3.1.md b/doc/update/3.0-to-3.1.md
index 3206df3499bcd2402c8976967974ebdb5cca4a7d..a30485c42f799a396141d9c546801b2c3e266a0e 100644
--- a/doc/update/3.0-to-3.1.md
+++ b/doc/update/3.0-to-3.1.md
@@ -1,4 +1,5 @@
 # From 3.0 to 3.1
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/3.0-to-3.1.md) for the most up to date instructions.*
 
 **IMPORTANT!**
 
diff --git a/doc/update/3.1-to-4.0.md b/doc/update/3.1-to-4.0.md
index 165f4e6a308f4f91ead71fdb24167a374d308f69..f1ef4df4744cae9304762ce956b8333346a12ee1 100644
--- a/doc/update/3.1-to-4.0.md
+++ b/doc/update/3.1-to-4.0.md
@@ -1,4 +1,5 @@
 # From 3.1 to 4.0
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/3.1-to-4.0.md) for the most up to date instructions.*
 
 ## Important changes
 
diff --git a/doc/update/4.0-to-4.1.md b/doc/update/4.0-to-4.1.md
index 4149ed6b08d5a12f4fbfb86e4a50f095ad45e927..d89d523591706ce0830300c77e17f1a5460dfcf7 100644
--- a/doc/update/4.0-to-4.1.md
+++ b/doc/update/4.0-to-4.1.md
@@ -1,4 +1,5 @@
 # From 4.0 to 4.1
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/4.0-to-4.1.md) for the most up to date instructions.*
 
 ## Important changes
 
diff --git a/doc/update/4.1-to-4.2.md b/doc/update/4.1-to-4.2.md
index 5ee8e8781e96b21524801cedd54a35701783f015..6fe4412ff90afaddee77e1b266b42e0fd1ac42a3 100644
--- a/doc/update/4.1-to-4.2.md
+++ b/doc/update/4.1-to-4.2.md
@@ -1,4 +1,5 @@
 # From 4.1 to 4.2
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/4.1-to-4.2.md) for the most up to date instructions.*
 
 ## 1. Stop server & Resque
 
diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md
index cde679598f7cacfd3ccc9101365a96b763e8aed9..f9faf65f9525d29367cc7fc21772ac5eb8cc2e7b 100644
--- a/doc/update/4.2-to-5.0.md
+++ b/doc/update/4.2-to-5.0.md
@@ -1,4 +1,5 @@
 # From 4.2 to 5.0
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/4.2-to-5.0.md) for the most up to date instructions.*
 
 ## Warning
 
@@ -41,8 +42,8 @@ git checkout v1.1.0
 # copy config
 cp config.yml.example config.yml
 
-# change url to GitLab instance
-# ! make sure url end with '/' like 'https://gitlab.example/'
+# change URL to GitLab instance
+# ! make sure the URL ends with '/' like 'https://gitlab.example/'
 vim config.yml
 
 # rewrite hooks
@@ -111,7 +112,7 @@ sudo chmod -R u+rwX  /home/git/gitlab/tmp/pids
 
 ```
 
-## 6. Update init.d script and nginx config
+## 6. Update init.d script and Nginx config
 
 ```bash
 # init.d
@@ -123,7 +124,7 @@ sudo chmod +x /etc/init.d/gitlab
 sudo -u git -H cp /home/git/gitlab/config/unicorn.rb /home/git/gitlab/config/unicorn.rb.old
 sudo -u git -H cp /home/git/gitlab/config/unicorn.rb.example /home/git/gitlab/config/unicorn.rb
 
-#nginx
+# Nginx
 # Replace path from '/home/gitlab/' to '/home/git/'
 sudo vim /etc/nginx/sites-enabled/gitlab
 sudo service nginx restart
@@ -137,7 +138,7 @@ sudo service gitlab start
 
 # check if unicorn and sidekiq started
 # If not try to logout, also check replaced path from '/home/gitlab/' to '/home/git/'
-# in nginx, unicorn, init.d etc
+# in Nginx, unicorn, init.d etc
 ps aux | grep unicorn
 ps aux | grep sidekiq
 
diff --git a/doc/update/5.0-to-5.1.md b/doc/update/5.0-to-5.1.md
index 0e597abb1a94390edc43d6284a988acd7a4415b2..9fbd1f88515eb62ec289c375df647c1458bd0d32 100644
--- a/doc/update/5.0-to-5.1.md
+++ b/doc/update/5.0-to-5.1.md
@@ -1,4 +1,5 @@
 # From 5.0 to 5.1
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.0-to-5.1.md) for the most up to date instructions.*
 
 ## Warning
 
diff --git a/doc/update/5.1-to-5.2.md b/doc/update/5.1-to-5.2.md
index 6ef559ac9f913f385444f5bc7bb6eed114a7f36a..cf9c4e4f770437662929f670e1dfc4a396a697ee 100644
--- a/doc/update/5.1-to-5.2.md
+++ b/doc/update/5.1-to-5.2.md
@@ -1,4 +1,5 @@
 # From 5.1 to 5.2
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.1-to-5.2.md) for the most up to date instructions.*
 
 ## Warning
 
diff --git a/doc/update/5.1-to-5.4.md b/doc/update/5.1-to-5.4.md
index 8ec56b266ca02def96a9a94b3c2572172c732319..97a98ede070d9abbe4d3cf729b5a46fd6d444b1b 100644
--- a/doc/update/5.1-to-5.4.md
+++ b/doc/update/5.1-to-5.4.md
@@ -1,4 +1,5 @@
 # From 5.1 to 5.4
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.1-to-5.4.md) for the most up to date instructions.*
 
 Also works starting from 5.2.
 
diff --git a/doc/update/5.1-to-6.0.md b/doc/update/5.1-to-6.0.md
index a76b371e6d683bc17163bcec8799b782d23e4054..a3fdd92bd2f17aac20f2b313c36a460ea069bfd8 100644
--- a/doc/update/5.1-to-6.0.md
+++ b/doc/update/5.1-to-6.0.md
@@ -1,4 +1,5 @@
 # From 5.1 to 6.0
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.1-to-6.0.md) for the most up to date instructions.*
 
 ## Warning
 
@@ -40,7 +41,7 @@ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 
 The migrations in this update are very sensitive to incomplete or inconsistent data. If you have a long-running GitLab installation and some of the previous upgrades did not work out 100% correct this may bite you now. The following can help you have a more smooth upgrade.
 
-### Find projets with invalid project names
+### Find projects with invalid project names
 
 #### MySQL
 Login to MySQL:
diff --git a/doc/update/5.2-to-5.3.md b/doc/update/5.2-to-5.3.md
index 61ddf13564111e6b00bd3e2d871f9d955c75eff3..27613aeda07e536a8b170480a39df9906addd7c8 100644
--- a/doc/update/5.2-to-5.3.md
+++ b/doc/update/5.2-to-5.3.md
@@ -1,4 +1,5 @@
 # From 5.2 to 5.3
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.2-to-5.3.md) for the most up to date instructions.*
 
 ## Warning
 
diff --git a/doc/update/5.3-to-5.4.md b/doc/update/5.3-to-5.4.md
index 8a0d43e3e642e958349adbe45bc115e1af258286..577b9a585ffb47407bd22ec2e5b8f1c5913996fc 100644
--- a/doc/update/5.3-to-5.4.md
+++ b/doc/update/5.3-to-5.4.md
@@ -1,4 +1,5 @@
 # From 5.3 to 5.4
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.3-to-5.4.md) for the most up to date instructions.*
 
 ## 0. Backup
 
diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md
index 7bf7bce6aa0a5f9c7d59b8adccd85f1081dfd1a8..d9c6d9bfb91cbc9b56f6865ee0761c5ba6e50af0 100644
--- a/doc/update/5.4-to-6.0.md
+++ b/doc/update/5.4-to-6.0.md
@@ -1,16 +1,20 @@
 # From 5.4 to 6.0
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.4-to-6.0.md) for the most up to date instructions.*
 
 ## Warning
 
 GitLab 6.0 is affected by critical security vulnerabilities CVE-2013-4490 and CVE-2013-4489.
 
+**You need to follow this guide first, before updating past 6.0, as it contains critical migration steps that are only present
+in the `6-0-stable` branch**
+
 ## Deprecations
 
 ### Global projects
 
 The root (global) namespace for projects is deprecated.
 
-So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote url. Please make sure you disable sending email when you do a test of the upgrade.
+So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote URL. Please make sure you disable sending email when you do a test of the upgrade.
 
 ### Teams
 
diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md
index 9d67a3bcb966dd1f652fefc530143c050259567b..c5eba1c01c457e341e28ef8b9508b082123d48f8 100644
--- a/doc/update/6.0-to-6.1.md
+++ b/doc/update/6.0-to-6.1.md
@@ -1,4 +1,5 @@
 # From 6.0 to 6.1
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.0-to-6.1.md) for the most up to date instructions.*
 
 ## Warning
 
diff --git a/doc/update/6.1-to-6.2.md b/doc/update/6.1-to-6.2.md
index efa6e43124cb96ecbdbe86499d9e826e9edb1666..a534528108a9171c1087159b5094be963659a1d4 100644
--- a/doc/update/6.1-to-6.2.md
+++ b/doc/update/6.1-to-6.2.md
@@ -1,4 +1,5 @@
 # From 6.1 to 6.2
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.1-to-6.2.md) for the most up to date instructions.*
 
 **You should update to 6.1 before installing 6.2 so all the necessary conversions are run.**
 
@@ -35,7 +36,7 @@ sudo -u git -H git checkout v1.7.9 # Addresses multiple critical security vulner
 ## 4. Install additional packages
 
 ```bash
-# Add support for lograte for better log file handling
+# Add support for logrotate for better log file handling
 sudo apt-get install logrotate
 ```
 
diff --git a/doc/update/6.2-to-6.3.md b/doc/update/6.2-to-6.3.md
index e9b3bdd2f5413a5d53b4e8bcdca0d596423d0234..b08ebde08084bbe584c87c4527c278bf50e93ca9 100644
--- a/doc/update/6.2-to-6.3.md
+++ b/doc/update/6.2-to-6.3.md
@@ -1,4 +1,5 @@
 # From 6.2 to 6.3
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.2-to-6.3.md) for the most up to date instructions.*
 
 **Requires version: 6.1 or 6.2.**
 
diff --git a/doc/update/6.3-to-6.4.md b/doc/update/6.3-to-6.4.md
index 96c2895981da1008b82766c7e3e7769f06e7041b..951d92dfeb54ec0ad9214e05ad41d225e3b23838 100644
--- a/doc/update/6.3-to-6.4.md
+++ b/doc/update/6.3-to-6.4.md
@@ -1,4 +1,5 @@
 # From 6.3 to 6.4
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.3-to-6.4.md) for the most up to date instructions.*
 
 ## 0. Backup
 
diff --git a/doc/update/6.4-to-6.5.md b/doc/update/6.4-to-6.5.md
index 1624296fc3f6c38848a56324e4103d7390068bfb..0dae9a9fe594788679a21f5bb8ef30daf955b28e 100644
--- a/doc/update/6.4-to-6.5.md
+++ b/doc/update/6.4-to-6.5.md
@@ -1,4 +1,5 @@
 # From 6.4 to 6.5
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.4-to-6.5.md) for the most up to date instructions.*
 
 ## 0. Backup
 
diff --git a/doc/update/6.5-to-6.6.md b/doc/update/6.5-to-6.6.md
index 544eee17fec5eaed777d05792a0314e703f7f358..c24e83eb006562fb4257bc931d516ee1e3797347 100644
--- a/doc/update/6.5-to-6.6.md
+++ b/doc/update/6.5-to-6.6.md
@@ -1,4 +1,5 @@
 # From 6.5 to 6.6
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.5-to-6.6.md) for the most up to date instructions.*
 
 ## 0. Backup
 
diff --git a/doc/update/6.6-to-6.7.md b/doc/update/6.6-to-6.7.md
index 77ac4d0bfa6e2ec9aae060b06ddfdc494d9f86bd..5622a7001ed1cc66a36a1e34a8081c5c19012c4b 100644
--- a/doc/update/6.6-to-6.7.md
+++ b/doc/update/6.6-to-6.7.md
@@ -1,4 +1,5 @@
 # From 6.6 to 6.7
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.6-to-6.7.md) for the most up to date instructions.*
 
 ## 0. Backup
 
diff --git a/doc/update/6.7-to-6.8.md b/doc/update/6.7-to-6.8.md
index 16f3439c998b03ecf5a209b0b9d266a59bd631d3..4fb90639f1690f6afe73240f7483c72859ed7487 100644
--- a/doc/update/6.7-to-6.8.md
+++ b/doc/update/6.7-to-6.8.md
@@ -1,4 +1,5 @@
 # From 6.7 to 6.8
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.7-to-6.8.md) for the most up to date instructions.*
 
 ## 0. Backup
 
diff --git a/doc/update/6.8-to-6.9.md b/doc/update/6.8-to-6.9.md
index 9efb384ff599ae078b028f6510a2bf8fa76b2895..b9b8b63f652fdc47a83f7aeb5def5a0aab418cea 100644
--- a/doc/update/6.8-to-6.9.md
+++ b/doc/update/6.8-to-6.9.md
@@ -1,4 +1,5 @@
 # From 6.8 to 6.9
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.8-to-6.9.md) for the most up to date instructions.*
 
 ### 0. Backup
 
diff --git a/doc/update/6.9-to-7.0.md b/doc/update/6.9-to-7.0.md
index 1f3421a799b58bf1382b0e02b4282a611d1df9d6..236430b5951618062a534e88e9a20ce9dfd2e5cc 100644
--- a/doc/update/6.9-to-7.0.md
+++ b/doc/update/6.9-to-7.0.md
@@ -1,4 +1,5 @@
 # From 6.9 to 7.0
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.9-to-7.0.md) for the most up to date instructions.*
 
 ### 0. Backup
 
diff --git a/doc/update/6.x-or-7.x-to-7.4.md b/doc/update/6.x-or-7.x-to-7.9.md
similarity index 84%
rename from doc/update/6.x-or-7.x-to-7.4.md
rename to doc/update/6.x-or-7.x-to-7.9.md
index dd90ae3bf3d6254d13b9b943bab809ae8d5f17b1..bd6eb6b211f9f4202262cb7aee7334c7d32222ce 100644
--- a/doc/update/6.x-or-7.x-to-7.4.md
+++ b/doc/update/6.x-or-7.x-to-7.9.md
@@ -1,6 +1,7 @@
-# From 6.x or 7.x to 7.4
+# From 6.x or 7.x to 7.9
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.x-or-7.x-to-7.9.md) for the most up to date instructions.*
 
-This allows you to upgrade any version of GitLab from 6.0 and up (including 7.0 and up) to 7.4.
+This allows you to upgrade any version of GitLab from 6.0 and up (including 7.0 and up) to 7.9.
 
 ## Global issue numbers
 
@@ -34,7 +35,7 @@ You can check which version you are running with `ruby -v`.
 
 If you are you running Ruby 2.0.x, you do not need to upgrade ruby, but can consider doing so for performance reasons.
 
-If you are running Ruby 2.1.1 consider upgrading to 2.1.2, because of the high memory usage of Ruby 2.1.1.
+If you are running Ruby 2.1.1 consider upgrading to 2.1.5, because of the high memory usage of Ruby 2.1.1.
 
 Install, update dependencies:
 
@@ -46,8 +47,8 @@ Download and compile Ruby:
 
 ```bash
 mkdir /tmp/ruby && cd /tmp/ruby
-curl --progress ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
-cd ruby-2.1.2
+curl --progress http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.5.tar.gz | tar xz
+cd ruby-2.1.5
 ./configure --disable-install-rdoc
 make
 sudo make install
@@ -70,7 +71,7 @@ sudo -u git -H git checkout -- db/schema.rb # local changes will be restored aut
 For GitLab Community Edition:
 
 ```bash
-sudo -u git -H git checkout 7-4-stable
+sudo -u git -H git checkout 7-9-stable
 ```
 
 OR
@@ -78,17 +79,23 @@ OR
 For GitLab Enterprise Edition:
 
 ```bash
-sudo -u git -H git checkout 7-4-stable-ee
+sudo -u git -H git checkout 7-9-stable-ee
 ```
 
 ## 4. Install additional packages
 
 ```bash
-# Add support for lograte for better log file handling
+# Add support for logrotate for better log file handling
 sudo apt-get install logrotate
 
 # Install pkg-config and cmake, which is needed for the latest versions of rugged
 sudo apt-get install pkg-config cmake
+
+# Install Kerberos header files, which are needed for GitLab EE Kerberos support
+sudo apt-get install libkrb5-dev
+
+# Install nodejs, javascript runtime required for assets
+sudo apt-get install nodejs
 ```
 
 ## 5. Configure Redis to use sockets
@@ -119,7 +126,7 @@ sudo apt-get install pkg-config cmake
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch
-sudo -u git -H git checkout v2.0.1
+sudo -u git -H git checkout v2.6.0
 ```
 
 ## 7. Install libs, migrations, etc.
@@ -154,14 +161,12 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
 TIP: to see what changed in `gitlab.yml.example` in this release use next command:
 
 ```
-git diff 6-0-stable:config/gitlab.yml.example 7-4-stable:config/gitlab.yml.example
+git diff 6-0-stable:config/gitlab.yml.example 7-9-stable:config/gitlab.yml.example
 ```
 
-* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/config/gitlab.yml.example but with your settings.
-* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/config/unicorn.rb.example but with your settings.
-* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.0.1/config.yml.example but with your settings.
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/lib/support/nginx/gitlab but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/lib/support/nginx/gitlab-ssl but with your settings.
+* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/config/gitlab.yml.example but with your settings.
+* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/config/unicorn.rb.example but with your settings.
+* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.6.0/config.yml.example but with your settings.
 * Copy rack attack middleware config
 
 ```bash
@@ -174,6 +179,12 @@ sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers
 sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
 ```
 
+### Change Nginx settings
+
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/lib/support/nginx/gitlab but with your settings.
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/lib/support/nginx/gitlab-ssl but with your settings.
+* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
+
 ## 9. Start application
 
     sudo service gitlab start
@@ -196,7 +207,7 @@ If all items are green, then congratulations upgrade complete!
 
 When using Google omniauth login, changes of the Google account required.
 Ensure that `Contacts API` and the `Google+ API` are enabled in the [Google Developers Console](https://console.developers.google.com/).
-More details can be found at the [integration documentation](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/google.md).
+More details can be found at the [integration documentation](../../../master/doc/integration/google.md).
 
 ## 12. Optional optimizations for GitLab setups with MySQL databases
 
@@ -217,13 +228,13 @@ mysql -u root -p
 # Convert all tables to use the InnoDB storage engine (added in GitLab 6.8)
 SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' ENGINE=InnoDB;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `ENGINE` <> 'InnoDB' AND `TABLE_TYPE` = 'BASE TABLE';
 
-# If previous query returned results, copy & run all outputed SQL statements
+# If previous query returned results, copy & run all shown SQL statements
 
 # Convert all tables to correct character set
 SET foreign_key_checks = 0;
 SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `TABLE_COLLATION` <> 'utf8_unicode_ci' AND `TABLE_TYPE` = 'BASE TABLE';
 
-# If previous query returned results, copy & run all outputed SQL statements
+# If previous query returned results, copy & run all shown SQL statements
 
 # turn foreign key checks back on
 SET foreign_key_checks = 1;
@@ -231,7 +242,7 @@ SET foreign_key_checks = 1;
 # Find MySQL users
 mysql> SELECT user FROM mysql.user WHERE user LIKE '%git%';
 
-# If git user exists and gitlab user does not exist 
+# If git user exists and gitlab user does not exist
 # you are done with the database cleanup tasks
 mysql> \q
 
@@ -269,11 +280,11 @@ mysql> \q
 sudo -u git -H editor /home/git/gitlab/config/database.yml
 ```
 
-## Things went south? Revert to previous version (6.0)
+## Things went south? Revert to previous version (7.0)
 
 ### 1. Revert the code to the previous version
 
-Follow the [upgrade guide from 5.4 to 6.0](5.4-to-6.0.md), except for the database migration (the backup is already migrated to the previous version).
+Follow the [upgrade guide from 6.9 to 7.0](6.9-to-7.0.md), except for the database migration (the backup is already migrated to the previous version).
 
 ### 2. Restore from the backup:
 
diff --git a/doc/update/7.0-to-7.1.md b/doc/update/7.0-to-7.1.md
index 82bb57087348e09a5b8643bfaf7587ce371d12a3..a4e9be9946e07fdcbc7f1e7f9416607862a45236 100644
--- a/doc/update/7.0-to-7.1.md
+++ b/doc/update/7.0-to-7.1.md
@@ -1,4 +1,5 @@
 # From 7.0 to 7.1
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/7.0-to-7.1.md) for the most up to date instructions.*
 
 ### 0. Backup
 
diff --git a/doc/update/7.1-to-7.2.md b/doc/update/7.1-to-7.2.md
index 699111f014398a2a60bc5c15e11210a6000baf16..88cb63d7d411a51ffb8c717a51142c2a9086bbbb 100644
--- a/doc/update/7.1-to-7.2.md
+++ b/doc/update/7.1-to-7.2.md
@@ -1,4 +1,5 @@
 # From 7.1 to 7.2
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/7.1-to-7.2.md) for the most up to date instructions.*
 
 ## Editable labels
 
diff --git a/doc/update/7.2-to-7.3.md b/doc/update/7.2-to-7.3.md
index ebdd4ff60fa3dc5bf0933850d1a50ebfb07228af..18f77d6396e378864b1cff46a6ead73c6ac585fd 100644
--- a/doc/update/7.2-to-7.3.md
+++ b/doc/update/7.2-to-7.3.md
@@ -1,4 +1,5 @@
 # From 7.2 to 7.3
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/7.2-to-7.3.md) for the most up to date instructions.*
 
 ### 0. Backup
 
diff --git a/doc/update/7.3-to-7.4.md b/doc/update/7.3-to-7.4.md
index 3f471500c82745b32450c085446e75ef1a24c558..53e739c06fba6e902d17aa2e07bae5e39ef2c8ce 100644
--- a/doc/update/7.3-to-7.4.md
+++ b/doc/update/7.3-to-7.4.md
@@ -1,4 +1,5 @@
 # From 7.3 to 7.4
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/7.3-to-7.4.md) for the most up to date instructions.*
 
 ### 0. Stop server
 
@@ -35,8 +36,6 @@ sudo -u git -H git checkout 7-4-stable-ee
 ### 3. Install libs, migrations, etc.
 
 ```bash
-cd /home/git/gitlab
-
 # MySQL installations (note: the line below states '--without ... postgres')
 sudo -u git -H bundle install --without development test postgres --deployment
 
@@ -70,14 +69,17 @@ git diff origin/7-3-stable:config/gitlab.yml.example origin/7-4-stable:config/gi
 sudo -u git -H editor config/unicorn.rb
 ```
 
-#### Change nginx https settings
+#### Change Nginx HTTPS settings
 
 * HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/lib/support/nginx/gitlab-ssl but with your setting
 
 #### MySQL Databases: Update database.yml config file
 
-* Add `collation: utf8_general_ci` to config/database.yml as seen in [config/database.yml.mysql](config/database.yml.mysql)
+* Add `collation: utf8_general_ci` to `config/database.yml` as seen in [config/database.yml.mysql](/config/database.yml.mysql)
 
+```
+sudo -u git -H editor config/database.yml
+```
 
 ### 5. Start application
 
@@ -116,13 +118,13 @@ mysql -u root -p
 # Convert all tables to use the InnoDB storage engine (added in GitLab 6.8)
 SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' ENGINE=InnoDB;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `ENGINE` <> 'InnoDB' AND `TABLE_TYPE` = 'BASE TABLE';
 
-# If previous query returned results, copy & run all outputed SQL statements
+# If previous query returned results, copy & run all shown SQL statements
 
 # Convert all tables to correct character set
 SET foreign_key_checks = 0;
 SELECT CONCAT('ALTER TABLE gitlabhq_production.', table_name, ' CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;') AS 'Copy & run these SQL statements:' FROM information_schema.tables WHERE table_schema = 'gitlabhq_production' AND `TABLE_COLLATION` <> 'utf8_unicode_ci' AND `TABLE_TYPE` = 'BASE TABLE';
 
-# If previous query returned results, copy & run all outputed SQL statements
+# If previous query returned results, copy & run all shown SQL statements
 
 # turn foreign key checks back on
 SET foreign_key_checks = 1;
@@ -167,6 +169,10 @@ mysql> \q
 #   Set production -> password: the password your replaced $password with earlier
 sudo -u git -H editor /home/git/gitlab/config/database.yml
 
+# Start GitLab
+sudo service gitlab start
+sudo service nginx restart
+
 # Run thorough check
 sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
 ```
diff --git a/doc/update/7.4-to-7.5.md b/doc/update/7.4-to-7.5.md
new file mode 100644
index 0000000000000000000000000000000000000000..673eab3c56ec21e025171df98f50aa850a5ffe64
--- /dev/null
+++ b/doc/update/7.4-to-7.5.md
@@ -0,0 +1,108 @@
+# From 7.4 to 7.5
+
+### 0. Stop server
+
+    sudo service gitlab stop
+
+### 1. Backup
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 2. Get latest code
+
+```bash
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+sudo -u git -H git checkout 7-5-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+sudo -u git -H git checkout 7-5-stable-ee
+```
+
+### 3. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch
+sudo -u git -H git checkout v2.2.0
+```
+
+### 4. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without ... postgres')
+sudo -u git -H bundle install --without development test postgres --deployment
+
+# PostgreSQL installations (note: the line below states '--without ... mysql')
+sudo -u git -H bundle install --without development test mysql --deployment
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+
+# Update init.d script
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+### 5. Update config files
+
+#### New configuration options for gitlab.yml
+
+There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml.
+
+```
+git diff origin/7-4-stable:config/gitlab.yml.example origin/7-5-stable:config/gitlab.yml.example
+```
+
+#### Change Nginx settings
+
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your setting
+
+### 6. Start application
+
+    sudo service gitlab start
+    sudo service nginx restart
+
+### 7. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+    sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+
+To make sure you didn't miss anything run a more thorough check with:
+
+    sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+
+If all items are green, then congratulations upgrade is complete!
+
+## Things went south? Revert to previous version (7.4)
+
+### 1. Revert the code to the previous version
+Follow the [upgrade guide from 7.3 to 7.4](7.3-to-7.4.md), except for the database migration
+(The backup is already migrated to the previous version)
+
+### 2. Restore from the backup:
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
diff --git a/doc/update/7.5-to-7.6.md b/doc/update/7.5-to-7.6.md
new file mode 100644
index 0000000000000000000000000000000000000000..35cd437fdc44dfadbbbd7e553e68e121fdebd8df
--- /dev/null
+++ b/doc/update/7.5-to-7.6.md
@@ -0,0 +1,114 @@
+# From 7.5 to 7.6
+
+### 0. Stop server
+
+    sudo service gitlab stop
+
+### 1. Backup
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 2. Get latest code
+
+```bash
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+sudo -u git -H git checkout 7-6-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+sudo -u git -H git checkout 7-6-stable-ee
+```
+
+### 3. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch
+sudo -u git -H git checkout v2.4.0
+```
+
+### 4. Install libs, migrations, etc.
+
+```bash
+sudo apt-get install libkrb5-dev
+
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without ... postgres')
+sudo -u git -H bundle install --without development test postgres --deployment
+
+# PostgreSQL installations (note: the line below states '--without ... mysql')
+sudo -u git -H bundle install --without development test mysql --deployment
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+
+# Update init.d script
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+### 5. Update config files
+
+#### New configuration options for `gitlab.yml`
+
+There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+
+```
+git diff origin/7-5-stable:config/gitlab.yml.example origin/7-6-stable:config/gitlab.yml.example
+```
+
+#### Change Nginx settings
+
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your setting
+
+#### Setup time zone (optional)
+
+Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`](config/application.rb) (unlikely), unset it.
+
+### 6. Start application
+
+    sudo service gitlab start
+    sudo service nginx restart
+
+### 7. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+    sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+
+To make sure you didn't miss anything run a more thorough check with:
+
+    sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+
+If all items are green, then congratulations upgrade is complete!
+
+## Things went south? Revert to previous version (7.5)
+
+### 1. Revert the code to the previous version
+Follow the [upgrade guide from 7.4 to 7.5](7.4-to-7.5.md), except for the database migration
+(The backup is already migrated to the previous version)
+
+### 2. Restore from the backup:
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
diff --git a/doc/update/7.6-to-7.7.md b/doc/update/7.6-to-7.7.md
new file mode 100644
index 0000000000000000000000000000000000000000..59243713156c21d828363941282ed339ca762ce9
--- /dev/null
+++ b/doc/update/7.6-to-7.7.md
@@ -0,0 +1,119 @@
+# From 7.6 to 7.7
+
+### 0. Stop server
+
+    sudo service gitlab stop
+
+### 1. Backup
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 2. Get latest code
+
+```bash
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+sudo -u git -H git checkout 7-7-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+sudo -u git -H git checkout 7-7-stable-ee
+```
+
+### 3. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch
+sudo -u git -H git checkout v2.4.2
+```
+
+### 4. Install libs, migrations, etc.
+
+```bash
+sudo apt-get install libkrb5-dev
+
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without ... postgres')
+sudo -u git -H bundle install --without development test postgres --deployment
+
+# PostgreSQL installations (note: the line below states '--without ... mysql')
+sudo -u git -H bundle install --without development test mysql --deployment
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+
+# Update init.d script
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+### 5. Update config files
+
+#### New configuration options for `gitlab.yml`
+
+There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+
+```
+git diff origin/7-6-stable:config/gitlab.yml.example origin/7-7-stable:config/gitlab.yml.example
+```
+
+#### Change Nginx settings
+
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your setting
+
+#### Setup time zone (optional)
+
+Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`](config/application.rb) (unlikely), unset it.
+
+### 6. Start application
+
+    sudo service gitlab start
+    sudo service nginx restart
+
+### 7. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+    sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+
+To make sure you didn't miss anything run a more thorough check with:
+
+    sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+
+If all items are green, then congratulations upgrade is complete!
+
+### 8. GitHub settings (if applicable)
+
+If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it 
+only contains a root URL (ex. `https://gitlab.example.com/`)
+
+## Things went south? Revert to previous version (7.6)
+
+### 1. Revert the code to the previous version
+Follow the [upgrade guide from 7.5 to 7.6](7.5-to-7.6.md), except for the database migration
+(The backup is already migrated to the previous version)
+
+### 2. Restore from the backup:
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
diff --git a/doc/update/7.7-to-7.8.md b/doc/update/7.7-to-7.8.md
new file mode 100644
index 0000000000000000000000000000000000000000..46ca163c1bbda22adce732130f2797c5ca1c53fc
--- /dev/null
+++ b/doc/update/7.7-to-7.8.md
@@ -0,0 +1,120 @@
+# From 7.7 to 7.8
+
+### 0. Stop server
+
+    sudo service gitlab stop
+
+### 1. Backup
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 2. Get latest code
+
+```bash
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+sudo -u git -H git checkout 7-8-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+sudo -u git -H git checkout 7-8-stable-ee
+```
+
+### 3. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch
+sudo -u git -H git checkout v2.5.4
+```
+
+### 4. Install libs, migrations, etc.
+
+```bash
+sudo apt-get install libkrb5-dev
+
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without ... postgres')
+sudo -u git -H bundle install --without development test postgres --deployment
+
+# PostgreSQL installations (note: the line below states '--without ... mysql')
+sudo -u git -H bundle install --without development test mysql --deployment
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+
+# Update init.d script
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+### 5. Update config files
+
+#### New configuration options for `gitlab.yml`
+
+There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+
+```
+git diff origin/7-7-stable:config/gitlab.yml.example origin/7-8-stable:config/gitlab.yml.example
+```
+
+#### Change Nginx settings
+
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings.
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your settings.
+* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
+
+#### Setup time zone (optional)
+
+Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`](config/application.rb) (unlikely), unset it.
+
+### 6. Start application
+
+    sudo service gitlab start
+    sudo service nginx restart
+
+### 7. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+    sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+
+To make sure you didn't miss anything run a more thorough check with:
+
+    sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+
+If all items are green, then congratulations upgrade is complete!
+
+### 8. GitHub settings (if applicable)
+
+If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it
+only contains a root URL (ex. `https://gitlab.example.com/`)
+
+## Things went south? Revert to previous version (7.7)
+
+### 1. Revert the code to the previous version
+Follow the [upgrade guide from 7.6 to 7.7](7.6-to-7.7.md), except for the database migration
+(The backup is already migrated to the previous version)
+
+### 2. Restore from the backup:
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
diff --git a/doc/update/7.8-to-7.9.md b/doc/update/7.8-to-7.9.md
new file mode 100644
index 0000000000000000000000000000000000000000..28fd433e1c8272246a06fdd800194d9e67852b69
--- /dev/null
+++ b/doc/update/7.8-to-7.9.md
@@ -0,0 +1,120 @@
+# From 7.8 to 7.9
+
+### 0. Stop server
+
+    sudo service gitlab stop
+
+### 1. Backup
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 2. Get latest code
+
+```bash
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+sudo -u git -H git checkout 7-9-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+sudo -u git -H git checkout 7-9-stable-ee
+```
+
+### 3. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch
+sudo -u git -H git checkout v2.6.0
+```
+
+### 4. Install libs, migrations, etc.
+
+```bash
+sudo apt-get install nodejs
+
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without ... postgres')
+sudo -u git -H bundle install --without development test postgres --deployment
+
+# PostgreSQL installations (note: the line below states '--without ... mysql')
+sudo -u git -H bundle install --without development test mysql --deployment
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+
+# Update init.d script
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+### 5. Update config files
+
+#### New configuration options for `gitlab.yml`
+
+There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+
+```
+git diff origin/7-8-stable:config/gitlab.yml.example origin/7-9-stable:config/gitlab.yml.example
+```
+
+#### Change Nginx settings
+
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings.
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your settings.
+* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
+
+#### Setup time zone (optional)
+
+Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`](config/application.rb) (unlikely), unset it.
+
+### 6. Start application
+
+    sudo service gitlab start
+    sudo service nginx restart
+
+### 7. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+    sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+
+To make sure you didn't miss anything run a more thorough check with:
+
+    sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+
+If all items are green, then congratulations upgrade is complete!
+
+### 8. GitHub settings (if applicable)
+
+If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it
+only contains a root URL (ex. `https://gitlab.example.com/`)
+
+## Things went south? Revert to previous version (7.8)
+
+### 1. Revert the code to the previous version
+Follow the [upgrade guide from 7.7 to 7.8](7.7-to-7.8.md), except for the database migration
+(The backup is already migrated to the previous version)
+
+### 2. Restore from the backup:
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
diff --git a/doc/update/README.md b/doc/update/README.md
index 30e9137d7b718451db043995f85cf2676fd83144..0472537eeb5ff9532cece6381f30b9e451363bb0 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -4,13 +4,13 @@ Depending on the installation method and your GitLab version, there are multiple
 
 - [Omnibus update guide](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md) contains the steps needed to update a GitLab [package](https://about.gitlab.com/downloads/).
 
-## Manual Installation
+## Installation from source
 
-- [The individual upgrade guides](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update) are for those who have installed GitLab manually.
+- [The individual upgrade guides](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update) are for those who have installed GitLab from source.
 - [The CE to EE update guides](https://gitlab.com/subscribers/gitlab-ee/tree/master/doc/update) are for subscribers of the Enterprise Edition only. The steps are very similar to a version upgrade: stop the server, get the code, update config files for the new functionality, install libs and do migrations, update the init script, start the application and check the application status.
-- [Upgrader](upgrader.md) is an automatic ruby script that performs the update for manual installations.
+- [Upgrader](upgrader.md) is an automatic ruby script that performs the update for installations from source.
 - [Patch versions](patch_versions.md) guide includes the steps needed for a patch version, eg. 6.2.0 to 6.2.1.
 
 ## Miscellaneous
 
-- [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating your database from MySQL to PostrgreSQL.
+- [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating your database from MySQL to PostgreSQL.
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index 695c083d3611737d4a2c8b3ddce57bcdd6989243..50941db25f6ef494c4ef2624dea2086c1ba9399e 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -1,4 +1,5 @@
 # Migrating GitLab from MySQL to Postgres
+*Make sure you view this [guide from the `master` branch](../../../master/doc/update/mysql_to_postgresql.md) for the most up to date instructions.*
 
 If you are replacing MySQL with Postgres while keeping GitLab on the same server all you need to do is to export from MySQL, import into Postgres and rebuild the indexes as described below. If you are also moving GitLab to another server, or if you are switching to omnibus-gitlab, you may want to use a GitLab backup file. The second part of this documents explains the procedure to do this.
 
@@ -11,9 +12,9 @@ sudo service gitlab stop
 
 # Update /home/git/gitlab/config/database.yml
 
-git clone https://github.com/gitlabhq/mysql-postgresql-converter.git
+git clone https://github.com/gitlabhq/mysql-postgresql-converter.git -b gitlab
 cd mysql-postgresql-converter
-mysqldump --compatible=postgresql --default-character-set=utf8 -r databasename.mysql -u root gitlabhq_production
+mysqldump --compatible=postgresql --default-character-set=utf8 -r databasename.mysql -u root gitlabhq_production -p
 python db_converter.py databasename.mysql databasename.psql
 
 # Import the database dump as the application database user
@@ -38,7 +39,7 @@ On non-omnibus installations (distributed using Git) we retrieve the index decla
 ```
 # Clone the database converter on your Postgres-backed GitLab server
 cd /tmp
-git clone https://github.com/gitlabhq/mysql-postgresql-converter.git
+git clone https://github.com/gitlabhq/mysql-postgresql-converter.git -b gitlab
 
 cd /home/git/gitlab
 
@@ -59,7 +60,7 @@ On omnibus-gitlab we need to get the index declarations from a file called `sche
 ```
 # Clone the database converter on your Postgres-backed GitLab server
 cd /tmp
-/opt/gitlab/embedded/bin/git clone https://github.com/gitlabhq/mysql-postgresql-converter.git
+/opt/gitlab/embedded/bin/git clone https://github.com/gitlabhq/mysql-postgresql-converter.git -b gitlab
 cd /tmp/mysql-postgresql-converter
 
 # Download schema.rb.bundled if necessary
@@ -75,7 +76,7 @@ test -e /opt/gitlab/embedded/service/gitlab-rails/db/schema.rb.bundled || sudo /
 ## Converting a GitLab backup file from MySQL to Postgres
 **Note:** Please make sure to have Python 2.7.x (or higher) installed.
 
-GitLab backup files (<timestamp>_gitlab_backup.tar) contain a SQL dump. Using the lanyrd database converter we can replace a MySQL database dump inside the tar file with a Postgres database dump. This can be useful if you are moving to another server.
+GitLab backup files (`<timestamp>_gitlab_backup.tar`) contain a SQL dump. Using the lanyrd database converter we can replace a MySQL database dump inside the tar file with a Postgres database dump. This can be useful if you are moving to another server.
 
 ```
 # Stop GitLab
@@ -94,10 +95,10 @@ sudo -u git -H mv tmp/backups/TIMESTAMP_gitlab_backup.tar tmp/backups/postgresql
 
 # Create a separate database dump with PostgreSQL compatibility
 cd tmp/backups/postgresql
-sudo -u git -H mysqldump --compatible=postgresql --default-character-set=utf8 -r gitlabhq_production.mysql -u root gitlabhq_production
+sudo -u git -H mysqldump --compatible=postgresql --default-character-set=utf8 -r gitlabhq_production.mysql -u root gitlabhq_production -p
 
 # Clone the database converter
-sudo -u git -H git clone https://github.com/gitlabhq/mysql-postgresql-converter.git
+sudo -u git -H git clone https://github.com/gitlabhq/mysql-postgresql-converter.git -b gitlab
 
 # Convert gitlabhq_production.mysql
 sudo -u git -H mkdir db
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index 629c46ad0308c1bddfd3821953ccfc74e0d19a57..e29ee2a7b3d295eb378fc3c2abc51a2a54047544 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -1,4 +1,5 @@
 # Universal update guide for patch versions
+*Make sure you view this [upgrade guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/patch_versions.md) from the `master` branch for the most up to date instructions.*
 
 For example from 6.2.0 to 6.2.1, also see the [semantic versioning specification](http://semver.org/).
 
diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md
index 44e18a9ed4237c626d3af8f170b4f8a43f0646dd..f62a53d3340c22a670b07e37b55fae2489190d64 100644
--- a/doc/update/upgrader.md
+++ b/doc/update/upgrader.md
@@ -1,4 +1,5 @@
 # GitLab Upgrader
+*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/upgrader.md) for the most up to date instructions.*
 
 GitLab Upgrader - a ruby script that allows you easily upgrade GitLab to latest minor version.
 
@@ -10,6 +11,8 @@ If you have local changes to your GitLab repository the script will stash them a
 
 **GitLab Upgrader is available only for GitLab version 6.4.2 or higher.**
 
+**This script does NOT update gitlab-shell, it needs manual update. See step 5 below.**
+
 ## 0. Backup
 
     cd /home/git/gitlab
@@ -21,7 +24,7 @@ If you have local changes to your GitLab repository the script will stash them a
 
 ## 2. Run GitLab upgrade tool
 
-Note: GitLab 7.2 adds `pkg-config` and `cmake` as dependency. Please check the dependencies in the [installation guide.](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
+Note: GitLab 7.9 adds `nodejs` as a dependency. GitLab 7.6 adds `libkrb5-dev` as a dependency (installed by default on Ubuntu and OSX). GitLab 7.2 adds `pkg-config` and `cmake` as dependency. Please check the dependencies in the [installation guide.](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
 
     # Starting with GitLab version 7.0 upgrader script has been moved to bin directory
     cd /home/git/gitlab
diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md
index f19517c0f18a5ab1925264ff2b72e396a4a821e7..851f50f5e9ad84061f67d28cced26bf3d28b247a 100644
--- a/doc/web_hooks/web_hooks.md
+++ b/doc/web_hooks/web_hooks.md
@@ -16,24 +16,29 @@ Triggered when you push to the repository except when pushing tags.
 
 ```json
 {
+  "object_kind": "push",
   "before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
   "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
   "ref": "refs/heads/master",
   "user_id": 4,
   "user_name": "John Smith",
+  "user_email": "john@example.com",
   "project_id": 15,
   "repository": {
     "name": "Diaspora",
-    "url": "git@example.com:diaspora.git",
+    "url": "git@example.com:mike/diasporadiaspora.git",
     "description": "",
-    "homepage": "http://example.com/diaspora"
+    "homepage": "http://example.com/mike/diaspora", 
+    "git_http_url":"http://example.com/mike/diaspora.git",
+    "git_ssh_url":"git@example.com:mike/diaspora.git",
+    "visibility_level":0
   },
   "commits": [
     {
       "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
       "message": "Update Catalan translation to e38cb41.",
       "timestamp": "2011-12-12T14:27:31+02:00",
-      "url": "http://example.com/diaspora/commits/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
+      "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
       "author": {
         "name": "Jordi Mallach",
         "email": "jordi@softcatala.org"
@@ -43,7 +48,7 @@ Triggered when you push to the repository except when pushing tags.
       "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
       "message": "fixed readme",
       "timestamp": "2012-01-03T23:36:29+02:00",
-      "url": "http://example.com/diaspora/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+      "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
       "author": {
         "name": "GitLab dev user",
         "email": "gitlabdev@dv6700.(none)"
@@ -54,6 +59,35 @@ Triggered when you push to the repository except when pushing tags.
 }
 ```
 
+## Tag events
+
+Triggered when you create (or delete) tags to the repository.
+
+**Request body:**
+
+```json
+{
+  "object_kind": "tag_push",
+  "ref": "refs/tags/v1.0.0",
+  "before": "0000000000000000000000000000000000000000",
+  "after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7",
+  "user_id": 1,
+  "user_name": "John Smith",
+  "project_id": 1,
+  "repository": {
+    "name": "jsmith",
+    "url": "ssh://git@example.com/jsmith/example.git",
+    "description": "",
+    "homepage": "http://example.com/jsmith/example",
+    "git_http_url":"http://example.com/jsmith/example.git",
+    "git_ssh_url":"git@example.com:jsmith/example.git",
+    "visibility_level":0
+  },
+  "commits": [],
+  "total_commits_count": 0
+}
+```
+
 ## Issues events
 
 Triggered when a new issue is created or an existing issue was updated/closed/reopened.
@@ -143,7 +177,9 @@ Triggered when a new merge request is created or an existing merge request was u
         "name": "GitLab dev user",
         "email": "gitlabdev@dv6700.(none)"
       }
-    }
+    },
+    "url": "http://example.com/diaspora/merge_requests/1",
+    "action": "open"
   }
 }
 ```
diff --git a/doc/workflow/README.md b/doc/workflow/README.md
index c26d85e99552cc56041d68e6bdc86326f484fcfd..6e70235f5b88c429075bb660ea62a97381cfceda 100644
--- a/doc/workflow/README.md
+++ b/doc/workflow/README.md
@@ -1,4 +1,6 @@
-- [Workflow](workflow.md)
+# Workflow
+
+- [Feature branch workflow](workflow.md)
 - [Project Features](project_features.md)
 - [Authorization for merge requests](authorization_for_merge_requests.md)
 - [Groups](groups.md)
@@ -6,3 +8,7 @@
 - [GitLab Flow](gitlab_flow.md)
 - [Notifications](notifications.md)
 - [Migrating from SVN to GitLab](migrating_from_svn.md)
+- [Project importing from GitHub to GitLab](import_projects_from_github.md)
+- [Project importing from GitLab.com to your private GitLab instance](import_projects_from_gitlab_com.md)
+- [Protected branches](protected_branches.md)
+- [Web Editor](web_editor.md)
diff --git a/doc/workflow/github_importer/importer.png b/doc/workflow/github_importer/importer.png
new file mode 100644
index 0000000000000000000000000000000000000000..57636717571a17ea17ee5cfdabbd4408597fd668
Binary files /dev/null and b/doc/workflow/github_importer/importer.png differ
diff --git a/doc/workflow/github_importer/new_project_page.png b/doc/workflow/github_importer/new_project_page.png
new file mode 100644
index 0000000000000000000000000000000000000000..002f22d81d7d07eeece0deaec177b0dbc70745f6
Binary files /dev/null and b/doc/workflow/github_importer/new_project_page.png differ
diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md
index f8fd7c97e2a9b8921c1eb46316eabef4b066c407..0e87dc74217d40e9df803c1b9b4988c12405f341 100644
--- a/doc/workflow/gitlab_flow.md
+++ b/doc/workflow/gitlab_flow.md
@@ -1,6 +1,6 @@
 ![GitLab Flow](gitlab_flow.png)
 
-# Introduction
+## Introduction
 
 Version management with git makes branching and merging much easier than older versioning systems such as SVN.
 This allows a wide variety of branching strategies and workflows.
@@ -29,9 +29,9 @@ People have a hard time figuring out which branch they should develop on or depl
 Frequently the reaction to this problem is to adopt a standardized pattern such as [git flow](http://nvie.com/posts/a-successful-git-branching-model/) and [GitHub flow](http://scottchacon.com/2011/08/31/github-flow.html)
 We think there is still room for improvement and will detail a set of practices we call GitLab flow.
 
-# Git flow and its problems
+## Git flow and its problems
 
-[![Git Flow timeline by Vincent Driessen, used with persmission](gitdashflow.png)
+[![Git Flow timeline by Vincent Driessen, used with permission](gitdashflow.png)
 
 Git flow was one of the first proposals to use git branches and it has gotten a lot of attention.
 It advocates a master branch and a separate develop branch as well as supporting branches for features, releases and hotfixes.
@@ -43,14 +43,14 @@ Since most tools automatically make the master branch the default one and displa
 The second problem of git flow is the complexity introduced by the hotfix and release branches.
 These branches can be a good idea for some organizations but are overkill for the vast majority of them.
 Nowadays most organizations practice continuous delivery which means that your default branch can be deployed.
-This means that hotfixed and release branches can be prevented including all the ceremony they introduce.
+This means that hotfix and release branches can be prevented including all the ceremony they introduce.
 An example of this ceremony is the merging back of release branches.
 Though specialized tools do exist to solve this, they require documentation and add complexity.
 Frequently developers make a mistake and for example changes are only merged into master and not into the develop branch.
 The root cause of these errors is that git flow is too complex for most of the use cases.
 And doing releases doesn't automatically mean also doing hotfixes.
 
-# GitHub flow as a simpler alternative
+## GitHub flow as a simpler alternative
 
 ![Master branch with feature branches merged in](github_flow.png)
 
@@ -62,13 +62,13 @@ Merging everything into the master branch and deploying often means you minimize
 But this flow still leaves a lot of questions unanswered regarding deployments, environments, releases and integrations with issues.
 With GitLab flow we offer additional guidance for these questions.
 
-# Production branch with GitLab flow
+## Production branch with GitLab flow
 
 ![Master branch and production branch with arrow that indicate deployments](production_branch.png)
 
 GitHub flow does assume you are able to deploy to production every time you merge a feature branch.
 This is possible for SaaS applications but are many cases where this is not possible.
-One would be a situation where you are not in control of the exact release moment, for example an iOS application that needs to pass AppStore validation.
+One would be a situation where you are not in control of the exact release moment, for example an iOS application that needs to pass App Store validation.
 Another example is when you have deployment windows (workdays from 10am to 4pm when the operations team is at full capacity) but you also merge code at other times.
 In these cases you can make a production branch that reflects the deployed code.
 You can deploy a new version by merging in master to the production branch.
@@ -78,7 +78,7 @@ This time is pretty accurate if you automatically deploy your production branch.
 If you need a more exact time you can have your deployment script create a tag on each deployment.
 This flow prevents the overhead of releasing, tagging and merging that is common to git flow.
 
-# Environment branches with GitLab flow
+## Environment branches with GitLab flow
 
 ![Multiple branches with the code cascading from one to another](environment_branches.png)
 
@@ -93,14 +93,14 @@ If master is good to go (it should be if you a practicing [continuous delivery](
 If this is not possible because more manual testing is required you can send merge requests from the feature branch to the downstream branches.
 An 'extreme' version of environment branches are setting up an environment for each feature branch as done by [Teatro](http://teatro.io/).
 
-# 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.
 In this case, each branch contains a minor version (2-3-stable, 2-4-stable, etc.).
 The stable branch uses master as a starting point and is created as late as possible.
-By branching as late as possible you minimize the time you have to apply bugfixes to multiple branches.
+By branching as late as possible you minimize the time you have to apply bug fixes to multiple branches.
 After a release branch is announced, only serious bug fixes are included in the release branch.
 If possible these bug fixes are first merged into master and then cherry-picked into the release branch.
 This way you can't forget to cherry-pick them into master and encounter the same bug on subsequent releases.
@@ -109,7 +109,7 @@ Every time a bug-fix is included in a release branch the patch version is raised
 Some projects also have a stable branch that points to the same commit as the latest released branch.
 In this flow it is not common to have a production branch (or git flow master branch).
 
-# Merge/pull requests with GitLab flow
+## Merge/pull requests with GitLab flow
 
 ![Merge request with line comments](mr_inline_comments.png)
 
@@ -134,7 +134,7 @@ If the assigned person does not feel comfortable they can close the merge reques
 In GitLab it is common to protect the long-lived branches (e.g. the master branch) so that normal developers [can't modify these protected branches](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/permissions/permissions.md).
 So if you want to merge it into a protected branch you assign it to someone with master authorizations.
 
-# Issues with GitLab flow
+## Issues with GitLab flow
 
 ![Merge request with the branch name 15-require-a-password-to-change-it and assignee field shown](merge_request.png)
 
@@ -168,7 +168,7 @@ In this case it is no problem to reuse the same branch name since it was deleted
 At any time there is at most one branch for every issue.
 It is possible that one feature branch solves more than one issue.
 
-# Linking and closing issues from merge requests
+## Linking and closing issues from merge requests
 
 ![Merge request showing the linked issues that will be closed](close_issue_mr.png)
 
@@ -177,11 +177,11 @@ In GitLab this creates a comment in the issue that the merge requests mentions t
 And the merge request shows the linked issues.
 These issues are closed once code is merged into the default branch.
 
-If you only want to make the reference without closing the issue you can also just mention it: "Ducktyping is preferred. #12".
+If you only want to make the reference without closing the issue you can also just mention it: "Duck typing is preferred. #12".
 
 If you have an issue that spans across multiple repositories, the best thing is to create an issue for each repository and link all issues to a parent issue.
 
-# Squashing commits with rebase
+## Squashing commits with rebase
 
 ![Vim screen showing the rebase view](rebase.png)
 
@@ -189,7 +189,7 @@ With git you can use an interactive rebase (rebase -i) to squash multiple commit
 This functionality is useful if you made a couple of commits for small changes during development and want to replace them with a single commit or if you want to make the order more logical.
 However you should never rebase commits you have pushed to a remote server.
 Somebody can have referred to the commits or cherry-picked them.
-When you rebase you change the identifier (SHA1) of the commit and this is confusing.
+When you rebase you change the identifier (SHA-1) of the commit and this is confusing.
 If you do that the same change will be known under multiple identifiers and this can cause much confusion.
 If people already reviewed your code it will be hard for them to review only the improvements you made since then if you have rebased everything into one commit.
 
@@ -207,7 +207,7 @@ If you revert a merge and you change your mind, revert the revert instead of mer
 Being able to revert a merge is a good reason always to create a merge commit when you merge manually with the `--no-ff` option.
 Git management software will always create a merge commit when you accept a merge request.
 
-# Do not order commits with rebase
+## Do not order commits with rebase
 
 ![List of sequential merge commits](merge_commits.png)
 
@@ -231,8 +231,8 @@ The last reason for creating merge commits is having long lived branches that yo
 Martin Fowler, in [his article about feature branches](http://martinfowler.com/bliki/FeatureBranch.html) talks about this Continuous Integration (CI).
 At GitLab we are guilty of confusing CI with branch testing. Quoting Martin Fowler: "I've heard people say they are doing CI because they are running builds, perhaps using a CI server, on every branch with every commit.
 That's continuous building, and a Good Thing, but there's no integration, so it's not CI.".
-The solution to prevent many merge commits is to keep your feature branches shortlived, the vast majority should take less than one day of work.
-If your feature branches commenly take more than a day of work, look into ways to create smaller units of work and/or use [feature toggles](http://martinfowler.com/bliki/FeatureToggle.html).
+The solution to prevent many merge commits is to keep your feature branches short-lived, the vast majority should take less than one day of work.
+If your feature branches commonly take more than a day of work, look into ways to create smaller units of work and/or use [feature toggles](http://martinfowler.com/bliki/FeatureToggle.html).
 As for the long running branches that take more than one day there are two strategies.
 In a CI strategy you can merge in master at the start of the day to prevent painful merges at a later time.
 In a synchronization point strategy you only merge in from well defined points in time, for example a tagged release.
@@ -244,7 +244,7 @@ Developing software happen in small messy steps and it is OK to have your histor
 You can use tools to view the network graphs of commits and understand the messy history that created your code.
 If you rebase code the history is incorrect, and there is no way for tools to remedy this because they can't deal with changing commit identifiers.
 
-# Voting on merge requests
+## Voting on merge requests
 
 ![Voting slider in GitLab](voting_slider.png)
 
@@ -252,7 +252,7 @@ It is common to voice approval or disapproval by using +1 or -1 emoticons.
 In GitLab the +1 and -1 are aggregated and shown at the top of the merge request.
 As a rule of thumb anything that doesn't have two times more +1's than -1's is suspect and should not be merged yet.
 
-# Pushing and removing branches
+## Pushing and removing branches
 
 ![Remove checkbox for branch in merge requests](remove_checkbox.png)
 
@@ -266,7 +266,7 @@ This ensures that the branch overview in the repository management software show
 This also ensures that when someone reopens the issue a new branch with the same name can be used without problem.
 When you reopen an issue you need to create a new merge request.
 
-# Committing often and with the right message
+## Committing often and with the right message
 
 ![Good and bad commit message](good_commit.png)
 
@@ -282,7 +282,7 @@ Some words that are bad commit messages because they don't contain munch informa
 The word fix or fixes is also a red flag, unless it comes after the commit sentence and references an issue number.
 To see more information about the formatting of commit messages please see this great [blog post by Tim Pope](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
 
-# Testing before merging
+## Testing before merging
 
 ![Merge requests showing the test states, red, yellow and green](ci_mr.png)
 
@@ -299,7 +299,7 @@ If there are no merge conflicts and the feature branches are short lived the ris
 If there are merge conflicts you merge the master branch into the feature branch and the CI server will rerun the tests.
 If you have long lived feature branches that last for more than a few days you should make your issues smaller.
 
-# Merging in other code
+## Merging in other code
 
 ![Shell output showing git pull output](git_pull.png)
 
diff --git a/doc/workflow/gitlab_importer/importer.png b/doc/workflow/gitlab_importer/importer.png
new file mode 100644
index 0000000000000000000000000000000000000000..d2a286d8cac32caf6594537b6842ebdcfaedee58
Binary files /dev/null and b/doc/workflow/gitlab_importer/importer.png differ
diff --git a/doc/workflow/gitlab_importer/new_project_page.png b/doc/workflow/gitlab_importer/new_project_page.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e239208e1e73ec80d5ff16eced9ea371b721df2
Binary files /dev/null and b/doc/workflow/gitlab_importer/new_project_page.png differ
diff --git a/doc/workflow/import_projects_from_github.md b/doc/workflow/import_projects_from_github.md
new file mode 100644
index 0000000000000000000000000000000000000000..8644b4ffc73c23cb356fdee969de9aceef8dac91
--- /dev/null
+++ b/doc/workflow/import_projects_from_github.md
@@ -0,0 +1,13 @@
+# Project importing from GitHub to GitLab
+
+You can import your existing GitHub projects to GitLab. But keep in mind that it is possible only if
+GitHub support is enabled on your GitLab instance. You can read more about GitHub support [here](http://doc.gitlab.com/ce/integration/github.html)
+To get to the importer page you need to go to "New project" page.
+
+![New project page](github_importer/new_project_page.png) 
+
+Click on the "Import project from GitHub" link and you will be redirected to GitHub for permission to access your projects. After accepting, you'll be automatically redirected to the importer.
+
+![Importer page](github_importer/importer.png)
+
+To import a project, you can simple click "Add". The importer will import your repository and issues. Once the importer is done, a new GitLab project will be created with your imported data.
\ No newline at end of file
diff --git a/doc/workflow/import_projects_from_gitlab_com.md b/doc/workflow/import_projects_from_gitlab_com.md
new file mode 100644
index 0000000000000000000000000000000000000000..f4c4e955d46982c9d54291deb9c3902ba4ff6c4a
--- /dev/null
+++ b/doc/workflow/import_projects_from_gitlab_com.md
@@ -0,0 +1,18 @@
+# Project importing from GitLab.com to your private GitLab instance
+
+You can import your existing GitLab.com projects to your GitLab instance. But keep in mind that it is possible only if
+GitLab support is enabled on your GitLab instance. 
+You can read more about Gitlab support [here](http://doc.gitlab.com/ce/integration/gitlab.html)
+To get to the importer page you need to go to "New project" page.
+
+![New project page](gitlab_importer/new_project_page.png)
+
+Click on the "Import projects from Gitlab.com" link and you will be redirected to GitLab.com 
+for permission to access your projects. After accepting, you'll be automatically redirected to the importer.
+
+
+![Importer page](gitlab_importer/importer.png)
+
+
+To import a project, you can simple click "Import". The importer will import your repository and issues. 
+Once the importer is done, a new GitLab project will be created with your imported data.
\ No newline at end of file
diff --git a/doc/workflow/migrating_from_svn.md b/doc/workflow/migrating_from_svn.md
index 207e36418024dfb0b939cd15077696ea5152017f..485db4834e97c635d546cbfeb02c14e893051cfd 100644
--- a/doc/workflow/migrating_from_svn.md
+++ b/doc/workflow/migrating_from_svn.md
@@ -3,7 +3,7 @@
 SVN stands for Subversion and is a version control system (VCS).
 Git is a distributed version control system.
 
-There are some major differences between the two, for more information consult your favourite search engine.
+There are some major differences between the two, for more information consult your favorite search engine.
 
 Git has tools for migrating SVN repositories to git, namely `git svn`. You can read more about this at
 [git documentation pages](http://git-scm.com/book/en/Git-and-Other-Systems-Git-and-Subversion).
diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md
index 3c3ce162df5c27567e529e7c48f5f4ff651acce9..17215de677e153d2aedfae3f91f7f51b0a57f2f1 100644
--- a/doc/workflow/notifications.md
+++ b/doc/workflow/notifications.md
@@ -24,14 +24,14 @@ Each of these settings have levels of notification:
 #### Global Settings
 
 Global Settings are at the bottom of the hierarchy.
-Any setting set here will be overriden by a setting at the group or a project level.
+Any setting set here will be overridden by a setting at the group or a project level.
 
 Group or Project settings can use `global` notification setting which will then use
 anything that is set at Global Settings.
 
 #### Group Settings
 
-Group Settings are taking presedence over Global Settings but are on a level below Project Settings.
+Group Settings are taking precedence over Global Settings but are on a level below Project Settings.
 This means that you can set a different level of notifications per group while still being able
 to have a finer level setting per project.
 Organization like this is suitable for users that belong to different groups but don't have the
@@ -39,7 +39,7 @@ same need for being notified for every group they are member of.
 
 #### Project Settings
 
-Project Settings are at the top level and any setting placed at this level will take presedence of any
+Project Settings are at the top level and any setting placed at this level will take precedence of any
 other setting.
 This is suitable for users that have different needs for notifications per project basis.
 
diff --git a/doc/workflow/protected_branches.md b/doc/workflow/protected_branches.md
new file mode 100644
index 0000000000000000000000000000000000000000..805f7f8d35c46e130836174c48b10770cadf0cb8
--- /dev/null
+++ b/doc/workflow/protected_branches.md
@@ -0,0 +1,33 @@
+# Protected branches
+
+Permission in GitLab are fundamentally defined around the idea of having read or write permission to the repository and branches.
+
+To prevent people from messing with history or pushing code without review, we've created protected branches.
+
+A protected branch does three simple things:
+
+* it prevents pushes from everybody except users with Master permission
+* it prevents anyone from force pushing to the branch
+* it prevents anyone from deleting the branch
+
+You can make any branch a protected branch. GitLab makes the master branch a protected branch by default.
+
+To protect a branch, user needs to have at least a Master permission level, see [permissions document](permissions/permissions.md).
+
+![protected branches page](protected_branches/protected_branches1.png)
+
+Navigate to project settings page and select `protected branches`. From the `Branch` dropdown menu select the branch you want to protect.
+
+Some workflows, like [GitLab workflow](gitlab_flow.md), require all users with write access to submit a Merge request in order to get the code into a protected branch.
+
+Since Masters and Owners can already push to protected branches, that means Developers cannot push to protected branch and need to submit a Merge request.
+
+However, there are workflows where that is not needed and only protecting from force pushes and branch removal is useful.
+
+For those workflows, you can allow everyone with write access to push to a protected branch by selecting `Developers can push` check box.
+
+On already protected branches you can also allow developers to push to the repository by selecting the `Developers can push` check box.
+
+![Developers can push](protected_branches/protected_branches2.png)
+
+
diff --git a/doc/workflow/protected_branches/protected_branches1.png b/doc/workflow/protected_branches/protected_branches1.png
new file mode 100644
index 0000000000000000000000000000000000000000..5c2a3de5f7043225788bb65cf35652525a0bb357
Binary files /dev/null and b/doc/workflow/protected_branches/protected_branches1.png differ
diff --git a/doc/workflow/protected_branches/protected_branches2.png b/doc/workflow/protected_branches/protected_branches2.png
new file mode 100644
index 0000000000000000000000000000000000000000..2dca35413655a79768911db229db1462e5397018
Binary files /dev/null and b/doc/workflow/protected_branches/protected_branches2.png differ
diff --git a/doc/workflow/web_editor.md b/doc/workflow/web_editor.md
new file mode 100644
index 0000000000000000000000000000000000000000..7fc8f96b9ec6ab1af2bbee1b2e26f8e79d604c05
--- /dev/null
+++ b/doc/workflow/web_editor.md
@@ -0,0 +1,26 @@
+# GitLab Web Editor
+
+In GitLab you can create new files and edit existing files using our web editor.
+This is especially useful if you don't have access to a command line or you just want to do a quick fix.
+You can easily access the web editor, depending on the context.
+Let's start from newly created project.
+
+Click on `Add a file`
+to create the first file and open it in the web editor.
+
+![web editor 1](web_editor/empty_project.png)
+
+Fill in a file name, some content, a commit message, branch name 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. Also you can save your change to another branch by filling out field `branch`
+
+![web editor 3](web_editor/edit_file.png)
diff --git a/doc/workflow/web_editor/edit_file.png b/doc/workflow/web_editor/edit_file.png
new file mode 100644
index 0000000000000000000000000000000000000000..f480c69ac3eafbbfd85b30ca0b1324d824f89409
Binary files /dev/null and b/doc/workflow/web_editor/edit_file.png differ
diff --git a/doc/workflow/web_editor/empty_project.png b/doc/workflow/web_editor/empty_project.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a049f6beafbb1f449e43baa5925b10d31410cad
Binary files /dev/null and b/doc/workflow/web_editor/empty_project.png differ
diff --git a/doc/workflow/web_editor/new_file.png b/doc/workflow/web_editor/new_file.png
new file mode 100644
index 0000000000000000000000000000000000000000..55ebd9e025720ed108f16d5b6d61926701510c10
Binary files /dev/null and b/doc/workflow/web_editor/new_file.png differ
diff --git a/doc/workflow/web_editor/show_file.png b/doc/workflow/web_editor/show_file.png
new file mode 100644
index 0000000000000000000000000000000000000000..9cafcb551091a8959671dbedc113062ddbd7da7e
Binary files /dev/null and b/doc/workflow/web_editor/show_file.png differ
diff --git a/doc/workflow/workflow.md b/doc/workflow/workflow.md
index ab29cfb670b4ae847389acd4f7e38bb459b6c309..f70e41df842faf1ae0c4b64d0fb3c2be92ce5ac2 100644
--- a/doc/workflow/workflow.md
+++ b/doc/workflow/workflow.md
@@ -1,4 +1,4 @@
-# Workflow
+# Feature branch workflow
 
 1.  Clone project:
 
diff --git a/docker/.dockerignore b/docker/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..dd449725e188f816bcebfc05678064efcbc29a81
--- /dev/null
+++ b/docker/.dockerignore
@@ -0,0 +1 @@
+*.md
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..f0a8b9f53dfabe2428de57a161e04800754fafee
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,33 @@
+FROM ubuntu:14.04
+
+# Install required packages
+RUN apt-get update -q \
+    && DEBIAN_FRONTEND=noninteractive apt-get install -qy --no-install-recommends \
+      ca-certificates \
+      openssh-server \
+      wget
+
+# Download & Install GitLab
+# If the Omnibus package version below is outdated please contribute a merge request to update it.
+# If you run GitLab Enterprise Edition point it to a location where you have downloaded it.
+RUN TMP_FILE=$(mktemp); \
+    wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.9.1-omnibus.1-1_amd64.deb \
+    && dpkg -i $TMP_FILE \
+    && rm -f $TMP_FILE
+
+# Manage SSHD through runit
+RUN mkdir -p /opt/gitlab/sv/sshd/supervise \
+    && mkfifo /opt/gitlab/sv/sshd/supervise/ok \
+    && printf "#!/bin/sh\nexec 2>&1\numask 077\nexec /usr/sbin/sshd -D" > /opt/gitlab/sv/sshd/run \
+    && chmod a+x /opt/gitlab/sv/sshd/run \
+    && ln -s /opt/gitlab/sv/sshd /opt/gitlab/service \
+    && mkdir -p /var/run/sshd
+
+# Expose web & ssh
+EXPOSE 80 22
+
+# Copy assets
+COPY assets/wrapper /usr/local/bin/
+
+# Wrapper to handle signal, trigger runit and reconfigure GitLab
+CMD ["/usr/local/bin/wrapper"]
diff --git a/docker/README.md b/docker/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b7e8b0db7e75ba61872a1496e95e28250f1a54d7
--- /dev/null
+++ b/docker/README.md
@@ -0,0 +1,88 @@
+What is GitLab?
+===============
+
+GitLab offers git repository management, code reviews, issue tracking, activity feeds, wikis. It has LDAP/AD integration, handles 25,000 users on a single server but can also run on a highly available active/active cluster. A subscription gives you access to our support team and to GitLab Enterprise Edition that contains extra features aimed at larger organizations.
+
+<https://about.gitlab.com>
+
+![GitLab Logo](https://gitlab.com/uploads/appearance/logo/1/brand_logo-c37eb221b456bb4b472cc1084480991f.png)
+
+
+How to use these images
+======================
+
+At this moment GitLab doesn't have official Docker images. For convinience we will use suffix _xy where xy is current version of GitLab.
+Build your own based on the Omnibus packages with the following commands (it assumes you're in the GitLab repo root directory):
+
+```bash
+sudo docker build --tag gitlab_data_image docker/data/
+sudo docker build --tag gitlab_app_image_xy docker/
+```
+
+We assume using a data volume container, this will simplify migrations and backups.
+This empty container will exist to persist as volumes the 3 directories used by GitLab, so remember not to delete it.
+
+The directories on data container are:
+
+- `/var/opt/gitlab` for application data
+- `/var/log/gitlab` for logs
+- `/etc/gitlab` for configuration
+
+Create the data container with:
+
+```bash
+sudo docker run --name gitlab_data gitlab_data_image /bin/true
+```
+
+After creating data container run GitLab container:
+
+```bash
+sudo docker run --detach --name gitlab_app_xy --publish 8080:80 --publish 2222:22 --volumes-from gitlab_data gitlab_app_image_xy
+```
+
+It might take a while before the docker container is responding to queries. You can follow the configuration process with `sudo docker logs -f gitlab_app_xy`.
+
+You can then go to `http://localhost:8080/` (or `http://192.168.59.103:8080/` if you use boot2docker).
+You can login with username `root` and password `5iveL!fe`.
+Next time, you can just use `sudo docker start gitlab_app` and `sudo docker stop gitlab_app`.
+
+
+How to configure GitLab
+========================
+
+This container uses the official Omnibus GitLab distribution, so all configuration is done in the unique configuration file `/etc/gitlab/gitlab.rb`.
+
+To access GitLab configuration, you can start an interactive command line in a new container using the shared data volume container, you will be able to browse the 3 directories and use your favorite text editor:
+
+```bash
+sudo docker run -ti -e TERM=linux --rm --volumes-from gitlab_data ubuntu 
+vi /etc/gitlab/gitlab.rb
+```
+
+**Note** that GitLab will reconfigure itself **at each container start.** You will need to restart the container to reconfigure your GitLab.
+
+You can find all available options in [Omnibus GitLab documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#configuration).
+
+How to upgrade GitLab
+========================
+
+To updgrade GitLab to new versions, stop running container, create new docker image and container from that image.
+
+It Assumes that you're upgrading from 7.8 to 7.9 and you're in the updated GitLab repo root directory:
+
+```bash
+sudo docker stop gitlab_app_78
+sudo docker build --tag gitlab_app_image_79 docker/
+sudo docker run --detach --name gitlab_app_79 --publish 8080:80 --publish 2222:22 --volumes-from gitlab_data gitlab_app_image_79
+```
+
+On the first run GitLab will reconfigure and update itself. If everything runs OK don't forget to cleanup old container and image:
+
+```bash
+sudo docker rm gitlab_app_78
+sudo docker rmi gitlab_app_image_78
+```
+
+Troubleshooting
+=========================
+Please see the [troubleshooting](troubleshooting.md) file in this directory.
diff --git a/docker/assets/wrapper b/docker/assets/wrapper
new file mode 100755
index 0000000000000000000000000000000000000000..9e6e7a05903021813c6c629df7864dc7ca63531c
--- /dev/null
+++ b/docker/assets/wrapper
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+function sigterm_handler() {
+    echo "SIGTERM signal received, try to gracefully shutdown all services..."
+    gitlab-ctl stop
+}
+
+trap "sigterm_handler; exit" TERM
+
+function entrypoint() {
+    # Default is to run runit and reconfigure GitLab
+    gitlab-ctl reconfigure &
+    /opt/gitlab/embedded/bin/runsvdir-start &
+    wait
+}
+
+entrypoint
diff --git a/docker/data/Dockerfile b/docker/data/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..ea0175c4aa2a6fabc335eee3566ff5521f444f08
--- /dev/null
+++ b/docker/data/Dockerfile
@@ -0,0 +1,8 @@
+FROM busybox
+
+# Declare volumes
+VOLUME ["/var/opt/gitlab", "/var/log/gitlab", "/etc/gitlab"]
+# Copy assets
+COPY assets/gitlab.rb /etc/gitlab/
+
+CMD /bin/sh
diff --git a/docker/data/assets/gitlab.rb b/docker/data/assets/gitlab.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7fddf309c01e6bb8420386bfe2db485ba24990d0
--- /dev/null
+++ b/docker/data/assets/gitlab.rb
@@ -0,0 +1,37 @@
+# External URL should be your Docker instance.
+# By default, this example is the "standard" boot2docker IP.
+# Always use port 80 here to force the internal nginx to bind port 80,
+# even if you intend to use another port in Docker.
+external_url "http://192.168.59.103/"
+
+# Prevent Postgres from trying to allocate 25% of total memory
+postgresql['shared_buffers'] = '1MB'
+
+# Configure GitLab to redirect PostgreSQL logs to the data volume
+postgresql['log_directory'] = '/var/log/gitlab/postgresql'
+
+# Some configuration of GitLab
+# You can find more at https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#configuration
+gitlab_rails['gitlab_email_from'] = 'gitlab@example.com'
+gitlab_rails['gitlab_support_email'] = 'support@example.com'
+gitlab_rails['time_zone'] = 'Europe/Paris'
+
+# SMTP settings
+# You must use an external server, the Docker container does not install an SMTP server
+gitlab_rails['smtp_enable'] = true
+gitlab_rails['smtp_address'] = "smtp.example.com"
+gitlab_rails['smtp_port'] = 587
+gitlab_rails['smtp_user_name'] = "user"
+gitlab_rails['smtp_password'] = "password"
+gitlab_rails['smtp_domain'] = "example.com"
+gitlab_rails['smtp_authentication'] = "plain"
+gitlab_rails['smtp_enable_starttls_auto'] = true
+
+# Enable LDAP authentication
+# gitlab_rails['ldap_enabled'] = true
+# gitlab_rails['ldap_host'] = 'ldap.example.com'
+# gitlab_rails['ldap_port'] = 389
+# gitlab_rails['ldap_method'] = 'plain' # 'ssl' or 'plain'
+# gitlab_rails['ldap_allow_username_or_email_login'] = false
+# gitlab_rails['ldap_uid'] = 'uid'
+# gitlab_rails['ldap_base'] = 'ou=users,dc=example,dc=com'
diff --git a/docker/troubleshooting.md b/docker/troubleshooting.md
new file mode 100644
index 0000000000000000000000000000000000000000..b1b70de5997aff463cdd8595f9e83d165d0739ca
--- /dev/null
+++ b/docker/troubleshooting.md
@@ -0,0 +1,63 @@
+# Troubleshooting
+
+This is to troubleshoot https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/245
+But it might contain useful commands for other cases as well.
+
+The configuration to add the postgres log in vim is:
+postgresql['log_directory'] = '/var/log/gitlab/postgresql'
+
+# Commands
+
+```bash
+sudo docker build --tag gitlab_image docker/
+
+sudo docker rm -f gitlab_app
+sudo docker rm -f gitlab_data
+
+sudo docker run --name gitlab_data gitlab_image /bin/true
+
+sudo docker run -ti --rm --volumes-from gitlab_data ubuntu apt-get update && sudo apt-get install -y vim && sudo vim /etc/gitlab/gitlab.rb
+
+sudo docker run --detach --name gitlab_app --publish 8080:80 --publish 2222:22 --volumes-from gitlab_data gitlab_image
+
+sudo docker run -t --rm --volumes-from gitlab_data ubuntu tail -f /var/log/gitlab/reconfigure.log
+
+sudo docker run -t --rm --volumes-from gitlab_data ubuntu tail -f /var/log/gitlab/postgresql/current
+
+sudo docker run -t --rm --volumes-from gitlab_data ubuntu cat /var/opt/gitlab/postgresql/data/postgresql.conf | grep shared_buffers
+
+sudo docker run -t --rm --volumes-from gitlab_data ubuntu cat /etc/gitlab/gitlab.rb
+```
+
+# Interactively
+
+```bash
+# First start a GitLab container without starting GitLab
+# This is almost the same as starting the GitLab container except:
+# - we run interactively (-t -i)
+# - we define TERM=linux because it allows to use arrow keys in vi (!!!)
+# - we choose another startup command (bash)
+sudo docker run -ti -e TERM=linux --name gitlab_app --publish 8080:80 --publish 2222:22 --volumes-from gitlab_data gitlab_image bash
+
+# Configure GitLab to redirect PostgreSQL logs
+echo "postgresql['log_directory'] = '/var/log/gitlab/postgresql'" >> /etc/gitlab/gitlab.rb
+
+# Prevent Postgres from allocating 25% of total memory
+echo "postgresql['shared_buffers'] = '1MB'" >> /etc/gitlab/gitlab.rb
+
+# You can now start GitLab manually from Bash (in the background)
+# Maybe the command below is still missing something to run in the background
+gitlab-ctl reconfigure > /var/log/gitlab/reconfigure.log & /opt/gitlab/embedded/bin/runsvdir-start &
+
+# Inspect PostgreSQL config
+cat /var/opt/gitlab/postgresql/data/postgresql.conf | grep shared_buffers
+
+# And tail the logs (PostgreSQL log may not exist immediately)
+tail -f /var/log/gitlab/reconfigure.log /var/log/gitlab/postgresql/current
+
+# And get the memory
+cat /proc/meminfo
+head /proc/sys/kernel/shmmax /proc/sys/kernel/shmall
+free -m
+
+```
diff --git a/features/admin/applications.feature b/features/admin/applications.feature
new file mode 100644
index 0000000000000000000000000000000000000000..2a00e1666c01239e7c44dc1bd40e2a0344124955
--- /dev/null
+++ b/features/admin/applications.feature
@@ -0,0 +1,18 @@
+@admin
+Feature: Admin Applications
+  Background:
+    Given I sign in as an admin
+    And I visit applications page
+    
+  Scenario: I can manage application
+    Then I click on new application button
+    And I should see application form
+    Then I fill application form out and submit
+    And I see application
+    Then I click edit
+    And I see edit application form
+    Then I change name of application and submit
+    And I see that application was changed
+    Then I visit applications page
+    And I click to remove application
+    Then I see that application is removed
\ No newline at end of file
diff --git a/features/admin/settings.feature b/features/admin/settings.feature
new file mode 100644
index 0000000000000000000000000000000000000000..52e47307b23494f57c351161b0730a0b29de68e3
--- /dev/null
+++ b/features/admin/settings.feature
@@ -0,0 +1,16 @@
+@admin
+Feature: Admin Settings
+  Background:
+    Given I sign in as an admin
+    And I visit admin settings page
+
+  Scenario: Change application settings
+    When I modify settings and save form
+    Then I should see application settings saved
+
+  Scenario: Change Slack Service Template settings
+    When I click on "Service Templates"
+    And I click on "Slack" service
+    Then I check all events and submit form
+    And I should see service template settings saved
+    And I should see all checkboxes checked
diff --git a/features/admin/users.feature b/features/admin/users.feature
index 278f6a43e942d19cf194ef93bdd50fe1c0b7ae46..1a8720dd77edfb081a99badfc4b3e047e6baa19e 100644
--- a/features/admin/users.feature
+++ b/features/admin/users.feature
@@ -35,3 +35,13 @@ Feature: Admin Users
     And I see the secondary email
     When I click remove secondary email
     Then I should not see secondary email anymore
+
+  Scenario: Show user keys
+    Given user "Pete" with ssh keys
+    And I visit admin users page
+    And click on user "Pete"
+    Then I should see key list
+    And I click on the key title
+    Then I should see key details
+    And I click on remove key
+    Then I should see the key removed
diff --git a/features/dashboard/archived_projects.feature b/features/dashboard/archived_projects.feature
index 3af93bc373c50e346457734f2815dffbbb14cab4..69b3a7764419da1d477afb7019c2a55b62bae350 100644
--- a/features/dashboard/archived_projects.feature
+++ b/features/dashboard/archived_projects.feature
@@ -10,8 +10,3 @@ Feature: Dashboard Archived Projects
   Scenario: I should see non-archived projects on dashboard
     Then I should see "Shop" project link
     And I should not see "Forum" project link
-
-  Scenario: I should see all projects on projects page
-    And I visit dashboard projects page
-    Then I should see "Shop" project link
-    And I should see "Forum" project link
diff --git a/features/dashboard/dashboard.feature b/features/dashboard/dashboard.feature
index bebaa78e46c5c6f5cd0ea7c5d83184aa46e8c4b4..1959d3270823f22209e0db4f15afada303362343 100644
--- a/features/dashboard/dashboard.feature
+++ b/features/dashboard/dashboard.feature
@@ -27,11 +27,11 @@ Feature: Dashboard
   Scenario: I should see User joined Project event
     Given user with name "John Doe" joined project "Shop"
     When I visit dashboard page
-    Then I should see "John Doe joined project at Shop" event
+    Then I should see "John Doe joined project Shop" event
 
   @javascript
   Scenario: I should see User left Project event
     Given user with name "John Doe" joined project "Shop"
     And user with name "John Doe" left project "Shop"
     When I visit dashboard page
-    Then I should see "John Doe left project at Shop" event
+    Then I should see "John Doe left project Shop" event
diff --git a/features/profile/group.feature b/features/dashboard/group.feature
similarity index 73%
rename from features/profile/group.feature
rename to features/dashboard/group.feature
index e2fbfde77be5402dd87e6ccbe8c4cda06047a631..cf4b8d7283b3c796fe1099884ec90aae9a290c69 100644
--- a/features/profile/group.feature
+++ b/features/dashboard/group.feature
@@ -1,5 +1,5 @@
-@profile
-Feature: Profile Group
+@dashboard
+Feature: Dashboard Group
   Background:
     Given I sign in as "John Doe"
     And "John Doe" is owner of group "Owned"
@@ -10,18 +10,18 @@ Feature: Profile Group
   @javascript
   Scenario: Owner should be able to leave from group if he is not the last owner
     Given "Mary Jane" is owner of group "Owned"
-    When I visit profile groups page
+    When I visit dashboard groups page
     Then I should see group "Owned" in group list
     Then I should see group "Guest" in group list
     When I click on the "Leave" button for group "Owned"
-    And I visit profile groups page
+    And I visit dashboard groups page
     Then I should not see group "Owned" in group list
     Then I should see group "Guest" in group list
 
   @javascript
   Scenario: Owner should not be able to leave from group if he is the last owner
     Given "Mary Jane" is guest of group "Owned"
-    When I visit profile groups page
+    When I visit dashboard groups page
     Then I should see group "Owned" in group list
     Then I should see group "Guest" in group list
     Then I should not see the "Leave" button for group "Owned"
@@ -29,20 +29,28 @@ Feature: Profile Group
   @javascript
   Scenario: Guest should be able to leave from group
     Given "Mary Jane" is guest of group "Guest"
-    When I visit profile groups page
+    When I visit dashboard groups page
     Then I should see group "Owned" in group list
     Then I should see group "Guest" in group list
     When I click on the "Leave" button for group "Guest"
-    When I visit profile groups page
+    When I visit dashboard groups page
     Then I should see group "Owned" in group list
     Then I should not see group "Guest" in group list
 
   @javascript
   Scenario: Guest should be able to leave from group even if he is the only user in the group
-    When I visit profile groups page
+    When I visit dashboard groups page
     Then I should see group "Owned" in group list
     Then I should see group "Guest" in group list
     When I click on the "Leave" button for group "Guest"
-    When I visit profile groups page
+    When I visit dashboard groups page
     Then I should see group "Owned" in group list
     Then I should not see group "Guest" in group list
+
+  Scenario: Create a group from dasboard
+    And I visit dashboard groups page
+    And I click new group link
+    And submit form with new group "Samurai" info
+    Then I should be redirected to group "Samurai" page
+    And I should see newly created group "Samurai"
+
diff --git a/features/dashboard/issues.feature b/features/dashboard/issues.feature
index 72627e43e05c9484b2104af9b6f96079c5ae4e8d..99dad88a40289274f1c4fd5da5d8066f8d6e002a 100644
--- a/features/dashboard/issues.feature
+++ b/features/dashboard/issues.feature
@@ -10,10 +10,12 @@ Feature: Dashboard Issues
   Scenario: I should see assigned issues
     Then I should see issues assigned to me
 
+  @javascript
   Scenario: I should see authored issues
     When I click "Authored by me" link
     Then I should see issues authored by me
 
+  @javascript
   Scenario: I should see all issues
     When I click "All" link
     Then I should see all issues
diff --git a/features/dashboard/merge_requests.feature b/features/dashboard/merge_requests.feature
index dcef1290e7e3ac96d30ab0e8728ab738e6b246d4..4a2c997d707f7dfae6877a3bec2fd94e2eb0df96 100644
--- a/features/dashboard/merge_requests.feature
+++ b/features/dashboard/merge_requests.feature
@@ -10,10 +10,12 @@ Feature: Dashboard Merge Requests
   Scenario: I should see assigned merge_requests
     Then I should see merge requests assigned to me
 
+  @javascript
   Scenario: I should see authored merge_requests
     When I click "Authored by me" link
     Then I should see merge requests authored by me
 
+  @javascript
   Scenario: I should see all merge_requests
     When I click "All" link
     Then I should see all merge requests
diff --git a/features/dashboard/new_project.feature b/features/dashboard/new_project.feature
new file mode 100644
index 0000000000000000000000000000000000000000..431dc4ccfcb258c50a042274bb53d40832049b3b
--- /dev/null
+++ b/features/dashboard/new_project.feature
@@ -0,0 +1,13 @@
+@dashboard
+Feature: New Project
+Background:
+  Given I sign in as a user
+  And I own project "Shop"
+  And I visit dashboard page
+
+  @javascript
+  Scenario: I should see New projects page
+  Given I click "New project" link
+  Then I see "New project" page
+  When I click on "Import project from GitHub"
+  Then I see instructions on how to import from GitHub
diff --git a/features/dashboard/projects.feature b/features/dashboard/projects.feature
deleted file mode 100644
index bb4e84f01590ded42a4c2d5c3e6dbeaeed13134f..0000000000000000000000000000000000000000
--- a/features/dashboard/projects.feature
+++ /dev/null
@@ -1,9 +0,0 @@
-@dashboard
-Feature: Dashboard Projects
-  Background:
-    Given I sign in as a user
-    And I own project "Shop"
-    And I visit dashboard projects page
-
-  Scenario: I should see projects list
-    Then I should see projects list
diff --git a/features/dashboard/starred_projects.feature b/features/dashboard/starred_projects.feature
new file mode 100644
index 0000000000000000000000000000000000000000..9dfd2fbab9cb2a43e3364f25ccd22b5185259d20
--- /dev/null
+++ b/features/dashboard/starred_projects.feature
@@ -0,0 +1,12 @@
+@dashboard
+Feature: Dashboard Starred Projects
+  Background:
+    Given I sign in as a user
+    And public project "Community"
+    And I starred project "Community"
+    And I own project "Shop"
+    And I visit dashboard starred projects page
+
+  Scenario: I should see projects list
+    Then I should see project "Community"
+    And I should not see project "Shop"
diff --git a/features/explore/groups.feature b/features/explore/groups.feature
index b50a3e766c64449e020f46b6efbcb982aa3bc3f0..c11634bd74a800b23d145995768c2bc48c97c50d 100644
--- a/features/explore/groups.feature
+++ b/features/explore/groups.feature
@@ -28,7 +28,6 @@ Feature: Explore Groups
     Given group "TestGroup" has internal project "Internal"
     When I sign in as a user
     And I visit group "TestGroup" issues page
-    And I change filter to Everyone's
     Then I should see project "Internal" items
     And I should not see project "Enterprise" items
 
@@ -36,7 +35,6 @@ Feature: Explore Groups
     Given group "TestGroup" has internal project "Internal"
     When I sign in as a user
     And I visit group "TestGroup" merge requests page
-    And I change filter to Everyone's
     Then I should see project "Internal" items
     And I should not see project "Enterprise" items
 
@@ -94,7 +92,6 @@ Feature: Explore Groups
     Given group "TestGroup" has public project "Community"
     When I sign in as a user
     And I visit group "TestGroup" issues page
-    And I change filter to Everyone's
     Then I should see project "Community" items
     And I should see project "Internal" items
     And I should not see project "Enterprise" items
@@ -104,7 +101,6 @@ Feature: Explore Groups
     Given group "TestGroup" has public project "Community"
     When I sign in as a user
     And I visit group "TestGroup" merge requests page
-    And I change filter to Everyone's
     Then I should see project "Community" items
     And I should see project "Internal" items
     And I should not see project "Enterprise" items
diff --git a/features/groups.feature b/features/groups.feature
index b5ff03db8441b44fc8ee413440469dcf9ee160b6..65d06a0daf9a8a4f3683ed7683cd3bc4d2a48479 100644
--- a/features/groups.feature
+++ b/features/groups.feature
@@ -10,14 +10,6 @@ Feature: Groups
     Then I should see group "Owned" projects list
     And I should see projects activity feed
 
-  Scenario: Create a group from dasboard
-    When I visit group "Owned" page
-    And I visit dashboard page
-    And I click new group link
-    And submit form with new group "Samurai" info
-    Then I should be redirected to group "Samurai" page
-    And I should see newly created group "Samurai"
-
   Scenario: I should see group "Owned" issues list
     Given project from group "Owned" has issues assigned to me
     When I visit group "Owned" issues page
@@ -55,6 +47,14 @@ Feature: Groups
     Then I should not see group "Owned" avatar
     And I should not see the "Remove avatar" button
 
+  @javascript
+  Scenario: Add user to group
+    Given gitlab user "Mike"
+    When I visit group "Owned" members page
+    And I click link "Add members"
+    When I select "Mike" as "Reporter"
+    Then I should see "Mike" in team list as "Reporter"
+
   # Leave
 
   @javascript
diff --git a/features/profile/profile.feature b/features/profile/profile.feature
index d7fa370fe2a81b52d4677c9995dbc67a8e75ac2e..d586167cdf5599e102226fe25e8bf9d826ea5fc8 100644
--- a/features/profile/profile.feature
+++ b/features/profile/profile.feature
@@ -71,6 +71,20 @@ Feature: Profile
     And I click on my profile picture
     Then I should see my user page
 
+  Scenario: I can manage application
+    Given I visit profile applications page
+    Then I click on new application button
+    And I should see application form
+    Then I fill application form out and submit
+    And I see application
+    Then I click edit
+    And I see edit application form
+    Then I change name of application and submit
+    And I see that application was changed
+    Then I visit profile applications page
+    And I click to remove application
+    Then I see that application is removed
+
   @javascript
   Scenario: I change my application theme
     Given I visit profile design page
@@ -83,22 +97,3 @@ Feature: Profile
     Given I visit profile design page
     When I change my code preview theme
     Then I should receive feedback that the changes were saved
-
-  @javascript
-  Scenario: I see the password strength indicator
-    Given I visit profile password page
-    When I try to set a weak password
-    Then I should see the input field yellow
-
-  @javascript
-  Scenario: I see the password strength indicator error
-    Given I visit profile password page
-    When I try to set a short password
-    Then I should see the input field red
-    And I should see the password error message
-
-  @javascript
-  Scenario: I see the password strength indicator with success
-    Given I visit profile password page
-    When I try to set a strong password
-    Then I should see the input field green
\ No newline at end of file
diff --git a/features/project/active_tab.feature b/features/project/active_tab.feature
index 8d3e0bd967f33cd62a91802d0fd68fcab86a428b..05faad4e645c79ea1bbad40874d34b54df2f7049 100644
--- a/features/project/active_tab.feature
+++ b/features/project/active_tab.feature
@@ -106,24 +106,19 @@ Feature: Project Active Tab
     And no other sub tabs should be active
     And the active main tab should be Commits
 
-  # Sub Tabs: Issues
-
   Scenario: On Project Issues/Browse
     Given I visit my project's issues page
-    Then the active sub tab should be Browse Issues
-    And no other sub tabs should be active
-    And the active main tab should be Issues
+    Then the active main tab should be Issues
+    And no other main tabs should be active
 
   Scenario: On Project Issues/Milestones
     Given I visit my project's issues page
     And I click the "Milestones" tab
-    Then the active sub tab should be Milestones
-    And no other sub tabs should be active
-    And the active main tab should be Issues
+    Then the active main tab should be Milestones
+    And no other main tabs should be active
 
   Scenario: On Project Issues/Labels
     Given I visit my project's issues page
     And I click the "Labels" tab
-    Then the active sub tab should be Labels
-    And no other sub tabs should be active
-    And the active main tab should be Issues
+    Then the active main tab should be Labels
+    And no other main tabs should be active
diff --git a/features/project/archived.feature b/features/project/archived.feature
index 9aac29384ba00665756e6449efd05e3149941524..ad466f4f3079613f81cdaabbdfe575339c5837cf 100644
--- a/features/project/archived.feature
+++ b/features/project/archived.feature
@@ -14,15 +14,6 @@ Feature: Project Archived
     And I visit project "Forum" page
     Then I should see "Archived"
 
-  Scenario: I should not see archived on projects page with no archived projects
-    And I visit dashboard projects page
-    Then I should not see "Archived"
-
-  Scenario: I should see archived on projects page with archived projects
-    And project "Forum" is archived
-    And I visit dashboard projects page
-    Then I should see "Archived"
-
   Scenario: I archive project
     When project "Shop" has push event
     And I visit project "Shop" page
diff --git a/features/project/commits/comments.feature b/features/project/commits/comments.feature
index e176752cfbfbd33620ac49fe9b4ba08c7dec571c..c41075d7ad43fad991f2bbca8606017923299d33 100644
--- a/features/project/commits/comments.feature
+++ b/features/project/commits/comments.feature
@@ -13,15 +13,10 @@ Feature: Project Commits Comments
   Scenario: I can't cancel the main form
     Then I should not see the cancel comment button
 
-  @javascript
-  Scenario: I can't preview without text
-    Given I haven't written any comment text
-    Then I should not see the comment preview button
-
   @javascript
   Scenario: I can preview with text
-    Given I write a comment like "Nice"
-    Then I should see the comment preview button
+    Given I write a comment like ":+1: Nice"
+    Then The comment preview tab should be display rendered Markdown
 
   @javascript
   Scenario: I preview a comment
@@ -32,7 +27,7 @@ Feature: Project Commits Comments
   @javascript
   Scenario: I can edit after preview
     Given I preview a comment text like "Bug fixed :smile:"
-    Then I should see the comment edit button
+    Then I should see the comment write tab
 
   @javascript
   Scenario: I have a reset form after posting from preview
@@ -46,3 +41,9 @@ Feature: Project Commits Comments
     Given I leave a comment like "XML attached"
     And I delete a comment
     Then I should not see a comment saying "XML attached"
+
+  @javascript
+  Scenario: I can edit a comment with +1
+    Given I leave a comment like "XML attached"
+    And I edit the last comment with a +1
+    Then I should see +1 in the description
diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature
index 46076b6f3e65c6e85c0bacdfca1dba89e1021670..c4b206edc95a30468157c41359e4687dbbd748df 100644
--- a/features/project/commits/commits.feature
+++ b/features/project/commits/commits.feature
@@ -21,10 +21,13 @@ Feature: Project Commits
     And I click side-by-side diff button
     Then I see inline diff button
 
+  @javascript
   Scenario: I compare refs
     Given I visit compare refs page
     And I fill compare fields with refs
     Then I see compared refs
+    And I unfold diff
+    Then I should see additional file lines
 
   Scenario: I browse commits for a specific path
     Given I visit my project's commits page for a specific path
diff --git a/features/project/commits/diff_comments.feature b/features/project/commits/diff_comments.feature
index a145ec84b78950b2996c20bf2f64fe4b3fd67e3b..56b9a13678db530b00445b5eb19806b5d8bc7e29 100644
--- a/features/project/commits/diff_comments.feature
+++ b/features/project/commits/diff_comments.feature
@@ -54,17 +54,11 @@ Feature: Project Commits Diff Comments
     Given I leave a diff comment like "Typo, please fix"
     Then I should see a discussion reply button
 
-  @javascript
-  Scenario: I can't preview without text
-    Given I open a diff comment form
-    And I haven't written any diff comment text
-    Then I should not see the diff comment preview button
-
   @javascript
   Scenario: I can preview with text
     Given I open a diff comment form
     And I write a diff comment like ":-1: I don't like this"
-    Then I should see the diff comment preview button
+    Then The diff comment preview tab should display rendered Markdown
 
   @javascript
   Scenario: I preview a diff comment
@@ -75,7 +69,7 @@ Feature: Project Commits Diff Comments
   @javascript
   Scenario: I can edit after preview
     Given I preview a diff comment text like "Should fix it :smile:"
-    Then I should see the diff comment edit button
+    Then I should see the diff comment write tab
 
   @javascript
   Scenario: The form gets removed after posting
diff --git a/features/project/edit_issuetracker.feature b/features/project/edit_issuetracker.feature
deleted file mode 100644
index cc0de07ca69449be9e1a8550590abf747d02c013..0000000000000000000000000000000000000000
--- a/features/project/edit_issuetracker.feature
+++ /dev/null
@@ -1,18 +0,0 @@
-Feature: Project Issue Tracker
-  Background:
-    Given I sign in as a user
-    And I own project "Shop"
-    And project "Shop" has issues enabled
-    And I visit project "Shop" page
-
-  Scenario: I set the issue tracker to "GitLab"
-    When I visit edit project "Shop" page
-    And change the issue tracker to "GitLab"
-    And I save project
-    Then I the project should have "GitLab" as issue tracker
-
-  Scenario: I set the issue tracker to "Redmine"
-    When I visit edit project "Shop" page
-    And change the issue tracker to "Redmine"
-    And I save project
-    Then I the project should have "Redmine" as issue tracker
diff --git a/features/project/fork.feature b/features/project/fork.feature
index d3d1180db04781f59fea521d772b01e470729c1c..22f68e5b340e28940dcc6cc814d80f49fcf6088e 100644
--- a/features/project/fork.feature
+++ b/features/project/fork.feature
@@ -6,9 +6,11 @@ Feature: Project Fork
 
   Scenario: User fork a project
     Given I click link "Fork"
+    When I fork to my namespace
     Then I should see the forked project page
 
   Scenario: User already has forked the project
     Given I already have a project named "Shop" in my namespace
     And I click link "Fork"
+    When I fork to my namespace
     Then I should see a "Name has already been taken" warning
diff --git a/features/project/issues/filter_labels.feature b/features/project/issues/filter_labels.feature
index 2c69a78a749e266520290d6dc5fa70dc029bbe8c..e316f519861ec86a4a622b60c6ec487a3f5acc8d 100644
--- a/features/project/issues/filter_labels.feature
+++ b/features/project/issues/filter_labels.feature
@@ -8,11 +8,7 @@ Feature: Project Issues Filter Labels
     And project "Shop" has issue "Feature1" with labels: "feature"
     Given I visit project "Shop" issues page
 
-  Scenario: I should see project issues
-    Then I should see "bug" in labels filter
-    And I should see "feature" in labels filter
-    And I should see "enhancement" in labels filter
-
+  @javascript
   Scenario: I filter by one label
     Given I click link "bug"
     Then I should see "Bugfix1" in issues list
diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature
index 4db8551559b94309aa8003df9906047bafd225ea..b9031f6f32b7673bad87df0d419b68ea0a3c9274 100644
--- a/features/project/issues/issues.feature
+++ b/features/project/issues/issues.feature
@@ -139,6 +139,15 @@ Feature: Project Issues
     And I leave a comment with task markdown
     Then I should not see task checkboxes in the comment
 
+  @javascript
+  Scenario: Issue notes should be editable with +1
+    Given project "Shop" has "Tasks-open" open issue with task markdown
+    When I visit issue page "Tasks-open"
+    And I leave a comment with a header containing "Comment with a header"
+    Then The comment with the header should not have an ID
+    And I edit the last comment with a +1
+    Then I should see +1 in the description
+
   # Task status in issues list
 
   Scenario: Issues list should display task status
@@ -159,3 +168,45 @@ Feature: Project Issues
     Given project "Shop" has "Tasks-closed" closed issue with task markdown
     When I visit issue page "Tasks-closed"
     Then Task checkboxes should be disabled
+
+  # Issue description preview
+
+  @javascript
+  Scenario: I can't preview without text
+    Given I click link "New Issue"
+    And I haven't written any description text
+    Then The Markdown preview tab should say there is nothing to do
+
+  @javascript
+  Scenario: I can preview with text
+    Given I click link "New Issue"
+    And I write a description like ":+1: Nice"
+    Then The Markdown preview tab should display rendered Markdown
+
+  @javascript
+  Scenario: I preview an issue description
+    Given I click link "New Issue"
+    And I preview a description text like "Bug fixed :smile:"
+    Then I should see the Markdown preview
+    And I should not see the Markdown text field
+
+  @javascript
+  Scenario: I can edit after preview
+    Given I click link "New Issue"
+    And I preview a description text like "Bug fixed :smile:"
+    Then I should see the Markdown write tab
+
+  @javascript
+  Scenario: I can preview when editing an existing issue
+    Given I click link "Release 0.4"
+    And I click link "Edit" for the issue
+    And I preview a description text like "Bug fixed :smile:"
+    Then I should see the Markdown write tab
+
+  @javascript
+  Scenario: I can unsubscribe from issue
+    Given project "Shop" has "Tasks-open" open issue with task markdown
+    When I visit issue page "Tasks-open"
+    Then I should see that I am subscribed
+    When I click button "Unsubscribe"
+    Then I should see that I am unsubscribed
diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature
index d20358a7dc68dfbf0c3f35838552224086eb79e1..cbb5c8eb39b6bb6331dfc21d6c917884e3938343 100644
--- a/features/project/merge_requests.feature
+++ b/features/project/merge_requests.feature
@@ -166,6 +166,13 @@ Feature: Project Merge Requests
     And I click Side-by-side Diff tab
     Then I should see comments on the side-by-side diff page
 
+  @javascript
+  Scenario: I view diffs on a merge request
+    Given project "Shop" have "Bug NS-05" open merge request with diffs inside
+    And I visit merge request page "Bug NS-05"
+    And I click on the Changes tab via Javascript
+    Then I should see the proper Inline and Side-by-side links
+
   # Task status in issues list
 
   Scenario: Merge requests list should display task status
@@ -187,3 +194,48 @@ Feature: Project Merge Requests
     And I visit merge request page "MR-task-open"
     And I click link "Close"
     Then Task checkboxes should be disabled
+
+  # Description preview
+
+  @javascript
+  Scenario: I can't preview without text
+    Given I visit merge request page "Bug NS-04"
+    And I click link "Edit" for the merge request
+    And I haven't written any description text
+    Then The Markdown preview tab should say there is nothing to do
+
+  @javascript
+  Scenario: I can preview with text
+    Given I visit merge request page "Bug NS-04"
+    And I click link "Edit" for the merge request
+    And I write a description like ":+1: Nice"
+    Then The Markdown preview tab should display rendered Markdown
+
+  @javascript
+  Scenario: I preview a merge request description
+    Given I visit merge request page "Bug NS-04"
+    And I click link "Edit" for the merge request
+    And I preview a description text like "Bug fixed :smile:"
+    Then I should see the Markdown preview
+    And I should not see the Markdown text field
+
+  @javascript
+  Scenario: I can edit after preview
+    Given I visit merge request page "Bug NS-04"
+    And I click link "Edit" for the merge request
+    And I preview a description text like "Bug fixed :smile:"
+    Then I should see the Markdown write tab
+
+  @javascript
+  Scenario: I search merge request
+    Given I click link "All"
+    When I fill in merge request search with "Fe"
+    Then I should see "Feature NS-03" in merge requests
+    And I should not see "Bug NS-04" in merge requests
+
+  @javascript
+  Scenario: I can unsubscribe from merge request
+    Given I visit merge request page "Bug NS-04"
+    Then I should see that I am subscribed
+    When I click button "Unsubscribe"
+    Then I should see that I am unsubscribed
diff --git a/features/project/project.feature b/features/project/project.feature
index 7bb24e013a9795152f90a2655a68a989d9940fc1..3e1fd54bee84ca92fcbb4cd61880287715e6e0b4 100644
--- a/features/project/project.feature
+++ b/features/project/project.feature
@@ -5,6 +5,19 @@ Feature: Project
     And project "Shop" has push event
     And I visit project "Shop" page
 
+  Scenario: I edit the project avatar
+    Given I visit edit project "Shop" page
+    When I change the project avatar
+    And I should see new project avatar
+    And I should see the "Remove avatar" button
+
+  Scenario: I remove the project avatar
+    Given I visit edit project "Shop" page
+    And I have an project avatar
+    When I remove my project avatar
+    Then I should see the default project avatar
+    And I should not see the "Remove avatar" button
+
   @javascript
   Scenario: I should see project activity
     When I visit project "Shop" page
diff --git a/features/project/service.feature b/features/project/service.feature
index 88fd038d45f6f6ba78df9422498e48cb979c047a..fdff640ec857e1ea267fbf77af7d3312a266c2d7 100644
--- a/features/project/service.feature
+++ b/features/project/service.feature
@@ -19,6 +19,12 @@ Feature: Project Services
     And I fill hipchat settings
     Then I should see hipchat service settings saved
 
+  Scenario: Activate hipchat service with custom server
+    When I visit project "Shop" services page
+    And I click hipchat service link
+    And I fill hipchat settings with custom server
+    Then I should see hipchat service settings with custom server saved
+
   Scenario: Activate pivotaltracker service
     When I visit project "Shop" services page
     And I click pivotaltracker service link
@@ -55,8 +61,26 @@ Feature: Project Services
     And I fill email on push settings
     Then I should see email on push service settings saved
 
+  Scenario: Activate Irker (IRC Gateway) service
+    When I visit project "Shop" services page
+    And I click Irker service link
+    And I fill Irker settings
+    Then I should see Irker service settings saved
+
   Scenario: Activate Atlassian Bamboo CI service
     When I visit project "Shop" services page
     And I click Atlassian Bamboo CI service link
     And I fill Atlassian Bamboo CI settings
     Then I should see Atlassian Bamboo CI service settings saved
+
+  Scenario: Activate jetBrains TeamCity CI service
+    When I visit project "Shop" services page
+    And I click jetBrains TeamCity CI service link
+    And I fill jetBrains TeamCity CI settings
+    Then I should see jetBrains TeamCity CI service settings saved
+
+  Scenario: Activate Asana service
+    When I visit project "Shop" services page
+    And I click Asana service link
+    And I fill Asana settings
+    Then I should see Asana service settings saved
diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature
index b7d70881d56cf2127fecf431b495ff34a71c6840..b16a65e61f86b19eaea0f42bf62ad227355ffb8a 100644
--- a/features/project/source/browse_files.feature
+++ b/features/project/source/browse_files.feature
@@ -34,6 +34,30 @@ Feature: Project Source Browse Files
     Then I am redirected to the new file
     And I should see its new content
 
+  @javascript
+  Scenario: I can create and commit file and specify new branch
+    Given I click on "new file" link in repo
+    And I edit code
+    And I fill the new file name
+    And I fill the commit message
+    And I fill the new branch name
+    And I click on "Commit Changes"
+    Then I am redirected to the new file on new branch
+    And I should see its new content
+
+  @javascript @tricky
+  Scenario: I can create file in empty repo
+    Given I own an empty project
+    And I visit my empty project page
+    And I create bare repo
+    When I click on "add a file" link
+    And I edit code
+    And I fill the new file name
+    And I fill the commit message
+    And I click on "Commit Changes"
+    Then I am redirected to the new file
+    And I should see its new content
+
   @javascript
   Scenario: If I enter an illegal file name I see an error message
     Given I click on "new file" link in repo
@@ -43,6 +67,16 @@ Feature: Project Source Browse Files
     And I click on "Commit changes"
     Then I am on the new file page
     And I see a commit error message
+    
+  @javascript
+  Scenario: I can upload file and commit
+    Given I click on "Upload" in repo
+    When I upload "user.feature"
+    And I fill the commit message
+    And I click on "Upload file"
+    And I check name of the upload file
+    Then I see the "user.feature"
+    
 
   @javascript
   Scenario: I can edit file
@@ -50,6 +84,16 @@ Feature: Project Source Browse Files
     And I click button "Edit"
     Then I can edit code
 
+  Scenario: If the file is binary the edit link is hidden
+    Given I visit a binary file in the repo
+    Then I cannot see the edit button
+
+  Scenario: If I don't have edit permission the edit link is disabled
+    Given public project "Community"
+    And I visit project "Community" source page
+    And I click on ".gitignore" file in repo
+    Then The edit button is disabled
+
   @javascript
   Scenario: I can edit and commit file
     Given I click on ".gitignore" file in repo
@@ -60,6 +104,17 @@ Feature: Project Source Browse Files
     Then I am redirected to the ".gitignore"
     And I should see its new content
 
+  @javascript
+  Scenario: I can edit and commit file to new branch
+    Given I click on ".gitignore" file in repo
+    And I click button "Edit"
+    And I edit code
+    And I fill the commit message
+    And I fill the new branch name
+    And I click on "Commit Changes"
+    Then I am redirected to the ".gitignore" on new branch
+    And I should see its new content
+
   @javascript  @wip
   Scenario: If I don't change the content of the file I see an error message
     Given I click on ".gitignore" file in repo
@@ -87,7 +142,19 @@ Feature: Project Source Browse Files
     And I click on "Remove file"
     Then I am redirected to the files URL
     And I don't see the ".gitignore"
-
+    
+  @javascript
+  Scenario: I can replace file and commit
+    Given I click on ".gitignore" file in repo
+    And I see the ".gitignore"
+    And I click on "Replace"
+    When I replace it with "LICENSE"
+    And I fill the commit message
+    And I click on "Replace file"
+    Then I am redirected to the ".gitignore"
+    And I should see new file content
+    
+    
   Scenario: I can browse directory with Browse Dir
     Given I click on files directory
     And I click on History link
@@ -103,7 +170,6 @@ Feature: Project Source Browse Files
     Then I see Browse code link
 
   # Permalink
-
   Scenario: I click on the permalink link from a branch ref
     Given I click on ".gitignore" file in repo
     And I click on Permalink
diff --git a/features/project/star.feature b/features/project/star.feature
index 3322f891805f5a475f51e258a446c23d0190f57c..a45f9c470ea8921eb2f023899752af0af6e83d38 100644
--- a/features/project/star.feature
+++ b/features/project/star.feature
@@ -13,7 +13,7 @@ Feature: Project Star
     Given public project "Community"
     And I visit project "Community" page
     When I click on the star toggle button
-    Then The project has 0 stars
+    Then I redirected to sign in page
 
   @javascript
   Scenario: Signed in users can toggle star
diff --git a/features/project/team_management.feature b/features/project/team_management.feature
index 86ea6cd6e9139037f633d8cd781de95d11042069..22393622bb94daad9d226a1def4a4da4fd092a64 100644
--- a/features/project/team_management.feature
+++ b/features/project/team_management.feature
@@ -13,7 +13,7 @@ Feature: Project Team Management
 
   @javascript
   Scenario: Add user to project
-    Given I click link "New Team Member"
+    Given I click link "Add members"
     And I select "Mike" as "Reporter"
     Then I should see "Mike" in team list as "Reporter"
 
diff --git a/features/search.feature b/features/search.feature
index 54708c175759bce3fd330a593417ac980ef1c118..def21e009234030142e0454ad4eec115db5da98f 100644
--- a/features/search.feature
+++ b/features/search.feature
@@ -13,15 +13,15 @@ Feature: Search
     And project has issues
     When I search for "Foo"
     And I click "Issues" link
-    Then I should see "Foo" link
-    And I should not see "Bar" link
+    Then I should see "Foo" link in the search results
+    And I should not see "Bar" link in the search results
 
   Scenario: I should see merge requests I am looking for
     And project has merge requests
     When I search for "Foo"
     When I click "Merge requests" link
-    Then I should see "Foo" link
-    And I should not see "Bar" link
+    Then I should see "Foo" link in the search results
+    And I should not see "Bar" link in the search results
 
   Scenario: I should see project code I am looking for
     When I click project "Shop" link
@@ -33,14 +33,14 @@ Feature: Search
     When I click project "Shop" link
     And I search for "Foo"
     And I click "Issues" link
-    Then I should see "Foo" link
-    And I should not see "Bar" link
+    Then I should see "Foo" link in the search results
+    And I should not see "Bar" link in the search results
 
   Scenario: I should see project merge requests
     And project has merge requests
     When I click project "Shop" link
     And I search for "Foo"
     And I click "Merge requests" link
-    Then I should see "Foo" link
-    And I should not see "Bar" link
+    Then I should see "Foo" link in the search results
+    And I should not see "Bar" link in the search results
 
diff --git a/features/steps/admin/applications.rb b/features/steps/admin/applications.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d59088fa3c32c815dc0f9aa0482bd2abd9762876
--- /dev/null
+++ b/features/steps/admin/applications.rb
@@ -0,0 +1,55 @@
+class Spinach::Features::AdminApplications < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+  include SharedAdmin
+
+  step 'I click on new application button' do
+    click_on 'New Application'
+  end
+
+  step 'I should see application form' do
+    page.should have_content "New application"
+  end
+
+  step 'I fill application form out and submit' do
+    fill_in :doorkeeper_application_name, with: 'test'
+    fill_in :doorkeeper_application_redirect_uri, with: 'https://test.com'
+    click_on "Submit"
+  end
+
+  step 'I see application' do
+    page.should have_content "Application: test"
+    page.should have_content "Application Id"
+    page.should have_content "Secret"
+  end
+
+  step 'I click edit' do
+    click_on "Edit"
+  end
+
+  step 'I see edit application form' do
+    page.should have_content "Edit application"
+  end
+
+  step 'I change name of application and submit' do
+    page.should have_content "Edit application"
+    fill_in :doorkeeper_application_name, with: 'test_changed'
+    click_on "Submit"
+  end
+
+  step 'I see that application was changed' do
+    page.should have_content "test_changed"
+    page.should have_content "Application Id"
+    page.should have_content "Secret"
+  end
+
+  step 'I click to remove application' do
+    within '.oauth-applications' do
+      click_on "Destroy"
+    end
+  end
+
+  step "I see that application is removed" do
+    page.find(".oauth-applications").should_not have_content "test_changed"
+  end
+end
diff --git a/features/steps/admin/groups.rb b/features/steps/admin/groups.rb
index d69a87cd07ef9d9b9747aab9e75c0d05f75d85ad..721460b93710f11b4df29fc7a5c213aaeadb6b3f 100644
--- a/features/steps/admin/groups.rb
+++ b/features/steps/admin/groups.rb
@@ -22,7 +22,7 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
   end
 
   step 'submit form with new group info' do
-    fill_in 'group_name', with: 'gitlab'
+    fill_in 'group_path', with: 'gitlab'
     fill_in 'group_description', with: 'Group description'
     click_button "Create group"
   end
@@ -33,15 +33,15 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
   end
 
   step 'I should be redirected to group page' do
-    current_path.should == admin_group_path(Group.last)
+    current_path.should == admin_group_path(Group.find_by(path: 'gitlab'))
   end
 
   When 'I select user "John Doe" from user list as "Reporter"' do
     select2(user_john.id, from: "#user_ids", multiple: true)
-    within "#new_team_member" do
+    within "#new_project_member" do
       select "Reporter", from: "access_level"
     end
-    click_button "Add users into group"
+    click_button "Add users to group"
   end
 
   step 'I should see "John Doe" in team list in every project as "Reporter"' do
diff --git a/features/steps/admin/projects.rb b/features/steps/admin/projects.rb
index 2fd6385fe7b7581d2e2a699bb8cc04b8bc3f56c8..9be4d39d2d5775bb5c75f33ebd49865fcc085394 100644
--- a/features/steps/admin/projects.rb
+++ b/features/steps/admin/projects.rb
@@ -15,17 +15,17 @@ class Spinach::Features::AdminProjects < Spinach::FeatureSteps
 
   step 'I should see project details' do
     project = Project.first
-    current_path.should == admin_project_path(project)
+    current_path.should == admin_namespace_project_path(project.namespace, project)
     page.should have_content(project.name_with_namespace)
     page.should have_content(project.creator.name)
   end
 
   step 'I visit admin project page' do
-    visit admin_project_path(project)
+    visit admin_namespace_project_path(project.namespace, project)
   end
 
   step 'I transfer project to group \'Web\'' do
-    find(:xpath, "//input[@id='namespace_id']").set group.id
+    find(:xpath, "//input[@id='new_namespace_id']").set group.id
     click_button 'Transfer'
   end
 
diff --git a/features/steps/admin/settings.rb b/features/steps/admin/settings.rb
new file mode 100644
index 0000000000000000000000000000000000000000..87d4e969ff51ec1582b3c0b568d94cc59e19ec15
--- /dev/null
+++ b/features/steps/admin/settings.rb
@@ -0,0 +1,47 @@
+class Spinach::Features::AdminSettings < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+  include SharedAdmin
+  include Gitlab::CurrentSettings
+
+  step 'I modify settings and save form' do
+    uncheck 'Gravatar enabled'
+    fill_in 'Home page url', with: 'https://about.gitlab.com/'
+    click_button 'Save'
+  end
+
+  step 'I should see application settings saved' do
+    current_application_settings.gravatar_enabled.should be_false
+    current_application_settings.home_page_url.should == 'https://about.gitlab.com/'
+    page.should have_content 'Application settings saved successfully'
+  end
+
+  step 'I click on "Service Templates"' do
+    click_link 'Service Templates'
+  end
+
+  step 'I click on "Slack" service' do
+    click_link 'Slack'
+  end
+
+  step 'I check all events and submit form' do
+    page.check('Active')
+    page.check('Push events')
+    page.check('Tag push events')
+    page.check('Comments')
+    page.check('Issues events')
+    page.check('Merge Request events')
+    fill_in 'Webhook', with: "http://localhost"
+    click_on 'Save'
+  end
+
+  step 'I should see service template settings saved' do
+    page.should have_content 'Application settings saved successfully'
+  end
+
+  step 'I should see all checkboxes checked' do
+    all('input[type=checkbox]').each do |checkbox|
+      checkbox.should be_checked
+    end
+  end
+end
diff --git a/features/steps/admin/users.rb b/features/steps/admin/users.rb
index 546c1bf2a12279eef607a20b7bb7006b60e0113d..e13830972487e0e4c99e1b94a806ca9d29900793 100644
--- a/features/steps/admin/users.rb
+++ b/features/steps/admin/users.rb
@@ -82,4 +82,36 @@ class Spinach::Features::AdminUsers < Spinach::FeatureSteps
     page.should have_content 'Account'
     page.should have_content 'Personal projects limit'
   end
+
+  step 'user "Pete" with ssh keys' do
+    user = create(:user, name: 'Pete')
+    create(:key, user: user, title: "ssh-rsa Key1", key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4FIEBXGi4bPU8kzxMefudPIJ08/gNprdNTaO9BR/ndy3+58s2HCTw2xCHcsuBmq+TsAqgEidVq4skpqoTMB+Uot5Uzp9z4764rc48dZiI661izoREoKnuRQSsRqUTHg5wrLzwxlQbl1MVfRWQpqiz/5KjBC7yLEb9AbusjnWBk8wvC1bQPQ1uLAauEA7d836tgaIsym9BrLsMVnR4P1boWD3Xp1B1T/ImJwAGHvRmP/ycIqmKdSpMdJXwxcb40efWVj0Ibbe7ii9eeoLdHACqevUZi6fwfbymdow+FeqlkPoHyGg3Cu4vD/D8+8cRc7mE/zGCWcQ15Var83Tczour Key1")
+    create(:key, user: user, title: "ssh-rsa Key2", key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQSTWXhJAX/He+nG78MiRRRn7m0Pb0XbcgTxE0etArgoFoh9WtvDf36HG6tOSg/0UUNcp0dICsNAmhBKdncp6cIyPaXJTURPRAGvhI0/VDk4bi27bRnccGbJ/hDaUxZMLhhrzY0r22mjVf8PF6dvv5QUIQVm1/LeaWYsHHvLgiIjwrXirUZPnFrZw6VLREoBKG8uWvfSXw1L5eapmstqfsME8099oi+vWLR8MgEysZQmD28M73fgW4zek6LDQzKQyJx9nB+hJkKUDvcuziZjGmRFlNgSA2mguERwL1OXonD8WYUrBDGKroIvBT39zS5d9tQDnidEJZ9Y8gv5ViYP7x Key2")
+  end
+
+  step 'click on user "Pete"' do
+    click_link 'Pete'
+  end
+
+  step 'I should see key list' do
+    page.should have_content 'ssh-rsa Key2'
+    page.should have_content 'ssh-rsa Key1'
+  end
+
+  step 'I click on the key title' do
+    click_link 'ssh-rsa Key2'
+  end
+
+  step 'I should see key details' do
+    page.should have_content 'ssh-rsa Key2'
+    page.should have_content 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQSTWXhJAX/He+nG78MiRRRn7m0Pb0XbcgTxE0etArgoFoh9WtvDf36HG6tOSg/0UUNcp0dICsNAmhBKdncp6cIyPaXJTURPRAGvhI0/VDk4bi27bRnccGbJ/hDaUxZMLhhrzY0r22mjVf8PF6dvv5QUIQVm1/LeaWYsHHvLgiIjwrXirUZPnFrZw6VLREoBKG8uWvfSXw1L5eapmstqfsME8099oi+vWLR8MgEysZQmD28M73fgW4zek6LDQzKQyJx9nB+hJkKUDvcuziZjGmRFlNgSA2mguERwL1OXonD8WYUrBDGKroIvBT39zS5d9tQDnidEJZ9Y8gv5ViYP7x Key2'
+  end
+
+  step 'I click on remove key' do
+    click_link 'Remove'
+  end
+
+  step 'I should see the key removed' do
+    page.should_not have_content 'ssh-rsa Key2'
+  end
 end
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
index 1826ead1d51a5a076041388e07687cf76131083c..8508b2a8096f04baaeda21bd2fbd36f25f98306a 100644
--- a/features/steps/dashboard/dashboard.rb
+++ b/features/steps/dashboard/dashboard.rb
@@ -21,7 +21,7 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps
   end
 
   step 'I see prefilled new Merge Request page' do
-    current_path.should == new_project_merge_request_path(@project)
+    current_path.should == new_namespace_project_merge_request_path(@project.namespace, @project)
     find("#merge_request_target_project_id").value.should == @project.id.to_s
     find("#merge_request_source_branch").value.should == "fix"
     find("#merge_request_target_branch").value.should == "master"
@@ -37,8 +37,8 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps
     )
   end
 
-  step 'I should see "John Doe joined project at Shop" event' do
-    page.should have_content "John Doe joined project at #{project.name_with_namespace}"
+  step 'I should see "John Doe joined project Shop" event' do
+    page.should have_content "John Doe joined project #{project.name_with_namespace}"
   end
 
   step 'user with name "John Doe" left project "Shop"' do
@@ -50,8 +50,8 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps
     )
   end
 
-  step 'I should see "John Doe left project at Shop" event' do
-    page.should have_content "John Doe left project at #{project.name_with_namespace}"
+  step 'I should see "John Doe left project Shop" event' do
+    page.should have_content "John Doe left project #{project.name_with_namespace}"
   end
 
   step 'I have group with projects' do
diff --git a/features/steps/profile/group.rb b/features/steps/dashboard/group.rb
similarity index 67%
rename from features/steps/profile/group.rb
rename to features/steps/dashboard/group.rb
index 0a10e04e219b0da374e2e69e250e9469d1028518..8384df2fb59cb15aaaf0dd83d03a80670492645a 100644
--- a/features/steps/profile/group.rb
+++ b/features/steps/dashboard/group.rb
@@ -1,4 +1,4 @@
-class Spinach::Features::ProfileGroup < Spinach::FeatureSteps
+class Spinach::Features::DashboardGroup < Spinach::FeatureSteps
   include SharedAuthentication
   include SharedGroup
   include SharedPaths
@@ -41,4 +41,23 @@ class Spinach::Features::ProfileGroup < Spinach::FeatureSteps
   step 'I should not see group "Guest" in group list' do
     page.should_not have_content("Guest")
   end
+
+  step 'I click new group link' do
+    click_link "New Group"
+  end
+
+  step 'submit form with new group "Samurai" info' do
+    fill_in 'group_path', with: 'Samurai'
+    fill_in 'group_description', with: 'Tokugawa Shogunate'
+    click_button "Create group"
+  end
+
+  step 'I should be redirected to group "Samurai" page' do
+    current_path.should == group_path(Group.find_by(name: 'Samurai'))
+  end
+
+  step 'I should see newly created group "Samurai"' do
+    page.should have_content "Samurai"
+    page.should have_content "Tokugawa Shogunate"
+  end
 end
diff --git a/features/steps/dashboard/issues.rb b/features/steps/dashboard/issues.rb
index 2a5850d091b05fe7d9c8ca1033f3c3d8164ae4d9..60da36e86de10928faac3d51788440c6b258ba0a 100644
--- a/features/steps/dashboard/issues.rb
+++ b/features/steps/dashboard/issues.rb
@@ -1,6 +1,7 @@
 class Spinach::Features::DashboardIssues < Spinach::FeatureSteps
   include SharedAuthentication
   include SharedPaths
+  include Select2Helper
 
   step 'I should see issues assigned to me' do
     should_see(assigned_issue)
@@ -35,15 +36,13 @@ class Spinach::Features::DashboardIssues < Spinach::FeatureSteps
   end
 
   step 'I click "Authored by me" link' do
-    within ".scope-filter" do
-      click_link 'Created by me'
-    end
+    select2(current_user.id, from: "#author_id")
+    select2(nil, from: "#assignee_id")
   end
 
   step 'I click "All" link' do
-    within ".scope-filter" do
-      click_link "Everyone's"
-    end
+    select2(nil, from: "#author_id")
+    select2(nil, from: "#assignee_id")
   end
 
   def should_see(issue)
diff --git a/features/steps/dashboard/merge_requests.rb b/features/steps/dashboard/merge_requests.rb
index 75e53173d3f2cdad71ec00b7a560e20b369f9d5e..9d92082bb83d5aa32b654558e1dc2e57ccda17bc 100644
--- a/features/steps/dashboard/merge_requests.rb
+++ b/features/steps/dashboard/merge_requests.rb
@@ -1,6 +1,7 @@
 class Spinach::Features::DashboardMergeRequests < Spinach::FeatureSteps
   include SharedAuthentication
   include SharedPaths
+  include Select2Helper
 
   step 'I should see merge requests assigned to me' do
     should_see(assigned_merge_request)
@@ -39,15 +40,13 @@ class Spinach::Features::DashboardMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I click "Authored by me" link' do
-    within ".scope-filter" do
-      click_link 'Created by me'
-    end
+    select2(current_user.id, from: "#author_id")
+    select2(nil, from: "#assignee_id")
   end
 
   step 'I click "All" link' do
-    within ".scope-filter" do
-      click_link "Everyone's"
-    end
+    select2(nil, from: "#author_id")
+    select2(nil, from: "#assignee_id")
   end
 
   def should_see(merge_request)
diff --git a/features/steps/dashboard/new_project.rb b/features/steps/dashboard/new_project.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5e588ceb780c7f4196ad2702a0adbf6b81370662
--- /dev/null
+++ b/features/steps/dashboard/new_project.rb
@@ -0,0 +1,27 @@
+class Spinach::Features::NewProject < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+  include SharedProject
+
+  step 'I click "New project" link' do
+    click_link "New project"
+  end
+
+  step 'I see "New project" page' do
+    page.should have_content("Project path")
+  end
+
+  step 'I click on "Import project from GitHub"' do
+    first('.how_to_import_link').click
+  end
+
+  step 'I see instructions on how to import from GitHub' do
+    github_modal = first('.modal-body')
+    github_modal.should be_visible
+    github_modal.should have_content "To enable importing projects from GitHub"
+
+    all('.modal-body').each do |element|
+      element.should_not be_visible unless element == github_modal
+    end
+  end
+end
diff --git a/features/steps/dashboard/projects.rb b/features/steps/dashboard/projects.rb
deleted file mode 100644
index 2a34816306000f14c98f6897918dc77c9dd3da25..0000000000000000000000000000000000000000
--- a/features/steps/dashboard/projects.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class Spinach::Features::DashboardProjects < Spinach::FeatureSteps
-  include SharedAuthentication
-  include SharedPaths
-  include SharedProject
-
-  step 'I should see projects list' do
-    @user.authorized_projects.all.each do |project|
-      page.should have_link project.name_with_namespace
-    end
-  end
-end
diff --git a/features/steps/dashboard/starred_projects.rb b/features/steps/dashboard/starred_projects.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b9ad2f13e293248e55a4307aeb2619a723093da1
--- /dev/null
+++ b/features/steps/dashboard/starred_projects.rb
@@ -0,0 +1,15 @@
+class Spinach::Features::DashboardStarredProjects < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+  include SharedProject
+
+  step 'I starred project "Community"' do
+    current_user.toggle_star(Project.find_by(name: 'Community'))
+  end
+
+  step 'I should not see project "Shop"' do
+    within 'aside' do
+      page.should_not have_content('Shop')
+    end
+  end
+end
diff --git a/features/steps/explore/groups.rb b/features/steps/explore/groups.rb
index ccbf6cda07e174e74bb3fad1bea074f744bbdc07..0c2127d4c4b3ba7133c1fdb68bf9d2fec1713dd8 100644
--- a/features/steps/explore/groups.rb
+++ b/features/steps/explore/groups.rb
@@ -35,7 +35,7 @@ class Spinach::Features::ExploreGroups < Spinach::FeatureSteps
   end
 
   step 'I visit group "TestGroup" members page' do
-    visit members_group_path(Group.find_by(name: "TestGroup"))
+    visit group_group_members_path(Group.find_by(name: "TestGroup"))
   end
 
   step 'I should not see project "Enterprise" items' do
diff --git a/features/steps/explore/projects.rb b/features/steps/explore/projects.rb
index 8172f7922ccebcd75e945b6a7c4df6123c6ec18b..26b71406bd8a9a52756a0f6fff4af0214a7f0412 100644
--- a/features/steps/explore/projects.rb
+++ b/features/steps/explore/projects.rb
@@ -65,7 +65,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
        title: "New feature",
        project: public_project
       )
-    visit project_issues_path(public_project)
+    visit namespace_project_issues_path(public_project.namespace, public_project)
   end
 
 
@@ -84,7 +84,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
        title: "New internal feature",
        project: internal_project
       )
-    visit project_issues_path(internal_project)
+    visit namespace_project_issues_path(internal_project.namespace, internal_project)
   end
 
 
@@ -95,7 +95,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
   end
 
   step 'I visit "Community" merge requests page' do
-    visit project_merge_requests_path(public_project)
+    visit namespace_project_merge_requests_path(public_project.namespace, public_project)
   end
 
   step 'project "Community" has "Bug fix" open merge request' do
@@ -112,7 +112,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
   end
 
   step 'I visit "Internal" merge requests page' do
-    visit project_merge_requests_path(internal_project)
+    visit namespace_project_merge_requests_path(internal_project.namespace, internal_project)
   end
 
   step 'project "Internal" has "Feature implemented" open merge request' do
diff --git a/features/steps/groups.rb b/features/steps/groups.rb
index 616a297db999ee99559980a5098193a4eededcc3..ec5213e4b93110227796166bdc8942e94aa77fdd 100644
--- a/features/steps/groups.rb
+++ b/features/steps/groups.rb
@@ -5,6 +5,32 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
   include SharedUser
   include Select2Helper
 
+  step 'gitlab user "Mike"' do
+    create(:user, name: "Mike")
+  end
+
+  step 'I click link "Add members"' do
+    find(:css, 'button.btn-new').click
+  end
+
+  step 'I select "Mike" as "Reporter"' do
+    user = User.find_by(name: "Mike")
+
+    within ".users-group-form" do
+      select2(user.id, from: "#user_ids", multiple: true)
+      select "Reporter", from: "access_level"
+    end
+
+    click_button "Add users to group"
+  end
+
+  step 'I should see "Mike" in team list as "Reporter"' do
+    within '.well-list' do
+      page.should have_content('Mike')
+      page.should have_content('Reporter')
+    end
+  end
+
   step 'I should see group "Owned" projects list' do
     Group.find_by(name: "Owned").projects.each do |project|
       page.should have_link project.name
@@ -29,12 +55,12 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
 
   step 'I select user "Mary Jane" from list with role "Reporter"' do
     user = User.find_by(name: "Mary Jane") || create(:user, name: "Mary Jane")
-    click_link 'Add members'
+    click_button 'Add members'
     within ".users-group-form" do
       select2(user.id, from: "#user_ids", multiple: true)
       select "Reporter", from: "access_level"
     end
-    click_button "Add users into group"
+    click_button "Add users to group"
   end
 
   step 'I should see user "John Doe" in team list' do
@@ -72,34 +98,15 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
       author: current_user
   end
 
-  When 'I click new group link' do
-    click_link "New group"
-  end
-
-  step 'submit form with new group "Samurai" info' do
-    fill_in 'group_name', with: 'Samurai'
-    fill_in 'group_description', with: 'Tokugawa Shogunate'
-    click_button "Create group"
-  end
-
-  step 'I should be redirected to group "Samurai" page' do
-    current_path.should == group_path(Group.last)
-  end
-
-  step 'I should see newly created group "Samurai"' do
-    page.should have_content "Samurai"
-    page.should have_content "Tokugawa Shogunate"
-    page.should have_content "Currently you are only seeing events from the"
-  end
-
   step 'I change group "Owned" name to "new-name"' do
     fill_in 'group_name', with: 'new-name'
+    fill_in 'group_path', with: 'new-name'
     click_button "Save group"
   end
 
   step 'I should see new group "Owned" name' do
     within ".navbar-gitlab" do
-      page.should have_content "group: new-name"
+      page.should have_content "new-name"
     end
   end
 
@@ -110,7 +117,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
   end
 
   step 'I should see new group "Owned" avatar' do
-    Group.find_by(name: "Owned").avatar.should be_instance_of AttachmentUploader
+    Group.find_by(name: "Owned").avatar.should be_instance_of AvatarUploader
     Group.find_by(name: "Owned").avatar.url.should == "/uploads/group/avatar/#{ Group.find_by(name:"Owned").id }/gitlab_logo.png"
   end
 
@@ -188,15 +195,14 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
   end
 
   step 'I should see group milestone with descriptions and expiry date' do
-    page.should have_content('Lorem Ipsum is simply dummy text of the printing and typesetting industry')
     page.should have_content('expires at Aug 20, 2114')
   end
 
   step 'I should see group milestone with all issues and MRs assigned to that milestone' do
     page.should have_content('Milestone GL-113')
     page.should have_content('Progress: 0 closed – 4 open')
-    page.should have_link(@issue1.title, href: project_issue_path(@project1, @issue1))
-    page.should have_link(@mr3.title, href: project_merge_request_path(@project3, @mr3))
+    page.should have_link(@issue1.title, href: namespace_project_issue_path(@project1.namespace, @project1, @issue1))
+    page.should have_link(@mr3.title, href: namespace_project_merge_request_path(@project3.namespace, @project3, @mr3))
   end
 
   protected
diff --git a/features/steps/profile/notifications.rb b/features/steps/profile/notifications.rb
index df96dddd06ebf71030d3f205e2d0abb60998d77e..13e93618eb748d8f11c83cf1d8aa83f5991bba0d 100644
--- a/features/steps/profile/notifications.rb
+++ b/features/steps/profile/notifications.rb
@@ -7,6 +7,6 @@ class Spinach::Features::ProfileNotifications < Spinach::FeatureSteps
   end
 
   step 'I should see global notifications settings' do
-    page.should have_content "Notifications settings"
+    page.should have_content "Notifications Settings"
   end
 end
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
index 6d747b65bae29bac72c8a758dde317210d7fe02b..791982d16c3b433b87cac034ddc168d813965b94 100644
--- a/features/steps/profile/profile.rb
+++ b/features/steps/profile/profile.rb
@@ -3,7 +3,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
   include SharedPaths
 
   step 'I should see my profile info' do
-    page.should have_content "Profile settings"
+    page.should have_content "Profile Settings"
   end
 
   step 'I change my profile info' do
@@ -11,6 +11,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
     fill_in "user_linkedin", with: "testlinkedin"
     fill_in "user_twitter", with: "testtwitter"
     fill_in "user_website_url", with: "testurl"
+    fill_in "user_location", with: "Ukraine"
     click_button "Save changes"
     @user.reload
   end
@@ -20,6 +21,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
     @user.linkedin.should == 'testlinkedin'
     @user.twitter.should == 'testtwitter'
     @user.website_url.should == 'testurl'
+    find("#user_location").value.should == "Ukraine"
   end
 
   step 'I change my avatar' do
@@ -29,7 +31,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
   end
 
   step 'I should see new avatar' do
-    @user.avatar.should be_instance_of AttachmentUploader
+    @user.avatar.should be_instance_of AvatarUploader
     @user.avatar.url.should == "/uploads/user/avatar/#{ @user.id }/gitlab_logo.png"
   end
 
@@ -58,34 +60,16 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
 
   step 'I try change my password w/o old one' do
     within '.update-password' do
-      fill_in "user_password_profile", with: "22233344"
+      fill_in "user_password", with: "22233344"
       fill_in "user_password_confirmation", with: "22233344"
       click_button "Save"
     end
   end
 
-  step 'I try to set a weak password' do
-    within '.update-password' do
-      fill_in "user_password_profile", with: "22233344"
-    end
-  end
-
-  step 'I try to set a short password' do
-    within '.update-password' do
-      fill_in "user_password_profile", with: "short"
-    end
-  end
-
-  step 'I try to set a strong password' do
-    within '.update-password' do
-      fill_in "user_password_profile", with: "Itulvo9z8uud%$"
-    end
-  end
-
   step 'I change my password' do
     within '.update-password' do
       fill_in "user_current_password", with: "12345678"
-      fill_in "user_password_profile", with: "22233344"
+      fill_in "user_password", with: "22233344"
       fill_in "user_password_confirmation", with: "22233344"
       click_button "Save"
     end
@@ -94,7 +78,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
   step 'I unsuccessfully change my password' do
     within '.update-password' do
       fill_in "user_current_password", with: "12345678"
-      fill_in "user_password_profile", with: "password"
+      fill_in "user_password", with: "password"
       fill_in "user_password_confirmation", with: "confirmation"
       click_button "Save"
     end
@@ -104,22 +88,6 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
     page.should have_content "You must provide a valid current password"
   end
 
-  step 'I should see the input field yellow' do
-    page.should have_css 'div.has-warning'
-  end
-
-  step 'I should see the input field green' do
-    page.should have_css 'div.has-success'
-  end
-
-  step 'I should see the input field red' do
-    page.should have_css 'div.has-error'
-  end
-
-  step 'I should see the password error message' do
-    page.should have_content 'Your password is too short'
-  end
-
   step "I should see a password error message" do
     page.should have_content "Password confirmation doesn't match"
   end
@@ -170,7 +138,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
   end
 
   step "I am not an ldap user" do
-    current_user.update_attributes(extern_uid: nil,  provider: '')
+    current_user.identities.delete
     current_user.ldap_user?.should be_false
   end
 
@@ -180,7 +148,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
 
   step 'I submit new password' do
     fill_in :user_current_password, with: '12345678'
-    fill_in :user_password_profile, with: '12345678'
+    fill_in :user_password, with: '12345678'
     fill_in :user_password_confirmation, with: '12345678'
     click_button "Set new password"
   end
@@ -221,4 +189,54 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
   step 'I should see groups I belong to' do
     page.should have_css('.profile-groups-avatars', visible: true)
   end
+
+  step 'I click on new application button' do
+    click_on 'New Application'
+  end
+
+  step 'I should see application form' do
+    page.should have_content "New application"
+  end
+
+  step 'I fill application form out and submit' do
+    fill_in :doorkeeper_application_name, with: 'test'
+    fill_in :doorkeeper_application_redirect_uri, with: 'https://test.com'
+    click_on "Submit"
+  end
+
+  step 'I see application' do
+    page.should have_content "Application: test"
+    page.should have_content "Application Id"
+    page.should have_content "Secret"
+  end
+
+  step 'I click edit' do
+    click_on "Edit"
+  end
+
+  step 'I see edit application form' do
+    page.should have_content "Edit application"
+  end
+
+  step 'I change name of application and submit' do
+    page.should have_content "Edit application"
+    fill_in :doorkeeper_application_name, with: 'test_changed'
+    click_on "Submit"
+  end
+
+  step 'I see that application was changed' do
+    page.should have_content "test_changed"
+    page.should have_content "Application Id"
+    page.should have_content "Secret"
+  end
+
+  step 'I click to remove application' do
+    within '.oauth-applications' do
+      click_on "Destroy"
+    end
+  end
+
+  step "I see that application is removed" do
+    page.find(".oauth-applications").should_not have_content "test_changed"
+  end
 end
diff --git a/features/steps/profile/ssh_keys.rb b/features/steps/profile/ssh_keys.rb
index d1e87d407054123511d48ca00250c69a08cfde05..ea912e5b4da0c10f271db8ba8ca9593354d2da2f 100644
--- a/features/steps/profile/ssh_keys.rb
+++ b/features/steps/profile/ssh_keys.rb
@@ -37,9 +37,7 @@ class Spinach::Features::ProfileSshKeys < Spinach::FeatureSteps
   end
 
   step 'I should not see "Work" ssh key' do
-    within "#keys-table" do
-      page.should_not have_content "Work"
-    end
+    page.should_not have_content "Work"
   end
 
   step 'I have ssh key "ssh-rsa Work"' do
diff --git a/features/steps/project/active_tab.rb b/features/steps/project/active_tab.rb
index 83796b0ba881b755a30ec43a232ea6d674d9e70e..dd3215adb1a2a4ee84f67c7d7d322109f69214a9 100644
--- a/features/steps/project/active_tab.rb
+++ b/features/steps/project/active_tab.rb
@@ -89,15 +89,15 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
     click_link('Labels')
   end
 
-  step 'the active sub tab should be Browse Issues' do
-    ensure_active_sub_tab('Browse Issues')
+  step 'the active sub tab should be Issues' do
+    ensure_active_sub_tab('Issues')
   end
 
-  step 'the active sub tab should be Milestones' do
-    ensure_active_sub_tab('Milestones')
+  step 'the active main tab should be Milestones' do
+    ensure_active_main_tab('Milestones')
   end
 
-  step 'the active sub tab should be Labels' do
-    ensure_active_sub_tab('Labels')
+  step 'the active main tab should be Labels' do
+    ensure_active_main_tab('Labels')
   end
 end
diff --git a/features/steps/project/archived.rb b/features/steps/project/archived.rb
index afbf4d5950dbf39856d4ba94f8402dfbdea11cd1..37ad0c776555da2384d9d501d2109f96daf5a8c6 100644
--- a/features/steps/project/archived.rb
+++ b/features/steps/project/archived.rb
@@ -15,7 +15,7 @@ class Spinach::Features::ProjectArchived < Spinach::FeatureSteps
 
   When 'I visit project "Forum" page' do
     project = Project.find_by(name: "Forum")
-    visit project_path(project)
+    visit namespace_project_path(project.namespace, project)
   end
 
   step 'I should not see "Archived"' do
diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb
index 935f313e2981c9c19ee76e68d18515b72bcfa44a..57b727f837ed4d007f881f9c7dc551a16d3c7077 100644
--- a/features/steps/project/commits/commits.rb
+++ b/features/steps/project/commits/commits.rb
@@ -24,7 +24,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
   end
 
   step 'I click on commit link' do
-    visit project_commit_path(@project, sample_commit.id)
+    visit namespace_project_commit_path(@project.namespace, @project, sample_commit.id)
   end
 
   step 'I see commit info' do
@@ -38,6 +38,18 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
     click_button "Compare"
   end
 
+  step 'I unfold diff' do
+    @diff = first('.js-unfold')
+    @diff.click
+    sleep 2
+  end
+
+  step 'I should see additional file lines' do
+    within @diff.parent do
+      first('.new_line').text.should_not have_content "..."
+    end
+  end
+
   step 'I see compared refs' do
     page.should have_content "Compare View"
     page.should have_content "Commits (1)"
@@ -58,7 +70,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
 
   step 'I visit big commit page' do
     Commit::DIFF_SAFE_FILES = 20
-    visit project_commit_path(@project, sample_big_commit.id)
+    visit namespace_project_commit_path(@project.namespace, @project, sample_big_commit.id)
   end
 
   step 'I see big commit warning' do
@@ -68,7 +80,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
   end
 
   step 'I visit a commit with an image that changed' do
-    visit project_commit_path(@project, sample_image_commit.id)
+    visit namespace_project_commit_path(@project.namespace, @project, sample_image_commit.id)
   end
 
   step 'The diff links to both the previous and current image' do
@@ -78,14 +90,14 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
   end
 
   step 'I click side-by-side diff button' do
-    click_link "Side-by-side Diff"
+    click_link "Side-by-side"
   end
 
   step 'I see side-by-side diff button' do
-    page.should have_content "Side-by-side Diff"
+    page.should have_content "Side-by-side"
   end
 
   step 'I see inline diff button' do
-    page.should have_content "Inline Diff"
+    page.should have_content "Inline"
   end
 end
diff --git a/features/steps/project/commits/user_lookup.rb b/features/steps/project/commits/user_lookup.rb
index 0622fef43bb3cfaa9dba847b3e1d4c1a9e57fb01..63ff84c82ef0645a0d08fbc53bc8b506f54106c5 100644
--- a/features/steps/project/commits/user_lookup.rb
+++ b/features/steps/project/commits/user_lookup.rb
@@ -4,11 +4,11 @@ class Spinach::Features::ProjectCommitsUserLookup < Spinach::FeatureSteps
   include SharedPaths
 
   step 'I click on commit link' do
-    visit project_commit_path(@project, sample_commit.id)
+    visit namespace_project_commit_path(@project.namespace, @project, sample_commit.id)
   end
 
   step 'I click on another commit link' do
-    visit project_commit_path(@project, sample_commit.parent_id)
+    visit namespace_project_commit_path(@project.namespace, @project, sample_commit.parent_id)
   end
 
   step 'I have user with primary email' do
diff --git a/features/steps/project/create.rb b/features/steps/project/create.rb
index e1062a6ce39d99f65fa61858946228ac3ff4ca8a..6b85cf74f5f239b718ff0085cf7ea252ad71c32f 100644
--- a/features/steps/project/create.rb
+++ b/features/steps/project/create.rb
@@ -3,13 +3,13 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps
   include SharedPaths
 
   step 'fill project form with valid data' do
-    fill_in 'project_name', with: 'Empty'
+    fill_in 'project_path', with: 'Empty'
     click_button "Create project"
   end
 
   step 'I should see project page' do
     page.should have_content "Empty"
-    current_path.should == project_path(Project.last)
+    current_path.should == namespace_project_path(Project.last.namespace, Project.last)
   end
 
   step 'I should see empty project instuctions' do
diff --git a/features/steps/project/deploy_keys.rb b/features/steps/project/deploy_keys.rb
index 914da31322f6c42beb0bb7d4d565e3ef39719e1c..4bf5cb5fa40bbb3077805fbb25afb614a5c0b3bf 100644
--- a/features/steps/project/deploy_keys.rb
+++ b/features/steps/project/deploy_keys.rb
@@ -24,7 +24,7 @@ class Spinach::Features::ProjectDeployKeys < Spinach::FeatureSteps
   end
 
   step 'I should be on deploy keys page' do
-    current_path.should == project_deploy_keys_path(@project)
+    current_path.should == namespace_project_deploy_keys_path(@project.namespace, @project)
   end
 
   step 'I should see newly created deploy key' do
diff --git a/features/steps/project/fork.rb b/features/steps/project/fork.rb
index da50ba9ced062908ea3946ec440e142c605b8775..8e58597db205f47ea0b4ad4076903cfc1817c005 100644
--- a/features/steps/project/fork.rb
+++ b/features/steps/project/fork.rb
@@ -25,4 +25,10 @@ class Spinach::Features::ProjectFork < Spinach::FeatureSteps
   step 'I should see a "Name has already been taken" warning' do
     page.should have_content "Name has already been taken"
   end
+
+  step 'I fork to my namespace' do
+    within '.fork-namespaces' do
+      click_link current_user.name
+    end
+  end
 end
diff --git a/features/steps/project/forked_merge_requests.rb b/features/steps/project/forked_merge_requests.rb
index ccef84cdcc5cf9550f32385d2bcc407aec6ec069..63ad90e124135bc42b81fd4ce52109b5b43fe7f4 100644
--- a/features/steps/project/forked_merge_requests.rb
+++ b/features/steps/project/forked_merge_requests.rb
@@ -23,7 +23,7 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
   step 'I should see merge request "Merge Request On Forked Project"' do
     @project.merge_requests.size.should >= 1
     @merge_request = @project.merge_requests.last
-    current_path.should == project_merge_request_path(@project, @merge_request)
+    current_path.should == namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
     @merge_request.title.should == "Merge Request On Forked Project"
     @merge_request.source_project.should == @forked_project
     @merge_request.source_branch.should == "fix"
@@ -64,14 +64,14 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I see prefilled new Merge Request page for the forked project' do
-    current_path.should == new_project_merge_request_path(@forked_project)
+    current_path.should == new_namespace_project_merge_request_path(@forked_project.namespace, @forked_project)
     find("#merge_request_source_project_id").value.should == @forked_project.id.to_s
     find("#merge_request_target_project_id").value.should == @project.id.to_s
     find("#merge_request_source_branch").value.should have_content "new_design"
     find("#merge_request_target_branch").value.should have_content "master"
     find("#merge_request_title").value.should == "New Design"
-    verify_commit_link(".mr_target_commit",@project)
-    verify_commit_link(".mr_source_commit",@forked_project)
+    verify_commit_link(".mr_target_commit", @project)
+    verify_commit_link(".mr_source_commit", @forked_project)
   end
 
   step 'I update the merge request title' do
@@ -86,7 +86,7 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
     page.should have_content "An Edited Forked Merge Request"
     @project.merge_requests.size.should >= 1
     @merge_request = @project.merge_requests.last
-    current_path.should == project_merge_request_path(@project, @merge_request)
+    current_path.should == namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
     @merge_request.source_project.should == @forked_project
     @merge_request.source_branch.should == "fix"
     @merge_request.target_branch.should == "master"
@@ -106,7 +106,7 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I see the edit page prefilled for "Merge Request On Forked Project"' do
-    current_path.should == edit_project_merge_request_path(@project, @merge_request)
+    current_path.should == edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
     page.should have_content "Edit merge request ##{@merge_request.id}"
     find("#merge_request_title").value.should == "Merge Request On Forked Project"
   end
@@ -114,7 +114,7 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
   step 'I fill out an invalid "Merge Request On Forked Project" merge request' do
     select "Select branch", from: "merge_request_target_branch"
     find(:select, "merge_request_source_project_id", {}).value.should == @forked_project.id.to_s
-    find(:select, "merge_request_target_project_id", {}).value.should == project.id.to_s
+    find(:select, "merge_request_target_project_id", {}).value.should == @project.id.to_s
     find(:select, "merge_request_source_branch", {}).value.should == ""
     find(:select, "merge_request_target_branch", {}).value.should == ""
     click_button "Compare branches"
@@ -125,7 +125,7 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
   end
 
   step 'the target repository should be the original repository' do
-    page.should have_select("merge_request_target_project_id", selected: project.path_with_namespace)
+    page.should have_select("merge_request_target_project_id", selected: @project.path_with_namespace)
   end
 
   # Verify a link is generated against the correct project
diff --git a/features/steps/project/graph.rb b/features/steps/project/graph.rb
index ba460ac8097c928fb33cce4edd0bc63d5645c4fa..a2807c340f6824156c17315bf270f9b377cd26d2 100644
--- a/features/steps/project/graph.rb
+++ b/features/steps/project/graph.rb
@@ -8,16 +8,16 @@ class Spinach::Features::ProjectGraph < Spinach::FeatureSteps
 
   When 'I visit project "Shop" graph page' do
     project = Project.find_by(name: "Shop")
-    visit project_graph_path(project, "master")
+    visit namespace_project_graph_path(project.namespace, project, "master")
   end
 
   step 'I visit project "Shop" commits graph page' do
     project = Project.find_by(name: "Shop")
-    visit commits_project_graph_path(project, "master")
+    visit commits_namespace_project_graph_path(project.namespace, project, "master")
   end
 
   step 'page should have commits graphs' do
-    page.should have_content "Commits statistic for master"
+    page.should have_content "Commit statistics for master"
     page.should have_content "Commits per day of month"
   end
 end
diff --git a/features/steps/project/hooks.rb b/features/steps/project/hooks.rb
index f4b8d372be8fcd8dd43505d010aa8ac8e32f2b65..4b1352025934e64da3bfb20ea3d28246b29d3206 100644
--- a/features/steps/project/hooks.rb
+++ b/features/steps/project/hooks.rb
@@ -29,7 +29,7 @@ class Spinach::Features::ProjectHooks < Spinach::FeatureSteps
   end
 
   step 'I should see newly created hook' do
-    current_path.should == project_hooks_path(current_project)
+    current_path.should == namespace_project_hooks_path(current_project.namespace, current_project)
     page.should have_content(@url)
   end
 
@@ -44,7 +44,7 @@ class Spinach::Features::ProjectHooks < Spinach::FeatureSteps
   end
 
   step 'hook should be triggered' do
-    current_path.should == project_hooks_path(current_project)
+    current_path.should == namespace_project_hooks_path(current_project.namespace, current_project)
     page.should have_selector '.flash-notice',
                               text: 'Hook successfully executed.'
   end
diff --git a/features/steps/project/issue_tracker.rb b/features/steps/project/issue_tracker.rb
deleted file mode 100644
index e1700292701f76725af0b4d45f46141c6a9bdc99..0000000000000000000000000000000000000000
--- a/features/steps/project/issue_tracker.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-class Spinach::Features::ProjectIssueTracker < Spinach::FeatureSteps
-  include SharedAuthentication
-  include SharedProject
-  include SharedPaths
-
-  step 'project "Shop" has issues enabled' do
-    @project = Project.find_by(name: "Shop")
-    @project ||= create(:project, name: "Shop", namespace: @user.namespace)
-    @project.issues_enabled = true
-  end
-
-  step 'change the issue tracker to "GitLab"' do
-    select 'GitLab', from: 'project_issues_tracker'
-  end
-
-  step 'I the project should have "GitLab" as issue tracker' do
-    find_field('project_issues_tracker').value.should == 'gitlab'
-  end
-
-  step 'change the issue tracker to "Redmine"' do
-    select 'Redmine', from: 'project_issues_tracker'
-  end
-
-  step 'I the project should have "Redmine" as issue tracker' do
-    find_field('project_issues_tracker').value.should == 'redmine'
-  end
-
-  step 'I save project' do
-    click_button 'Save changes'
-  end
-end
diff --git a/features/steps/project/issues/filter_labels.rb b/features/steps/project/issues/filter_labels.rb
index e62fa9c84c8490a847a147408b19839baf87a697..5740bd12837ba6aa0e1a5f172270c9beecc42d07 100644
--- a/features/steps/project/issues/filter_labels.rb
+++ b/features/steps/project/issues/filter_labels.rb
@@ -2,24 +2,7 @@ class Spinach::Features::ProjectIssuesFilterLabels < Spinach::FeatureSteps
   include SharedAuthentication
   include SharedProject
   include SharedPaths
-
-  step 'I should see "bug" in labels filter' do
-    within ".labels-filter" do
-      page.should have_content "bug"
-    end
-  end
-
-  step 'I should see "feature" in labels filter' do
-    within ".labels-filter" do
-      page.should have_content "feature"
-    end
-  end
-
-  step 'I should see "enhancement" in labels filter' do
-    within ".labels-filter" do
-      page.should have_content "enhancement"
-    end
-  end
+  include Select2Helper
 
   step 'I should see "Bugfix1" in issues list' do
     within ".issues-list" do
@@ -46,9 +29,7 @@ class Spinach::Features::ProjectIssuesFilterLabels < Spinach::FeatureSteps
   end
 
   step 'I click link "bug"' do
-    within ".labels-filter" do
-      click_link "bug"
-    end
+    select2('bug', from: "#label_name")
   end
 
   step 'I click link "feature"' do
diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb
index 640603562ddd72de90130e23f5a1dd33952d74e9..e8ca3f7c1761c846a6e1d19af9db0ceb02d6a05f 100644
--- a/features/steps/project/issues/issues.rb
+++ b/features/steps/project/issues/issues.rb
@@ -1,5 +1,6 @@
 class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
   include SharedAuthentication
+  include SharedIssuable
   include SharedProject
   include SharedNote
   include SharedPaths
@@ -17,10 +18,23 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
     page.should_not have_content "Tweet control"
   end
 
+  step 'I should see that I am subscribed' do
+    find(".subscribe-button span").text.should == "Unsubscribe"
+  end
+
+  step 'I should see that I am unsubscribed' do
+    sleep 0.2
+    find(".subscribe-button span").text.should == "Subscribe"
+  end
+
   step 'I click link "Closed"' do
     click_link "Closed"
   end
 
+  step 'I click button "Unsubscribe"' do
+    click_on "Unsubscribe"
+  end
+
   step 'I should see "Release 0.3" in issues' do
     page.should have_content "Release 0.3"
   end
@@ -167,7 +181,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
 
   When 'I visit empty project page' do
     project = Project.find_by(name: 'Empty Project')
-    visit project_path(project)
+    visit namespace_project_path(project.namespace, project)
   end
 
   step 'I see empty project details with ssh clone info' do
@@ -179,7 +193,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
 
   When "I visit empty project's issues page" do
     project = Project.find_by(name: 'Empty Project')
-    visit project_issues_path(project)
+    visit namespace_project_issues_path(project.namespace, project)
   end
 
   step 'I leave a comment with code block' do
diff --git a/features/steps/project/issues/labels.rb b/features/steps/project/issues/labels.rb
index 3e3e90824b476e450440f4ecc2637a784b68d1d7..6ce34c500c6f5d1ffc494a711f0dc9fb2d929976 100644
--- a/features/steps/project/issues/labels.rb
+++ b/features/steps/project/issues/labels.rb
@@ -4,7 +4,7 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps
   include SharedPaths
 
   step 'I visit \'bug\' label edit page' do
-    visit edit_project_label_path(project, bug_label)
+    visit edit_namespace_project_label_path(project.namespace, project, bug_label)
   end
 
   step 'I remove label \'bug\'' do
diff --git a/features/steps/project/issues/milestones.rb b/features/steps/project/issues/milestones.rb
index 89d7af3c9ee415b3dee7780a80d887331695c00a..cce87a6d9817a192da022c3f36f6afd0d1ac5129 100644
--- a/features/steps/project/issues/milestones.rb
+++ b/features/steps/project/issues/milestones.rb
@@ -8,7 +8,7 @@ class Spinach::Features::ProjectIssuesMilestones < Spinach::FeatureSteps
     milestone = @project.milestones.find_by(title: "v2.2")
     page.should have_content(milestone.title[0..10])
     page.should have_content(milestone.expires_at)
-    page.should have_content("Browse Issues")
+    page.should have_content("Issues")
   end
 
   step 'I click link "v2.2"' do
@@ -28,7 +28,7 @@ class Spinach::Features::ProjectIssuesMilestones < Spinach::FeatureSteps
     milestone = @project.milestones.find_by(title: "v2.3")
     page.should have_content(milestone.title[0..10])
     page.should have_content(milestone.expires_at)
-    page.should have_content("Browse Issues")
+    page.should have_content("Issues")
   end
 
   step 'project "Shop" has milestone "v2.2"' do
diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb
index fae0cec53a64a3e29304294dc451e3b4a01e53b7..40c102833a46bf6254c9debfd7daceee8d4f15e2 100644
--- a/features/steps/project/merge_requests.rb
+++ b/features/steps/project/merge_requests.rb
@@ -1,5 +1,6 @@
 class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
   include SharedAuthentication
+  include SharedIssuable
   include SharedProject
   include SharedNote
   include SharedPaths
@@ -55,10 +56,21 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
     page.should_not have_content "Bug NS-04"
   end
 
+  step 'I should see that I am subscribed' do
+    find(".subscribe-button span").text.should == "Unsubscribe"
+  end
+
+  step 'I should see that I am unsubscribed' do
+    sleep 0.2
+    find(".subscribe-button span").text.should == "Subscribe"
+  end
+
+  step 'I click button "Unsubscribe"' do
+    click_on "Unsubscribe"
+  end
+
   step 'I click link "Close"' do
-    within '.page-title' do
-      click_link "Close"
-    end
+    first(:css, '.close-mr-link').click
   end
 
   step 'I submit new merge request "Wiki Feature"' do
@@ -102,15 +114,33 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I switch to the diff tab' do
-    visit diffs_project_merge_request_path(project, merge_request)
+    visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)
+  end
+
+  step 'I click on the Changes tab via Javascript' do
+    find('.diffs-tab').click
+    sleep 2
+  end
+
+  step 'I should see the proper Inline and Side-by-side links' do
+    buttons = all('#commit-diff-viewtype')
+    expect(buttons.count).to eq(2)
+
+    buttons.each do |b|
+      expect(b['href']).should_not have_content('json')
+    end
   end
 
   step 'I switch to the merge request\'s comments tab' do
-    visit project_merge_request_path(project, merge_request)
+    visit namespace_project_merge_request_path(project.namespace, project, merge_request)
   end
 
   step 'I click on the commit in the merge request' do
-    within '.mr-commits' do
+    within '.merge-request-tabs' do
+      click_link 'Commits'
+    end
+
+    within '.commits' do
       click_link Commit.truncate_sha(sample_commit.id)
     end
   end
@@ -153,7 +183,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
   end
 
   step 'merge request is mergeable' do
-    page.should have_content 'You can accept this request automatically'
+    page.should have_button 'Accept Merge Request'
   end
 
   step 'I modify merge commit message' do
@@ -170,7 +200,9 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
       merge!: true,
     )
 
-    click_button "Accept Merge Request"
+    within '.can_be_merged' do
+      click_button "Accept Merge Request"
+    end
   end
 
   step 'I should see merged request' do
@@ -180,26 +212,24 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I click link "Reopen"' do
-    within '.page-title' do
-      click_link "Reopen"
-    end
+    first(:css, '.reopen-mr-link').click
   end
 
   step 'I should see reopened merge request "Bug NS-04"' do
-    within '.state-label' do
+    within '.issue-box' do
       page.should have_content "Open"
     end
   end
 
   step 'I click link "Hide inline discussion" of the second file' do
     within '.files [id^=diff]:nth-child(2)' do
-      click_link "Diff comments"
+      find('.js-toggle-diff-comments').click
     end
   end
 
   step 'I click link "Show inline discussion" of the second file' do
     within '.files [id^=diff]:nth-child(2)' do
-      click_link "Diff comments"
+      find('.js-toggle-diff-comments').click
     end
   end
 
@@ -210,7 +240,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I should see a comment like "Line is wrong" in the second file' do
-    within '.files [id^=diff]:nth-child(2) .note-text' do
+    within '.files [id^=diff]:nth-child(2) .note-body > .note-text' do
       page.should have_visible_content "Line is wrong"
     end
   end
@@ -222,7 +252,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I should see a comment like "Line is wrong here" in the second file' do
-    within '.files [id^=diff]:nth-child(2) .note-text' do
+    within '.files [id^=diff]:nth-child(2) .note-body > .note-text' do
       page.should have_visible_content "Line is wrong here"
     end
   end
@@ -235,7 +265,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
       click_button "Add Comment"
     end
 
-    within ".files [id^=diff]:nth-child(1) .note-text" do
+    within ".files [id^=diff]:nth-child(1) .note-body > .note-text" do
       page.should have_content "Line is correct"
     end
   end
@@ -250,7 +280,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I should still see a comment like "Line is correct" in the first file' do
-    within '.files [id^=diff]:nth-child(1) .note-text' do
+    within '.files [id^=diff]:nth-child(1) .note-body > .note-text' do
       page.should have_visible_content "Line is correct"
     end
   end
@@ -264,15 +294,19 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I click Side-by-side Diff tab' do
-    click_link 'Side-by-side Diff'
+    find('a', text: 'Side-by-side').trigger('click')
   end
 
   step 'I should see comments on the side-by-side diff page' do
-    within '.files [id^=diff]:nth-child(1) .note-text' do
+    within '.files [id^=diff]:nth-child(1) .parallel .note-body > .note-text' do
       page.should have_visible_content "Line is correct"
     end
   end
 
+  step 'I fill in merge request search with "Fe"' do
+    fill_in 'issue_search', with: "Fe"
+  end
+
   def merge_request
     @merge_request ||= MergeRequest.find_by!(title: "Bug NS-05")
   end
diff --git a/features/steps/project/network_graph.rb b/features/steps/project/network_graph.rb
index 14fdc72b8b67325ac010a0ef10e0805b9e8e469d..a15688ace6aef3f4ab15ccc3e3ab51553fb4b142 100644
--- a/features/steps/project/network_graph.rb
+++ b/features/steps/project/network_graph.rb
@@ -12,7 +12,7 @@ class Spinach::Features::ProjectNetworkGraph < Spinach::FeatureSteps
     Network::Graph.stub(max_count: 10)
 
     project = Project.find_by(name: "Shop")
-    visit project_network_path(project, "master")
+    visit namespace_project_network_path(project.namespace, project, "master")
   end
 
   step 'page should select "master" in select box' do
diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb
index 5e7312d90ffca01706671b75cdf5b7a5bea6c8a5..d39c8e7d2db82d10935ce52e5b06aa716c080db0 100644
--- a/features/steps/project/project.rb
+++ b/features/steps/project/project.rb
@@ -17,17 +17,58 @@ class Spinach::Features::Project < Spinach::FeatureSteps
   end
 
   step 'change project path settings' do
-    fill_in "project_path", with: "new-path"
-    click_button "Rename"
+    fill_in 'project_path', with: 'new-path'
+    click_button 'Rename'
   end
 
   step 'I should see project with new path settings' do
-    project.path.should == "new-path"
+    project.path.should == 'new-path'
+  end
+
+  step 'I change the project avatar' do
+    attach_file(
+      :project_avatar,
+      File.join(Rails.root, 'public', 'gitlab_logo.png')
+    )
+    click_button 'Save changes'
+    @project.reload
+  end
+
+  step 'I should see new project avatar' do
+    @project.avatar.should be_instance_of AvatarUploader
+    url = @project.avatar.url
+    url.should == "/uploads/project/avatar/#{ @project.id }/gitlab_logo.png"
+  end
+
+  step 'I should see the "Remove avatar" button' do
+    page.should have_link('Remove avatar')
+  end
+
+  step 'I have an project avatar' do
+    attach_file(
+      :project_avatar,
+      File.join(Rails.root, 'public', 'gitlab_logo.png')
+    )
+    click_button 'Save changes'
+    @project.reload
+  end
+
+  step 'I remove my project avatar' do
+    click_link 'Remove avatar'
+    @project.reload
+  end
+
+  step 'I should see the default project avatar' do
+    @project.avatar?.should be_false
+  end
+
+  step 'I should not see the "Remove avatar" button' do
+    page.should_not have_link('Remove avatar')
   end
 
   step 'I should see project "Shop" version' do
     within '.project-side' do
-      page.should have_content "Version: 6.7.0.pre"
+      page.should have_content 'Version: 6.7.0.pre'
     end
   end
 
@@ -45,12 +86,12 @@ class Spinach::Features::Project < Spinach::FeatureSteps
   end
 
   step 'I should see project "Forum" README' do
-    page.should have_link "README.md"
-    page.should have_content "Sample repo for testing gitlab features"
+    page.should have_link 'README.md'
+    page.should have_content 'Sample repo for testing gitlab features'
   end
 
   step 'I should see project "Shop" README' do
-    page.should have_link "README.md"
-    page.should have_content "testme"
+    page.should have_link 'README.md'
+    page.should have_content 'testme'
   end
 end
diff --git a/features/steps/project/redirects.rb b/features/steps/project/redirects.rb
index e54637120ce685fa1b9efa112671c803c26fca90..57c6e39c80198e49ba25da6cd889f65b4a4936e3 100644
--- a/features/steps/project/redirects.rb
+++ b/features/steps/project/redirects.rb
@@ -13,11 +13,11 @@ class Spinach::Features::ProjectRedirects < Spinach::FeatureSteps
 
   step 'I visit project "Community" page' do
     project = Project.find_by(name: 'Community')
-    visit project_path(project)
+    visit namespace_project_path(project.namespace, project)
   end
 
   step 'I should see project "Community" home page' do
-    Gitlab.config.gitlab.stub(:host).and_return("www.example.com")
+    Gitlab.config.gitlab.should_receive(:host).and_return("www.example.com")
     within '.navbar-gitlab .title' do
       page.should have_content 'Community'
     end
@@ -25,12 +25,12 @@ class Spinach::Features::ProjectRedirects < Spinach::FeatureSteps
 
   step 'I visit project "Enterprise" page' do
     project = Project.find_by(name: 'Enterprise')
-    visit project_path(project)
+    visit namespace_project_path(project.namespace, project)
   end
 
   step 'I visit project "CommunityDoesNotExist" page' do
     project = Project.find_by(name: 'Community')
-    visit project_path(project) + 'DoesNotExist'
+    visit namespace_project_path(project.namespace, project) + 'DoesNotExist'
   end
 
   step 'I click on "Sign In"' do
diff --git a/features/steps/project/services.rb b/features/steps/project/services.rb
index d5d58070d8632011bc3721240943f59861481327..4b3d79324ab62facffa21048e6f2165a3c4b09c5 100644
--- a/features/steps/project/services.rb
+++ b/features/steps/project/services.rb
@@ -4,17 +4,20 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
   include SharedPaths
 
   step 'I visit project "Shop" services page' do
-    visit project_services_path(@project)
+    visit namespace_project_services_path(@project.namespace, @project)
   end
 
   step 'I should see list of available services' do
     page.should have_content 'Project services'
     page.should have_content 'Campfire'
-    page.should have_content 'Hipchat'
+    page.should have_content 'HipChat'
     page.should have_content 'GitLab CI'
     page.should have_content 'Assembla'
     page.should have_content 'Pushover'
     page.should have_content 'Atlassian Bamboo'
+    page.should have_content 'JetBrains TeamCity'
+    page.should have_content 'Asana'
+    page.should have_content 'Irker (IRC gateway)'
   end
 
   step 'I click gitlab-ci service link' do
@@ -33,7 +36,7 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
   end
 
   step 'I click hipchat service link' do
-    click_link 'Hipchat'
+    click_link 'HipChat'
   end
 
   step 'I fill hipchat settings' do
@@ -47,6 +50,17 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
     find_field('Room').value.should == 'gitlab'
   end
 
+  step 'I fill hipchat settings with custom server' do
+    check 'Active'
+    fill_in 'Room', with: 'gitlab_custom'
+    fill_in 'Token', with: 'secretCustom'
+    fill_in 'Server', with: 'https://chat.example.com'
+    click_button 'Save'
+  end
+
+  step 'I should see hipchat service settings with custom server saved' do
+    find_field('Server').value.should == 'https://chat.example.com'
+  end
 
   step 'I click pivotaltracker service link' do
     click_link 'PivotalTracker'
@@ -90,6 +104,22 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
     find_field('Token').value.should == 'verySecret'
   end
 
+  step 'I click Asana service link' do
+    click_link 'Asana'
+  end
+
+  step 'I fill Asana settings' do
+    check 'Active'
+    fill_in 'Api key', with: 'verySecret'
+    fill_in 'Restrict to branch', with: 'master'
+    click_button 'Save'
+  end
+
+  step 'I should see Asana service settings saved' do
+    find_field('Api key').value.should == 'verySecret'
+    find_field('Restrict to branch').value.should == 'master'
+  end
+
   step 'I click email on push service link' do
     click_link 'Emails on push'
   end
@@ -103,6 +133,22 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
     find_field('Recipients').value.should == 'qa@company.name'
   end
 
+  step 'I click Irker service link' do
+    click_link 'Irker (IRC gateway)'
+  end
+
+  step 'I fill Irker settings' do
+    check 'Active'
+    fill_in 'Recipients', with: 'irc://chat.freenode.net/#commits'
+    check 'Colorize messages'
+    click_button 'Save'
+  end
+
+  step 'I should see Irker service settings saved' do
+    find_field('Recipients').value.should == 'irc://chat.freenode.net/#commits'
+    find_field('Colorize messages').value.should == '1'
+  end
+
   step 'I click Slack service link' do
     click_link 'Slack'
   end
@@ -157,4 +203,23 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
     find_field('Build key').value.should == 'KEY'
     find_field('Username').value.should == 'user'
   end
+
+  step 'I click JetBrains TeamCity CI service link' do
+    click_link 'JetBrains TeamCity CI'
+  end
+
+  step 'I fill JetBrains TeamCity CI settings' do
+    check 'Active'
+    fill_in 'Teamcity url', with: 'http://teamcity.example.com'
+    fill_in 'Build type', with: 'GitlabTest_Build'
+    fill_in 'Username', with: 'user'
+    fill_in 'Password', with: 'verySecret'
+    click_button 'Save'
+  end
+
+  step 'I should see JetBrains TeamCity CI service settings saved' do
+    find_field('Teamcity url').value.should == 'http://teamcity.example.com'
+    find_field('Build type').value.should == 'GitlabTest_Build'
+    find_field('Username').value.should == 'user'
+  end
 end
diff --git a/features/steps/project/snippets.rb b/features/steps/project/snippets.rb
index 4a39bfdbb7937591fa6b3dd2a0b103a4a73f03ad..343aeb53b11e4d274dd63876a535c83916e4e95b 100644
--- a/features/steps/project/snippets.rb
+++ b/features/steps/project/snippets.rb
@@ -86,7 +86,7 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps
   end
 
   step 'I visit snippet page "Snippet one"' do
-    visit project_snippet_path(project, project_snippet)
+    visit namespace_project_snippet_path(project.namespace, project, project_snippet)
   end
 
   def project_snippet
diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb
index ddd501d4f88288159e9687794327715465d7f5f3..da0080afbaab65b1eef2c8fe867df83053e22a9e 100644
--- a/features/steps/project/source/browse_files.rb
+++ b/features/steps/project/source/browse_files.rb
@@ -11,7 +11,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I should see files from repository for "6d39438"' do
-    current_path.should == project_tree_path(@project, "6d39438")
+    current_path.should == namespace_project_tree_path(@project.namespace, @project, "6d39438")
     page.should have_content ".gitignore"
     page.should have_content "LICENSE"
   end
@@ -19,6 +19,10 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   step 'I see the ".gitignore"' do
     page.should have_content '.gitignore'
   end
+  
+  step 'I see the "user.feature"' do
+    page.should have_content 'user.feature'
+  end
 
   step 'I don\'t see the ".gitignore"' do
     page.should_not have_content '.gitignore'
@@ -35,6 +39,10 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   step 'I should see its new content' do
     page.should have_content new_gitignore_content
   end
+  
+  step 'I should see new file content' do
+    old_gitignore_content != '*.rbc'
+  end
 
   step 'I click link "Raw"' do
     click_link 'Raw'
@@ -48,9 +56,17 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
     click_link 'Edit'
   end
 
+  step 'I cannot see the edit button' do
+    page.should_not have_link 'edit'
+  end
+
+  step 'The edit button is disabled' do
+    page.should have_css '.disabled', text: 'Edit'
+  end
+
   step 'I can edit code' do
     set_new_content
-    evaluate_script('editor.getValue()').should == new_gitignore_content
+    evaluate_script('blob.editor.getValue()').should == new_gitignore_content
   end
 
   step 'I edit code' do
@@ -61,6 +77,10 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
     fill_in :file_name, with: new_file_name
   end
 
+  step 'I fill the new branch name' do
+    fill_in :new_branch, with: 'new_branch_name'
+  end
+
   step 'I fill the new file name with an illegal name' do
     fill_in :file_name, with: '.git'
   end
@@ -70,7 +90,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I click link "Diff"' do
-    click_link 'Diff'
+    click_link 'Preview changes'
   end
 
   step 'I click on "Commit Changes"' do
@@ -85,6 +105,14 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
     click_button 'Remove file'
   end
 
+  step 'I click on "Replace"' do
+    click_button  "Replace"
+  end
+  
+  step 'I click on "Replace file"' do
+    click_button  'Replace file'
+  end
+  
   step 'I see diff' do
     page.should have_css '.line_holder.new'
   end
@@ -95,10 +123,32 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
 
   step 'I can see new file page' do
     page.should have_content "New file"
-    page.should have_content "File name"
     page.should have_content "Commit message"
   end
 
+  step 'I click on "Upload" in repo' do
+    click_button "Upload"
+  end
+
+  step 'I click on "Upload file"' do
+    click_button 'Upload file'
+  end
+  
+  step 'I upload "user.feature"' do
+    attach_file(:file_upload, File.join('features', 'user.feature'))
+  end
+  
+  step 'I check name of the upload file' do
+    ".gitignore" != "user.feature"
+    "LICENSE" != "user.feature"
+    "VERSION" != "user.feature"
+  end
+  
+  step 'I replace it with "LICENSE"' do
+    attach_file(:file_upload, "LICENSE")
+    old_gitignore_content = "LICENSE"
+  end
+
   step 'I click on files directory' do
     click_link 'files'
   end
@@ -134,21 +184,33 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I am redirected to the files URL' do
-    current_path.should == project_tree_path(@project, 'master')
+    current_path.should == namespace_project_tree_path(@project.namespace, @project, 'master')
   end
 
   step 'I am redirected to the ".gitignore"' do
-    expect(current_path).to eq(project_blob_path(@project, 'master/.gitignore'))
+    expect(current_path).to eq(namespace_project_blob_path(@project.namespace, @project, 'master/.gitignore'))
+  end
+
+  step 'I am redirected to the ".gitignore" on new branch' do
+    expect(current_path).to eq(namespace_project_blob_path(@project.namespace, @project, 'new_branch_name/.gitignore'))
   end
 
   step 'I am redirected to the permalink URL' do
-    expect(current_path).to eq(project_blob_path(
-      @project, @project.repository.commit.sha + '/.gitignore'))
+    expect(current_path).to(
+      eq(namespace_project_blob_path(@project.namespace, @project,
+                                     @project.repository.commit.sha +
+                                     '/.gitignore'))
+    )
   end
 
   step 'I am redirected to the new file' do
-    expect(current_path).to eq(project_blob_path(
-      @project, 'master/' + new_file_name))
+    expect(current_path).to eq(namespace_project_blob_path(
+      @project.namespace, @project, 'master/' + new_file_name))
+  end
+
+  step 'I am redirected to the new file on new branch' do
+    expect(current_path).to eq(namespace_project_blob_path(
+      @project.namespace, @project, 'new_branch_name/' + new_file_name))
   end
 
   step "I don't see the permalink link" do
@@ -159,10 +221,21 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
     expect(page).to have_content('Your changes could not be committed')
   end
 
-  private
+  step 'I create bare repo' do
+    click_link 'Create empty bare repository'
+  end
+
+  step 'I click on "add a file" link' do
+    click_link 'add a file'
 
+    # Remove pre-receive hook so we can push without auth
+    FileUtils.rm_f(File.join(@project.repository.path, 'hooks', 'pre-receive'))
+  end
+
+  private
+  
   def set_new_content
-    execute_script("editor.setValue('#{new_gitignore_content}')")
+    execute_script("blob.editor.setValue('#{new_gitignore_content}')")
   end
 
   # Content of the gitignore file on the seed repository.
diff --git a/features/steps/project/source/markdown_render.rb b/features/steps/project/source/markdown_render.rb
index 53578ee5970ecb91ef712dd07f9603d10761c03c..7961fdedad8a906ca70e66c0f186ff2520936804 100644
--- a/features/steps/project/source/markdown_render.rb
+++ b/features/steps/project/source/markdown_render.rb
@@ -13,7 +13,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I should see files from repository in markdown' do
-    current_path.should == project_tree_path(@project, "markdown")
+    current_path.should == namespace_project_tree_path(@project.namespace, @project, "markdown")
     page.should have_content "README.md"
     page.should have_content "CHANGELOG"
   end
@@ -33,7 +33,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I should see correct document rendered' do
-    current_path.should == project_blob_path(@project, "markdown/doc/api/README.md")
+    current_path.should == namespace_project_blob_path(@project.namespace, @project, "markdown/doc/api/README.md")
     page.should have_content "All API requests require authentication"
   end
 
@@ -42,7 +42,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I should see correct directory rendered' do
-    current_path.should == project_tree_path(@project, "markdown/doc/raketasks")
+    current_path.should == namespace_project_tree_path(@project.namespace, @project, "markdown/doc/raketasks")
     page.should have_content "backup_restore.md"
     page.should have_content "maintenance.md"
   end
@@ -52,7 +52,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I should see correct doc/api directory rendered' do
-    current_path.should == project_tree_path(@project, "markdown/doc/api")
+    current_path.should == namespace_project_tree_path(@project.namespace, @project, "markdown/doc/api")
     page.should have_content "README.md"
     page.should have_content "users.md"
   end
@@ -62,7 +62,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I should see correct maintenance file rendered' do
-    current_path.should == project_blob_path(@project, "markdown/doc/raketasks/maintenance.md")
+    current_path.should == namespace_project_blob_path(@project.namespace, @project, "markdown/doc/raketasks/maintenance.md")
     page.should have_content "bundle exec rake gitlab:env:info RAILS_ENV=production"
   end
 
@@ -93,7 +93,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I see correct file rendered' do
-    current_path.should == project_blob_path(@project, "markdown/doc/api/README.md")
+    current_path.should == namespace_project_blob_path(@project.namespace, @project, "markdown/doc/api/README.md")
     page.should have_content "Contents"
     page.should have_link "Users"
     page.should have_link "Rake tasks"
@@ -104,7 +104,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I should see the correct document file' do
-    current_path.should == project_blob_path(@project, "markdown/doc/api/users.md")
+    current_path.should == namespace_project_blob_path(@project.namespace, @project, "markdown/doc/api/users.md")
     page.should have_content "Get a list of users."
   end
 
@@ -115,100 +115,100 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   # Markdown branch
 
   When 'I visit markdown branch' do
-    visit project_tree_path(@project, "markdown")
+    visit namespace_project_tree_path(@project.namespace, @project, "markdown")
   end
 
   When 'I visit markdown branch "README.md" blob' do
-    visit project_blob_path(@project, "markdown/README.md")
+    visit namespace_project_blob_path(@project.namespace, @project, "markdown/README.md")
   end
 
   When 'I visit markdown branch "d" tree' do
-    visit project_tree_path(@project, "markdown/d")
+    visit namespace_project_tree_path(@project.namespace, @project, "markdown/d")
   end
 
   When 'I visit markdown branch "d/README.md" blob' do
-    visit project_blob_path(@project, "markdown/d/README.md")
+    visit namespace_project_blob_path(@project.namespace, @project, "markdown/d/README.md")
   end
 
   step 'I should see files from repository in markdown branch' do
-    current_path.should == project_tree_path(@project, "markdown")
+    current_path.should == namespace_project_tree_path(@project.namespace, @project, "markdown")
     page.should have_content "README.md"
     page.should have_content "CHANGELOG"
   end
 
   step 'I see correct file rendered in markdown branch' do
-    current_path.should == project_blob_path(@project, "markdown/doc/api/README.md")
+    current_path.should == namespace_project_blob_path(@project.namespace, @project, "markdown/doc/api/README.md")
     page.should have_content "Contents"
     page.should have_link "Users"
     page.should have_link "Rake tasks"
   end
 
   step 'I should see correct document rendered for markdown branch' do
-    current_path.should == project_blob_path(@project, "markdown/doc/api/README.md")
+    current_path.should == namespace_project_blob_path(@project.namespace, @project, "markdown/doc/api/README.md")
     page.should have_content "All API requests require authentication"
   end
 
   step 'I should see correct directory rendered for markdown branch' do
-    current_path.should == project_tree_path(@project, "markdown/doc/raketasks")
+    current_path.should == namespace_project_tree_path(@project.namespace, @project, "markdown/doc/raketasks")
     page.should have_content "backup_restore.md"
     page.should have_content "maintenance.md"
   end
 
   step 'I should see the users document file in markdown branch' do
-    current_path.should == project_blob_path(@project, "markdown/doc/api/users.md")
+    current_path.should == namespace_project_blob_path(@project.namespace, @project, "markdown/doc/api/users.md")
     page.should have_content "Get a list of users."
   end
 
   # Expected link contents
 
   step 'The link with text "empty" should have url "tree/markdown"' do
-    find('a', text: /^empty$/)['href'] == current_host + project_tree_path(@project, "markdown")
+    find('a', text: /^empty$/)['href'] == current_host + namespace_project_tree_path(@project.namespace, @project, "markdown")
   end
 
   step 'The link with text "empty" should have url "blob/markdown/README.md"' do
-    find('a', text: /^empty$/)['href'] == current_host + project_blob_path(@project, "markdown/README.md")
+    find('a', text: /^empty$/)['href'] == current_host + namespace_project_blob_path(@project.namespace, @project, "markdown/README.md")
   end
 
   step 'The link with text "empty" should have url "tree/markdown/d"' do
-    find('a', text: /^empty$/)['href'] == current_host + project_tree_path(@project, "markdown/d")
+    find('a', text: /^empty$/)['href'] == current_host + namespace_project_tree_path(@project.namespace, @project, "markdown/d")
   end
 
   step 'The link with text "empty" should have '\
        'url "blob/markdown/d/README.md"' do
-    find('a', text: /^empty$/)['href'] == current_host + project_blob_path(@project, "markdown/d/README.md")
+    find('a', text: /^empty$/)['href'] == current_host + namespace_project_blob_path(@project.namespace, @project, "markdown/d/README.md")
   end
 
   step 'The link with text "ID" should have url "tree/markdownID"' do
-    find('a', text: /^#id$/)['href'] == current_host + project_tree_path(@project, "markdown") + '#id'
+    find('a', text: /^#id$/)['href'] == current_host + namespace_project_tree_path(@project.namespace, @project, "markdown") + '#id'
   end
 
   step 'The link with text "/ID" should have url "tree/markdownID"' do
-    find('a', text: /^\/#id$/)['href'] == current_host + project_tree_path(@project, "markdown") + '#id'
+    find('a', text: /^\/#id$/)['href'] == current_host + namespace_project_tree_path(@project.namespace, @project, "markdown") + '#id'
   end
 
   step 'The link with text "README.mdID" '\
        'should have url "blob/markdown/README.mdID"' do
-    find('a', text: /^README.md#id$/)['href'] == current_host + project_blob_path(@project, "markdown/README.md") + '#id'
+    find('a', text: /^README.md#id$/)['href'] == current_host + namespace_project_blob_path(@project.namespace, @project, "markdown/README.md") + '#id'
   end
 
   step 'The link with text "d/README.mdID" should have '\
        'url "blob/markdown/d/README.mdID"' do
-    find('a', text: /^d\/README.md#id$/)['href'] == current_host + project_blob_path(@project, "d/markdown/README.md") + '#id'
+    find('a', text: /^d\/README.md#id$/)['href'] == current_host + namespace_project_blob_path(@project.namespace, @project, "d/markdown/README.md") + '#id'
   end
 
   step 'The link with text "ID" should have url "blob/markdown/README.mdID"' do
-    find('a', text: /^#id$/)['href'] == current_host + project_blob_path(@project, "markdown/README.md") + '#id'
+    find('a', text: /^#id$/)['href'] == current_host + namespace_project_blob_path(@project.namespace, @project, "markdown/README.md") + '#id'
   end
 
   step 'The link with text "/ID" should have url "blob/markdown/README.mdID"' do
-    find('a', text: /^\/#id$/)['href'] == current_host + project_blob_path(@project, "markdown/README.md") + '#id'
+    find('a', text: /^\/#id$/)['href'] == current_host + namespace_project_blob_path(@project.namespace, @project, "markdown/README.md") + '#id'
   end
 
   # Wiki
 
   step 'I go to wiki page' do
     click_link "Wiki"
-    current_path.should == project_wiki_path(@project, "home")
+    current_path.should == namespace_project_wiki_path(@project.namespace, @project, "home")
   end
 
   step 'I add various links to the wiki page' do
@@ -218,7 +218,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'Wiki page should have added links' do
-    current_path.should == project_wiki_path(@project, "home")
+    current_path.should == namespace_project_wiki_path(@project.namespace, @project, "home")
     page.should have_content "test GitLab API doc Rake tasks"
   end
 
@@ -237,13 +237,13 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I see new wiki page named test' do
-    current_path.should ==  project_wiki_path(@project, "test")
+    current_path.should ==  namespace_project_wiki_path(@project.namespace, @project, "test")
     page.should have_content "Editing"
   end
 
   When 'I go back to wiki page home' do
-    visit project_wiki_path(@project, "home")
-    current_path.should == project_wiki_path(@project, "home")
+    visit namespace_project_wiki_path(@project.namespace, @project, "home")
+    current_path.should == namespace_project_wiki_path(@project.namespace, @project, "home")
   end
 
   step 'I click on GitLab API doc link' do
@@ -251,7 +251,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I see Gitlab API document' do
-    current_path.should == project_wiki_path(@project, "api")
+    current_path.should == namespace_project_wiki_path(@project.namespace, @project, "api")
     page.should have_content "Editing"
   end
 
@@ -260,13 +260,13 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I see Rake tasks directory' do
-    current_path.should == project_wiki_path(@project, "raketasks")
+    current_path.should == namespace_project_wiki_path(@project.namespace, @project, "raketasks")
     page.should have_content "Editing"
   end
 
   step 'I go directory which contains README file' do
-    visit project_tree_path(@project, "markdown/doc/api")
-    current_path.should == project_tree_path(@project, "markdown/doc/api")
+    visit namespace_project_tree_path(@project.namespace, @project, "markdown/doc/api")
+    current_path.should == namespace_project_tree_path(@project.namespace, @project, "markdown/doc/api")
   end
 
   step 'I click on a relative link in README' do
@@ -274,7 +274,7 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
   end
 
   step 'I should see the correct markdown' do
-    current_path.should == project_blob_path(@project, "markdown/doc/api/users.md")
+    current_path.should == namespace_project_blob_path(@project.namespace, @project, "markdown/doc/api/users.md")
     page.should have_content "List users"
   end
 
diff --git a/features/steps/project/star.rb b/features/steps/project/star.rb
index ae2e4c7a20152c251ecab34f7816c53e9aadc43e..50cdfd73c347501a0fcd69386f97fd8f3b376cd2 100644
--- a/features/steps/project/star.rb
+++ b/features/steps/project/star.rb
@@ -22,12 +22,16 @@ class Spinach::Features::ProjectStar < Spinach::FeatureSteps
 
   # Requires @javascript
   step "I click on the star toggle button" do
-    find(".star .toggle", visible: true).click
+    find(".star-btn", visible: true).click
+  end
+
+  step 'I redirected to sign in page' do
+    current_path.should == new_user_session_path
   end
 
   protected
 
   def has_n_stars(n)
-    expect(page).to have_css(".star .count", text: /^#{n}$/, visible: true)
+    expect(page).to have_css(".star-btn .count", text: n, visible: true)
   end
 end
diff --git a/features/steps/project/team_management.rb b/features/steps/project/team_management.rb
index 7907f2a6fe3e21f984d281e3862c861b9e0bfa3e..0eefe2b56887708169b9bcd0a874b826dc02b448 100644
--- a/features/steps/project/team_management.rb
+++ b/features/steps/project/team_management.rb
@@ -15,18 +15,18 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps
     page.should have_content(user.username)
   end
 
-  step 'I click link "New Team Member"' do
-    click_link "New project member"
+  step 'I click link "Add members"' do
+    find(:css, 'button.btn-new').click
   end
 
   step 'I select "Mike" as "Reporter"' do
     user = User.find_by(name: "Mike")
 
-    select2(user.id, from: "#user_ids", multiple: true)
-    within "#new_project_member" do
+    within ".users-project-form" do
+      select2(user.id, from: "#user_ids", multiple: true)
       select "Reporter", from: "access_level"
     end
-    click_button "Add users"
+    click_button "Add users to project"
   end
 
   step 'I should see "Mike" in team list as "Reporter"' do
@@ -42,9 +42,13 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps
   end
 
   step 'I change "Sam" role to "Reporter"' do
-    user = User.find_by(name: "Sam")
-    within "#user_#{user.id}" do
+    project = Project.find_by(name: "Shop")
+    user = User.find_by(name: 'Sam')
+    project_member = project.project_members.find_by(user_id: user.id)
+    within "#project_member_#{project_member.id}" do
+      click_button "Edit access level"
       select "Reporter", from: "project_member_access_level"
+      click_button "Save"
     end
   end
 
@@ -100,7 +104,10 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps
   end
 
   step 'I click cancel link for "Sam"' do
-    within "#user_#{User.find_by(name: 'Sam').id}" do
+    project = Project.find_by(name: "Shop")
+    user = User.find_by(name: 'Sam')
+    project_member = project.project_members.find_by(user_id: user.id)
+    within "#project_member_#{project_member.id}" do
       click_link('Remove user from team')
     end
   end
diff --git a/features/steps/project/wiki.rb b/features/steps/project/wiki.rb
index aa00818c6021506a427d4f08f980c1eec5f291bc..cd7d5eac24313177716b52e2be0a5b06f050c411 100644
--- a/features/steps/project/wiki.rb
+++ b/features/steps/project/wiki.rb
@@ -11,7 +11,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps
   end
 
   step 'I should be redirected back to the Edit Home Wiki page' do
-    current_path.should == project_wiki_path(project, :home)
+    current_path.should == namespace_project_wiki_path(project.namespace, project, :home)
   end
 
   step 'I create the Wiki Home page' do
@@ -33,7 +33,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps
   end
 
   step 'I browse to that Wiki page' do
-    visit project_wiki_path(project, @page)
+    visit namespace_project_wiki_path(project.namespace, project, @page)
   end
 
   step 'I click on the Edit button' do
@@ -50,7 +50,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps
   end
 
   step 'I should be redirected back to that Wiki page' do
-    current_path.should == project_wiki_path(project, @page)
+    current_path.should == namespace_project_wiki_path(project.namespace, project, @page)
   end
 
   step 'That page has two revisions' do
@@ -90,7 +90,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps
   end
 
   step 'I browse to wiki page with images' do
-    visit project_wiki_path(project, @wiki_page)
+    visit namespace_project_wiki_path(project.namespace, project, @wiki_page)
   end
 
   step 'I click on existing image link' do
diff --git a/features/steps/search.rb b/features/steps/search.rb
index f3d8bd80f1331ea7f19f2338ac3fa516ea55b912..6f0e038c4d6332eb486948f893293f4cd7a485cf 100644
--- a/features/steps/search.rb
+++ b/features/steps/search.rb
@@ -59,11 +59,11 @@ class Spinach::Features::Search < Spinach::FeatureSteps
     create(:merge_request, :simple, title: "Bar", source_project: project, target_project: project)
   end
 
-  step 'I should see "Foo" link' do
-    page.should have_link "Foo"
+  step 'I should see "Foo" link in the search results' do
+    find(:css, '.search-results').should have_link 'Foo'
   end
 
-  step 'I should not see "Bar" link' do
-    page.should_not have_link "Bar"
+  step 'I should not see "Bar" link in the search results' do
+    find(:css, '.search-results').should_not have_link 'Bar'
   end
 end
diff --git a/features/steps/shared/active_tab.rb b/features/steps/shared/active_tab.rb
index f41b59a6f2b5160c08514de4e7de1f7270f97e43..9beb688bd16c163c40063b1aefa0a196d61d7a8b 100644
--- a/features/steps/shared/active_tab.rb
+++ b/features/steps/shared/active_tab.rb
@@ -2,7 +2,7 @@ module SharedActiveTab
   include Spinach::DSL
 
   def ensure_active_main_tab(content)
-    find('.main-nav li.active').should have_content(content)
+    find('.nav-sidebar > li.active').should have_content(content)
   end
 
   def ensure_active_sub_tab(content)
@@ -10,11 +10,11 @@ module SharedActiveTab
   end
 
   def ensure_active_sub_nav(content)
-    find('div.content ul.nav-stacked-menu li.active').should have_content(content)
+    find('.sidebar-subnav > li.active').should have_content(content)
   end
 
   step 'no other main tabs should be active' do
-    page.should have_selector('.main-nav li.active', count: 1)
+    page.should have_selector('.nav-sidebar > li.active', count: 1)
   end
 
   step 'no other sub tabs should be active' do
@@ -22,11 +22,11 @@ module SharedActiveTab
   end
 
   step 'no other sub navs should be active' do
-    page.should have_selector('div.content ul.nav-stacked-menu li.active', count: 1)
+    page.should have_selector('.sidebar-subnav > li.active', count: 1)
   end
 
   step 'the active main tab should be Home' do
-    ensure_active_main_tab('Activity')
+    ensure_active_main_tab('Your Projects')
   end
 
   step 'the active main tab should be Projects' do
diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb
index 10f3ed90b5653661c6afc4c97a129ff62ea455f3..510e0f0f93892e94d581172a4c9d4a2fde2c1455 100644
--- a/features/steps/shared/diff_note.rb
+++ b/features/steps/shared/diff_note.rb
@@ -32,7 +32,7 @@ module SharedDiffNote
     click_diff_line(sample_commit.line_code)
     within("#{diff_file_selector} form[rel$='#{sample_commit.line_code}']") do
       fill_in "note[note]", with: "Should fix it :smile:"
-      find(".js-note-preview-button").trigger("click")
+      find('.js-md-preview-button').click
     end
   end
 
@@ -41,7 +41,7 @@ module SharedDiffNote
 
     within("#{diff_file_selector} form[rel$='#{sample_commit.del_line_code}']") do
       fill_in "note[note]", with: "DRY this up"
-      find(".js-note-preview-button").trigger("click")
+      find('.js-md-preview-button').click
     end
   end
 
@@ -71,15 +71,16 @@ module SharedDiffNote
     end
   end
 
-  step 'I should not see the diff comment preview button' do
+  step 'The diff comment preview tab should say there is nothing to do' do
     within(diff_file_selector) do
-      page.should have_css(".js-note-preview-button", visible: false)
+      find('.js-md-preview-button').click
+      expect(find('.js-md-preview')).to have_content('Nothing to preview.')
     end
   end
 
   step 'I should not see the diff comment text field' do
     within(diff_file_selector) do
-      page.should have_css(".js-note-text", visible: false)
+      expect(find('.js-note-text')).not_to be_visible
     end
   end
 
@@ -114,7 +115,7 @@ module SharedDiffNote
   end
 
   step 'I should see add a diff comment button' do
-    page.should have_css(".js-add-diff-note-button", visible: false)
+    page.should have_css('.js-add-diff-note-button', visible: true)
   end
 
   step 'I should see an empty diff comment form' do
@@ -131,27 +132,28 @@ module SharedDiffNote
 
   step 'I should see the diff comment preview' do
     within("#{diff_file_selector} form") do
-      page.should have_css(".js-note-preview", visible: false)
+      expect(page).to have_css('.js-md-preview', visible: true)
     end
   end
 
-  step 'I should see the diff comment edit button' do
+  step 'I should see the diff comment write tab' do
     within(diff_file_selector) do
-      page.should have_css(".js-note-write-button", visible: true)
+      expect(page).to have_css('.js-md-write-button', visible: true)
     end
   end
 
-  step 'I should see the diff comment preview button' do
+  step 'The diff comment preview tab should display rendered Markdown' do
     within(diff_file_selector) do
-      page.should have_css(".js-note-preview-button", visible: true)
+      find('.js-md-preview-button').click
+      expect(find('.js-md-preview')).to have_css('img.emoji', visible: true)
     end
   end
 
   step 'I should see two separate previews' do
     within(diff_file_selector) do
-      page.should have_css(".js-note-preview", visible: true, count: 2)
-      page.should have_content("Should fix it")
-      page.should have_content("DRY this up")
+      expect(page).to have_css('.js-md-preview', visible: true, count: 2)
+      expect(page).to have_content('Should fix it')
+      expect(page).to have_content('DRY this up')
     end
   end
 
diff --git a/features/steps/shared/issuable.rb b/features/steps/shared/issuable.rb
new file mode 100644
index 0000000000000000000000000000000000000000..41db2612f2623f75147e4e8fc98c5cc85c0589f5
--- /dev/null
+++ b/features/steps/shared/issuable.rb
@@ -0,0 +1,15 @@
+module SharedIssuable
+  include Spinach::DSL
+
+  def edit_issuable
+   find(:css, '.issuable-edit').click
+  end
+
+  step 'I click link "Edit" for the merge request' do
+    edit_issuable
+  end
+
+  step 'I click link "Edit" for the issue' do
+    edit_issuable
+  end
+end
diff --git a/features/steps/shared/markdown.rb b/features/steps/shared/markdown.rb
index 8bf138065b035bbc96cedd324ca959245b22a808..e71700880cde96622a3a307ad47e79deaba25e80 100644
--- a/features/steps/shared/markdown.rb
+++ b/features/steps/shared/markdown.rb
@@ -54,4 +54,49 @@ EOT
       'div.description li.task-list-item input[type="checkbox"]:disabled'
     )
   end
+
+  step 'I should not see the Markdown preview' do
+    expect(find('.gfm-form .js-md-preview')).not_to be_visible
+  end
+
+  step 'The Markdown preview tab should say there is nothing to do' do
+    within('.gfm-form') do
+      find('.js-md-preview-button').click
+      expect(find('.js-md-preview')).to have_content('Nothing to preview.')
+    end
+  end
+
+  step 'I should not see the Markdown text field' do
+    expect(find('.gfm-form textarea')).not_to be_visible
+  end
+
+  step 'I should see the Markdown write tab' do
+    expect(find('.gfm-form')).to have_css('.js-md-write-button', visible: true)
+  end
+
+  step 'I should see the Markdown preview' do
+    expect(find('.gfm-form')).to have_css('.js-md-preview', visible: true)
+  end
+
+  step 'The Markdown preview tab should display rendered Markdown' do
+    within('.gfm-form') do
+      find('.js-md-preview-button').click
+      expect(find('.js-md-preview')).to have_css('img.emoji', visible: true)
+    end
+  end
+
+  step 'I write a description like ":+1: Nice"' do
+    find('.gfm-form').fill_in 'Description', with: ':+1: Nice'
+  end
+
+  step 'I preview a description text like "Bug fixed :smile:"' do
+    within('.gfm-form') do
+      fill_in 'Description', with: 'Bug fixed :smile:'
+      find('.js-md-preview-button').click
+    end
+  end
+
+  step 'I haven\'t written any description text' do
+    find('.gfm-form').fill_in 'Description', with: ''
+  end
 end
diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb
index 2b2cb47a715c7f2bbac161a5008be24ccd34e1d4..583746d44755320df2bac93fc76426a038f0def7 100644
--- a/features/steps/shared/note.rb
+++ b/features/steps/shared/note.rb
@@ -23,7 +23,7 @@ module SharedNote
   step 'I preview a comment text like "Bug fixed :smile:"' do
     within(".js-main-target-form") do
       fill_in "note[note]", with: "Bug fixed :smile:"
-      find(".js-note-preview-button").trigger("click")
+      find('.js-md-preview-button').click
     end
   end
 
@@ -33,9 +33,9 @@ module SharedNote
     end
   end
 
-  step 'I write a comment like "Nice"' do
+  step 'I write a comment like ":+1: Nice"' do
     within(".js-main-target-form") do
-      fill_in "note[note]", with: "Nice"
+      fill_in 'note[note]', with: ':+1: Nice'
     end
   end
 
@@ -51,19 +51,20 @@ module SharedNote
 
   step 'I should not see the comment preview' do
     within(".js-main-target-form") do
-      page.should have_css(".js-note-preview", visible: false)
+      expect(find('.js-md-preview')).not_to be_visible
     end
   end
 
-  step 'I should not see the comment preview button' do
+  step 'The comment preview tab should say there is nothing to do' do
     within(".js-main-target-form") do
-      page.should have_css(".js-note-preview-button", visible: false)
+      find('.js-md-preview-button').click
+      expect(find('.js-md-preview')).to have_content('Nothing to preview.')
     end
   end
 
   step 'I should not see the comment text field' do
     within(".js-main-target-form") do
-      page.should have_css(".js-note-text", visible: false)
+      expect(find('.js-note-text')).not_to be_visible
     end
   end
 
@@ -79,21 +80,22 @@ module SharedNote
     end
   end
 
-  step 'I should see the comment edit button' do
+  step 'I should see the comment write tab' do
     within(".js-main-target-form") do
-      page.should have_css(".js-note-write-button", visible: true)
+      expect(page).to have_css('.js-md-write-button', visible: true)
     end
   end
 
-  step 'I should see the comment preview' do
+  step 'The comment preview tab should be display rendered Markdown' do
     within(".js-main-target-form") do
-      page.should have_css(".js-note-preview", visible: true)
+      find('.js-md-preview-button').click
+      expect(find('.js-md-preview')).to have_css('img.emoji', visible: true)
     end
   end
 
-  step 'I should see the comment preview button' do
+  step 'I should see the comment preview' do
     within(".js-main-target-form") do
-      page.should have_css(".js-note-preview-button", visible: true)
+      expect(page).to have_css('.js-md-preview', visible: true)
     end
   end
 
@@ -114,7 +116,7 @@ module SharedNote
   end
 
   step 'The comment with the header should not have an ID' do
-    within(".note-text") do
+    within(".note-body > .note-text") do
       page.should     have_content("Comment with a header")
       page.should_not have_css("#comment-with-a-header")
     end
@@ -133,4 +135,21 @@ module SharedNote
       'li.note div.timeline-content input[type="checkbox"]'
     )
   end
+
+  step 'I edit the last comment with a +1' do
+    find(".note").hover
+    find('.js-note-edit').click
+
+    within(".current-note-edit-form") do
+      fill_in 'note[note]', with: '+1 Awesome!'
+      click_button 'Save Comment'
+      sleep 0.05
+    end
+  end
+
+  step 'I should see +1 in the description' do
+    within(".note") do
+      page.should have_content("+1 Awesome!")
+    end
+  end
 end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index 5f292255ce137a3b244621c1d8d649b9c1f7d3f4..e3cf1b92cda3bb508293ace1e13fc791c57ddb32 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -1,6 +1,7 @@
 module SharedPaths
   include Spinach::DSL
   include RepoHelpers
+  include DashboardHelper
 
   step 'I visit new project page' do
     visit new_project_path
@@ -31,7 +32,7 @@ module SharedPaths
   end
 
   step 'I visit group "Owned" members page' do
-    visit members_group_path(Group.find_by(name:"Owned"))
+    visit group_group_members_path(Group.find_by(name:"Owned"))
   end
 
   step 'I visit group "Owned" settings page' do
@@ -51,7 +52,7 @@ module SharedPaths
   end
 
   step 'I visit group "Guest" members page' do
-    visit members_group_path(Group.find_by(name:"Guest"))
+    visit group_group_members_path(Group.find_by(name:"Guest"))
   end
 
   step 'I visit group "Guest" settings page' do
@@ -71,11 +72,11 @@ module SharedPaths
   end
 
   step 'I visit dashboard issues page' do
-    visit issues_dashboard_path
+    visit assigned_issues_dashboard_path
   end
 
   step 'I visit dashboard merge requests page' do
-    visit merge_requests_dashboard_path
+    visit assigned_mrs_dashboard_path
   end
 
   step 'I visit dashboard search page' do
@@ -86,6 +87,18 @@ module SharedPaths
     visit help_path
   end
 
+  step 'I visit dashboard groups page' do
+    visit dashboard_groups_path
+  end
+
+  step 'I should be redirected to the dashboard groups page' do
+    current_path.should == dashboard_groups_path
+  end
+
+  step 'I visit dashboard starred projects page' do
+    visit starred_dashboard_projects_path
+  end
+
   # ----------------------------------------
   # Profile
   # ----------------------------------------
@@ -94,6 +107,10 @@ module SharedPaths
     visit profile_path
   end
 
+  step 'I visit profile applications page' do
+    visit applications_profile_path
+  end
+
   step 'I visit profile password page' do
     visit edit_profile_password_path
   end
@@ -114,14 +131,6 @@ module SharedPaths
     visit history_profile_path
   end
 
-  step 'I visit profile groups page' do
-    visit profile_groups_path
-  end
-
-  step 'I should be redirected to the profile groups page' do
-    current_path.should == profile_groups_path
-  end
-
   # ----------------------------------------
   # Admin
   # ----------------------------------------
@@ -131,7 +140,7 @@ module SharedPaths
   end
 
   step 'I visit admin projects page' do
-    visit admin_projects_path
+    visit admin_namespaces_projects_path
   end
 
   step 'I visit admin users page' do
@@ -162,59 +171,72 @@ module SharedPaths
     visit admin_teams_path
   end
 
+  step 'I visit admin settings page' do
+    visit admin_application_settings_path
+  end
+
+  step 'I visit applications page' do
+    visit admin_applications_path
+  end
+
   # ----------------------------------------
   # Generic Project
   # ----------------------------------------
 
   step "I visit my project's home page" do
-    visit project_path(@project)
+    visit namespace_project_path(@project.namespace, @project)
   end
 
   step "I visit my project's settings page" do
-    visit edit_project_path(@project)
+    visit edit_namespace_project_path(@project.namespace, @project)
   end
 
   step "I visit my project's files page" do
-    visit project_tree_path(@project, root_ref)
+    visit namespace_project_tree_path(@project.namespace, @project, root_ref)
+  end
+
+  step 'I visit a binary file in the repo' do
+    visit namespace_project_blob_path(@project.namespace, @project, File.join(
+      root_ref, 'files/images/logo-black.png'))
   end
 
   step "I visit my project's commits page" do
-    visit project_commits_path(@project, root_ref, {limit: 5})
+    visit namespace_project_commits_path(@project.namespace, @project, root_ref, {limit: 5})
   end
 
   step "I visit my project's commits page for a specific path" do
-    visit project_commits_path(@project, root_ref + "/app/models/project.rb", {limit: 5})
+    visit namespace_project_commits_path(@project.namespace, @project, root_ref + "/app/models/project.rb", {limit: 5})
   end
 
   step 'I visit my project\'s commits stats page' do
-    visit stats_project_repository_path(@project)
+    visit stats_namespace_project_repository_path(@project.namespace, @project)
   end
 
   step "I visit my project's network page" do
     # Stub Graph max_size to speed up test (10 commits vs. 650)
     Network::Graph.stub(max_count: 10)
 
-    visit project_network_path(@project, root_ref)
+    visit namespace_project_network_path(@project.namespace, @project, root_ref)
   end
 
   step "I visit my project's issues page" do
-    visit project_issues_path(@project)
+    visit namespace_project_issues_path(@project.namespace, @project)
   end
 
   step "I visit my project's merge requests page" do
-    visit project_merge_requests_path(@project)
+    visit namespace_project_merge_requests_path(@project.namespace, @project)
   end
 
   step "I visit my project's wiki page" do
-    visit project_wiki_path(@project, :home)
+    visit namespace_project_wiki_path(@project.namespace, @project, :home)
   end
 
   step 'I visit project hooks page' do
-    visit project_hooks_path(@project)
+    visit namespace_project_hooks_path(@project.namespace, @project)
   end
 
   step 'I visit project deploy keys page' do
-    visit project_deploy_keys_path(@project)
+    visit namespace_project_deploy_keys_path(@project.namespace, @project)
   end
 
   # ----------------------------------------
@@ -222,153 +244,153 @@ module SharedPaths
   # ----------------------------------------
 
   step 'I visit project "Shop" page' do
-    visit project_path(project)
+    visit namespace_project_path(project.namespace, project)
   end
 
   step 'I visit project "Forked Shop" merge requests page' do
-    visit project_merge_requests_path(@forked_project)
+    visit namespace_project_merge_requests_path(@forked_project.namespace, @forked_project)
   end
 
   step 'I visit edit project "Shop" page' do
-    visit edit_project_path(project)
+    visit edit_namespace_project_path(project.namespace, project)
   end
 
   step 'I visit project branches page' do
-    visit project_branches_path(@project)
+    visit namespace_project_branches_path(@project.namespace, @project)
   end
 
   step 'I visit project protected branches page' do
-    visit project_protected_branches_path(@project)
+    visit namespace_project_protected_branches_path(@project.namespace, @project)
   end
 
   step 'I visit compare refs page' do
-    visit project_compare_index_path(@project)
+    visit namespace_project_compare_index_path(@project.namespace, @project)
   end
 
   step 'I visit project commits page' do
-    visit project_commits_path(@project, root_ref, {limit: 5})
+    visit namespace_project_commits_path(@project.namespace, @project, root_ref, {limit: 5})
   end
 
   step 'I visit project commits page for stable branch' do
-    visit project_commits_path(@project, 'stable', {limit: 5})
+    visit namespace_project_commits_path(@project.namespace, @project, 'stable', {limit: 5})
   end
 
   step 'I visit project source page' do
-    visit project_tree_path(@project, root_ref)
+    visit namespace_project_tree_path(@project.namespace, @project, root_ref)
   end
 
   step 'I visit blob file from repo' do
-    visit project_blob_path(@project, File.join(sample_commit.id, sample_blob.path))
+    visit namespace_project_blob_path(@project.namespace, @project, File.join(sample_commit.id, sample_blob.path))
   end
 
   step 'I visit ".gitignore" file in repo' do
-    visit project_blob_path(@project, File.join(root_ref, '.gitignore'))
+    visit namespace_project_blob_path(@project.namespace, @project, File.join(root_ref, '.gitignore'))
   end
 
   step 'I am on the new file page' do
-    current_path.should eq(project_new_tree_path(@project, root_ref))
+    current_path.should eq(namespace_project_create_blob_path(@project.namespace, @project, root_ref))
   end
 
   step 'I am on the ".gitignore" edit file page' do
-    current_path.should eq(project_edit_tree_path(
-      @project, File.join(root_ref, '.gitignore')))
+    current_path.should eq(namespace_project_edit_blob_path(
+      @project.namespace, @project, File.join(root_ref, '.gitignore')))
   end
 
   step 'I visit project source page for "6d39438"' do
-    visit project_tree_path(@project, "6d39438")
+    visit namespace_project_tree_path(@project.namespace, @project, "6d39438")
   end
 
   step 'I visit project source page for' \
        ' "6d394385cf567f80a8fd85055db1ab4c5295806f"' do
-    visit project_tree_path(@project,
+    visit namespace_project_tree_path(@project.namespace, @project,
                             '6d394385cf567f80a8fd85055db1ab4c5295806f')
   end
 
   step 'I visit project tags page' do
-    visit project_tags_path(@project)
+    visit namespace_project_tags_path(@project.namespace, @project)
   end
 
   step 'I visit project commit page' do
-    visit project_commit_path(@project, sample_commit.id)
+    visit namespace_project_commit_path(@project.namespace, @project, sample_commit.id)
   end
 
   step 'I visit project "Shop" issues page' do
-    visit project_issues_path(project)
+    visit namespace_project_issues_path(project.namespace, project)
   end
 
   step 'I visit issue page "Release 0.4"' do
     issue = Issue.find_by(title: "Release 0.4")
-    visit project_issue_path(issue.project, issue)
+    visit namespace_project_issue_path(issue.project.namespace, issue.project, issue)
   end
 
   step 'I visit issue page "Tasks-open"' do
     issue = Issue.find_by(title: 'Tasks-open')
-    visit project_issue_path(issue.project, issue)
+    visit namespace_project_issue_path(issue.project.namespace, issue.project, issue)
   end
 
   step 'I visit issue page "Tasks-closed"' do
     issue = Issue.find_by(title: 'Tasks-closed')
-    visit project_issue_path(issue.project, issue)
+    visit namespace_project_issue_path(issue.project.namespace, issue.project, issue)
   end
 
   step 'I visit project "Shop" labels page' do
     project = Project.find_by(name: 'Shop')
-    visit project_labels_path(project)
+    visit namespace_project_labels_path(project.namespace, project)
   end
 
   step 'I visit project "Forum" labels page' do
     project = Project.find_by(name: 'Forum')
-    visit project_labels_path(project)
+    visit namespace_project_labels_path(project.namespace, project)
   end
 
   step 'I visit project "Shop" new label page' do
     project = Project.find_by(name: 'Shop')
-    visit new_project_label_path(project)
+    visit new_namespace_project_label_path(project.namespace, project)
   end
 
   step 'I visit project "Forum" new label page' do
     project = Project.find_by(name: 'Forum')
-    visit new_project_label_path(project)
+    visit new_namespace_project_label_path(project.namespace, project)
   end
 
   step 'I visit merge request page "Bug NS-04"' do
     mr = MergeRequest.find_by(title: "Bug NS-04")
-    visit project_merge_request_path(mr.target_project, mr)
+    visit namespace_project_merge_request_path(mr.target_project.namespace, mr.target_project, mr)
   end
 
   step 'I visit merge request page "Bug NS-05"' do
     mr = MergeRequest.find_by(title: "Bug NS-05")
-    visit project_merge_request_path(mr.target_project, mr)
+    visit namespace_project_merge_request_path(mr.target_project.namespace, mr.target_project, mr)
   end
 
   step 'I visit merge request page "MR-task-open"' do
     mr = MergeRequest.find_by(title: 'MR-task-open')
-    visit project_merge_request_path(mr.target_project, mr)
+    visit namespace_project_merge_request_path(mr.target_project.namespace, mr.target_project, mr)
   end
 
   step 'I visit merge request page "MR-task-closed"' do
     mr = MergeRequest.find_by(title: 'MR-task-closed')
-    visit project_merge_request_path(mr.target_project, mr)
+    visit namespace_project_merge_request_path(mr.target_project.namespace, mr.target_project, mr)
   end
 
   step 'I visit project "Shop" merge requests page' do
-    visit project_merge_requests_path(project)
+    visit namespace_project_merge_requests_path(project.namespace, project)
   end
 
   step 'I visit forked project "Shop" merge requests page' do
-    visit project_merge_requests_path(project)
+    visit namespace_project_merge_requests_path(project.namespace, project)
   end
 
   step 'I visit project "Shop" milestones page' do
-    visit project_milestones_path(project)
+    visit namespace_project_milestones_path(project.namespace, project)
   end
 
   step 'I visit project "Shop" team page' do
-    visit project_team_index_path(project)
+    visit namespace_project_project_members_path(project.namespace, project)
   end
 
   step 'I visit project wiki page' do
-    visit project_wiki_path(@project, :home)
+    visit namespace_project_wiki_path(@project.namespace, @project, :home)
   end
 
   # ----------------------------------------
@@ -377,17 +399,22 @@ module SharedPaths
 
   step 'I visit project "Community" page' do
     project = Project.find_by(name: "Community")
-    visit project_path(project)
+    visit namespace_project_path(project.namespace, project)
+  end
+
+  step 'I visit project "Community" source page' do
+    project = Project.find_by(name: 'Community')
+    visit namespace_project_tree_path(project.namespace, project, root_ref)
   end
 
   step 'I visit project "Internal" page' do
     project = Project.find_by(name: "Internal")
-    visit project_path(project)
+    visit namespace_project_path(project.namespace, project)
   end
 
   step 'I visit project "Enterprise" page' do
     project = Project.find_by(name: "Enterprise")
-    visit project_path(project)
+    visit namespace_project_path(project.namespace, project)
   end
 
   # ----------------------------------------
@@ -396,7 +423,7 @@ module SharedPaths
 
   step "I visit empty project page" do
     project = Project.find_by(name: "Empty Public Project")
-    visit project_path(project)
+    visit namespace_project_path(project.namespace, project)
   end
 
   # ----------------------------------------
@@ -424,7 +451,7 @@ module SharedPaths
   # ----------------------------------------
 
   step 'I visit project "Shop" snippets page' do
-    visit project_snippets_path(project)
+    visit namespace_project_snippets_path(project.namespace, project)
   end
 
   step 'I visit snippets page' do
diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb
index bd7e6e1d8b325507b2f7eb72115b53819682ee01..41f71ae29cbfee33e54274bedc189a5035097a41 100644
--- a/features/steps/shared/project.rb
+++ b/features/steps/shared/project.rb
@@ -28,6 +28,11 @@ module SharedProject
     @project.team << [@user, :master]
   end
 
+  step 'I visit my empty project page' do
+    project = Project.find_by(name: 'Empty Project')
+    visit namespace_project_path(project.namespace, project)
+  end
+
   step 'project "Shop" has push event' do
     @project = Project.find_by(name: "Shop")
 
@@ -60,7 +65,7 @@ module SharedProject
   end
 
   step 'I should see project settings' do
-    current_path.should == edit_project_path(@project)
+    current_path.should == edit_namespace_project_path(@project.namespace, @project)
     page.should have_content("Project name")
     page.should have_content("Features:")
   end
@@ -131,7 +136,7 @@ module SharedProject
   end
 
   step 'public empty project "Empty Public Project"' do
-    create :empty_project, :public, name: "Empty Public Project"
+    create :project_empty_repo, :public, name: "Empty Public Project"
   end
 
   step 'project "Community" has comments' do
diff --git a/features/steps/shared/project_tab.rb b/features/steps/shared/project_tab.rb
index 6aa4f1b20dfe8e014416ea293b2b209da65cb6c8..c5aed19331cf0e96bab9e926bfce10177d17288e 100644
--- a/features/steps/shared/project_tab.rb
+++ b/features/steps/shared/project_tab.rb
@@ -41,6 +41,8 @@ module SharedProjectTab
   end
 
   step 'the active main tab should be Settings' do
-    ensure_active_main_tab('Settings')
+    within '.nav-sidebar' do
+      page.should have_content('Back to project')
+    end
   end
 end
diff --git a/features/steps/user.rb b/features/steps/user.rb
index d6f05ecb2c7181d41f6e9df04f267d32674d5dca..10cae692a88914a1afba9a3604f6c994e7ace4e0 100644
--- a/features/steps/user.rb
+++ b/features/steps/user.rb
@@ -7,4 +7,37 @@ class Spinach::Features::User < Spinach::FeatureSteps
   step 'I should see user "John Doe" page' do
     expect(title).to match(/^\s*John Doe/)
   end
+
+  step '"John Doe" has contributions' do
+    user = User.find_by(name: 'John Doe')
+    project = contributed_project
+
+    # Issue controbution
+    issue_params = { title: 'Bug in old browser' }
+    Issues::CreateService.new(project, user, issue_params).execute
+
+    # Push code contribution
+    push_params = {
+      project: project,
+      action: Event::PUSHED,
+      author_id: user.id,
+      data: { commit_count: 3 }
+    }
+
+    Event.create(push_params)
+  end
+
+  step 'I should see contributed projects' do
+    within '.contributed-projects' do
+      page.should have_content(@contributed_project.name)
+    end
+  end
+
+  step 'I should see contributions calendar' do
+    page.should have_css('.cal-heatmap-container')
+  end
+
+  def contributed_project
+    @contributed_project ||= create(:project, :public)
+  end
 end
diff --git a/features/support/env.rb b/features/support/env.rb
index 67660777842078e747b089c2eb0d59a8b7d193d2..be17065ccfd728ddb1c1b171dd75fa901e003e0d 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -47,8 +47,8 @@ Spinach.hooks.after_scenario do
 end
 
 Spinach.hooks.before_run do
+  include RSpec::Mocks::ExampleMethods
   TestEnv.init(mailer: false)
-  RSpec::Mocks::setup self
 
   include FactoryGirl::Syntax::Methods
 end
diff --git a/features/uploadfile.txt b/features/uploadfile.txt
new file mode 100644
index 0000000000000000000000000000000000000000..009ddab18c67a544d191878e62dbc332d6441150
--- /dev/null
+++ b/features/uploadfile.txt
@@ -0,0 +1 @@
+this is the test file for upload and replace functionality.
diff --git a/features/user.feature b/features/user.feature
index a2167935fd2c02b5b2f2778291d90ad35666cd5b..69618e929c4cee95581e22170438d837fa5ae6df 100644
--- a/features/user.feature
+++ b/features/user.feature
@@ -67,3 +67,12 @@ Feature: User
     And I should see project "Enterprise"
     And I should not see project "Internal"
     And I should not see project "Community"
+
+  @javascript
+  Scenario: "John Doe" contribution profile
+    Given I sign in as a user
+    And "John Doe" has contributions
+    When I visit user "John Doe" page
+    Then I should see user "John Doe" page
+    And I should see contributed projects
+    And I should see contributions calendar
diff --git a/lib/api/api.rb b/lib/api/api.rb
index d26667ba3f7ad34db41fbf8c1df19cc04b7cacfe..60858a394079eb191bed27de86a70e8056154508 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -2,10 +2,11 @@ Dir["#{Rails.root}/lib/api/*.rb"].each {|file| require file}
 
 module API
   class API < Grape::API
+    include APIGuard
     version 'v3', using: :path
 
     rescue_from ActiveRecord::RecordNotFound do
-      rack_response({'message' => '404 Not found'}.to_json, 404)
+      rack_response({ 'message' => '404 Not found' }.to_json, 404)
     end
 
     rescue_from :all do |exception|
@@ -18,7 +19,7 @@ module API
       message << "  " << trace.join("\n  ")
 
       API.logger.add Logger::FATAL, message
-      rack_response({'message' => '500 Internal Server Error'}, 500)
+      rack_response({ 'message' => '500 Internal Server Error' }, 500)
     end
 
     format :json
diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b9994fcefdaba024913d585c7d319bc978022ec5
--- /dev/null
+++ b/lib/api/api_guard.rb
@@ -0,0 +1,172 @@
+# Guard API with OAuth 2.0 Access Token
+
+require 'rack/oauth2'
+
+module APIGuard
+  extend ActiveSupport::Concern
+
+  included do |base|
+    # OAuth2 Resource Server Authentication
+    use Rack::OAuth2::Server::Resource::Bearer, 'The API' do |request|
+      # The authenticator only fetches the raw token string
+
+      # Must yield access token to store it in the env
+      request.access_token
+    end
+
+    helpers HelperMethods
+
+    install_error_responders(base)
+  end
+
+  # Helper Methods for Grape Endpoint
+  module HelperMethods
+    # Invokes the doorkeeper guard.
+    #
+    # If token is presented and valid, then it sets @current_user.
+    #
+    # If the token does not have sufficient scopes to cover the requred scopes,
+    # then it raises InsufficientScopeError.
+    #
+    # If the token is expired, then it raises ExpiredError.
+    #
+    # If the token is revoked, then it raises RevokedError.
+    #
+    # If the token is not found (nil), then it raises TokenNotFoundError.
+    #
+    # Arguments:
+    #
+    #   scopes: (optional) scopes required for this guard.
+    #           Defaults to empty array.
+    #
+    def doorkeeper_guard!(scopes: [])
+      if (access_token = find_access_token).nil?
+        raise TokenNotFoundError
+
+      else
+        case validate_access_token(access_token, scopes)
+        when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
+          raise InsufficientScopeError.new(scopes)
+        when Oauth2::AccessTokenValidationService::EXPIRED
+          raise ExpiredError
+        when Oauth2::AccessTokenValidationService::REVOKED
+          raise RevokedError
+        when Oauth2::AccessTokenValidationService::VALID
+          @current_user = User.find(access_token.resource_owner_id)
+        end
+      end
+    end
+
+    def doorkeeper_guard(scopes: [])
+      if access_token = find_access_token
+        case validate_access_token(access_token, scopes)
+        when Oauth2::AccessTokenValidationService::INSUFFICIENT_SCOPE
+          raise InsufficientScopeError.new(scopes)
+
+        when Oauth2::AccessTokenValidationService::EXPIRED
+          raise ExpiredError
+
+        when Oauth2::AccessTokenValidationService::REVOKED
+          raise RevokedError
+
+        when Oauth2::AccessTokenValidationService::VALID
+          @current_user = User.find(access_token.resource_owner_id)
+        end
+      end
+    end
+
+    def current_user
+      @current_user
+    end
+
+    private
+    def find_access_token
+      @access_token ||= Doorkeeper.authenticate(doorkeeper_request, Doorkeeper.configuration.access_token_methods)
+    end
+
+    def doorkeeper_request
+      @doorkeeper_request ||= ActionDispatch::Request.new(env)
+    end
+
+    def validate_access_token(access_token, scopes)
+      Oauth2::AccessTokenValidationService.validate(access_token, scopes: scopes)
+    end
+  end
+
+  module ClassMethods
+    # Installs the doorkeeper guard on the whole Grape API endpoint.
+    #
+    # Arguments:
+    #
+    #   scopes: (optional) scopes required for this guard.
+    #           Defaults to empty array.
+    #
+    def guard_all!(scopes: [])
+      before do
+        guard! scopes: scopes
+      end
+    end
+
+    private
+    def install_error_responders(base)
+      error_classes = [ MissingTokenError, TokenNotFoundError,
+                        ExpiredError, RevokedError, InsufficientScopeError]
+
+      base.send :rescue_from, *error_classes, oauth2_bearer_token_error_handler
+    end
+
+    def oauth2_bearer_token_error_handler
+      Proc.new do |e|
+        response =
+          case e
+          when MissingTokenError
+            Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new
+
+          when TokenNotFoundError
+            Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
+              :invalid_token,
+              "Bad Access Token.")
+
+          when ExpiredError
+            Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
+              :invalid_token,
+              "Token is expired. You can either do re-authorization or token refresh.")
+
+          when RevokedError
+            Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
+              :invalid_token,
+              "Token was revoked. You have to re-authorize from the user.")
+
+          when InsufficientScopeError
+            # FIXME: ForbiddenError (inherited from Bearer::Forbidden of Rack::Oauth2)
+            # does not include WWW-Authenticate header, which breaks the standard.
+            Rack::OAuth2::Server::Resource::Bearer::Forbidden.new(
+              :insufficient_scope,
+              Rack::OAuth2::Server::Resource::ErrorMethods::DEFAULT_DESCRIPTION[:insufficient_scope],
+              { scope: e.scopes })
+          end
+
+        response.finish
+      end
+    end
+  end
+
+  #
+  # Exceptions
+  #
+
+  class MissingTokenError < StandardError; end
+
+  class TokenNotFoundError < StandardError; end
+
+  class ExpiredError < StandardError; end
+
+  class RevokedError < StandardError; end
+
+  class InsufficientScopeError < StandardError
+    attr_reader :scopes
+    def initialize(scopes)
+      @scopes = scopes
+    end
+  end
+end
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 6ec1a753a69da9ade3d860d7492690f12d23053a..edfdf842f850b44f69a7b6aee9d864556bd09a83 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -1,4 +1,5 @@
 require 'mime/types'
+require 'uri'
 
 module API
   # Projects API
@@ -14,7 +15,8 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/branches
       get ":id/repository/branches" do
-        present user_project.repository.branches.sort_by(&:name), with: Entities::RepoObject, project: user_project
+        branches = user_project.repository.branches.sort_by(&:name)
+        present branches, with: Entities::RepoObject, project: user_project
       end
 
       # Get a single branch
@@ -26,7 +28,7 @@ module API
       #   GET /projects/:id/repository/branches/:branch
       get ':id/repository/branches/:branch', requirements: { branch: /.*/ } do
         @branch = user_project.repository.branches.find { |item| item.name == params[:branch] }
-        not_found!("Branch does not exist") if @branch.nil?
+        not_found!("Branch") unless @branch
         present @branch, with: Entities::RepoObject, project: user_project
       end
 
@@ -43,7 +45,7 @@ module API
         authorize_admin_project
 
         @branch = user_project.repository.find_branch(params[:branch])
-        not_found! unless @branch
+        not_found!("Branch") unless @branch
         protected_branch = user_project.protected_branches.find_by(name: @branch.name)
         user_project.protected_branches.create(name: @branch.name) unless protected_branch
 
@@ -63,7 +65,7 @@ module API
         authorize_admin_project
 
         @branch = user_project.repository.find_branch(params[:branch])
-        not_found! unless @branch
+        not_found!("Branch does not exist") unless @branch
         protected_branch = user_project.protected_branches.find_by(name: @branch.name)
         protected_branch.destroy if protected_branch
 
@@ -102,7 +104,7 @@ module API
       delete ":id/repository/branches/:branch" do
         authorize_push_project
         result = DeleteBranchService.new(user_project, current_user).
-          execute(params[:branch])
+          execute(URI.unescape(params[:branch]))
 
         if result[:status] == :success
           {
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index 6c5391b98c820dff50a4931bcbf2c03c4e9e2bf3..0de4e720ffe00ca8c8af9b0746e234b7d0ac3902 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -108,7 +108,7 @@ module API
         if note.save
           present note, with: Entities::CommitNote
         else
-          not_found!
+          render_api_error!("Failed to save note #{note.errors.messages}", 400)
         end
       end
     end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 42e4442365d9d28b8f493426571643935d492faa..489be2107846bb2844fc73761eb664b849ac2676 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -14,10 +14,14 @@ module API
       expose :bio, :skype, :linkedin, :twitter, :website_url
     end
 
+    class Identity < Grape::Entity
+      expose :provider, :extern_uid
+    end
+
     class UserFull < User
       expose :email
-      expose :theme_id, :color_scheme_id, :extern_uid, :provider, \
-             :projects_limit
+      expose :theme_id, :color_scheme_id, :projects_limit
+      expose :identities, using: Entities::Identity
       expose :can_create_group?, as: :can_create_group
       expose :can_create_project?, as: :can_create_project
     end
@@ -51,7 +55,8 @@ module API
       expose :path, :path_with_namespace
       expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at
       expose :namespace
-      expose :forked_from_project, using: Entities::ForkedFromProject, :if => lambda{ | project, options | project.forked? }
+      expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? }
+      expose :avatar_url
     end
 
     class ProjectMember < UserBasic
@@ -61,7 +66,7 @@ module API
     end
 
     class Group < Grape::Entity
-      expose :id, :name, :path, :owner_id
+      expose :id, :name, :path, :description
     end
 
     class GroupDetail < Group
@@ -138,11 +143,16 @@ module API
 
     class ProjectEntity < Grape::Entity
       expose :id, :iid
-      expose (:project_id) { |entity| entity.project.id }
+      expose(:project_id) { |entity| entity.project.id }
       expose :title, :description
       expose :state, :created_at, :updated_at
     end
 
+    class RepoDiff < Grape::Entity
+      expose :old_path, :new_path, :a_mode, :b_mode, :diff
+      expose :new_file, :renamed_file, :deleted_file
+    end
+
     class Milestone < ProjectEntity
       expose :due_date
     end
@@ -162,6 +172,12 @@ module API
       expose :milestone, using: Entities::Milestone
     end
 
+    class MergeRequestChanges < MergeRequest
+      expose :diffs, as: :changes, using: Entities::RepoDiff do |compare, _|
+        compare.diffs
+      end
+    end
+
     class SSHKey < Grape::Entity
       expose :id, :title, :key, :created_at
     end
@@ -232,11 +248,6 @@ module API
       expose :name, :color
     end
 
-    class RepoDiff < Grape::Entity
-      expose :old_path, :new_path, :a_mode, :b_mode, :diff
-      expose :new_file, :renamed_file, :deleted_file
-    end
-
     class Compare < Grape::Entity
       expose :commit, using: Entities::RepoCommit do |compare, options|
         Commit.decorate(compare.commits).last
@@ -260,5 +271,9 @@ module API
     class Contributor < Grape::Entity
       expose :name, :email, :commits, :additions, :deletions
     end
+
+    class BroadcastMessage < Grape::Entity
+      expose :message, :starts_at, :ends_at, :color, :font
+    end
   end
 end
diff --git a/lib/api/files.rb b/lib/api/files.rb
index 84e1d3117816e30111c2b7ca7155d28fab63c82d..3176ef0e256297e489176aea1a6d92123cbcb60a 100644
--- a/lib/api/files.rb
+++ b/lib/api/files.rb
@@ -35,7 +35,7 @@ module API
         file_path = attrs.delete(:file_path)
 
         commit = user_project.repository.commit(ref)
-        not_found! "Commit" unless commit
+        not_found! 'Commit' unless commit
 
         blob = user_project.repository.blob_at(commit.sha, file_path)
 
@@ -53,7 +53,7 @@ module API
             commit_id: commit.id,
           }
         else
-          render_api_error!('File not found', 404)
+          not_found! 'File'
         end
       end
 
@@ -117,7 +117,8 @@ module API
             branch_name: branch_name
           }
         else
-          render_api_error!(result[:message], 400)
+          http_status = result[:http_status] || 400
+          render_api_error!(result[:message], http_status)
         end
       end
 
diff --git a/lib/api/group_members.rb b/lib/api/group_members.rb
index d596517c816e5cbc46cab7d08a34e4e763618956..ed54c7f6ff058942b2d24b1900058bc1570583bb 100644
--- a/lib/api/group_members.rb
+++ b/lib/api/group_members.rb
@@ -3,22 +3,6 @@ module API
     before { authenticate! }
 
     resource :groups do
-      helpers do
-        def find_group(id)
-          group = Group.find(id)
-
-          if can?(current_user, :read_group, group)
-            group
-          else
-            render_api_error!("403 Forbidden - #{current_user.username} lacks sufficient access to #{group.name}", 403)
-          end
-        end
-
-        def validate_access_level?(level)
-          Gitlab::Access.options_with_owner.values.include? level.to_i
-        end
-      end
-
       # Get a list of group members viewable by the authenticated user.
       #
       # Example Request:
@@ -56,6 +40,30 @@ module API
         present member.user, with: Entities::GroupMember, group: group
       end
 
+      # Update group member
+      #
+      # Parameters:
+      #   id (required) - The ID of a group
+      #   user_id (required) - The ID of a group member
+      #   access_level (required) - Project access level
+      # Example Request:
+      #   PUT /groups/:id/members/:user_id
+      put ':id/members/:user_id' do
+        group = find_group(params[:id])
+        authorize! :manage_group, group
+        required_attributes! [:access_level]
+
+        group_member = group.group_members.find_by(user_id: params[:user_id])
+        not_found!('User can not be found') if group_member.nil?
+
+        if group_member.update_attributes(access_level: params[:access_level])
+          @member = group_member.user
+          present @member, with: Entities::GroupMember, group: group
+        else
+          handle_member_errors group_member.errors
+        end
+      end
+
       # Remove member.
       #
       # Parameters:
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index f0ab6938b1c3be04bc2413d4a474534ba5e23835..a92abd4b6907fe529d6689bcc88662feab81bb63 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -4,32 +4,19 @@ module API
     before { authenticate! }
 
     resource :groups do
-      helpers do
-        def find_group(id)
-          group = Group.find(id)
-
-          if can?(current_user, :read_group, group)
-            group
-          else
-            render_api_error!("403 Forbidden - #{current_user.username} lacks sufficient access to #{group.name}", 403)
-          end
-        end
-
-        def validate_access_level?(level)
-          Gitlab::Access.options_with_owner.values.include? level.to_i
-        end
-      end
-
       # Get a groups list
       #
       # Example Request:
       #  GET /groups
       get do
-        if current_user.admin
-          @groups = paginate Group
-        else
-          @groups = paginate current_user.groups
-        end
+        @groups = if current_user.admin
+                    Group.all
+                  else
+                    current_user.groups
+                  end
+
+        @groups = @groups.search(params[:search]) if params[:search].present?
+        @groups = paginate @groups
         present @groups, with: Entities::Group
       end
 
@@ -44,14 +31,14 @@ module API
         authenticated_as_admin!
         required_attributes! [:name, :path]
 
-        attrs = attributes_for_keys [:name, :path]
+        attrs = attributes_for_keys [:name, :path, :description]
         @group = Group.new(attrs)
-        @group.owner = current_user
 
         if @group.save
+          @group.add_owner(current_user)
           present @group, with: Entities::Group
         else
-          not_found!
+          render_api_error!("Failed to save group #{@group.errors.messages}", 400)
         end
       end
 
@@ -94,7 +81,7 @@ module API
         if result
           present group
         else
-          not_found!
+          render_api_error!("Failed to transfer project #{project.errors.messages}", 400)
         end
       end
     end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 027fb20ec469058805e263004dbb28007ca25a16..be133a2920bfaa0105b444b7f1c16391bd530d2f 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -11,7 +11,7 @@ module API
 
     def current_user
       private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s
-      @current_user ||= User.find_by(authentication_token: private_token)
+      @current_user ||= (User.find_by(authentication_token: private_token) || doorkeeper_guard)
 
       unless @current_user && Gitlab::UserAccess.allowed?(@current_user)
         return nil
@@ -20,7 +20,7 @@ module API
       identifier = sudo_identifier()
 
       # If the sudo is the current user do nothing
-      if (identifier && !(@current_user.id == identifier || @current_user.username == identifier))
+      if identifier && !(@current_user.id == identifier || @current_user.username == identifier)
         render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin?
         @current_user = User.by_username_or_id(identifier)
         not_found!("No user id or username for: #{identifier}") if @current_user.nil?
@@ -33,7 +33,7 @@ module API
       identifier ||= params[SUDO_PARAM] ||= env[SUDO_HEADER]
 
       # Regex for integers
-      if (!!(identifier =~ /^[0-9]+$/))
+      if !!(identifier =~ /^[0-9]+$/)
         identifier.to_i
       else
         identifier
@@ -42,7 +42,7 @@ module API
 
     def user_project
       @project ||= find_project(params[:id])
-      @project || not_found!
+      @project || not_found!("Project")
     end
 
     def find_project(id)
@@ -55,6 +55,21 @@ module API
       end
     end
 
+    def find_group(id)
+      begin
+        group = Group.find(id)
+      rescue ActiveRecord::RecordNotFound
+        group = Group.find_by!(path: id)
+      end
+
+      if can?(current_user, :read_group, group)
+        group
+      else
+        forbidden!("#{current_user.username} lacks sufficient "\
+        "access to #{group.name}")
+      end
+    end
+
     def paginate(relation)
       per_page  = params[:per_page].to_i
       paginated = relation.page(params[:page]).per(per_page)
@@ -68,7 +83,10 @@ module API
     end
 
     def authenticate_by_gitlab_shell_token!
-      unauthorized! unless secret_token == params['secret_token']
+      input = params['secret_token'].try(:chomp)
+      unless Devise.secure_compare(secret_token, input)
+        unauthorized!
+      end
     end
 
     def authenticated_as_admin!
@@ -135,10 +153,32 @@ module API
       errors
     end
 
+    def validate_access_level?(level)
+      Gitlab::Access.options_with_owner.values.include? level.to_i
+    end
+
+    def issuable_order_by
+      if params["order_by"] == 'updated_at'
+        'updated_at'
+      else
+        'created_at'
+      end
+    end
+
+    def issuable_sort
+      if params["sort"] == 'asc'
+        :asc
+      else
+        :desc
+      end
+    end
+
     # error helpers
 
-    def forbidden!
-      render_api_error!('403 Forbidden', 403)
+    def forbidden!(reason = nil)
+      message = ['403 Forbidden']
+      message << " - #{reason}" if reason
+      render_api_error!(message.join(' '), 403)
     end
 
     def bad_request!(attribute)
@@ -167,13 +207,13 @@ module API
     end
 
     def render_validation_error!(model)
-      unless model.valid?
+      if model.errors.any?
         render_api_error!(model.errors.messages || '400 Bad Request', 400)
       end
     end
 
     def render_api_error!(message, status)
-      error!({'message' => message}, status)
+      error!({ 'message' => message }, status)
     end
 
     private
@@ -199,7 +239,12 @@ module API
     end
 
     def secret_token
-      File.read(Rails.root.join('.gitlab_shell_secret'))
+      File.read(Rails.root.join('.gitlab_shell_secret')).chomp
+    end
+
+    def handle_member_errors(errors)
+      error!(errors[:access_level], 422) if errors[:access_level].any?
+      not_found!(errors)
     end
   end
 end
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index ebf2296097db666be730c3df1814938033cdcc6a..f98a17773e7e24d046d8e4780081529c8d4acb58 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -1,9 +1,7 @@
 module API
   # Internal access API
   class Internal < Grape::API
-    before {
-      authenticate_by_gitlab_shell_token!
-    }
+    before { authenticate_by_gitlab_shell_token! }
 
     namespace 'internal' do
       # Check if git command is allowed to project
@@ -18,37 +16,45 @@ module API
       #
       post "/allowed" do
         status 200
-        project_path = params[:project]
 
+        actor = 
+          if params[:key_id]
+            Key.find_by(id: params[:key_id])
+          elsif params[:user_id]
+            User.find_by(id: params[:user_id])
+          end
+
+        unless actor
+          return Gitlab::GitAccessStatus.new(false, 'No such user or key')
+        end
+
+        project_path = params[:project]
+        
         # Check for *.wiki repositories.
         # Strip out the .wiki from the pathname before finding the
         # project. This applies the correct project permissions to
         # the wiki repository as well.
-        access =
-          if project_path =~ /\.wiki\Z/
-            project_path.sub!(/\.wiki\Z/, '')
-            Gitlab::GitAccessWiki.new
-          else
-            Gitlab::GitAccess.new
-          end
+        wiki = project_path.end_with?('.wiki')
+        project_path.chomp!('.wiki') if wiki
 
         project = Project.find_with_namespace(project_path)
-        return false unless project
 
-        actor = if params[:key_id]
-                  Key.find(params[:key_id])
-                elsif params[:user_id]
-                  User.find(params[:user_id])
-                end
+        if project
+          access =
+            if wiki
+              Gitlab::GitAccessWiki.new(actor, project)
+            else
+              Gitlab::GitAccess.new(actor, project)
+            end
 
-        return false unless actor
+          status = access.check(params[:action], params[:changes])
+        end
 
-        access.allowed?(
-          actor,
-          params[:action],
-          project,
-          params[:changes]
-        )
+        if project && access.can_read_project?
+          status
+        else
+          Gitlab::GitAccessStatus.new(false, 'No such project')
+        end
       end
 
       #
@@ -66,6 +72,14 @@ module API
           gitlab_rev: Gitlab::REVISION,
         }
       end
+
+      get "/broadcast_message" do
+        if message = BroadcastMessage.current
+          present message, with: Entities::BroadcastMessage
+        else
+          {}
+        end
+      end
     end
   end
 end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index d2828b24c369c63bc0eff1b8f130dca03d439f24..ff062be60404976a99eeeabd2e997e845188e22e 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -27,7 +27,9 @@ module API
       # Parameters:
       #   state (optional) - Return "opened" or "closed" issues
       #   labels (optional) - Comma-separated list of label names
-
+      #   order_by (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
+      #   sort (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
+      #
       # Example Requests:
       #   GET /issues
       #   GET /issues?state=opened
@@ -39,8 +41,7 @@ module API
         issues = current_user.issues
         issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
         issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
-        issues = issues.order('issues.id DESC')
-
+        issues.reorder(issuable_order_by => issuable_sort)
         present paginate(issues), with: Entities::Issue
       end
     end
@@ -53,6 +54,8 @@ module API
       #   state (optional) - Return "opened" or "closed" issues
       #   labels (optional) - Comma-separated list of label names
       #   milestone (optional) - Milestone title
+      #   order_by (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
+      #   sort (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
       #
       # Example Requests:
       #   GET /projects/:id/issues
@@ -67,11 +70,12 @@ module API
         issues = user_project.issues
         issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
         issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
+
         unless params[:milestone].nil?
           issues = filter_issues_milestone(issues, params[:milestone])
         end
-        issues = issues.order('issues.id DESC')
 
+        issues.reorder(issuable_order_by => issuable_sort)
         present paginate(issues), with: Entities::Issue
       end
 
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index a365f1db00f6f07ad4c6fba2fd75a8725e89a3db..f3765f5ab03909ab1e8f40c624929cf4e76439e1 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -25,6 +25,8 @@ module API
       # Parameters:
       #   id (required) - The ID of a project
       #   state (optional) - Return requests "merged", "opened" or "closed"
+      #   order_by (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
+      #   sort (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
       #
       # Example:
       #   GET /projects/:id/merge_requests
@@ -37,25 +39,18 @@ module API
       #
       get ":id/merge_requests" do
         authorize! :read_merge_request, user_project
+        merge_requests = user_project.merge_requests
+
+        merge_requests =
+          case params["state"]
+          when "opened" then merge_requests.opened
+          when "closed" then merge_requests.closed
+          when "merged" then merge_requests.merged
+          else merge_requests
+          end
 
-        mrs = case params["state"]
-              when "opened" then user_project.merge_requests.opened
-              when "closed" then user_project.merge_requests.closed
-              when "merged" then user_project.merge_requests.merged
-              else user_project.merge_requests
-              end
-
-        sort = case params["sort"]
-               when 'desc' then 'DESC'
-               else 'ASC'
-               end
-
-        mrs = case params["order_by"]
-              when 'updated_at' then mrs.order("updated_at #{sort}")
-              else  mrs.order("created_at #{sort}")
-              end
-
-        present paginate(mrs), with: Entities::MergeRequest
+        merge_requests.reorder(issuable_order_by => issuable_sort)
+        present paginate(merge_requests), with: Entities::MergeRequest
       end
 
       # Show MR
@@ -75,6 +70,22 @@ module API
         present merge_request, with: Entities::MergeRequest
       end
 
+      # Show MR changes
+      #
+      # Parameters:
+      #   id (required)               - The ID of a project
+      #   merge_request_id (required) - The ID of MR
+      #
+      # Example:
+      #   GET /projects/:id/merge_request/:merge_request_id/changes
+      #
+      get ':id/merge_request/:merge_request_id/changes' do
+        merge_request = user_project.merge_requests.
+          find(params[:merge_request_id])
+        authorize! :read_merge_request, merge_request
+        present merge_request, with: Entities::MergeRequestChanges
+      end
+
       # Create MR
       #
       # Parameters:
@@ -167,13 +178,10 @@ module API
       put ":id/merge_request/:merge_request_id/merge" do
         merge_request = user_project.merge_requests.find(params[:merge_request_id])
 
-        action = if user_project.protected_branch?(merge_request.target_branch)
-                   :push_code_to_protected_branches
-                 else
-                   :push_code
-                 end
+        allowed = ::Gitlab::GitAccess.new(current_user, user_project).
+          can_push_to_branch?(merge_request.target_branch)
 
-        if can?(current_user, action, user_project)
+        if allowed
           if merge_request.unchecked?
             merge_request.check_if_can_be_merged
           end
@@ -233,7 +241,7 @@ module API
         if note.save
           present note, with: Entities::MRNote
         else
-          render_validation_error!(note)
+          render_api_error!("Failed to save note #{note.errors.messages}", 400)
         end
       end
     end
diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb
index a4fdb752d69a3a73c4978c0649c7fbf166232b81..c5cd73943fb84ee67e76e1c5fccc26621a47a9ce 100644
--- a/lib/api/milestones.rb
+++ b/lib/api/milestones.rb
@@ -48,7 +48,7 @@ module API
         if milestone.valid?
           present milestone, with: Entities::Milestone
         else
-          not_found!
+          render_api_error!("Failed to create milestone #{milestone.errors.messages}", 400)
         end
       end
 
@@ -72,9 +72,24 @@ module API
         if milestone.valid?
           present milestone, with: Entities::Milestone
         else
-          not_found!
+          render_api_error!("Failed to update milestone #{milestone.errors.messages}", 400)
         end
       end
+
+      # Get all issues for a single project milestone
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   milestone_id (required) - The ID of a project milestone
+      # Example Request:
+      #   GET /projects/:id/milestones/:milestone_id/issues
+      get ":id/milestones/:milestone_id/issues" do
+        authorize! :read_milestone, user_project
+
+        @milestone = user_project.milestones.find(params[:milestone_id])
+        present paginate(@milestone.issues), with: Entities::Issue
+      end
+
     end
   end
 end
diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb
index f9f2ed90ccc357ca49d1e0a436411f73b0888463..b90ed6af5fbe6e32f92a65e57df72f3a34d49c22 100644
--- a/lib/api/namespaces.rb
+++ b/lib/api/namespaces.rb
@@ -1,10 +1,10 @@
 module API
   # namespaces API
   class Namespaces < Grape::API
-    before {
+    before do
       authenticate!
       authenticated_as_admin!
-    }
+    end
 
     resource :namespaces do
       # Get a namespaces list
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index 0ef9a3c4beb17e1fdea6179b93e58e8722c93122..3726be7c5374c151be3e9db957a4be886b3d3537 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -61,9 +61,42 @@ module API
           if @note.valid?
             present @note, with: Entities::Note
           else
-            not_found!
+            not_found!("Note #{@note.errors.messages}")
           end
         end
+
+        # Modify existing +noteable+ note
+        #
+        # Parameters:
+        #   id (required) - The ID of a project
+        #   noteable_id (required) - The ID of an issue or snippet
+        #   node_id (required) - The ID of a note
+        #   body (required) - New content of a note
+        # Example Request:
+        #   PUT /projects/:id/issues/:noteable_id/notes/:note_id
+        #   PUT /projects/:id/snippets/:noteable_id/notes/:node_id
+        put ":id/#{noteables_str}/:#{noteable_id_str}/notes/:note_id" do
+          required_attributes! [:body]
+
+          authorize! :admin_note, user_project.notes.find(params[:note_id])
+
+          opts = {
+            note: params[:body],
+            note_id: params[:note_id],
+            noteable_type: noteables_str.classify,
+            noteable_id: params[noteable_id_str]
+          }
+
+          @note = ::Notes::UpdateService.new(user_project, current_user,
+                                             opts).execute
+
+          if @note.valid?
+            present @note, with: Entities::Note
+          else
+            render_api_error!("Failed to save note #{note.errors.messages}", 400)
+          end
+        end
+
       end
     end
   end
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index 7d056b9bf5872c4f6bbf78740c83d17f77a60bed..be9850367b9835def0549af04147db482f12e275 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -53,7 +53,7 @@ module API
           if @hook.errors[:url].present?
             error!("Invalid url given", 422)
           end
-          not_found!
+          not_found!("Project hook #{@hook.errors.messages}")
         end
       end
 
@@ -82,7 +82,7 @@ module API
           if @hook.errors[:url].present?
             error!("Invalid url given", 422)
           end
-          not_found!
+          not_found!("Project hook #{@hook.errors.messages}")
         end
       end
 
diff --git a/lib/api/project_members.rb b/lib/api/project_members.rb
index 1595ed0bc3653dc068a8cd7fc318eace0be245de..c756bb479fc2bc01507b99a50b30fb6bc4f0e974 100644
--- a/lib/api/project_members.rb
+++ b/lib/api/project_members.rb
@@ -4,14 +4,6 @@ module API
     before { authenticate! }
 
     resource :projects do
-      helpers do
-        def handle_project_member_errors(errors)
-          if errors[:access_level].any?
-            error!(errors[:access_level], 422)
-          end
-          not_found!
-        end
-      end
 
       # Get a project team members
       #
@@ -54,19 +46,19 @@ module API
         required_attributes! [:user_id, :access_level]
 
         # either the user is already a team member or a new one
-        team_member = user_project.team_member_by_id(params[:user_id])
-        if team_member.nil?
-          team_member = user_project.project_members.new(
+        project_member = user_project.project_member_by_id(params[:user_id])
+        if project_member.nil?
+          project_member = user_project.project_members.new(
             user_id: params[:user_id],
             access_level: params[:access_level]
           )
         end
 
-        if team_member.save
-          @member = team_member.user
+        if project_member.save
+          @member = project_member.user
           present @member, with: Entities::ProjectMember, project: user_project
         else
-          handle_project_member_errors team_member.errors
+          handle_member_errors project_member.errors
         end
       end
 
@@ -82,14 +74,14 @@ module API
         authorize! :admin_project, user_project
         required_attributes! [:access_level]
 
-        team_member = user_project.project_members.find_by(user_id: params[:user_id])
-        not_found!("User can not be found") if team_member.nil?
+        project_member = user_project.project_members.find_by(user_id: params[:user_id])
+        not_found!("User can not be found") if project_member.nil?
 
-        if team_member.update_attributes(access_level: params[:access_level])
-          @member = team_member.user
+        if project_member.update_attributes(access_level: params[:access_level])
+          @member = project_member.user
           present @member, with: Entities::ProjectMember, project: user_project
         else
-          handle_project_member_errors team_member.errors
+          handle_member_errors project_member.errors
         end
       end
 
@@ -102,11 +94,11 @@ module API
       #   DELETE /projects/:id/members/:user_id
       delete ":id/members/:user_id" do
         authorize! :admin_project, user_project
-        team_member = user_project.project_members.find_by(user_id: params[:user_id])
-        unless team_member.nil?
-          team_member.destroy
+        project_member = user_project.project_members.find_by(user_id: params[:user_id])
+        unless project_member.nil?
+          project_member.destroy
         else
-          {message: "Access revoked", id: params[:user_id].to_i}
+          { message: "Access revoked", id: params[:user_id].to_i }
         end
       end
     end
diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb
index 0c2d282f785134734a7d212eed004abb9972716f..54f2555903f0e3ed11f81f8a09e517ae296a7cf6 100644
--- a/lib/api/project_snippets.rb
+++ b/lib/api/project_snippets.rb
@@ -42,21 +42,22 @@ module API
       #   title (required) - The title of a snippet
       #   file_name (required) - The name of a snippet file
       #   code (required) - The content of a snippet
+      #   visibility_level (required) - The snippet's visibility
       # Example Request:
       #   POST /projects/:id/snippets
       post ":id/snippets" do
         authorize! :write_project_snippet, user_project
-        required_attributes! [:title, :file_name, :code]
+        required_attributes! [:title, :file_name, :code, :visibility_level]
 
-        attrs = attributes_for_keys [:title, :file_name]
+        attrs = attributes_for_keys [:title, :file_name, :visibility_level]
         attrs[:content] = params[:code] if params[:code].present?
-        @snippet = user_project.snippets.new attrs
-        @snippet.author = current_user
+        @snippet = CreateSnippetService.new(user_project, current_user,
+                                            attrs).execute
 
-        if @snippet.save
-          present @snippet, with: Entities::ProjectSnippet
-        else
+        if @snippet.errors.any?
           render_validation_error!(@snippet)
+        else
+          present @snippet, with: Entities::ProjectSnippet
         end
       end
 
@@ -68,19 +69,22 @@ module API
       #   title (optional) - The title of a snippet
       #   file_name (optional) - The name of a snippet file
       #   code (optional) - The content of a snippet
+      #   visibility_level (optional) - The snippet's visibility
       # Example Request:
       #   PUT /projects/:id/snippets/:snippet_id
       put ":id/snippets/:snippet_id" do
         @snippet = user_project.snippets.find(params[:snippet_id])
         authorize! :modify_project_snippet, @snippet
 
-        attrs = attributes_for_keys [:title, :file_name]
+        attrs = attributes_for_keys [:title, :file_name, :visibility_level]
         attrs[:content] = params[:code] if params[:code].present?
 
-        if @snippet.update_attributes attrs
-          present @snippet, with: Entities::ProjectSnippet
-        else
+        UpdateSnippetService.new(user_project, current_user, @snippet,
+                                 attrs).execute
+        if @snippet.errors.any?
           render_validation_error!(@snippet)
+        else
+          present @snippet, with: Entities::ProjectSnippet
         end
       end
 
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 7fcf97d1ad6531c9465bcb18670a64c403151046..e3fff79d68f5e6115a7314cca2bdf3081bd16bdc 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -11,23 +11,46 @@ module API
           attrs[:visibility_level] = Gitlab::VisibilityLevel::PUBLIC if !attrs[:visibility_level].present? && publik == true
           attrs
         end
+
+        def filter_projects(projects)
+          # If the archived parameter is passed, limit results accordingly
+          if params[:archived].present?
+            projects = projects.where(archived: parse_boolean(params[:archived]))
+          end
+
+          if params[:search].present?
+            projects = projects.search(params[:search])
+          end
+
+          projects.reorder(project_order_by => project_sort)
+        end
+
+        def project_order_by
+          order_fields = %w(id name path created_at updated_at last_activity_at)
+
+          if order_fields.include?(params['order_by'])
+            params['order_by']
+          else
+            'created_at'
+          end
+        end
+
+        def project_sort
+          if params["sort"] == 'asc'
+            :asc
+          else
+            :desc
+          end
+        end
       end
 
       # Get a projects list for authenticated user
       #
-      # Parameters:
-      #   archived (optional) - if passed, limit by archived status
-      #
       # Example Request:
       #   GET /projects
       get do
         @projects = current_user.authorized_projects
-
-        # If the archived parameter is passed, limit results accordingly
-        if params[:archived].present?
-          @projects = @projects.where(archived: parse_boolean(params[:archived]))
-        end
-
+        @projects = filter_projects(@projects)
         @projects = paginate @projects
         present @projects, with: Entities::Project
       end
@@ -37,7 +60,9 @@ module API
       # Example Request:
       #   GET /projects/owned
       get '/owned' do
-        @projects = paginate current_user.owned_projects
+        @projects = current_user.owned_projects
+        @projects = filter_projects(@projects)
+        @projects = paginate @projects
         present @projects, with: Entities::Project
       end
 
@@ -47,7 +72,9 @@ module API
       #   GET /projects/all
       get '/all' do
         authenticated_as_admin!
-        @projects = paginate Project
+        @projects = Project.all
+        @projects = filter_projects(@projects)
+        @projects = paginate @projects
         present @projects, with: Entities::Project
       end
 
@@ -61,17 +88,14 @@ module API
         present user_project, with: Entities::ProjectWithAccess, user: current_user
       end
 
-      # Get a single project events
+      # Get events for a single project
       #
       # Parameters:
       #   id (required) - The ID of a project
       # Example Request:
-      #   GET /projects/:id
+      #   GET /projects/:id/events
       get ":id/events" do
-        limit = (params[:per_page] || 20).to_i
-        offset = (params[:page] || 0).to_i * limit
-        events = user_project.events.recent.limit(limit).offset(offset)
-
+        events = paginate user_project.events.recent
         present events, with: Entities::Event
       end
 
@@ -170,6 +194,49 @@ module API
         end
       end
 
+      # Update an existing project
+      #
+      # Parameters:
+      #   id (required) - the id of a project
+      #   name (optional) - name of a project
+      #   path (optional) - path of a project
+      #   description (optional) - short project description
+      #   issues_enabled (optional)
+      #   merge_requests_enabled (optional)
+      #   wiki_enabled (optional)
+      #   snippets_enabled (optional)
+      #   public (optional) - if true same as setting visibility_level = 20
+      #   visibility_level (optional) - visibility level of a project
+      # Example Request
+      #   PUT /projects/:id
+      put ':id' do
+        attrs = attributes_for_keys [:name,
+                                     :path,
+                                     :description,
+                                     :default_branch,
+                                     :issues_enabled,
+                                     :merge_requests_enabled,
+                                     :wiki_enabled,
+                                     :snippets_enabled,
+                                     :public,
+                                     :visibility_level]
+        attrs = map_public_to_visibility_level(attrs)
+        authorize_admin_project
+        authorize! :rename_project, user_project if attrs[:name].present?
+        if attrs[:visibility_level].present?
+          authorize! :change_visibility_level, user_project
+        end
+
+        ::Projects::UpdateService.new(user_project,
+                                      current_user, attrs).execute
+
+        if user_project.errors.any?
+          render_validation_error!(user_project)
+        else
+          present user_project, with: Entities::Project
+        end
+      end
+
       # Remove project
       #
       # Parameters:
@@ -198,7 +265,7 @@ module API
             render_api_error!("Project already forked", 409)
           end
         else
-          not_found!
+          not_found!("Source Project")
         end
 
       end
@@ -227,6 +294,16 @@ module API
         ids = current_user.authorized_projects.map(&:id)
         visibility_levels = [ Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC ]
         projects = Project.where("(id in (?) OR visibility_level in (?)) AND (name LIKE (?))", ids, visibility_levels, "%#{params[:query]}%")
+        sort = params[:sort] == 'desc' ? 'desc' : 'asc'
+
+        projects = case params["order_by"]
+                   when 'id' then projects.order("id #{sort}")
+                   when 'name' then projects.order("name #{sort}")
+                   when 'created_at' then projects.order("created_at #{sort}")
+                   when 'last_activity_at' then projects.order("last_activity_at #{sort}")
+                   else projects
+                   end
+
         present paginate(projects), with: Entities::Project
       end
 
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index a1a7721b28894cd542d87728fa90bafd4eb0dfd6..b259914a01c4311015af4035133b8d85873fd903 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -58,11 +58,13 @@ module API
       #   ref_name (optional) - The name of a repository branch or tag, if not given the default branch is used
       # Example Request:
       #   GET /projects/:id/repository/tree
-      get ":id/repository/tree" do
+      get ':id/repository/tree' do
         ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
         path = params[:path] || nil
 
         commit = user_project.repository.commit(ref)
+        not_found!('Tree') unless commit
+
         tree = user_project.repository.tree(commit.id, path)
 
         present tree.sorted_entries, with: Entities::RepoTreeObject
@@ -100,14 +102,18 @@ module API
       #   sha (required) - The blob's sha
       # Example Request:
       #   GET /projects/:id/repository/raw_blobs/:sha
-      get ":id/repository/raw_blobs/:sha" do
+      get ':id/repository/raw_blobs/:sha' do
         ref = params[:sha]
 
         repo = user_project.repository
 
-        blob = Gitlab::Git::Blob.raw(repo, ref)
+        begin
+          blob = Gitlab::Git::Blob.raw(repo, ref)
+        rescue
+          not_found! 'Blob'
+        end
 
-        not_found! "Blob" unless blob
+        not_found! 'Blob' unless blob
 
         env['api.format'] = :txt
 
@@ -122,18 +128,28 @@ module API
       #   sha (optional) - the commit sha to download defaults to the tip of the default branch
       # Example Request:
       #   GET /projects/:id/repository/archive
-      get ":id/repository/archive", requirements: { format: Gitlab::Regex.archive_formats_regex } do
+      get ':id/repository/archive',
+          requirements: { format: Gitlab::Regex.archive_formats_regex } do
         authorize! :download_code, user_project
-        file_path = ArchiveRepositoryService.new.execute(user_project, params[:sha], params[:format])
+
+        begin
+          file_path = ArchiveRepositoryService.new.execute(
+              user_project,
+              params[:sha],
+              params[:format])
+        rescue
+          not_found!('File')
+        end
 
         if file_path && File.exists?(file_path)
           data = File.open(file_path, 'rb').read
-          header["Content-Disposition"] = "attachment; filename=\"#{File.basename(file_path)}\""
+          basename = File.basename(file_path)
+          header['Content-Disposition'] = "attachment; filename=\"#{basename}\""
           content_type MIME::Types.type_for(file_path).first.content_type
           env['api.format'] = :binary
           present data
         else
-          not_found!
+          not_found!('File')
         end
       end
 
@@ -161,7 +177,12 @@ module API
       get ':id/repository/contributors' do
         authorize! :download_code, user_project
 
-        present user_project.repository.contributors, with: Entities::Contributor
+        begin
+          present user_project.repository.contributors,
+                  with: Entities::Contributor
+        rescue
+          not_found!
+        end
       end
     end
   end
diff --git a/lib/api/system_hooks.rb b/lib/api/system_hooks.rb
index 3e239c5afe773502151d31ae109f31fd6934abc6..518964db50d3739a5472771b9f1f3a8e0ab9b1e4 100644
--- a/lib/api/system_hooks.rb
+++ b/lib/api/system_hooks.rb
@@ -1,10 +1,10 @@
 module API
   # Hooks API
   class SystemHooks < Grape::API
-    before {
+    before do
       authenticate!
       authenticated_as_admin!
-    }
+    end
 
     resource :hooks do
       # Get the list of system hooks
diff --git a/lib/api/users.rb b/lib/api/users.rb
index d07815a8a9774577d4abe5d9af78666d887dc334..032a5d76e4394027129936b6c2bfa8a1cae118bc 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -54,15 +54,24 @@ module API
       #   bio                               - Bio
       #   admin                             - User is admin - true or false (default)
       #   can_create_group                  - User can create groups - true or false
+      #   confirm                           - Require user confirmation - true (default) or false
       # Example Request:
       #   POST /users
       post do
         authenticated_as_admin!
         required_attributes! [:email, :password, :name, :username]
-        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
-        user = User.build_user(attrs)
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :can_create_group, :admin, :confirm]
         admin = attrs.delete(:admin)
+        confirm = !(attrs.delete(:confirm) =~ (/(false|f|no|0)$/i))
+        user = User.build_user(attrs)
         user.admin = admin unless admin.nil?
+        user.skip_confirmation! unless confirm
+
+        identity_attrs = attributes_for_keys [:provider, :extern_uid]
+        if identity_attrs.any?
+          user.identities.build(identity_attrs)
+        end
+
         if user.save
           present user, with: Entities::UserFull
         else
@@ -89,8 +98,6 @@ module API
       #   twitter                           - Twitter account
       #   website_url                       - Website url
       #   projects_limit                    - Limit projects each user can create
-      #   extern_uid                        - External authentication provider UID
-      #   provider                          - External provider
       #   bio                               - Bio
       #   admin                             - User is admin - true or false (default)
       #   can_create_group                  - User can create groups - true or false
@@ -99,7 +106,7 @@ module API
       put ":id" do
         authenticated_as_admin!
 
-        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :bio, :can_create_group, :admin]
         user = User.find(params[:id])
         not_found!('User') unless user
 
diff --git a/lib/backup/database.rb b/lib/backup/database.rb
index ea659e3b605fd81cb72fecb9395ff7b2f91efc64..9ab6aca276da7a274b464b404efafc62878c7605 100644
--- a/lib/backup/database.rb
+++ b/lib/backup/database.rb
@@ -13,10 +13,10 @@ module Backup
     def dump
       success = case config["adapter"]
       when /^mysql/ then
-        print "Dumping MySQL database #{config['database']} ... "
+        $progress.print "Dumping MySQL database #{config['database']} ... "
         system('mysqldump', *mysql_args, config['database'], out: db_file_name)
       when "postgresql" then
-        print "Dumping PostgreSQL database #{config['database']} ... "
+        $progress.print "Dumping PostgreSQL database #{config['database']} ... "
         pg_env
         system('pg_dump', config['database'], out: db_file_name)
       end
@@ -27,10 +27,10 @@ module Backup
     def restore
       success = case config["adapter"]
       when /^mysql/ then
-        print "Restoring MySQL database #{config['database']} ... "
+        $progress.print "Restoring MySQL database #{config['database']} ... "
         system('mysql', *mysql_args, config['database'], in: db_file_name)
       when "postgresql" then
-        print "Restoring PostgreSQL database #{config['database']} ... "
+        $progress.print "Restoring PostgreSQL database #{config['database']} ... "
         # Drop all tables because PostgreSQL DB dumps do not contain DROP TABLE
         # statements like MySQL.
         Rake::Task["gitlab:db:drop_all_tables"].invoke
@@ -69,9 +69,9 @@ module Backup
 
     def report_success(success)
       if success
-        puts '[DONE]'.green
+        $progress.puts '[DONE]'.green
       else
-        puts '[FAILED]'.red
+        $progress.puts '[FAILED]'.red
       end
     end
   end
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 03fe0f0b02f2fdc7b47275ab842398967918630b..afd05897509f97864b859b65fe841402e2b0d1bc 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -11,74 +11,82 @@ module Backup
       s[:tar_version]        = tar_version
       tar_file = "#{s[:backup_created_at].to_i}_gitlab_backup.tar"
 
-      Dir.chdir(Gitlab.config.backup.path)
+      Dir.chdir(Gitlab.config.backup.path) do
+        File.open("#{Gitlab.config.backup.path}/backup_information.yml",
+                  "w+") do |file|
+          file << s.to_yaml.gsub(/^---\n/,'')
+        end
 
-      File.open("#{Gitlab.config.backup.path}/backup_information.yml", "w+") do |file|
-        file << s.to_yaml.gsub(/^---\n/,'')
-      end
+        FileUtils.chmod_R(0700, %w{db uploads repositories})
 
-      # create archive
-      print "Creating backup archive: #{tar_file} ... "
-      if Kernel.system('tar', '-cf', tar_file, *BACKUP_CONTENTS)
-        puts "done".green
-      else
-        puts "failed".red
-        abort 'Backup failed'
-      end
+        # create archive
+        $progress.print "Creating backup archive: #{tar_file} ... "
+        orig_umask = File.umask(0077)
+        if Kernel.system('tar', '-cf', tar_file, *BACKUP_CONTENTS)
+          $progress.puts "done".green
+        else
+          puts "creating archive #{tar_file} failed".red
+          abort 'Backup failed'
+        end
+        File.umask(orig_umask)
 
-      upload(tar_file)
+        upload(tar_file)
+      end
     end
 
     def upload(tar_file)
       remote_directory = Gitlab.config.backup.upload.remote_directory
-      print "Uploading backup archive to remote storage #{remote_directory} ... "
+      $progress.print "Uploading backup archive to remote storage #{remote_directory} ... "
 
       connection_settings = Gitlab.config.backup.upload.connection
       if connection_settings.blank?
-        puts "skipped".yellow
+        $progress.puts "skipped".yellow
         return
       end
 
       connection = ::Fog::Storage.new(connection_settings)
       directory = connection.directories.get(remote_directory)
       if directory.files.create(key: tar_file, body: File.open(tar_file), public: false)
-        puts "done".green
+        $progress.puts "done".green
       else
-        puts "failed".red
+        puts "uploading backup to #{remote_directory} failed".red
         abort 'Backup failed'
       end
     end
 
     def cleanup
-      print "Deleting tmp directories ... "
-      if Kernel.system('rm', '-rf', *BACKUP_CONTENTS)
-        puts "done".green
-      else
-        puts "failed".red
-        abort 'Backup failed'
+      $progress.print "Deleting tmp directories ... "
+      BACKUP_CONTENTS.each do |dir|
+        if FileUtils.rm_rf(File.join(Gitlab.config.backup.path, dir))
+          $progress.puts "done".green
+        else
+          puts "deleting tmp directory '#{dir}' failed".red
+          abort 'Backup failed'
+        end
       end
     end
 
     def remove_old
       # delete backups
-      print "Deleting old backups ... "
+      $progress.print "Deleting old backups ... "
       keep_time = Gitlab.config.backup.keep_time.to_i
-      path = Gitlab.config.backup.path
 
       if keep_time > 0
         removed = 0
-        file_list = Dir.glob(Rails.root.join(path, "*_gitlab_backup.tar"))
-        file_list.map! { |f| $1.to_i if f =~ /(\d+)_gitlab_backup.tar/ }
-        file_list.sort.each do |timestamp|
-          if Time.at(timestamp) < (Time.now - keep_time)
-            if Kernel.system(*%W(rm #{timestamp}_gitlab_backup.tar))
-              removed += 1
+        Dir.chdir(Gitlab.config.backup.path) do
+          file_list = Dir.glob('*_gitlab_backup.tar')
+          file_list.map! { |f| $1.to_i if f =~ /(\d+)_gitlab_backup.tar/ }
+          file_list.sort.each do |timestamp|
+            if Time.at(timestamp) < (Time.now - keep_time)
+              if Kernel.system(*%W(rm #{timestamp}_gitlab_backup.tar))
+                removed += 1
+              end
             end
           end
         end
-        puts "done. (#{removed} removed)".green
+        $progress.puts "done. (#{removed} removed)".green
       else
-        puts "skipping".yellow
+        $progress.puts "skipping".yellow
       end
     end
 
@@ -101,12 +109,12 @@ module Backup
         exit 1
       end
 
-      print "Unpacking backup ... "
+      $progress.print "Unpacking backup ... "
       unless Kernel.system(*%W(tar -xf #{tar_file}))
-        puts "failed".red
+        puts "unpacking backup failed".red
         exit 1
       else
-        puts "done".green
+        $progress.puts "done".green
       end
 
       settings = YAML.load_file("backup_information.yml")
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index faa1b3b40996896666bf419ae7cbfde091d1dcab..5b5afc3b78d8bdec3ae2ec221f6cc6cc0327463e 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -8,19 +8,21 @@ module Backup
       prepare
 
       Project.find_each(batch_size: 1000) do |project|
-        print " * #{project.path_with_namespace} ... "
+        $progress.print " * #{project.path_with_namespace} ... "
 
         # Create namespace dir if missing
         FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.path)) if project.namespace
 
         if project.empty_repo?
-          puts "[SKIPPED]".cyan
+          $progress.puts "[SKIPPED]".cyan
         else
-          output, status = Gitlab::Popen.popen(%W(git --git-dir=#{path_to_repo(project)} bundle create #{path_to_bundle(project)} --all))
+          cmd = %W(tar -cf #{path_to_bundle(project)} -C #{path_to_repo(project)} .)
+          output, status = Gitlab::Popen.popen(cmd)
           if status.zero?
-            puts "[DONE]".green
+            $progress.puts "[DONE]".green
           else
             puts "[FAILED]".red
+            puts "failed: #{cmd.join(' ')}"
             puts output
             abort 'Backup failed'
           end
@@ -29,15 +31,17 @@ module Backup
         wiki = ProjectWiki.new(project)
 
         if File.exists?(path_to_repo(wiki))
-          print " * #{wiki.path_with_namespace} ... "
+          $progress.print " * #{wiki.path_with_namespace} ... "
           if wiki.repository.empty?
-            puts " [SKIPPED]".cyan
+            $progress.puts " [SKIPPED]".cyan
           else
-            output, status = Gitlab::Popen.popen(%W(git --git-dir=#{path_to_repo(wiki)} bundle create #{path_to_bundle(wiki)} --all))
+            cmd = %W(git --git-dir=#{path_to_repo(wiki)} bundle create #{path_to_bundle(wiki)} --all)
+            output, status = Gitlab::Popen.popen(cmd)
             if status.zero?
-              puts " [DONE]".green
+              $progress.puts " [DONE]".green
             else
               puts " [FAILED]".red
+              puts "failed: #{cmd.join(' ')}"
               abort 'Backup failed'
             end
           end
@@ -55,41 +59,63 @@ module Backup
       FileUtils.mkdir_p(repos_path)
 
       Project.find_each(batch_size: 1000) do |project|
-        print "#{project.path_with_namespace} ... "
+        $progress.print " * #{project.path_with_namespace} ... "
+        Properly fix wiki restore.
+        Remove unnecessary backported change
 
         project.namespace.ensure_dir_exist if project.namespace
 
         if File.exists?(path_to_bundle(project))
-          cmd = %W(git clone --bare #{path_to_bundle(project)} #{path_to_repo(project)})
+          FileUtils.mkdir_p(path_to_repo(project))
+          cmd = %W(tar -xf #{path_to_bundle(project)} -C #{path_to_repo(project)})
         else
           cmd = %W(git init --bare #{path_to_repo(project)})
         end
 
         if system(*cmd, silent)
-          puts "[DONE]".green
+          $progress.puts "[DONE]".green
         else
           puts "[FAILED]".red
+          puts "failed: #{cmd.join(' ')}"
           abort 'Restore failed'
         end
 
         wiki = ProjectWiki.new(project)
 
         if File.exists?(path_to_bundle(wiki))
+<<<<<<< HEAD
+          $progress.print " * #{wiki.path_with_namespace} ... "
+=======
           print " * #{wiki.path_with_namespace} ... "
-          if system(*%W(git clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)}), silent)
+>>>>>>> Properly fix wiki restore.
+
+          # If a wiki bundle exists, first remove the empty repo
+          # that was initialized with ProjectWiki.new() and then
+          # try to restore with 'git clone --bare'.
+          FileUtils.rm_rf(path_to_repo(wiki))
+          cmd = %W(git clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)})
+
+          if system(*cmd, silent)
+<<<<<<< HEAD
+            $progress.puts " [DONE]".green
+=======
             puts " [DONE]".green
+>>>>>>> Properly fix wiki restore.
           else
             puts " [FAILED]".red
+            puts "failed: #{cmd.join(' ')}"
             abort 'Restore failed'
           end
         end
       end
 
-      print 'Put GitLab hooks in repositories dirs'.yellow
-      if system("#{Gitlab.config.gitlab_shell.path}/bin/create-hooks")
-        puts " [DONE]".green
+      $progress.print 'Put GitLab hooks in repositories dirs'.yellow
+      cmd = "#{Gitlab.config.gitlab_shell.path}/bin/create-hooks"
+      if system(cmd)
+        $progress.puts " [DONE]".green
       else
         puts " [FAILED]".red
+        puts "failed: #{cmd}"
       end
 
     end
diff --git a/lib/email_validator.rb b/lib/email_validator.rb
index 0a67ebcd7959672cd617603235ae544dc84b5a5b..f509f0a584336fc0b3a1a5cccd36477eeb4c7fd4 100644
--- a/lib/email_validator.rb
+++ b/lib/email_validator.rb
@@ -1,5 +1,5 @@
 # Based on https://github.com/balexand/email_validator
-# 
+#
 # Extended to use only strict mode with following allowed characters:
 # ' - apostrophe
 #
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index e51cb30bdd919db3cd3829e8c7bba63ff2f84361..6e4ed01e079c2dde1f15c7431a4d415b73b180cb 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -1,17 +1,9 @@
 # Module providing methods for dealing with separating a tree-ish string and a
 # file path string when combined in a request parameter
 module ExtractsPath
-  extend ActiveSupport::Concern
-
   # Raised when given an invalid file path
   class InvalidPathError < StandardError; end
 
-  included do
-    if respond_to?(:before_filter)
-      before_filter :assign_ref_vars
-    end
-  end
-
   # Given a string containing both a Git tree-ish, such as a branch or tag, and
   # a filesystem path joined by forward slashes, attempts to separate the two.
   #
@@ -110,7 +102,8 @@ module ExtractsPath
     raise InvalidPathError unless @commit
 
     @hex_path = Digest::SHA1.hexdigest(@path)
-    @logs_path = logs_file_project_ref_path(@project, @ref, @path)
+    @logs_path = logs_file_namespace_project_ref_path(@project.namespace,
+                                                      @project, @ref, @path)
 
   rescue RuntimeError, NoMethodError, InvalidPathError
     not_found!
diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb
index 411b2b9a3cc7e014ce20134ff91c9ba2e04a37b9..424541b4a04c259b5e5de0761f7f7d03fec61d28 100644
--- a/lib/gitlab/access.rb
+++ b/lib/gitlab/access.rb
@@ -11,6 +11,11 @@ module Gitlab
     MASTER    = 40
     OWNER     = 50
 
+    # Branch protection settings
+    PROTECTION_NONE         = 0
+    PROTECTION_DEV_CAN_PUSH = 1
+    PROTECTION_FULL         = 2
+
     class << self
       def values
         options.values
@@ -43,6 +48,18 @@ module Gitlab
           master:    MASTER,
         }
       end
+
+      def protection_options
+        {
+          "Not protected, developers and masters can (force) push and delete the branch" => PROTECTION_NONE,
+          "Partially protected, developers can also push but prevent all force pushes and deletion" => PROTECTION_DEV_CAN_PUSH,
+          "Fully protected, only masters can push and prevent all force pushes and deletion" => PROTECTION_FULL,
+        }
+      end
+
+      def protection_values
+        protection_options.values
+      end
     end
 
     def human_access
diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
index df1461a45c988e21cb485adab198eb062ac8e790..050b5ba29dd5e31b5b052680fef474966f2d5778 100644
--- a/lib/gitlab/backend/grack_auth.rb
+++ b/lib/gitlab/backend/grack_auth.rb
@@ -1,3 +1,4 @@
+require_relative 'rack_attack_helpers'
 require_relative 'shell_env'
 
 module Grack
@@ -10,8 +11,9 @@ module Grack
       @request = Rack::Request.new(env)
       @auth = Request.new(env)
 
-      # Need this patch due to the rails mount
+      @gitlab_ci = false
 
+      # Need this patch due to the rails mount
       # Need this if under RELATIVE_URL_ROOT
       unless Gitlab.config.gitlab.relative_url_root.empty?
         # If website is mounted using relative_url_root need to remove it first
@@ -22,8 +24,12 @@ module Grack
 
       @env['SCRIPT_NAME'] = ""
 
-      if project
-        auth!
+      auth!
+
+      if project && authorized_request?
+        @app.call(env)
+      elsif @user.nil? && !@gitlab_ci
+        unauthorized
       else
         render_not_found
       end
@@ -32,35 +38,30 @@ module Grack
     private
 
     def auth!
-      if @auth.provided?
-        return bad_request unless @auth.basic?
-
-        # Authentication with username and password
-        login, password = @auth.credentials
+      return unless @auth.provided?
 
-        # Allow authentication for GitLab CI service
-        # if valid token passed
-        if gitlab_ci_request?(login, password)
-          return @app.call(env)
-        end
+      return bad_request unless @auth.basic?
 
-        @user = authenticate_user(login, password)
+      # Authentication with username and password
+      login, password = @auth.credentials
 
-        if @user
-          Gitlab::ShellEnv.set_env(@user)
-          @env['REMOTE_USER'] = @auth.username
-        end
+      # Allow authentication for GitLab CI service
+      # if valid token passed
+      if gitlab_ci_request?(login, password)
+        @gitlab_ci = true
+        return
       end
 
-      if authorized_request?
-        @app.call(env)
-      else
-        unauthorized
+      @user = authenticate_user(login, password)
+
+      if @user
+        Gitlab::ShellEnv.set_env(@user)
+        @env['REMOTE_USER'] = @auth.username
       end
     end
 
     def gitlab_ci_request?(login, password)
-      if login == "gitlab-ci-token" && project.gitlab_ci?
+      if login == "gitlab-ci-token" && project && project.gitlab_ci?
         token = project.gitlab_ci_service.token
 
         if token.present? && token == password && git_cmd == 'git-upload-pack'
@@ -71,16 +72,64 @@ module Grack
       false
     end
 
+    def oauth_access_token_check(login, password)
+      if login == "oauth2" && git_cmd == 'git-upload-pack' && password.present?
+        token = Doorkeeper::AccessToken.by_token(password)
+        token && token.accessible? && User.find_by(id: token.resource_owner_id)
+      end
+    end
+
     def authenticate_user(login, password)
-      auth = Gitlab::Auth.new
-      auth.find(login, password)
+      user = Gitlab::Auth.new.find(login, password)
+
+      unless user
+        user = oauth_access_token_check(login, password)
+      end
+
+      # If the user authenticated successfully, we reset the auth failure count
+      # from Rack::Attack for that IP. A client may attempt to authenticate
+      # with a username and blank password first, and only after it receives
+      # a 401 error does it present a password. Resetting the count prevents
+      # false positives from occurring.
+      #
+      # Otherwise, we let Rack::Attack know there was a failed authentication
+      # attempt from this IP. This information is stored in the Rails cache
+      # (Redis) and will be used by the Rack::Attack middleware to decide
+      # whether to block requests from this IP.
+      config = Gitlab.config.rack_attack.git_basic_auth
+
+      if config.enabled
+        if user
+          # A successful login will reset the auth failure count from this IP
+          Rack::Attack::Allow2Ban.reset(@request.ip, config)
+        else
+          banned = Rack::Attack::Allow2Ban.filter(@request.ip, config) do
+            # Unless the IP is whitelisted, return true so that Allow2Ban
+            # increments the counter (stored in Rails.cache) for the IP
+            if config.ip_whitelist.include?(@request.ip)
+              false
+            else
+              true
+            end
+          end
+
+          if banned
+            Rails.logger.info "IP #{@request.ip} failed to login " \
+              "as #{login} but has been temporarily banned from Git auth"
+          end
+        end
+      end
+
+      user
     end
 
     def authorized_request?
+      return true if @gitlab_ci
+
       case git_cmd
       when *Gitlab::GitAccess::DOWNLOAD_COMMANDS
         if user
-          Gitlab::GitAccess.new.download_allowed?(user, project)
+          Gitlab::GitAccess.new(user, project).download_access_check.allowed?
         elsif project.public?
           # Allow clone/fetch for public projects
           true
@@ -111,7 +160,9 @@ module Grack
     end
 
     def project
-      @project ||= project_by_path(@request.path_info)
+      return @project if defined?(@project)
+
+      @project = project_by_path(@request.path_info)
     end
 
     def project_by_path(path)
@@ -119,12 +170,13 @@ module Grack
         path_with_namespace = m.last
         path_with_namespace.gsub!(/\.wiki$/, '')
 
+        path_with_namespace[0] = '' if path_with_namespace.start_with?('/')
         Project.find_with_namespace(path_with_namespace)
       end
     end
 
     def render_not_found
-      [404, {"Content-Type" => "text/plain"}, ["Not Found"]]
+      [404, { "Content-Type" => "text/plain" }, ["Not Found"]]
     end
   end
 end
diff --git a/lib/gitlab/backend/rack_attack_helpers.rb b/lib/gitlab/backend/rack_attack_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8538f3f6ecab3eaf0069455447ba47c84fa9693b
--- /dev/null
+++ b/lib/gitlab/backend/rack_attack_helpers.rb
@@ -0,0 +1,31 @@
+# rack-attack v4.2.0 doesn't yet support clearing of keys.
+# Taken from https://github.com/kickstarter/rack-attack/issues/113
+class Rack::Attack::Allow2Ban
+  def self.reset(discriminator, options)
+    findtime = options[:findtime] or raise ArgumentError, "Must pass findtime option"
+
+    cache.reset_count("#{key_prefix}:count:#{discriminator}", findtime)
+    cache.delete("#{key_prefix}:ban:#{discriminator}")
+  end
+end
+
+class Rack::Attack::Cache
+  def reset_count(unprefixed_key, period)
+    epoch_time = Time.now.to_i
+    # Add 1 to expires_in to avoid timing error: http://git.io/i1PHXA
+    expires_in = period - (epoch_time % period) + 1
+    key = "#{(epoch_time / period).to_i}:#{unprefixed_key}"
+    delete(key)
+  end
+
+  def delete(unprefixed_key)
+    store.delete("#{prefix}:#{unprefixed_key}")
+  end
+end
+
+class Rack::Attack::StoreProxy::RedisStoreProxy
+  def delete(key, options={})
+    self.del(key)
+    rescue Redis::BaseError
+  end
+end
diff --git a/lib/gitlab/backend/shell_adapter.rb b/lib/gitlab/backend/shell_adapter.rb
index f247f4593d7ffc8f1e2211245033b75a24d5fa16..fbe2a7a0d721ad474e85c72090c8b6431ce386da 100644
--- a/lib/gitlab/backend/shell_adapter.rb
+++ b/lib/gitlab/backend/shell_adapter.rb
@@ -9,4 +9,3 @@ module Gitlab
     end
   end
 end
-
diff --git a/lib/gitlab/bitbucket_import.rb b/lib/gitlab/bitbucket_import.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7298152e7e98515524815f239706ca9abf9f558d
--- /dev/null
+++ b/lib/gitlab/bitbucket_import.rb
@@ -0,0 +1,6 @@
+module Gitlab
+  module BitbucketImport
+    mattr_accessor :public_key
+    @public_key = nil
+  end
+end
diff --git a/lib/gitlab/bitbucket_import/client.rb b/lib/gitlab/bitbucket_import/client.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5b1952b9675f126671b0d85db88e149e13b52f54
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/client.rb
@@ -0,0 +1,99 @@
+module Gitlab
+  module BitbucketImport
+    class Client
+      attr_reader :consumer, :api
+
+      def initialize(access_token = nil, access_token_secret = nil)
+        @consumer = ::OAuth::Consumer.new(
+          config.app_id,
+          config.app_secret,
+          bitbucket_options
+        )
+
+        if access_token && access_token_secret
+          @api = ::OAuth::AccessToken.new(@consumer, access_token, access_token_secret)
+        end
+      end
+
+      def request_token(redirect_uri)
+        request_token = consumer.get_request_token(oauth_callback: redirect_uri)
+
+        {
+          oauth_token:              request_token.token,
+          oauth_token_secret:       request_token.secret,
+          oauth_callback_confirmed: request_token.callback_confirmed?.to_s
+        }
+      end
+
+      def authorize_url(request_token, redirect_uri)
+        request_token = ::OAuth::RequestToken.from_hash(consumer, request_token) if request_token.is_a?(Hash)
+
+        if request_token.callback_confirmed?
+          request_token.authorize_url
+        else
+          request_token.authorize_url(oauth_callback: redirect_uri)
+        end
+      end
+
+      def get_token(request_token, oauth_verifier, redirect_uri)
+        request_token = ::OAuth::RequestToken.from_hash(consumer, request_token) if request_token.is_a?(Hash)
+
+        if request_token.callback_confirmed?
+          request_token.get_access_token(oauth_verifier: oauth_verifier)
+        else
+          request_token.get_access_token(oauth_callback: redirect_uri)
+        end
+      end
+
+      def user
+        JSON.parse(api.get("/api/1.0/user").body)
+      end
+
+      def issues(project_identifier)
+        JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/issues").body)
+      end
+
+      def issue_comments(project_identifier, issue_id)
+        JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/issues/#{issue_id}/comments").body)
+      end
+
+      def project(project_identifier)
+        JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}").body)
+      end
+
+      def find_deploy_key(project_identifier, key)
+        JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/deploy-keys").body).find do |deploy_key|
+          deploy_key["key"].chomp == key.chomp
+        end
+      end
+
+      def add_deploy_key(project_identifier, key)
+        deploy_key = find_deploy_key(project_identifier, key)
+        return if deploy_key
+
+        JSON.parse(api.post("/api/1.0/repositories/#{project_identifier}/deploy-keys", key: key, label: "GitLab import key").body)
+      end
+
+      def delete_deploy_key(project_identifier, key)
+        deploy_key = find_deploy_key(project_identifier, key)
+        return unless deploy_key
+
+        api.delete("/api/1.0/repositories/#{project_identifier}/deploy-keys/#{deploy_key["pk"]}").code == "204"
+      end
+
+      def projects
+        JSON.parse(api.get("/api/1.0/user/repositories").body).select { |repo| repo["scm"] == "git" }
+      end
+
+      private
+
+      def config
+        Gitlab.config.omniauth.providers.find { |provider| provider.name == "bitbucket"}
+      end
+
+      def bitbucket_options
+        OmniAuth::Strategies::Bitbucket.default_options[:client_options].symbolize_keys
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..42c93707caa69cba20af39ff39af6112b90bdbc1
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/importer.rb
@@ -0,0 +1,52 @@
+module Gitlab
+  module BitbucketImport
+    class Importer
+      attr_reader :project, :client
+
+      def initialize(project)
+        @project = project
+        @client = Client.new(project.creator.bitbucket_access_token, project.creator.bitbucket_access_token_secret)
+        @formatter = Gitlab::ImportFormatter.new
+      end
+
+      def execute
+        project_identifier = project.import_source
+
+        return true unless client.project(project_identifier)["has_issues"]
+
+        #Issues && Comments
+        issues = client.issues(project_identifier)
+        
+        issues["issues"].each do |issue|
+          body = @formatter.author_line(issue["reported_by"]["username"], issue["content"])
+          
+          comments = client.issue_comments(project_identifier, issue["local_id"])
+          
+          if comments.any?
+            body += @formatter.comments_header
+          end
+
+          comments.each do |comment|
+            body += @formatter.comment(comment["author_info"]["username"], comment["utc_created_on"], comment["content"])
+          end
+
+          project.issues.create!(
+            description: body, 
+            title: issue["title"],
+            state: %w(resolved invalid duplicate wontfix).include?(issue["status"]) ? 'closed' : 'opened',
+            author_id: gl_user_id(project, issue["reported_by"]["username"])
+          )
+        end
+        
+        true
+      end
+
+      private
+
+      def gl_user_id(project, bitbucket_id)
+        user = User.joins(:identities).find_by("identities.extern_uid = ? AND identities.provider = 'bitbucket'", bitbucket_id.to_s)
+        (user && user.id) || project.creator_id
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/bitbucket_import/key_adder.rb b/lib/gitlab/bitbucket_import/key_adder.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9931aa7e029996fbb95f63ac13f11d94db79569c
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/key_adder.rb
@@ -0,0 +1,23 @@
+module Gitlab
+  module BitbucketImport
+    class KeyAdder
+      attr_reader :repo, :current_user, :client
+
+      def initialize(repo, current_user)
+        @repo, @current_user = repo, current_user
+        @client = Client.new(current_user.bitbucket_access_token, current_user.bitbucket_access_token_secret)
+      end
+
+      def execute
+        return false unless BitbucketImport.public_key.present?
+        
+        project_identifier = "#{repo["owner"]}/#{repo["slug"]}"
+        client.add_deploy_key(project_identifier, BitbucketImport.public_key)
+
+        true
+      rescue
+        false
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/bitbucket_import/key_deleter.rb b/lib/gitlab/bitbucket_import/key_deleter.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1a24a86fc37c0f00d8900633e11fd0efa261566c
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/key_deleter.rb
@@ -0,0 +1,23 @@
+module Gitlab
+  module BitbucketImport
+    class KeyDeleter
+      attr_reader :project, :current_user, :client
+
+      def initialize(project)
+        @project = project
+        @current_user = project.creator
+        @client = Client.new(current_user.bitbucket_access_token, current_user.bitbucket_access_token_secret)
+      end
+
+      def execute
+        return false unless BitbucketImport.public_key.present?
+        
+        client.delete_deploy_key(project.import_source, BitbucketImport.public_key)
+
+        true
+      rescue
+        false
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/bitbucket_import/project_creator.rb b/lib/gitlab/bitbucket_import/project_creator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..db33af2c2dae945d30542e52264c6232f364edf6
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/project_creator.rb
@@ -0,0 +1,39 @@
+module Gitlab
+  module BitbucketImport
+    class ProjectCreator
+      attr_reader :repo, :namespace, :current_user
+
+      def initialize(repo, namespace, current_user)
+        @repo = repo
+        @namespace = namespace
+        @current_user = current_user
+      end
+
+      def execute
+        @project = Project.new(
+          name: repo["name"],
+          path: repo["slug"],
+          description: repo["description"],
+          namespace: namespace,
+          creator: current_user,
+          visibility_level: repo["is_private"] ? Gitlab::VisibilityLevel::PRIVATE : Gitlab::VisibilityLevel::PUBLIC,
+          import_type: "bitbucket",
+          import_source: "#{repo["owner"]}/#{repo["slug"]}",
+          import_url: "ssh://git@bitbucket.org/#{repo["owner"]}/#{repo["slug"]}.git"
+        )
+
+        if @project.save!
+          @project.reload
+
+          if @project.import_failed?
+            @project.import_retry
+          else
+            @project.import_start
+          end
+        end
+
+        @project
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/closing_issue_extractor.rb b/lib/gitlab/closing_issue_extractor.rb
index 401e6e047b16115f61a00901daac460e282ac4bd..a9fd59f03d92bbb1869b1a8bb6ef454896acb84d 100644
--- a/lib/gitlab/closing_issue_extractor.rb
+++ b/lib/gitlab/closing_issue_extractor.rb
@@ -3,14 +3,19 @@ module Gitlab
     ISSUE_CLOSING_REGEX = Regexp.new(Gitlab.config.gitlab.issue_closing_pattern)
 
     def self.closed_by_message_in_project(message, project)
-      md = ISSUE_CLOSING_REGEX.match(message)
-      if md
-        extractor = Gitlab::ReferenceExtractor.new
-        extractor.analyze(md[0], project)
-        extractor.issues_for(project)
-      else
-        []
+      issues = []
+
+      unless message.nil?
+        md = message.scan(ISSUE_CLOSING_REGEX)
+
+        md.each do |ref|
+          extractor = Gitlab::ReferenceExtractor.new
+          extractor.analyze(ref[0], project)
+          issues += extractor.issues_for(project)
+        end
       end
+
+      issues.uniq
     end
   end
 end
diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3fd0823df063662b5f05ead5446e6c4897200ba5
--- /dev/null
+++ b/lib/gitlab/contributions_calendar.rb
@@ -0,0 +1,56 @@
+module Gitlab
+  class ContributionsCalendar
+    attr_reader :timestamps, :projects, :user
+
+    def initialize(projects, user)
+      @projects = projects
+      @user = user
+    end
+
+    def timestamps
+      return @timestamps if @timestamps.present?
+
+      @timestamps = {}
+      date_from = 1.year.ago
+      date_to = Date.today
+
+      events = Event.reorder(nil).contributions.where(author_id: user.id).
+        where("created_at > ?", date_from).where(project_id: projects).
+        group('date(created_at)').
+        select('date(created_at), count(id) as total_amount').
+        map(&:attributes)
+
+      dates = (1.year.ago.to_date..(Date.today + 1.day)).to_a
+
+      dates.each do |date|
+        date_id = date.to_time.to_i.to_s
+        @timestamps[date_id] = 0
+        day_events = events.find { |day_events| day_events["date"] == date }
+
+        if day_events
+          @timestamps[date_id] = day_events["total_amount"]
+        end
+      end
+
+      @timestamps
+    end
+
+    def events_by_date(date)
+      events = Event.contributions.where(author_id: user.id).
+        where("created_at > ? AND created_at < ?", date.beginning_of_day, date.end_of_day).
+        where(project_id: projects)
+
+      events.select do |event|
+        event.push? || event.issue? || event.merge_request?
+      end
+    end
+
+    def starting_year
+      (Time.now - 1.year).strftime("%Y")
+    end
+
+    def starting_month
+      Date.today.strftime("%m").to_i
+    end
+  end
+end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0ebebfa09c4329e9f59d75da9bb065cad8293181
--- /dev/null
+++ b/lib/gitlab/current_settings.rb
@@ -0,0 +1,27 @@
+module Gitlab
+  module CurrentSettings
+    def current_application_settings
+      key = :current_application_settings
+
+      RequestStore.store[key] ||= begin
+        if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('application_settings')
+          ApplicationSetting.current || ApplicationSetting.create_from_defaults
+        else
+          fake_application_settings
+        end
+      end
+    end
+
+    def fake_application_settings
+      OpenStruct.new(
+        default_projects_limit: Settings.gitlab['default_projects_limit'],
+        default_branch_protection: Settings.gitlab['default_branch_protection'],
+        signup_enabled: Settings.gitlab['signup_enabled'],
+        signin_enabled: Settings.gitlab['signin_enabled'],
+        gravatar_enabled: Settings.gravatar['enabled'],
+        sign_in_text: Settings.extra['sign_in_text'],
+        restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels']
+      )
+    end
+  end
+end
diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb
index f7c1f20d76295e3b2147f1a38203bd9e059f811f..c1d9520ddf10deacc2f90daf96af9693618f71c7 100644
--- a/lib/gitlab/diff/parser.rb
+++ b/lib/gitlab/diff/parser.rb
@@ -4,7 +4,7 @@ module Gitlab
       include Enumerable
 
       def parse(lines)
-        @lines = lines,
+        @lines = lines
         lines_obj = []
         line_obj_index = 0
         line_old = 1
@@ -27,7 +27,7 @@ module Gitlab
             line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0
             line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
 
-            next if line_old == 1 && line_new == 1 #top of file
+            next if line_old <= 1 && line_new <= 1 #top of file
             lines_obj << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
             line_obj_index += 1
             next
@@ -74,7 +74,7 @@ module Gitlab
 
       def html_escape(str)
         replacements = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;', "'" => '&#39;' }
-          str.gsub(/[&"'><]/, replacements)
+        str.gsub(/[&"'><]/, replacements)
       end
     end
   end
diff --git a/lib/gitlab/force_push_check.rb b/lib/gitlab/force_push_check.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fdb6a35c78d02fef0e24c4dc888a90b304249ff3
--- /dev/null
+++ b/lib/gitlab/force_push_check.rb
@@ -0,0 +1,15 @@
+module Gitlab
+  class ForcePushCheck
+    def self.force_push?(project, oldrev, newrev)
+      return false if project.empty_repo?
+
+      # Created or deleted branch
+      if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
+        false
+      else
+        missed_refs, _ = Gitlab::Popen.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev}))
+        missed_refs.split("\n").size > 0
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index 67aca5e36e90580f0b381e7231400bd3e14758bc..0c350d7c675e1977077944a7c1eff2f5a355c93b 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -1,5 +1,25 @@
 module Gitlab
   module Git
     BLANK_SHA = '0' * 40
+    TAG_REF_PREFIX = "refs/tags/"
+    BRANCH_REF_PREFIX = "refs/heads/"
+
+    class << self
+      def ref_name(ref)
+        ref.gsub(/\Arefs\/(tags|heads)\//, '')
+      end
+
+      def tag_ref?(ref)
+        ref.start_with?(TAG_REF_PREFIX)
+      end
+
+      def branch_ref?(ref)
+        ref.start_with?(BRANCH_REF_PREFIX)
+      end
+
+      def blank_ref?(ref)
+        ref == BLANK_SHA
+      end
+    end
   end
 end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 129881060d5ce4e14e36ca43c879ca4c8889953f..bc72b7528d590839f660af3e978872f941ef3317 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -3,106 +3,178 @@ module Gitlab
     DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
     PUSH_COMMANDS = %w{ git-receive-pack }
 
-    attr_reader :params, :project, :git_cmd, :user
+    attr_reader :actor, :project
 
-    def allowed?(actor, cmd, project, changes = nil)
+    def initialize(actor, project)
+      @actor    = actor
+      @project  = project
+    end
+
+    def user
+      return @user if defined?(@user)
+
+      @user = 
+        case actor
+        when User
+          actor
+        when DeployKey
+          nil
+        when Key
+          actor.user
+        end
+    end
+
+    def deploy_key
+      actor if actor.is_a?(DeployKey)
+    end
+
+    def can_push_to_branch?(ref)
+      return false unless user
+
+      if project.protected_branch?(ref)  &&
+          !(project.developers_can_push_to_protected_branch?(ref) && project.team.developer?(user))
+        user.can?(:push_code_to_protected_branches, project)
+      else
+        user.can?(:push_code, project)
+      end
+    end
+
+    def can_read_project?
+      if user
+        user.can?(:read_project, project)
+      elsif deploy_key
+        deploy_key.projects.include?(project)
+      else
+        false
+      end
+    end
+
+    def check(cmd, changes = nil)
       case cmd
       when *DOWNLOAD_COMMANDS
-        if actor.is_a? User
-          download_allowed?(actor, project)
-        elsif actor.is_a? DeployKey
-          actor.projects.include?(project)
-        elsif actor.is_a? Key
-          download_allowed?(actor.user, project)
-        else
-          raise 'Wrong actor'
-        end
+        download_access_check
       when *PUSH_COMMANDS
-        if actor.is_a? User
-          push_allowed?(actor, project, changes)
-        elsif actor.is_a? DeployKey
-          # Deploy key not allowed to push
-          return false
-        elsif actor.is_a? Key
-          push_allowed?(actor.user, project, changes)
-        else
-          raise 'Wrong actor'
-        end
+        push_access_check(changes)
       else
-        false
+        build_status_object(false, "Wrong command")
       end
     end
 
-    def download_allowed?(user, project)
-      if user && user_allowed?(user)
-        user.can?(:download_code, project)
+    def download_access_check
+      if user
+        user_download_access_check
+      elsif deploy_key
+        deploy_key_download_access_check
       else
-        false
+        raise 'Wrong actor'
       end
     end
 
-    def push_allowed?(user, project, changes)
-      return false unless user && user_allowed?(user)
-      return true if changes.blank?
+    def push_access_check(changes)
+      if user
+        user_push_access_check(changes)
+      elsif deploy_key
+        build_status_object(false, "Deploy key not allowed to push")
+      else
+        raise 'Wrong actor'
+      end
+    end
+
+    def user_download_access_check
+      if user && user_allowed? && user.can?(:download_code, project)
+        build_status_object(true)
+      else
+        build_status_object(false, "You don't have access")
+      end
+    end
+
+    def deploy_key_download_access_check
+      if can_read_project?
+        build_status_object(true)
+      else
+        build_status_object(false, "Deploy key not allowed to access this project")
+      end
+    end
+
+    def user_push_access_check(changes)
+      unless user && user_allowed?
+        return build_status_object(false, "You don't have access")
+      end
+
+      if changes.blank?
+        return build_status_object(true)
+      end
+
+      unless project.repository.exists?
+        return build_status_object(false, "Repository does not exist")
+      end
 
       changes = changes.lines if changes.kind_of?(String)
 
       # Iterate over all changes to find if user allowed all of them to be applied
-      changes.each do |change|
-        unless change_allowed?(user, project, change)
+      changes.map(&:strip).reject(&:blank?).each do |change|
+        status = change_access_check(change)
+        unless status.allowed?
           # If user does not have access to make at least one change - cancel all push
-          return false
+          return status
         end
       end
 
-      # If user has access to make all changes
-      true
+      build_status_object(true)
     end
 
-    def change_allowed?(user, project, change)
+    def change_access_check(change)
       oldrev, newrev, ref = change.split(' ')
 
-      action = if project.protected_branch?(branch_name(ref))
-                 # we dont allow force push to protected branch
-                 if forced_push?(project, oldrev, newrev)
-                   :force_push_code_to_protected_branches
-                   # and we dont allow remove of protected branch
-                 elsif newrev == Gitlab::Git::BLANK_SHA
-                   :remove_protected_branches
-                 else
-                   :push_code_to_protected_branches
-                 end
-               elsif project.repository && project.repository.tag_names.include?(tag_name(ref))
-                 # Prevent any changes to existing git tag unless user has permissions
-                 :admin_project
-               else
-                 :push_code
-               end
-
-      user.can?(action, project)
-    end
-
-    def forced_push?(project, oldrev, newrev)
-      return false if project.empty_repo?
-
-      if oldrev != Gitlab::Git::BLANK_SHA && newrev != Gitlab::Git::BLANK_SHA
-        missed_refs = IO.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})).read
-        missed_refs.split("\n").size > 0
+      action = 
+        if project.protected_branch?(branch_name(ref))
+          protected_branch_action(oldrev, newrev, branch_name(ref))
+        elsif protected_tag?(tag_name(ref))
+          # Prevent any changes to existing git tag unless user has permissions
+          :admin_project
+        else
+          :push_code
+        end
+
+      if user.can?(action, project)
+        build_status_object(true)
       else
-        false
+        build_status_object(false, "You don't have permission")
       end
     end
 
+    def forced_push?(oldrev, newrev)
+      Gitlab::ForcePushCheck.force_push?(project, oldrev, newrev)
+    end
+
     private
 
-    def user_allowed?(user)
+    def protected_branch_action(oldrev, newrev, branch_name)
+      # we dont allow force push to protected branch
+      if forced_push?(oldrev, newrev)
+        :force_push_code_to_protected_branches
+      elsif Gitlab::Git.blank_ref?(newrev)
+        # and we dont allow remove of protected branch
+        :remove_protected_branches
+      elsif project.developers_can_push_to_protected_branch?(branch_name)
+        :push_code
+      else
+        :push_code_to_protected_branches
+      end
+    end
+
+    def protected_tag?(tag_name)
+      project.repository.tag_names.include?(tag_name)
+    end
+
+    def user_allowed?
       Gitlab::UserAccess.allowed?(user)
     end
 
     def branch_name(ref)
       ref = ref.to_s
-      if ref.start_with?('refs/heads')
-        ref.sub(%r{\Arefs/heads/}, '')
+      if Gitlab::Git.branch_ref?(ref)
+        Gitlab::Git.ref_name(ref)
       else
         nil
       end
@@ -110,11 +182,17 @@ module Gitlab
 
     def tag_name(ref)
       ref = ref.to_s
-      if ref.start_with?('refs/tags')
-        ref.sub(%r{\Arefs/tags/}, '')
+      if Gitlab::Git.tag_ref?(ref)
+        Gitlab::Git.ref_name(ref)
       else
         nil
       end
     end
+
+    protected
+
+    def build_status_object(status, message = '')
+      GitAccessStatus.new(status, message)
+    end
   end
 end
diff --git a/lib/gitlab/git_access_status.rb b/lib/gitlab/git_access_status.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5a806ff6e0df59e196f51b4ded5fd41963679168
--- /dev/null
+++ b/lib/gitlab/git_access_status.rb
@@ -0,0 +1,15 @@
+module Gitlab
+  class GitAccessStatus
+    attr_accessor :status, :message
+    alias_method :allowed?, :status
+
+    def initialize(status, message = '')
+      @status = status
+      @message = message
+    end
+
+    def to_json
+      { status: @status, message: @message }.to_json
+    end
+  end
+end
diff --git a/lib/gitlab/git_access_wiki.rb b/lib/gitlab/git_access_wiki.rb
index 9f0eb3be20f5ed85ef0f16a5a0ea68601999714f..73d99b96202af29ec1ccd38e35d7a57301c38f27 100644
--- a/lib/gitlab/git_access_wiki.rb
+++ b/lib/gitlab/git_access_wiki.rb
@@ -1,7 +1,11 @@
 module Gitlab
   class GitAccessWiki < GitAccess
-    def change_allowed?(user, project, change)
-      user.can?(:write_wiki, project)
+    def change_access_check(change)
+      if user.can?(:write_wiki, project)
+        build_status_object(true)
+      else
+        build_status_object(false, "You don't have access")
+      end
     end
   end
 end
diff --git a/lib/gitlab/github_import/client.rb b/lib/gitlab/github_import/client.rb
new file mode 100644
index 0000000000000000000000000000000000000000..270cbcd9ccd92b9ec35da9d90ec688b81f05b983
--- /dev/null
+++ b/lib/gitlab/github_import/client.rb
@@ -0,0 +1,53 @@
+module Gitlab
+  module GithubImport
+    class Client
+      attr_reader :client, :api
+
+      def initialize(access_token)
+        @client = ::OAuth2::Client.new(
+          config.app_id,
+          config.app_secret,
+          github_options
+        )
+
+        if access_token
+          ::Octokit.auto_paginate = true
+          @api = ::Octokit::Client.new(access_token: access_token)
+        end
+      end
+
+      def authorize_url(redirect_uri)
+        client.auth_code.authorize_url({
+          redirect_uri: redirect_uri,
+          scope: "repo, user, user:email"
+        })
+      end
+
+      def get_token(code)
+        client.auth_code.get_token(code).token
+      end
+
+      def method_missing(method, *args, &block)
+        if api.respond_to?(method)
+          api.send(method, *args, &block)
+        else
+          super(method, *args, &block)
+        end
+      end
+
+      def respond_to?(method)
+        api.respond_to?(method) || super
+      end
+
+      private
+
+      def config
+        Gitlab.config.omniauth.providers.find{|provider| provider.name == "github"}
+      end
+
+      def github_options
+        OmniAuth::Strategies::GitHub.default_options[:client_options].symbolize_keys
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..23832b3233ce048bb9b7cc01836bba1421cc9c31
--- /dev/null
+++ b/lib/gitlab/github_import/importer.rb
@@ -0,0 +1,46 @@
+module Gitlab
+  module GithubImport
+    class Importer
+      attr_reader :project, :client
+
+      def initialize(project)
+        @project = project
+        @client = Client.new(project.creator.github_access_token)
+        @formatter = Gitlab::ImportFormatter.new
+      end
+
+      def execute
+        #Issues && Comments
+        client.list_issues(project.import_source, state: :all).each do |issue|
+          if issue.pull_request.nil?
+
+            body = @formatter.author_line(issue.user.login, issue.body)
+
+            if issue.comments > 0
+              body += @formatter.comments_header
+
+              client.issue_comments(project.import_source, issue.number).each do |c|
+                body += @formatter.comment(c.user.login, c.created_at, c.body)
+              end
+            end
+
+            project.issues.create!(
+              description: body,
+              title: issue.title,
+              state: issue.state == 'closed' ? 'closed' : 'opened',
+              author_id: gl_user_id(project, issue.user.id)
+            )
+          end
+        end
+      end
+
+      private
+
+      def gl_user_id(project, github_id)
+        user = User.joins(:identities).
+          find_by("identities.extern_uid = ? AND identities.provider = 'github'", github_id.to_s)
+        (user && user.id) || project.creator_id
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/github_import/project_creator.rb b/lib/gitlab/github_import/project_creator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9439ca6cbf4803f12a50dcf416f519b32026a37d
--- /dev/null
+++ b/lib/gitlab/github_import/project_creator.rb
@@ -0,0 +1,39 @@
+module Gitlab
+  module GithubImport
+    class ProjectCreator
+      attr_reader :repo, :namespace, :current_user
+
+      def initialize(repo, namespace, current_user)
+        @repo = repo
+        @namespace = namespace
+        @current_user = current_user
+      end
+
+      def execute
+        @project = Project.new(
+          name: repo.name,
+          path: repo.name,
+          description: repo.description,
+          namespace: namespace,
+          creator: current_user,
+          visibility_level: repo.private ? Gitlab::VisibilityLevel::PRIVATE : Gitlab::VisibilityLevel::PUBLIC,
+          import_type: "github",
+          import_source: repo.full_name,
+          import_url: repo.clone_url.sub("https://", "https://#{current_user.github_access_token}@")
+        )
+
+        if @project.save!
+          @project.reload
+
+          if @project.import_failed?
+            @project.import_retry
+          else
+            @project.import_start
+          end
+        end
+
+        @project
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/gitlab_import/client.rb b/lib/gitlab/gitlab_import/client.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f48ede9d06795fb87f12eb128b2c5af783ec60e3
--- /dev/null
+++ b/lib/gitlab/gitlab_import/client.rb
@@ -0,0 +1,78 @@
+module Gitlab
+  module GitlabImport
+    class Client
+      attr_reader :client, :api
+
+      PER_PAGE = 100
+
+      def initialize(access_token)
+        @client = ::OAuth2::Client.new(
+          config.app_id,
+          config.app_secret,
+          gitlab_options
+        )
+
+        if access_token
+          @api = OAuth2::AccessToken.from_hash(@client, access_token: access_token)
+        end
+      end
+
+      def authorize_url(redirect_uri)
+        client.auth_code.authorize_url({
+          redirect_uri: redirect_uri,
+          scope: "api"
+        })
+      end
+
+      def get_token(code, redirect_uri)
+        client.auth_code.get_token(code, redirect_uri: redirect_uri).token
+      end
+
+      def issues(project_identifier)
+        lazy_page_iterator(PER_PAGE) do |page|
+          api.get("/api/v3/projects/#{project_identifier}/issues?per_page=#{PER_PAGE}&page=#{page}").parsed
+        end
+      end
+
+      def issue_comments(project_identifier, issue_id)
+        lazy_page_iterator(PER_PAGE) do |page|
+          api.get("/api/v3/projects/#{project_identifier}/issues/#{issue_id}/notes?per_page=#{PER_PAGE}&page=#{page}").parsed
+        end
+      end
+
+      def project(id)
+        api.get("/api/v3/projects/#{id}").parsed
+      end
+
+      def projects
+        lazy_page_iterator(PER_PAGE) do |page|
+          api.get("/api/v3/projects?per_page=#{PER_PAGE}&page=#{page}").parsed
+        end
+      end
+
+      private
+
+      def lazy_page_iterator(per_page)
+        Enumerator.new do |y|
+          page = 1
+          loop do
+            items = yield(page)
+            items.each do |item|
+              y << item
+            end
+            break if items.empty? || items.size < per_page
+            page += 1
+          end
+        end
+      end
+
+      def config
+        Gitlab.config.omniauth.providers.find{|provider| provider.name == "gitlab"}
+      end
+
+      def gitlab_options
+        OmniAuth::Strategies::GitLab.default_options[:client_options].symbolize_keys
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/gitlab_import/importer.rb b/lib/gitlab/gitlab_import/importer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c5304a0699b9e1c424040e1a36b75fee3165507f
--- /dev/null
+++ b/lib/gitlab/gitlab_import/importer.rb
@@ -0,0 +1,50 @@
+module Gitlab
+  module GitlabImport
+    class Importer
+      attr_reader :project, :client
+
+      def initialize(project)
+        @project = project
+        @client = Client.new(project.creator.gitlab_access_token)
+        @formatter = Gitlab::ImportFormatter.new
+      end
+
+      def execute
+        project_identifier = URI.encode(project.import_source, '/')
+
+        #Issues && Comments
+        issues = client.issues(project_identifier)
+        
+        issues.each do |issue|
+          body = @formatter.author_line(issue["author"]["name"], issue["description"])
+          
+          comments = client.issue_comments(project_identifier, issue["id"])
+          
+          if comments.any?
+            body += @formatter.comments_header
+          end
+
+          comments.each do |comment|
+            body += @formatter.comment(comment["author"]["name"], comment["created_at"], comment["body"])
+          end
+
+          project.issues.create!(
+            description: body, 
+            title: issue["title"],
+            state: issue["state"],
+            author_id: gl_user_id(project, issue["author"]["id"])
+          )
+        end
+        
+        true
+      end
+
+      private
+
+      def gl_user_id(project, gitlab_id)
+        user = User.joins(:identities).find_by("identities.extern_uid = ? AND identities.provider = 'gitlab'", gitlab_id.to_s)
+        (user && user.id) || project.creator_id
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/gitlab_import/project_creator.rb b/lib/gitlab/gitlab_import/project_creator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6424d56f8f1b41ab5f0c88bf0e3ffbc8afb049c2
--- /dev/null
+++ b/lib/gitlab/gitlab_import/project_creator.rb
@@ -0,0 +1,39 @@
+module Gitlab
+  module GitlabImport
+    class ProjectCreator
+      attr_reader :repo, :namespace, :current_user
+
+      def initialize(repo, namespace, current_user)
+        @repo = repo
+        @namespace = namespace
+        @current_user = current_user
+      end
+
+      def execute
+        @project = Project.new(
+          name: repo["name"],
+          path: repo["path"],
+          description: repo["description"],
+          namespace: namespace,
+          creator: current_user,
+          visibility_level: repo["visibility_level"],
+          import_type: "gitlab",
+          import_source: repo["path_with_namespace"],
+          import_url: repo["http_url_to_repo"].sub("://", "://oauth2:#{current_user.gitlab_access_token}@")
+        )
+
+        if @project.save!
+          @project.reload
+
+          if @project.import_failed?
+            @project.import_retry
+          else
+            @project.import_start
+          end
+        end
+
+        @project
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/gitorious_import/client.rb b/lib/gitlab/gitorious_import/client.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5043f6a2ebd72ae661eddf710d25af438d698bf0
--- /dev/null
+++ b/lib/gitlab/gitorious_import/client.rb
@@ -0,0 +1,63 @@
+module Gitlab
+  module GitoriousImport
+    GITORIOUS_HOST = "https://gitorious.org"
+
+    class Client
+      attr_reader :repo_list
+
+      def initialize(repo_list)
+        @repo_list = repo_list
+      end
+
+      def authorize_url(redirect_uri)
+        "#{GITORIOUS_HOST}/gitlab-import?callback_url=#{redirect_uri}"
+      end
+
+      def repos
+        @repos ||= repo_names.map { |full_name| Repository.new(full_name) }
+      end
+
+      def repo(id)
+        repos.find { |repo| repo.id == id }
+      end
+
+      private
+
+      def repo_names
+        repo_list.to_s.split(',').map(&:strip).reject(&:blank?)
+      end
+    end
+
+    Repository = Struct.new(:full_name) do
+      def id
+        Digest::SHA1.hexdigest(full_name)
+      end
+
+      def namespace
+        segments.first
+      end
+
+      def path
+        segments.last
+      end
+
+      def name
+        path.titleize
+      end
+
+      def description
+        ""
+      end
+
+      def import_url
+        "#{GITORIOUS_HOST}/#{full_name}.git"
+      end
+
+      private
+
+      def segments
+        full_name.split('/')
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/gitorious_import/project_creator.rb b/lib/gitlab/gitorious_import/project_creator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3cbebe53997414d96918713d80c52a6326e2012d
--- /dev/null
+++ b/lib/gitlab/gitorious_import/project_creator.rb
@@ -0,0 +1,39 @@
+module Gitlab
+  module GitoriousImport
+    class ProjectCreator
+      attr_reader :repo, :namespace, :current_user
+
+      def initialize(repo, namespace, current_user)
+        @repo = repo
+        @namespace = namespace
+        @current_user = current_user
+      end
+
+      def execute
+        @project = Project.new(
+          name: repo.name,
+          path: repo.path,
+          description: repo.description,
+          namespace: namespace,
+          creator: current_user,
+          visibility_level: Gitlab::VisibilityLevel::PUBLIC,
+          import_type: "gitorious",
+          import_source: repo.full_name,
+          import_url: repo.import_url
+        )
+
+        if @project.save!
+          @project.reload
+
+          if @project.import_failed?
+            @project.import_retry
+          else
+            @project.import_start
+          end
+        end
+
+        @project
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/import_formatter.rb b/lib/gitlab/import_formatter.rb
new file mode 100644
index 0000000000000000000000000000000000000000..72e041a90b1d59824ef958a56b11ea3bf3affd67
--- /dev/null
+++ b/lib/gitlab/import_formatter.rb
@@ -0,0 +1,15 @@
+module Gitlab
+  class ImportFormatter
+    def comment(author, date, body)
+      "\n\n*By #{author} on #{date}*\n\n#{body}"
+    end
+
+    def comments_header
+      "\n\n\n**Imported comments:**\n"
+    end
+
+    def author_line(author, body)
+      "*Created by: #{author}*\n\n#{body}"
+    end
+  end
+end
diff --git a/lib/gitlab/ldap/access.rb b/lib/gitlab/ldap/access.rb
index eb2c4e48ff27961868a98a1059a248fc91623da1..960fb3849b47fa2547232ef8d4f720e8a235fdce 100644
--- a/lib/gitlab/ldap/access.rb
+++ b/lib/gitlab/ldap/access.rb
@@ -8,7 +8,7 @@ module Gitlab
       attr_reader :adapter, :provider, :user
 
       def self.open(user, &block)
-        Gitlab::LDAP::Adapter.open(user.provider) do |adapter|
+        Gitlab::LDAP::Adapter.open(user.ldap_identity.provider) do |adapter|
           block.call(self.new(user, adapter))
         end
       end
@@ -28,13 +28,21 @@ module Gitlab
       def initialize(user, adapter=nil)
         @adapter = adapter
         @user = user
-        @provider = user.provider
+        @provider = user.ldap_identity.provider
       end
 
       def allowed?
-        if Gitlab::LDAP::Person.find_by_dn(user.extern_uid, adapter)
+        if Gitlab::LDAP::Person.find_by_dn(user.ldap_identity.extern_uid, adapter)
           return true unless ldap_config.active_directory
-          !Gitlab::LDAP::Person.disabled_via_active_directory?(user.extern_uid, adapter)
+
+          # Block user in GitLab if he/she was blocked in AD
+          if Gitlab::LDAP::Person.disabled_via_active_directory?(user.ldap_identity.extern_uid, adapter)
+            user.block unless user.blocked?
+            false
+          else
+            user.activate if user.blocked?
+            true
+          end
         else
           false
         end
diff --git a/lib/gitlab/ldap/adapter.rb b/lib/gitlab/ldap/adapter.rb
index 256cdb4c2f10928e35e25c8890532df43127636d..577a890a7d9879f8cc9f51a454644757c1dd6ff6 100644
--- a/lib/gitlab/ldap/adapter.rb
+++ b/lib/gitlab/ldap/adapter.rb
@@ -63,8 +63,10 @@ module Gitlab
       end
 
       def dn_matches_filter?(dn, filter)
-        ldap_search(base: dn, filter: filter,
-          scope: Net::LDAP::SearchScope_BaseObject, attributes: %w{dn}).any?
+        ldap_search(base: dn,
+                    filter: filter,
+                    scope: Net::LDAP::SearchScope_BaseObject,
+                    attributes: %w{dn}).any?
       end
 
       def ldap_search(*args)
diff --git a/lib/gitlab/ldap/authentication.rb b/lib/gitlab/ldap/authentication.rb
index 8af2c74e959d42bb310711ab0004ee670832fbe0..649cf3194b8a895b0a494740a73284c54602fe4b 100644
--- a/lib/gitlab/ldap/authentication.rb
+++ b/lib/gitlab/ldap/authentication.rb
@@ -50,7 +50,7 @@ module Gitlab
       end
 
       def user_filter(login)
-        filter = Net::LDAP::Filter.eq(config.uid, login)
+        filter = Net::LDAP::Filter.equals(config.uid, login)
 
         # Apply LDAP user filter if present
         if config.user_filter.present?
diff --git a/lib/gitlab/ldap/person.rb b/lib/gitlab/ldap/person.rb
index 3e0b3e6cbf87c00c1f2a47c4596f6ceab90f79b1..b81f3e8e8f5b8d18312cc583b5239de090663853 100644
--- a/lib/gitlab/ldap/person.rb
+++ b/lib/gitlab/ldap/person.rb
@@ -9,6 +9,7 @@ module Gitlab
       attr_accessor :entry, :provider
 
       def self.find_by_uid(uid, adapter)
+        uid = Net::LDAP::Filter.escape(uid)
         adapter.user(adapter.config.uid, uid)
       end
 
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index 3176e9790a7e8d968286cb066191df16d4a988cd..cfa8692659d569444ba892600f433351729419f7 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -12,9 +12,10 @@ module Gitlab
       class << self
         def find_by_uid_and_provider(uid, provider)
           # LDAP distinguished name is case-insensitive
-          ::User.
+          identity = ::Identity.
             where(provider: [provider, :ldap]).
             where('lower(extern_uid) = ?', uid.downcase).last
+          identity && identity.user
         end
       end
 
@@ -34,19 +35,21 @@ module Gitlab
       end
 
       def find_by_email
-        model.find_by(email: auth_hash.email)
+        ::User.find_by(email: auth_hash.email)
       end
 
       def update_user_attributes
-        gl_user.attributes = {
-          extern_uid: auth_hash.uid,
-          provider: auth_hash.provider,
-          email: auth_hash.email
-        }
+        gl_user.email = auth_hash.email
+
+        # Build new identity only if we dont have have same one
+        gl_user.identities.find_or_initialize_by(provider: auth_hash.provider,
+                                                 extern_uid: auth_hash.uid)
+
+        gl_user
       end
 
       def changed?
-        gl_user.changed?
+        gl_user.changed? || gl_user.identities.any?(&:changed?)
       end
 
       def needs_blocking?
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index 068c342398b2daa9ce93da2650a06e8ebde3da4e..41bb8d0892437e3985339e9ff20b02b89fee9b96 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -14,6 +14,7 @@ module Gitlab
   #   * !123 for merge requests
   #   * $123 for snippets
   #   * 123456 for commits
+  #   * 123456...7890123 for commit ranges (comparisons)
   #
   # It also parses Emoji codes to insert images. See
   # http://www.emoji-cheat-sheet.com/ for a list of the supported icons.
@@ -33,17 +34,23 @@ module Gitlab
 
     attr_reader :html_options
 
-    def gfm_with_tasks(text, project = @project, html_options = {})
-      text = gfm(text, project, html_options)
-      parse_tasks(text)
+    # Public: Parse the provided text with GitLab-Flavored Markdown
+    #
+    # text         - the source text
+    # project      - extra options for the reference links as given to link_to
+    # html_options - extra options for the reference links as given to link_to
+    def gfm(text, project = @project, html_options = {})
+      gfm_with_options(text, {}, project, html_options)
     end
 
     # Public: Parse the provided text with GitLab-Flavored Markdown
     #
     # text         - the source text
+    # options      - parse_tasks: true - render tasks
+    #              - xhtml: true       - output XHTML instead of HTML
     # project      - extra options for the reference links as given to link_to
     # html_options - extra options for the reference links as given to link_to
-    def gfm(text, project = @project, html_options = {})
+    def gfm_with_options(text, options = {}, project = @project, html_options = {})
       return text if text.nil?
 
       # Duplicate the string so we don't alter the original, then call to_str
@@ -72,28 +79,52 @@ module Gitlab
 
       # Used markdown pipelines in GitLab:
       # GitlabEmojiFilter - performs emoji replacement.
+      # SanitizationFilter - remove unsafe HTML tags and attributes
       #
       # see https://gitlab.com/gitlab-org/html-pipeline-gitlab for more filters
       filters = [
-        HTML::Pipeline::Gitlab::GitlabEmojiFilter
+        HTML::Pipeline::Gitlab::GitlabEmojiFilter,
+        HTML::Pipeline::SanitizationFilter
       ]
 
+      whitelist = HTML::Pipeline::SanitizationFilter::WHITELIST
+      whitelist[:attributes][:all].push('class', 'id')
+      whitelist[:elements].push('span')
+
+      # Remove the rel attribute that the sanitize gem adds, and remove the
+      # href attribute if it contains inline javascript
+      fix_anchors = lambda do |env|
+        name, node = env[:node_name], env[:node]
+        if name == 'a'
+          node.remove_attribute('rel')
+          if node['href'] && node['href'].match('javascript:')
+            node.remove_attribute('href')
+          end
+        end
+      end
+      whitelist[:transformers].push(fix_anchors)
+
       markdown_context = {
               asset_root: Gitlab.config.gitlab.url,
-              asset_host: Gitlab::Application.config.asset_host
+              asset_host: Gitlab::Application.config.asset_host,
+              whitelist: whitelist
       }
 
       markdown_pipeline = HTML::Pipeline::Gitlab.new(filters).pipeline
 
       result = markdown_pipeline.call(text, markdown_context)
-      text = result[:output].to_html(save_with: 0)
+      saveoptions = 0
+      if options[:xhtml]
+        saveoptions |= Nokogiri::XML::Node::SaveOptions::AS_XHTML
+      end
+
+      text = result[:output].to_html(save_with: saveoptions)
 
-      allowed_attributes = ActionView::Base.sanitized_allowed_attributes
-      allowed_tags = ActionView::Base.sanitized_allowed_tags
+      if options[:parse_tasks]
+        text = parse_tasks(text)
+      end
 
-      sanitize text.html_safe,
-               attributes: allowed_attributes + %w(id class),
-               tags: allowed_tags + %w(table tr td th)
+      text.html_safe
     end
 
     private
@@ -121,24 +152,26 @@ module Gitlab
       text
     end
 
-    NAME_STR = '[a-zA-Z][a-zA-Z0-9_\-\.]*'
+    NAME_STR = '[a-zA-Z0-9_][a-zA-Z0-9_\-\.]*'
     PROJ_STR = "(?<project>#{NAME_STR}/#{NAME_STR})"
 
     REFERENCE_PATTERN = %r{
       (?<prefix>\W)?                         # Prefix
       (                                      # Reference
          @(?<user>#{NAME_STR})               # User name
+        |~(?<label>\d+)                      # Label ID
         |(?<issue>([A-Z\-]+-)\d+)            # JIRA Issue ID
         |#{PROJ_STR}?\#(?<issue>([a-zA-Z\-]+-)?\d+) # Issue ID
         |#{PROJ_STR}?!(?<merge_request>\d+)  # MR ID
         |\$(?<snippet>\d+)                   # Snippet ID
+        |(#{PROJ_STR}@)?(?<commit_range>[\h]{6,40}\.{2,3}[\h]{6,40}) # Commit range
         |(#{PROJ_STR}@)?(?<commit>[\h]{6,40}) # Commit ID
         |(?<skip>gfm-extraction-[\h]{6,40})  # Skip gfm extractions. Otherwise will be parsed as commit
       )
       (?<suffix>\W)?                         # Suffix
     }x.freeze
 
-    TYPES = [:user, :issue, :merge_request, :snippet, :commit].freeze
+    TYPES = [:user, :issue, :label, :merge_request, :snippet, :commit, :commit_range].freeze
 
     def parse_references(text, project = @project)
       # parse reference links
@@ -197,18 +230,38 @@ module Gitlab
 
     def reference_user(identifier, project = @project, _ = nil)
       options = html_options.merge(
-          class: "gfm gfm-team_member #{html_options[:class]}"
+          class: "gfm gfm-project_member #{html_options[:class]}"
         )
 
       if identifier == "all"
-        link_to("@all", project_url(project), options)
-      elsif User.find_by(username: identifier)
-        link_to("@#{identifier}", user_url(identifier), options)
+        link_to("@all", namespace_project_url(project.namespace, project), options)
+      elsif namespace = Namespace.find_by(path: identifier)
+        url =
+          if namespace.type == "Group"
+            group_url(identifier)
+          else 
+            user_url(identifier)
+          end
+          
+        link_to("@#{identifier}", url, options)
+      end
+    end
+
+    def reference_label(identifier, project = @project, _ = nil)
+      if label = project.labels.find_by(id: identifier)
+        options = html_options.merge(
+          class: "gfm gfm-label #{html_options[:class]}"
+        )
+        link_to(
+          render_colored_label(label),
+          namespace_project_issues_path(project.namespace, project, label_name: label.name),
+          options
+        )
       end
     end
 
     def reference_issue(identifier, project = @project, prefix_text = nil)
-      if project.used_default_issues_tracker? || !external_issues_tracker_enabled?
+      if project.default_issues_tracker?
         if project.issue_exists? identifier
           url = url_for_issue(identifier, project)
           title = title_for_issue(identifier, project)
@@ -220,10 +273,8 @@ module Gitlab
           link_to("#{prefix_text}##{identifier}", url, options)
         end
       else
-        config = Gitlab.config
-        external_issue_tracker = config.issues_tracker[project.issues_tracker]
-        if external_issue_tracker.present?
-          reference_external_issue(identifier, external_issue_tracker, project,
+        if project.external_issue_tracker.present?
+          reference_external_issue(identifier, project,
                                    prefix_text)
         end
       end
@@ -236,7 +287,8 @@ module Gitlab
           title: "Merge Request: #{merge_request.title}",
           class: "gfm gfm-merge_request #{html_options[:class]}"
         )
-        url = project_merge_request_url(project, merge_request)
+        url = namespace_project_merge_request_url(project.namespace, project,
+                                                  merge_request)
         link_to("#{prefix_text}!#{identifier}", url, options)
       end
     end
@@ -247,8 +299,11 @@ module Gitlab
           title: "Snippet: #{snippet.title}",
           class: "gfm gfm-snippet #{html_options[:class]}"
         )
-        link_to("$#{identifier}", project_snippet_url(project, snippet),
-                options)
+        link_to(
+          "$#{identifier}",
+          namespace_project_snippet_url(project.namespace, project, snippet),
+          options
+        )
       end
     end
 
@@ -261,16 +316,40 @@ module Gitlab
         prefix_text = "#{prefix_text}@" if prefix_text
         link_to(
           "#{prefix_text}#{identifier}",
-          project_commit_url(project, commit),
+          namespace_project_commit_url(project.namespace, project, commit),
+          options
+        )
+      end
+    end
+
+    def reference_commit_range(identifier, project = @project, prefix_text = nil)
+      from_id, to_id = identifier.split(/\.{2,3}/, 2)
+
+      inclusive = identifier !~ /\.{3}/
+      from_id << "^" if inclusive
+
+      if project.valid_repo? && 
+          from = project.repository.commit(from_id) && 
+          to = project.repository.commit(to_id)
+
+        options = html_options.merge(
+          title: "Commits #{from_id} through #{to_id}",
+          class: "gfm gfm-commit_range #{html_options[:class]}"
+        )
+        prefix_text = "#{prefix_text}@" if prefix_text
+
+        link_to(
+          "#{prefix_text}#{identifier}",
+          namespace_project_compare_url(project.namespace, project, from: from_id, to: to_id),
           options
         )
       end
     end
 
-    def reference_external_issue(identifier, issue_tracker, project = @project,
+    def reference_external_issue(identifier, project = @project,
                                  prefix_text = nil)
       url = url_for_issue(identifier, project)
-      title = issue_tracker['title']
+      title = project.external_issue_tracker.title
 
       options = html_options.merge(
         title: "Issue in #{title}",
@@ -289,11 +368,12 @@ module Gitlab
       # ActiveSupport::SafeBuffer, hence the `String.new`
       String.new(text).gsub(Taskable::TASK_PATTERN_HTML) do
         checked = $LAST_MATCH_INFO[:checked].downcase == 'x'
+        p_tag = $LAST_MATCH_INFO[:p_tag]
 
         if checked
-          "#{li_tag}#{checked_box}"
+          "#{li_tag}#{p_tag}#{checked_box}"
         else
-          "#{li_tag}#{unchecked_box}"
+          "#{li_tag}#{p_tag}#{unchecked_box}"
         end
       end
     end
diff --git a/lib/gitlab/middleware/static.rb b/lib/gitlab/middleware/static.rb
new file mode 100644
index 0000000000000000000000000000000000000000..85ffa8aca68ccaae90c7bcf3159b2d33d734a887
--- /dev/null
+++ b/lib/gitlab/middleware/static.rb
@@ -0,0 +1,13 @@
+module Gitlab
+  module Middleware
+    class Static < ActionDispatch::Static
+      UPLOADS_REGEX = /\A\/uploads(\/|\z)/.freeze
+
+      def call(env)
+        return @app.call(env) if env['PATH_INFO'] =~ UPLOADS_REGEX
+
+        super
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/note_data_builder.rb b/lib/gitlab/note_data_builder.rb
new file mode 100644
index 0000000000000000000000000000000000000000..644dec45dca6db0eec39da424f2d443c2a2abc27
--- /dev/null
+++ b/lib/gitlab/note_data_builder.rb
@@ -0,0 +1,77 @@
+module Gitlab
+  class NoteDataBuilder
+    class << self
+      # Produce a hash of post-receive data
+      #
+      # For all notes:
+      #
+      # data = {
+      #   object_kind: "note",
+      #   user: {
+      #     name: String,
+      #     username: String,
+      #     avatar_url: String
+      #   }
+      #   project_id: Integer,
+      #   repository: {
+      #     name: String,
+      #     url: String,
+      #     description: String,
+      #     homepage: String,
+      #   }
+      #  object_attributes: {
+      #    <hook data for note>
+      #  }
+      #  <note-specific data>: {
+      # }
+      # note-specific data is a hash with one of the following keys and contains
+      # the hook data for that type.
+      #  - commit
+      #  - issue
+      #  - merge_request
+      #  - snippet
+      #
+      def build(note, user)
+        project = note.project
+        data = build_base_data(project, user, note)
+
+        if note.for_commit?
+          data[:commit] = build_data_for_commit(project, user, note)
+        elsif note.for_issue?
+          data[:issue] = note.noteable.hook_attrs
+        elsif note.for_merge_request?
+          data[:merge_request] = note.noteable.hook_attrs
+        elsif note.for_project_snippet?
+          data[:snippet] = note.noteable.hook_attrs
+        end
+
+        data
+      end
+
+      def build_base_data(project, user, note)
+        base_data = {
+          object_kind: "note",
+          user: user.hook_attrs,
+          project_id: project.id,
+          repository: {
+            name: project.name,
+            url: project.url_to_repo,
+            description: project.description,
+            homepage: project.web_url,
+          },
+          object_attributes: note.hook_attrs
+        }
+
+        base_data[:object_attributes][:url] =
+             Gitlab::UrlBuilder.new(:note).build(note.id)
+        base_data
+      end
+
+      def build_data_for_commit(project, user, note)
+        # commit_id is the SHA hash
+        commit = project.repository.commit(note.commit_id)
+        commit.hook_attrs(project)
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb
index 47f62153a5003e3f57d171b3184261808d9c230a..c023d275703bc94921d24acd02eb63311f7ad94a 100644
--- a/lib/gitlab/oauth/user.rb
+++ b/lib/gitlab/oauth/user.rb
@@ -5,6 +5,8 @@
 #
 module Gitlab
   module OAuth
+    class ForbiddenAction < StandardError; end
+
     class User
       attr_accessor :auth_hash, :gl_user
 
@@ -70,24 +72,25 @@ module Gitlab
       end
 
       def find_by_uid_and_provider
-        model.where(provider: auth_hash.provider, extern_uid: auth_hash.uid).last
+        identity = Identity.find_by(provider: auth_hash.provider, extern_uid: auth_hash.uid)
+        identity && identity.user
       end
 
       def build_new_user
-        model.new(user_attributes).tap do |user|
-          user.skip_confirmation!
-        end
+        user = ::User.new(user_attributes)
+        user.skip_confirmation!
+        user.identities.new(extern_uid: auth_hash.uid, provider: auth_hash.provider)
+        user
       end
 
       def user_attributes
         {
-          extern_uid: auth_hash.uid,
-          provider: auth_hash.provider,
-          name: auth_hash.name,
-          username: auth_hash.username,
-          email: auth_hash.email,
-          password: auth_hash.password,
-          password_confirmation: auth_hash.password,
+          name:                       auth_hash.name,
+          username:                   ::User.clean_username(auth_hash.username),
+          email:                      auth_hash.email,
+          password:                   auth_hash.password,
+          password_confirmation:      auth_hash.password,
+          password_automatically_set: true
         }
       end
 
@@ -95,12 +98,8 @@ module Gitlab
         Gitlab::AppLogger
       end
 
-      def model
-        ::User
-      end
-
-      def raise_unauthorized_to_create
-        raise StandardError.new("Unauthorized to create user, signup disabled for #{auth_hash.provider}")
+      def unauthorized_to_create
+        raise ForbiddenAction.new("Unauthorized to create user, signup disabled for #{auth_hash.provider}")
       end
     end
   end
diff --git a/lib/gitlab/popen.rb b/lib/gitlab/popen.rb
index e2fbafb389911ef68e4da2da7da917f6acb9e86a..43e07e0916045d84d4587cfa35b7ec34aa9ba9db 100644
--- a/lib/gitlab/popen.rb
+++ b/lib/gitlab/popen.rb
@@ -21,12 +21,15 @@ module Gitlab
       @cmd_output = ""
       @cmd_status = 0
       Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|
+        # We are not using stdin so we should close it, in case the command we
+        # are running waits for input.
+        stdin.close
         @cmd_output << stdout.read
         @cmd_output << stderr.read
         @cmd_status = wait_thr.value.exitstatus
       end
 
-      return @cmd_output, @cmd_status
+      [@cmd_output, @cmd_status]
     end
   end
 end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index 8b85f3da83fd19d4198403ee0977b98cfab469e7..0dab7bcfa4d0c9af1081042fdd3121bdb924b779 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -67,7 +67,7 @@ module Gitlab
     end
 
     def notes
-      Note.where(project_id: limit_project_ids).search(query).order('updated_at DESC')
+      Note.where(project_id: limit_project_ids).user.search(query).order('updated_at DESC')
     end
 
     def limit_project_ids
diff --git a/lib/gitlab/push_data_builder.rb b/lib/gitlab/push_data_builder.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f8da452e4c07cf676294419fa044679095020cbe
--- /dev/null
+++ b/lib/gitlab/push_data_builder.rb
@@ -0,0 +1,90 @@
+module Gitlab
+  class PushDataBuilder
+    class << self
+      # Produce a hash of post-receive data
+      #
+      # data = {
+      #   before: String,
+      #   after: String,
+      #   ref: String,
+      #   user_id: String,
+      #   user_name: String,
+      #   user_email: String
+      #   project_id: String,
+      #   repository: {
+      #     name: String,
+      #     url: String,
+      #     description: String,
+      #     homepage: String,
+      #   },
+      #   commits: Array,
+      #   total_commits_count: Fixnum
+      # }
+      #
+      def build(project, user, oldrev, newrev, ref, commits = [], message = nil)
+        # Total commits count
+        commits_count = commits.size
+
+        # Get latest 20 commits ASC
+        commits_limited = commits.last(20)
+        
+        # For performance purposes maximum 20 latest commits
+        # will be passed as post receive hook data.
+        commit_attrs = commits_limited.map do |commit|
+          commit.hook_attrs(project)
+        end
+
+        type = Gitlab::Git.tag_ref?(ref) ? "tag_push" : "push"
+        # Hash to be passed as post_receive_data
+        data = {
+          object_kind: type,
+          before: oldrev,
+          after: newrev,
+          ref: ref,
+          checkout_sha: checkout_sha(project.repository, newrev, ref),
+          message: message,
+          user_id: user.id,
+          user_name: user.name,
+          user_email: user.email,
+          project_id: project.id,
+          repository: {
+            name: project.name,
+            url: project.url_to_repo,
+            description: project.description,
+            homepage: project.web_url,
+            git_http_url: project.http_url_to_repo,
+            git_ssh_url: project.ssh_url_to_repo,
+            visibility_level: project.visibility_level
+          },
+          commits: commit_attrs,
+          total_commits_count: commits_count
+        }
+
+        data
+      end
+
+      # This method provide a sample data generated with
+      # existing project and commits to test web hooks
+      def build_sample(project, user)
+        commits = project.repository.commits(project.default_branch, nil, 3)
+        ref = "#{Gitlab::Git::BRANCH_REF_PREFIX}#{project.default_branch}"
+        build(project, user, commits.last.id, commits.first.id, ref, commits)
+      end
+
+      def checkout_sha(repository, newrev, ref)
+        # Find sha for tag, except when it was deleted.
+        if Gitlab::Git.tag_ref?(ref) && !Gitlab::Git.blank_ref?(newrev)
+          tag_name = Gitlab::Git.ref_name(ref)
+          tag = repository.find_tag(tag_name)
+
+          if tag
+            commit = repository.commit(tag.target)
+            commit.try(:sha)
+          end
+        else
+          newrev
+        end
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index 99165950aef447e8cca812727513ae7a653c6928..1058d4c43d9b9427da6581000992ff0eab815469 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -1,16 +1,23 @@
 module Gitlab
   # Extract possible GFM references from an arbitrary String for further processing.
   class ReferenceExtractor
-    attr_accessor :users, :issues, :merge_requests, :snippets, :commits
+    attr_accessor :users, :labels, :issues, :merge_requests, :snippets, :commits, :commit_ranges
 
     include Markdown
 
     def initialize
-      @users, @issues, @merge_requests, @snippets, @commits = [], [], [], [], []
+      @users, @labels, @issues, @merge_requests, @snippets, @commits, @commit_ranges =
+        [], [], [], [], [], [], []
     end
 
     def analyze(string, project)
-      parse_references(string.dup, project)
+      text = string.dup
+
+      # Remove preformatted/code blocks so that references are not included
+      text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) { |match| '' }
+      text.gsub!(%r{^```.*?^```}m) { |match| '' }
+
+      parse_references(text, project)
     end
 
     # Given a valid project, resolve the extracted identifiers of the requested type to
@@ -22,6 +29,12 @@ module Gitlab
       end.reject(&:nil?)
     end
 
+    def labels_for(project = nil)
+      labels.map do |entry|
+        project.labels.where(id: entry[:id]).first
+      end.reject(&:nil?)
+    end
+
     def issues_for(project = nil)
       issues.map do |entry|
         if should_lookup?(project, entry[:project])
@@ -53,6 +66,16 @@ module Gitlab
       end.reject(&:nil?)
     end
 
+    def commit_ranges_for(project = nil)
+      commit_ranges.map do |entry|
+        repo = entry[:project].repository if entry[:project]
+        if repo && should_lookup?(project, entry[:project])
+          from_id, to_id = entry[:id].split(/\.{2,3}/, 2)
+          [repo.commit(from_id), repo.commit(to_id)]
+        end
+      end.reject(&:nil?)
+    end
+
     private
 
     def reference_link(type, identifier, project, _)
@@ -64,7 +87,7 @@ module Gitlab
       if entry_project.nil?
         false
       else
-        project.nil? || project.id == entry_project.id
+        project.nil? || entry_project.default_issues_tracker?
       end
     end
   end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index c4d0d85b7f58903e4171d8602857aae16622f445..cf6e260f25750be6200f4b4b8030102cf5c6e991 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -11,7 +11,7 @@ module Gitlab
     end
 
     def project_name_regex
-      /\A[a-zA-Z0-9_][a-zA-Z0-9_\-\. ]*\z/
+      /\A[a-zA-Z0-9_.][a-zA-Z0-9_\-\. ]*\z/
     end
 
     def project_regex_message
diff --git a/lib/gitlab/satellite/action.rb b/lib/gitlab/satellite/action.rb
index be45cb5c98e46c9f1cacca9fbfe55fb1a757f7cc..4890ccf21e6338672f4e397427eda69e7e3fd87a 100644
--- a/lib/gitlab/satellite/action.rb
+++ b/lib/gitlab/satellite/action.rb
@@ -44,7 +44,7 @@ module Gitlab
       end
 
       def default_options(options = {})
-        {raise: true, timeout: true}.merge(options)
+        { raise: true, timeout: true }.merge(options)
       end
 
       def handle_exception(exception)
diff --git a/lib/gitlab/satellite/files/delete_file_action.rb b/lib/gitlab/satellite/files/delete_file_action.rb
index 30462999aa3b5d7e35d0d6d8e0ebdb0cb7190594..0d37b9dea8502e765aed57cfedfea514f29dcc9e 100644
--- a/lib/gitlab/satellite/files/delete_file_action.rb
+++ b/lib/gitlab/satellite/files/delete_file_action.rb
@@ -13,7 +13,7 @@ module Gitlab
           prepare_satellite!(repo)
 
           # create target branch in satellite at the corresponding commit from bare repo
-          repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
+          repo.git.checkout({ raise: true, timeout: true, b: true }, ref, "origin/#{ref}")
 
           # update the file in the satellite's working dir
           file_path_in_satellite = File.join(repo.working_dir, file_path)
@@ -36,7 +36,7 @@ module Gitlab
 
           # push commit back to bare repo
           # will raise CommandFailed when push fails
-          repo.git.push({raise: true, timeout: true}, :origin, ref)
+          repo.git.push({ raise: true, timeout: true }, :origin, ref)
 
           # everything worked
           true
diff --git a/lib/gitlab/satellite/files/edit_file_action.rb b/lib/gitlab/satellite/files/edit_file_action.rb
index cbdf70f7d129c10866b0a08e0882be7123be244c..3cb9c0b5ecbceed9529812162d235befca60ffb7 100644
--- a/lib/gitlab/satellite/files/edit_file_action.rb
+++ b/lib/gitlab/satellite/files/edit_file_action.rb
@@ -10,12 +10,16 @@ module Gitlab
       # Returns false if committing the change fails
       # Returns false if pushing from the satellite to bare repo failed or was rejected
       # Returns true otherwise
-      def commit!(content, commit_message, encoding)
+      def commit!(content, commit_message, encoding, new_branch = nil)
         in_locked_and_timed_satellite do |repo|
           prepare_satellite!(repo)
 
           # create target branch in satellite at the corresponding commit from bare repo
-          repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
+          begin
+            repo.git.checkout({ raise: true, timeout: true, b: true }, ref, "origin/#{ref}")
+          rescue Grit::Git::CommandFailed => ex
+            log_and_raise(CheckoutFailed, ex.message)
+          end
 
           # update the file in the satellite's working dir
           file_path_in_satellite = File.join(repo.working_dir, file_path)
@@ -31,19 +35,33 @@ module Gitlab
 
           # commit the changes
           # will raise CommandFailed when commit fails
-          repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
+          begin
+            repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
+          rescue Grit::Git::CommandFailed => ex
+            log_and_raise(CommitFailed, ex.message)
+          end
 
 
+          target_branch = new_branch.present? ? "#{ref}:#{new_branch}" : ref
+
           # push commit back to bare repo
           # will raise CommandFailed when push fails
-          repo.git.push({raise: true, timeout: true}, :origin, ref)
+          begin
+            repo.git.push({ raise: true, timeout: true }, :origin, target_branch)
+          rescue Grit::Git::CommandFailed => ex
+            log_and_raise(PushFailed, ex.message)
+          end
 
           # everything worked
           true
         end
-      rescue Grit::Git::CommandFailed => ex
-        Gitlab::GitLogger.error(ex.message)
-        false
+      end
+
+      private
+
+      def log_and_raise(errorClass, message)
+        Gitlab::GitLogger.error(message)
+        raise(errorClass, message)
       end
     end
   end
diff --git a/lib/gitlab/satellite/files/file_action.rb b/lib/gitlab/satellite/files/file_action.rb
index 6446b14568a5de087d3e0cbbf91506dacf24fa74..f5803f97446cb7ace65682f877224f25d30a02eb 100644
--- a/lib/gitlab/satellite/files/file_action.rb
+++ b/lib/gitlab/satellite/files/file_action.rb
@@ -14,10 +14,11 @@ module Gitlab
       end
 
       def write_file(abs_file_path, content, file_encoding = 'text')
-        if file_encoding == 'base64'
-          File.open(abs_file_path, 'wb') { |f| f.write(Base64.decode64(content)) }
-        else
-          File.open(abs_file_path, 'w') { |f| f.write(content) }
+	if file_encoding == 'base64'
+		 File.open(abs_file_path, 'wb') { |f| f.write(Base64.encode64(content))}
+	else
+		 enc_64 = Base64.encode64(content)
+		 File.open(abs_file_path, 'wb') { |f| f.write(Base64.decode64(enc_64))} 
         end
       end
     end
diff --git a/lib/gitlab/satellite/files/new_file_action.rb b/lib/gitlab/satellite/files/new_file_action.rb
index 15e9b7a6f77555471910088deff2a231533179ec..724dfa0d042e1a80376a40dad4a34967998fdf5e 100644
--- a/lib/gitlab/satellite/files/new_file_action.rb
+++ b/lib/gitlab/satellite/files/new_file_action.rb
@@ -9,12 +9,19 @@ module Gitlab
       # Returns false if committing the change fails
       # Returns false if pushing from the satellite to bare repo failed or was rejected
       # Returns true otherwise
-      def commit!(content, commit_message, encoding)
+      def commit!(content, commit_message, encoding, new_branch = nil)
         in_locked_and_timed_satellite do |repo|
           prepare_satellite!(repo)
 
           # create target branch in satellite at the corresponding commit from bare repo
-          repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
+          current_ref =
+            if @project.empty_repo?
+              # skip this step if we want to add first file to empty repo
+              Satellite::PARKING_BRANCH
+            else
+              repo.git.checkout({ raise: true, timeout: true, b: true }, ref, "origin/#{ref}")
+              ref
+            end
 
           file_path_in_satellite = File.join(repo.working_dir, file_path)
           dir_name_in_satellite = File.dirname(file_path_in_satellite)
@@ -38,10 +45,15 @@ module Gitlab
           # will raise CommandFailed when commit fails
           repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
 
+          target_branch = if new_branch.present? && !@project.empty_repo?
+                            "#{ref}:#{new_branch}"
+                          else
+                            "#{current_ref}:#{ref}"
+                          end
 
           # push commit back to bare repo
           # will raise CommandFailed when push fails
-          repo.git.push({raise: true, timeout: true}, :origin, ref)
+          repo.git.push({ raise: true, timeout: true }, :origin, target_branch)
 
           # everything worked
           true
diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb
index e9141f735aa89438fd7bcb5bca08932541fa7aa8..1f2e5f82dd5348017eba0fa9385ef0e38357907a 100644
--- a/lib/gitlab/satellite/merge_action.rb
+++ b/lib/gitlab/satellite/merge_action.rb
@@ -86,7 +86,7 @@ module Gitlab
         in_locked_and_timed_satellite do |merge_repo|
           prepare_satellite!(merge_repo)
           update_satellite_source_and_target!(merge_repo)
-          patch = merge_repo.git.format_patch(default_options({stdout: true}), "origin/#{merge_request.target_branch}..source/#{merge_request.source_branch}")
+          patch = merge_repo.git.format_patch(default_options({ stdout: true }), "origin/#{merge_request.target_branch}..source/#{merge_request.source_branch}")
         end
       rescue Grit::Git::CommandFailed => ex
         handle_exception(ex)
@@ -97,7 +97,7 @@ module Gitlab
         in_locked_and_timed_satellite do |merge_repo|
           prepare_satellite!(merge_repo)
           update_satellite_source_and_target!(merge_repo)
-          if (merge_request.for_fork?)
+          if merge_request.for_fork?
             repository = Gitlab::Git::Repository.new(merge_repo.path)
             commits = Gitlab::Git::Commit.between(
               repository,
@@ -128,7 +128,7 @@ module Gitlab
 
         # merge the source branch into the satellite
         # will raise CommandFailed when merge fails
-        repo.git.merge(default_options({no_ff: true}), "-m#{message}", "source/#{merge_request.source_branch}")
+        repo.git.merge(default_options({ no_ff: true }), "-m#{message}", "source/#{merge_request.source_branch}")
       rescue Grit::Git::CommandFailed => ex
         handle_exception(ex)
       end
@@ -137,7 +137,7 @@ module Gitlab
       def update_satellite_source_and_target!(repo)
         repo.remote_add('source', merge_request.source_project.repository.path_to_repo)
         repo.remote_fetch('source')
-        repo.git.checkout(default_options({b: true}), merge_request.target_branch, "origin/#{merge_request.target_branch}")
+        repo.git.checkout(default_options({ b: true }), merge_request.target_branch, "origin/#{merge_request.target_branch}")
       rescue Grit::Git::CommandFailed => ex
         handle_exception(ex)
       end
diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb
index 1de84309d15e2386c31b4eeebf98359add9ff555..f24c6199c440d78cd7306e3166f8ba7cc7c7f122 100644
--- a/lib/gitlab/satellite/satellite.rb
+++ b/lib/gitlab/satellite/satellite.rb
@@ -1,5 +1,9 @@
 module Gitlab
   module Satellite
+    class CheckoutFailed < StandardError; end
+    class CommitFailed < StandardError; end
+    class PushFailed < StandardError; end
+
     class Satellite
       include Gitlab::Popen
 
@@ -95,16 +99,12 @@ module Gitlab
         heads = repo.heads.map(&:name)
 
         # update or create the parking branch
-        if heads.include? PARKING_BRANCH
-          repo.git.checkout({}, PARKING_BRANCH)
-        else
-          repo.git.checkout(default_options({b: true}), PARKING_BRANCH)
-        end
+        repo.git.checkout(default_options({ B: true }), PARKING_BRANCH)
 
         # remove the parking branch from the list of heads ...
         heads.delete(PARKING_BRANCH)
         # ... and delete all others
-        heads.each { |head| repo.git.branch(default_options({D: true}), head) }
+        heads.each { |head| repo.git.branch(default_options({ D: true }), head) }
       end
 
       # Deletes all remotes except origin
@@ -126,7 +126,7 @@ module Gitlab
       end
 
       def default_options(options = {})
-        {raise: true, timeout: true}.merge(options)
+        { raise: true, timeout: true }.merge(options)
       end
 
       # Create directory for storing
diff --git a/lib/gitlab/sidekiq_middleware/memory_killer.rb b/lib/gitlab/sidekiq_middleware/memory_killer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0f2db50e98c9625c28a6db405c36e94656cfb988
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/memory_killer.rb
@@ -0,0 +1,53 @@
+module Gitlab
+  module SidekiqMiddleware
+    class MemoryKiller
+      # Default the RSS limit to 0, meaning the MemoryKiller is disabled
+      MAX_RSS = (ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS'] || 0).to_s.to_i
+      # Give Sidekiq 15 minutes of grace time after exceeding the RSS limit
+      GRACE_TIME = (ENV['SIDEKIQ_MEMORY_KILLER_GRACE_TIME'] || 15 * 60).to_s.to_i
+      # Wait 30 seconds for running jobs to finish during graceful shutdown
+      SHUTDOWN_WAIT = (ENV['SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT'] || 30).to_s.to_i
+
+      # Create a mutex used to ensure there will be only one thread waiting to
+      # shut Sidekiq down
+      MUTEX = Mutex.new
+
+      def call(worker, job, queue)
+        yield
+        current_rss = get_rss
+
+        return unless MAX_RSS > 0 && current_rss > MAX_RSS
+
+        Thread.new do
+          # Return if another thread is already waiting to shut Sidekiq down
+          return unless MUTEX.try_lock
+
+          Sidekiq.logger.warn "current RSS #{current_rss} exceeds maximum RSS "\
+            "#{MAX_RSS}"
+          Sidekiq.logger.warn "spawned thread that will shut down PID "\
+            "#{Process.pid} in #{GRACE_TIME} seconds"
+          sleep(GRACE_TIME)
+
+          Sidekiq.logger.warn "sending SIGUSR1 to PID #{Process.pid}"
+          Process.kill('SIGUSR1', Process.pid)
+
+          Sidekiq.logger.warn "waiting #{SHUTDOWN_WAIT} seconds before sending "\
+            "SIGTERM to PID #{Process.pid}"
+          sleep(SHUTDOWN_WAIT)
+
+          Sidekiq.logger.warn "sending SIGTERM to PID #{Process.pid}"
+          Process.kill('SIGTERM', Process.pid)
+        end
+      end
+
+      private
+
+      def get_rss
+        output, status = Gitlab::Popen.popen(%W(ps -o rss= -p #{Process.pid}))
+        return 0 unless status.zero?
+
+        output.to_i
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/theme.rb b/lib/gitlab/theme.rb
index b7c50cb734d763fa8a7cd14bb10524fb7f088b8f..43093c7d27ebbf804adef24176611b0a31ed6075 100644
--- a/lib/gitlab/theme.rb
+++ b/lib/gitlab/theme.rb
@@ -5,6 +5,7 @@ module Gitlab
     MODERN = 3 unless const_defined?(:MODERN)
     GRAY   = 4 unless const_defined?(:GRAY)
     COLOR  = 5 unless const_defined?(:COLOR)
+    BLUE   = 6 unless const_defined?(:BLUE)
 
     def self.css_class_by_id(id)
       themes = {
@@ -12,12 +13,27 @@ module Gitlab
         MARS   => "ui_mars",
         MODERN => "ui_modern",
         GRAY   => "ui_gray",
-        COLOR  => "ui_color"
+        COLOR  => "ui_color",
+        BLUE   => "ui_blue"
       }
 
       id ||= Gitlab.config.gitlab.default_theme
 
-      return themes[id]
+      themes[id]
+    end
+
+    def self.type_css_class_by_id(id)
+      types = {
+        BASIC  => 'light_theme',
+        MARS   => 'dark_theme',
+        MODERN => 'dark_theme',
+        GRAY   => 'dark_theme',
+        COLOR  => 'dark_theme'
+      }
+
+      id ||= Gitlab.config.gitlab.default_theme
+
+      types[id]
     end
   end
 end
diff --git a/lib/gitlab/upgrader.rb b/lib/gitlab/upgrader.rb
index 74b049b5143748bc23696a7586539c2e27714966..0570c2fbeb53c11d0e091636ac18d02138c8a22d 100644
--- a/lib/gitlab/upgrader.rb
+++ b/lib/gitlab/upgrader.rb
@@ -62,7 +62,7 @@ module Gitlab
     end
 
     def env
-      {'RAILS_ENV' => 'production'}
+      { 'RAILS_ENV' => 'production' }
     end
 
     def upgrade
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
index 877488d847174ef3a59ee91493f41a3006eb108d..11b0d44f34067e461f5410b16acd4081769e751e 100644
--- a/lib/gitlab/url_builder.rb
+++ b/lib/gitlab/url_builder.rb
@@ -1,6 +1,7 @@
 module Gitlab
   class UrlBuilder
     include Rails.application.routes.url_helpers
+    include GitlabRoutingHelper
 
     def initialize(type)
       @type = type
@@ -9,17 +10,51 @@ module Gitlab
     def build(id)
       case @type
       when :issue
-        issue_url(id)
+        build_issue_url(id)
+      when :merge_request
+        build_merge_request_url(id)
+      when :note
+        build_note_url(id)
+
       end
     end
 
     private
 
-    def issue_url(id)
+    def build_issue_url(id)
       issue = Issue.find(id)
-      project_issue_url(id: issue.iid,
-                        project_id: issue.project,
-                        host: Gitlab.config.gitlab['url'])
+      issue_url(issue, host: Gitlab.config.gitlab['url'])
+    end
+
+    def build_merge_request_url(id)
+      merge_request = MergeRequest.find(id)
+      merge_request_url(merge_request, host: Gitlab.config.gitlab['url'])
+    end
+
+    def build_note_url(id)
+      note = Note.find(id)
+      if note.for_commit?
+        namespace_project_commit_url(namespace_id: note.project.namespace,
+                                     id: note.commit_id,
+                                     project_id: note.project,
+                                     host: Gitlab.config.gitlab['url'],
+                                     anchor: "note_#{note.id}")
+      elsif note.for_issue?
+        issue = Issue.find(note.noteable_id)
+        issue_url(issue,
+                  host: Gitlab.config.gitlab['url'],
+                  anchor: "note_#{note.id}")
+      elsif note.for_merge_request?
+        merge_request = MergeRequest.find(note.noteable_id)
+        merge_request_url(merge_request,
+                          host: Gitlab.config.gitlab['url'],
+                          anchor: "note_#{note.id}")
+      elsif note.for_project_snippet?
+        snippet = Snippet.find(note.noteable_id)
+        project_snippet_url(snippet,
+                            host: Gitlab.config.gitlab['url'],
+                            anchor: "note_#{note.id}")
+      end
     end
   end
 end
diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb
index d0b6cde3c7e70ad60e7b89c677ad487979d5cbe2..582fc759efd2026ef45165b08c9c5541c6c11d54 100644
--- a/lib/gitlab/visibility_level.rb
+++ b/lib/gitlab/visibility_level.rb
@@ -5,6 +5,8 @@
 #
 module Gitlab
   module VisibilityLevel
+    extend CurrentSettings
+
     PRIVATE  = 0 unless const_defined?(:PRIVATE)
     INTERNAL = 10 unless const_defined?(:INTERNAL)
     PUBLIC   = 20 unless const_defined?(:PUBLIC)
@@ -23,21 +25,27 @@ module Gitlab
       end
 
       def allowed_for?(user, level)
-        user.is_admin? || allowed_level?(level)
+        user.is_admin? || allowed_level?(level.to_i)
       end
 
-      # Level can be a string `"public"` or a value `20`, first check if valid,
-      # then check if the corresponding string appears in the config
+      # Return true if the specified level is allowed for the current user.
+      # Level should be a numeric value, e.g. `20`.
       def allowed_level?(level)
-        if options.has_key?(level.to_s)
-          non_restricted_level?(level)
-        elsif options.has_value?(level.to_i)
-          non_restricted_level?(options.key(level.to_i).downcase)
-        end
+        valid_level?(level) && non_restricted_level?(level)
       end
 
       def non_restricted_level?(level)
-        ! Gitlab.config.gitlab.restricted_visibility_levels.include?(level)
+        restricted_levels = current_application_settings.restricted_visibility_levels
+
+        if restricted_levels.nil?
+          true
+        else
+          !restricted_levels.include?(level)
+        end
+      end
+
+      def valid_level?(level)
+        options.has_value?(level)
       end
     end
 
diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb
index 54d740908d5fe17b5080352a7c64ba6aa3999b81..10efff2ae9f12f7b250c82f2cd7907a27bd7e32b 100644
--- a/lib/redcarpet/render/gitlab_html.rb
+++ b/lib/redcarpet/render/gitlab_html.rb
@@ -3,13 +3,20 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
   attr_reader :template
   alias_method :h, :template
 
-  def initialize(template, options = {})
+  def initialize(template, color_scheme, options = {})
     @template = template
+    @color_scheme = color_scheme
     @project = @template.instance_variable_get("@project")
     @options = options.dup
     super options
   end
 
+  def preprocess(full_document)
+    # Redcarpet doesn't allow SMB links when `safe_links_only` is enabled.
+    # FTP links are allowed, so we trick Redcarpet.
+    full_document.gsub("smb://", "ftp://smb:")
+  end
+
   # If project has issue number 39, apostrophe will be linked in
   # regular text to the issue as Redcarpet will convert apostrophe to
   # #39;
@@ -21,23 +28,22 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
     text.gsub("'", "&rsquo;")
   end
 
+  # Stolen from Rugments::Plugins::Redcarpet as this module is not required
+  # from Rugments's gem root.
   def block_code(code, language)
-    # New lines are placed to fix an rendering issue
-    # with code wrapped inside <h1> tag for next case:
-    #
-    # # Title kinda h1
-    #
-    #     ruby code here
-    #
-    <<-HTML
+    lexer = Rugments::Lexer.find_fancy(language, code) || Rugments::Lexers::PlainText
 
-<div class="highlighted-data #{h.user_color_scheme_class}">
-  <div class="highlight">
-    <pre><code class="#{language}">#{h.send(:html_escape, code)}</code></pre>
-  </div>
-</div>
+    # XXX HACK: Redcarpet strips hard tabs out of code blocks,
+    # so we assume you're not using leading spaces that aren't tabs,
+    # and just replace them here.
+    if lexer.tag == 'make'
+      code.gsub! /^    /, "\t"
+    end
 
-    HTML
+    formatter = Rugments::Formatters::HTML.new(
+      cssclass: "code highlight #{@color_scheme} #{lexer.tag}"
+    )
+    formatter.format(lexer.lex(code))
   end
 
   def link(link, title, content)
@@ -55,14 +61,12 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
   end
 
   def postprocess(full_document)
+    full_document.gsub!("ftp://smb:", "smb://")
+
     full_document.gsub!("&rsquo;", "'")
     unless @template.instance_variable_get("@project_wiki") || @project.nil?
       full_document = h.create_relative_links(full_document)
     end
-    if @options[:parse_tasks]
-      h.gfm_with_tasks(full_document)
-    else
-      h.gfm(full_document)
-    end
+    h.gfm_with_options(full_document, @options)
   end
 end
diff --git a/lib/repository_cache.rb b/lib/repository_cache.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fa016a170cd69e3ff3758c52321524bd03f7ec8a
--- /dev/null
+++ b/lib/repository_cache.rb
@@ -0,0 +1,21 @@
+# Interface to the Redis-backed cache store used by the Repository model
+class RepositoryCache
+  attr_reader :namespace, :backend
+
+  def initialize(namespace, backend = Rails.cache)
+    @namespace = namespace
+    @backend = backend
+  end
+
+  def cache_key(type)
+    "#{type}:#{namespace}"
+  end
+
+  def expire(key)
+    backend.delete(cache_key(key))
+  end
+
+  def fetch(key, &block)
+    backend.fetch(cache_key(key), &block)
+  end
+end
diff --git a/lib/support/deploy/deploy.sh b/lib/support/deploy/deploy.sh
index 4684957233a2bd79a995aa6f8ba1dc89dc86a90c..adea4c7a747db27ca2b3f03cff55ece93e0506dc 100755
--- a/lib/support/deploy/deploy.sh
+++ b/lib/support/deploy/deploy.sh
@@ -4,7 +4,7 @@
 # If any command return non-zero status - stop deploy
 set -e
 
-echo 'Deploy: Stoping sidekiq..'
+echo 'Deploy: Stopping sidekiq..'
 cd /home/git/gitlab/ && sudo -u git -H bundle exec rake sidekiq:stop RAILS_ENV=production
 
 echo 'Deploy: Show deploy index page'
diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab
index c8b769ace8e0bdce9ed5f32c7d15390786d3932a..62a4276536c4d733bdcbff28720a41111e657a26 100644
--- a/lib/support/nginx/gitlab
+++ b/lib/support/nginx/gitlab
@@ -1,5 +1,5 @@
 ## GitLab
-## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller
+## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller, DouweM
 ##
 ## Lines starting with two hashes (##) are comments with information.
 ## Lines starting with one hash (#) are configuration parameters that can be uncommented.
@@ -56,6 +56,27 @@ server {
     try_files $uri $uri/index.html $uri.html @gitlab;
   }
 
+  ## We route uploads through GitLab to prevent XSS and enforce access control.
+  location /uploads/ {
+    ## If you use HTTPS make sure you disable gzip compression
+    ## to be safe against BREACH attack.
+    # gzip off;
+
+    ## https://github.com/gitlabhq/gitlabhq/issues/694
+    ## Some requests take more than 30 seconds.
+    proxy_read_timeout      300;
+    proxy_connect_timeout   300;
+    proxy_redirect          off;
+
+    proxy_set_header    Host                $http_host;
+    proxy_set_header    X-Real-IP           $remote_addr;
+    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
+    proxy_set_header    X-Forwarded-Proto   $scheme;
+    proxy_set_header    X-Frame-Options     SAMEORIGIN;
+
+    proxy_pass http://gitlab;
+  }
+
   ## If a file, which is not found in the root folder is requested,
   ## then the proxy passes the request to the upsteam (gitlab unicorn).
   location @gitlab {
diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl
index 4e53d5e8b50b1660d8ef328dd4593a194dc6ec33..2aefc94469824694fa29e2af0a442072667c9a8e 100644
--- a/lib/support/nginx/gitlab-ssl
+++ b/lib/support/nginx/gitlab-ssl
@@ -1,5 +1,5 @@
 ## GitLab
-## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller
+## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller, DouweM
 ##
 ## Modified from nginx http version
 ## Modified from http://blog.phusion.nl/2012/04/21/tutorial-setting-up-gitlab-on-debian-6/
@@ -39,7 +39,7 @@ upstream gitlab {
 ## Redirects all HTTP traffic to the HTTPS host
 server {
   listen 0.0.0.0:80;
-  listen [::]:80 default_server;
+  listen [::]:80 ipv6only=on default_server;
   server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
   server_tokens off; ## Don't show the nginx version number, a security best practice
   return 301 https://$server_name$request_uri;
@@ -51,7 +51,7 @@ server {
 ## HTTPS host
 server {
   listen 0.0.0.0:443 ssl;
-  listen [::]:443 ssl default_server;
+  listen [::]:443 ipv6only=on ssl default_server;
   server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
   server_tokens off; ## Don't show the nginx version number, a security best practice
   root /home/git/gitlab/public;
@@ -101,6 +101,28 @@ server {
     try_files $uri $uri/index.html $uri.html @gitlab;
   }
 
+  ## We route uploads through GitLab to prevent XSS and enforce access control.
+  location /uploads/ {
+    ## If you use HTTPS make sure you disable gzip compression
+    ## to be safe against BREACH attack.
+    gzip off;
+
+    ## https://github.com/gitlabhq/gitlabhq/issues/694
+    ## Some requests take more than 30 seconds.
+    proxy_read_timeout      300;
+    proxy_connect_timeout   300;
+    proxy_redirect          off;
+
+    proxy_set_header    Host                $http_host;
+    proxy_set_header    X-Real-IP           $remote_addr;
+    proxy_set_header    X-Forwarded-Ssl     on;
+    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
+    proxy_set_header    X-Forwarded-Proto   $scheme;
+    proxy_set_header    X-Frame-Options     SAMEORIGIN;
+
+    proxy_pass http://gitlab;
+  }
+
   ## If a file, which is not found in the root folder is requested,
   ## then the proxy passes the request to the upsteam (gitlab unicorn).
   location @gitlab {
diff --git a/lib/tasks/brakeman.rake b/lib/tasks/brakeman.rake
new file mode 100644
index 0000000000000000000000000000000000000000..3a225801ff21d884aa97ac5f1383d59e734de7ba
--- /dev/null
+++ b/lib/tasks/brakeman.rake
@@ -0,0 +1,9 @@
+desc 'Security check via brakeman'
+task :brakeman do
+  if system("brakeman --skip-files lib/backup/repository.rb -w3 -z")
+    puts 'Security check succeed'
+  else
+    puts 'Security check failed'
+    exit 1
+  end
+end
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index 2eff1260b6199877978f6af87d4ac8dd8e28b573..0230fbb010b4d50f929e89a65a2961a4d3cb6968 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -6,6 +6,7 @@ namespace :gitlab do
     desc "GITLAB | Create a backup of the GitLab system"
     task create: :environment do
       warn_user_is_not_gitlab
+      configure_cron_mode
 
       Rake::Task["gitlab:backup:db:create"].invoke
       Rake::Task["gitlab:backup:repo:create"].invoke
@@ -21,6 +22,7 @@ namespace :gitlab do
     desc "GITLAB | Restore a previously created backup"
     task restore: :environment do
       warn_user_is_not_gitlab
+      configure_cron_mode
 
       backup = Backup::Manager.new
       backup.unpack
@@ -35,43 +37,54 @@ namespace :gitlab do
 
     namespace :repo do
       task create: :environment do
-        puts "Dumping repositories ...".blue
+        $progress.puts "Dumping repositories ...".blue
         Backup::Repository.new.dump
-        puts "done".green
+        $progress.puts "done".green
       end
 
       task restore: :environment do
-        puts "Restoring repositories ...".blue
+        $progress.puts "Restoring repositories ...".blue
         Backup::Repository.new.restore
-        puts "done".green
+        $progress.puts "done".green
       end
     end
 
     namespace :db do
       task create: :environment do
-        puts "Dumping database ... ".blue
+        $progress.puts "Dumping database ... ".blue
         Backup::Database.new.dump
-        puts "done".green
+        $progress.puts "done".green
       end
 
       task restore: :environment do
-        puts "Restoring database ... ".blue
+        $progress.puts "Restoring database ... ".blue
         Backup::Database.new.restore
-        puts "done".green
+        $progress.puts "done".green
       end
     end
 
     namespace :uploads do
       task create: :environment do
-        puts "Dumping uploads ... ".blue
+        $progress.puts "Dumping uploads ... ".blue
         Backup::Uploads.new.dump
-        puts "done".green
+        $progress.puts "done".green
       end
 
       task restore: :environment do
-        puts "Restoring uploads ... ".blue
+        $progress.puts "Restoring uploads ... ".blue
         Backup::Uploads.new.restore
-        puts "done".green
+        $progress.puts "done".green
+      end
+    end
+
+    def configure_cron_mode
+      if ENV['CRON']
+        # We need an object we can say 'puts' and 'print' to; let's use a
+        # StringIO.
+        require 'stringio'
+        $progress = StringIO.new
+      else
+        $progress = $stdout
       end
     end
   end # namespace end: backup
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 7ff23a7600a68c7763eb95bcd9c27295fb106600..d791b7155f9a4fc72bb884977969c68c03f69ec3 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -29,6 +29,7 @@ namespace :gitlab do
       check_redis_version
       check_ruby_version
       check_git_version
+      check_active_users
 
       finished_checking "GitLab"
     end
@@ -328,16 +329,20 @@ namespace :gitlab do
       if correct_options.all?
         puts "yes".green
       else
-        puts "no".red
-        try_fixing_it(
-          sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global user.name  \"#{options["user.name"]}\""),
-          sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global user.email \"#{options["user.email"]}\""),
-          sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global core.autocrlf \"#{options["core.autocrlf"]}\"")
-        )
-        for_more_information(
-          see_installation_guide_section "GitLab"
-        )
-        fix_and_rerun
+        print "Trying to fix Git error automatically. ..."
+        if auto_fix_git_config(options)
+          puts "Success".green
+        else
+          puts "Failed".red
+          try_fixing_it(
+            sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global user.name  \"#{options["user.name"]}\""),
+            sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global user.email \"#{options["user.email"]}\""),
+            sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global core.autocrlf \"#{options["core.autocrlf"]}\"")
+          )
+          for_more_information(
+            see_installation_guide_section "GitLab"
+          )
+        end
       end
     end
   end
@@ -585,10 +590,6 @@ namespace :gitlab do
     def gitlab_shell_patch_version
       Gitlab::Shell.version_required.split('.')[2].to_i
     end
-
-    def has_gitlab_shell3?
-      gitlab_shell_version.try(:start_with?, "v3.")
-    end
   end
 
 
@@ -785,19 +786,23 @@ namespace :gitlab do
     end
   end
 
+  def check_active_users
+    puts "Active users: #{User.active.count}"
+  end
+
   def omnibus_gitlab?
     Dir.pwd == '/opt/gitlab/embedded/service/gitlab-rails'
   end
 
   def sanitized_message(project)
-    if sanitize
+    if should_sanitize?
       "#{project.namespace_id.to_s.yellow}/#{project.id.to_s.yellow} ... "
     else
       "#{project.name_with_namespace.yellow} ... "
     end
   end
 
-  def sanitize
+  def should_sanitize?
     if ENV['SANITIZE'] == "true"
       true
     else
@@ -805,3 +810,4 @@ namespace :gitlab do
     end
   end
 end
+
diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake
index 189ad6090a41c7c7b7971028257e1fbd431ab86b..3c9802a0be4366c80552c8e41f728bb068169fc2 100644
--- a/lib/tasks/gitlab/cleanup.rake
+++ b/lib/tasks/gitlab/cleanup.rake
@@ -90,13 +90,14 @@ namespace :gitlab do
       warn_user_is_not_gitlab
       block_flag = ENV['BLOCK']
 
-      User.ldap.each do |ldap_user|
-        print "#{ldap_user.name} (#{ldap_user.extern_uid}) ..."
-        if Gitlab::LDAP::Access.allowed?(ldap_user)
+      User.find_each do |user|
+        next unless user.ldap_user?
+        print "#{user.name} (#{user.ldap_identity.extern_uid}) ..."
+        if Gitlab::LDAP::Access.allowed?(user)
           puts " [OK]".green
         else
           if block_flag
-            ldap_user.block! unless ldap_user.blocked?
+            user.block! unless user.blocked?
             puts " [BLOCKED]".red
           else
             puts " [NOT IN LDAP]".yellow
diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
index 3c693546c098886d62636ebc4d804a747c2610f0..20abb2fa5001c01e72c58817318228ebc3733994 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -25,7 +25,7 @@ namespace :gitlab do
 
         puts "Processing #{repo_path}".yellow
 
-        if path =~ /\.wiki\Z/
+        if path.end_with?('.wiki')
           puts " * Skipping wiki repo"
           next
         end
@@ -66,6 +66,7 @@ namespace :gitlab do
             puts " * Created #{project.name} (#{repo_path})".green
           else
             puts " * Failed trying to create #{project.name} (#{repo_path})".red
+            puts "   Validation Errors: #{project.errors.messages}".red
           end
         end
       end
diff --git a/lib/tasks/gitlab/mail_google_schema_whitelisting.rake b/lib/tasks/gitlab/mail_google_schema_whitelisting.rake
new file mode 100644
index 0000000000000000000000000000000000000000..102c6ae55d5afd9245e9234e1ddd14b683615d48
--- /dev/null
+++ b/lib/tasks/gitlab/mail_google_schema_whitelisting.rake
@@ -0,0 +1,73 @@
+require "#{Rails.root}/app/helpers/emails_helper"
+require 'action_view/helpers'
+extend ActionView::Helpers
+
+include ActionView::Context
+include EmailsHelper
+
+namespace :gitlab do
+  desc "Email google whitelisting email with example email for actions in inbox"
+  task mail_google_schema_whitelisting: :environment do
+    subject = "Rails | Implemented feature"
+    url = "#{Gitlab.config.gitlab.url}/base/rails-project/issues/#{rand(1..100)}#note_#{rand(10..1000)}"
+    schema = email_action(url)
+    body = email_template(schema, url)
+    mail = Notify.test_email("schema.whitelisting+sample@gmail.com", subject, body.html_safe)
+    if send_now
+      mail.deliver
+    else
+      puts "WOULD SEND:"
+    end
+    puts mail
+  end
+
+  def email_template(schema, url)
+    "<html lang='en'>
+      <head>
+        <meta content='text/html; charset=utf-8' http-equiv='Content-Type'>
+          <title>
+            GitLab
+          </title>
+        </meta>
+      </head>
+      <style>
+        img {
+          max-width: 100%;
+          height: auto;
+        }
+        p.details {
+          font-style:italic;
+          color:#777
+        }
+        .footer p {
+          font-size:small;
+          color:#777
+        }
+      </style>
+      <body>
+        <div class='content'>
+          <div>
+           <p>I like it :+1: </p>
+          </div>
+        </div>
+
+        <div class='footer' style='margin-top: 10px;'>
+          <p>
+          <br>
+            <a href=\"#{url}\">View it on GitLab</a>
+            You're receiving this notification because you are a member of the Base / Rails Project project team.
+            #{schema}
+          </p>
+        </div>
+      </body>
+    </html>"
+  end
+
+  def send_now
+    if ENV['SEND'] == "true"
+      true
+    else
+      false
+    end
+  end
+end
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
index 202e55c89adb4d2b1658f3e12bea8bb8e18635dc..e835d6cb9b7720566838327c8448c736c9a7519e 100644
--- a/lib/tasks/gitlab/shell.rake
+++ b/lib/tasks/gitlab/shell.rake
@@ -17,15 +17,19 @@ namespace :gitlab do
 
       # Clone if needed
       unless File.directory?(target_dir)
-        sh(*%W(git clone #{args.repo} #{target_dir}))
+        system(*%W(git clone -- #{args.repo} #{target_dir}))
       end
 
       # Make sure we're on the right tag
       Dir.chdir(target_dir) do
         # First try to checkout without fetching
         # to avoid stalling tests if the Internet is down.
-        reset = "git reset --hard $(git describe #{args.tag} || git describe origin/#{args.tag})"
-        sh "#{reset} || git fetch origin && #{reset}"
+        reseted = reset_to_commit(args)
+
+        unless reseted
+          system(*%W(git fetch origin))
+          reset_to_commit(args)
+        end
 
         config = {
           user: user,
@@ -54,7 +58,7 @@ namespace :gitlab do
         File.open("config.yml", "w+") {|f| f.puts config.to_yaml}
 
         # Launch installation process
-        sh "bin/install"
+        system(*%W(bin/install))
       end
 
       # Required for debian packaging with PKGR: Setup .ssh/environment with
@@ -108,6 +112,7 @@ namespace :gitlab do
         print '.'
       end
     end
+    puts ""
 
     unless $?.success?
       puts "Failed to add keys...".red
@@ -118,5 +123,16 @@ namespace :gitlab do
     puts "Quitting...".red
     exit 1
   end
+
+  def reset_to_commit(args)
+    tag, status = Gitlab::Popen.popen(%W(git describe -- #{args.tag}))
+
+    unless status.zero?
+      tag, status = Gitlab::Popen.popen(%W(git describe -- origin/#{args.tag}))
+    end
+
+    tag = tag.strip
+    system(*%W(git reset --hard #{tag}))
+  end
 end
 
diff --git a/lib/tasks/gitlab/task_helpers.rake b/lib/tasks/gitlab/task_helpers.rake
index da61c6e007f28b7296e32c513c02f3afd61e4291..14a130be2ca6afbfeffe7a495dd6e720683e8ed5 100644
--- a/lib/tasks/gitlab/task_helpers.rake
+++ b/lib/tasks/gitlab/task_helpers.rake
@@ -112,4 +112,20 @@ namespace :gitlab do
       @warned_user_not_gitlab = true
     end
   end
+
+  # Tries to configure git itself
+  #
+  # Returns true if all subcommands were successfull (according to their exit code)
+  # Returns false if any or all subcommands failed.
+  def auto_fix_git_config(options)
+    if !@warned_user_not_gitlab && options['user.email'] != 'example@example.com' # default email should be overridden?
+      command_success = options.map do |name, value|
+        system(%W(#{Gitlab.config.git.bin_path} config --global #{name} #{value}))
+      end
+
+      command_success.all?
+    else
+      false
+    end
+  end
 end
diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
index c01b00bd1c0141d54273e9080d8ddfed80aee8f5..b4c0ae3ff79a5c21de9a39815c319670b234d944 100644
--- a/lib/tasks/gitlab/test.rake
+++ b/lib/tasks/gitlab/test.rake
@@ -2,6 +2,8 @@ namespace :gitlab do
   desc "GITLAB | Run all tests"
   task :test do
     cmds = [
+      %W(rake brakeman),
+      %W(rake rubocop),
       %W(rake spinach),
       %W(rake spec),
       %W(rake jasmine:ci)
diff --git a/lib/tasks/rubocop.rake b/lib/tasks/rubocop.rake
new file mode 100644
index 0000000000000000000000000000000000000000..ddfaf5d51f281225a717c4fe8ef4e8ce4dc1a0e7
--- /dev/null
+++ b/lib/tasks/rubocop.rake
@@ -0,0 +1,4 @@
+unless Rails.env.production?
+  require 'rubocop/rake_task'
+  RuboCop::RakeTask.new
+end
diff --git a/lib/tasks/spinach.rake b/lib/tasks/spinach.rake
index 507b315759d2557c83f2a33181d62939f0967f3a..4aefc18ce1481b9c98754a17239ac5e16d226d57 100644
--- a/lib/tasks/spinach.rake
+++ b/lib/tasks/spinach.rake
@@ -2,9 +2,15 @@ Rake::Task["spinach"].clear if Rake::Task.task_defined?('spinach')
 
 desc "GITLAB | Run spinach"
 task :spinach do
+  tags = if ENV['SEMAPHORE']
+           '~@tricky'
+         else
+           '~@semaphore'
+         end
+
   cmds = [
     %W(rake gitlab:setup),
-    %W(spinach),
+    %W(spinach --tags #{tags}),
   ]
   run_commands(cmds)
 end
diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake
index 583f4a876da9c652b525f85b3d267b7eb76adb44..a39d96498761113bae71077a64a7e02510dbe35f 100644
--- a/lib/tasks/test.rake
+++ b/lib/tasks/test.rake
@@ -9,5 +9,5 @@ unless Rails.env.production?
   require 'coveralls/rake/task'
   Coveralls::RakeTask.new
   desc "GITLAB | Run all tests on CI with simplecov"
-  task :test_ci => [:spinach, :spec, 'coveralls:push']
+  task :test_ci => [:rubocop, :brakeman, 'jasmine:ci', :spinach, :spec, 'coveralls:push']
 end
diff --git a/safe/public.pem b/safe/public.pem
new file mode 100644
index 0000000000000000000000000000000000000000..c5ffe20a5c7bc19f5addf5e4aac0d9f099bcab19
--- /dev/null
+++ b/safe/public.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnp2mUaLBoHFX127ysonX
+OihiGpI4098eFfH1iAxpKHIof0vs0jFF05IUScNXJZ1U3w8G1U/unY/wGGa3NzAb
+ZfDd22eOF6X2Gfiey6U4w9dFf0/UT5x1bphlpX357yh4O9oWWuNaWD062DTbOOsJ
+U6UW2U/sZAu/QScys0Nw+gJ58t93hb4jFq+nO5IAQc6g4S8ek5YvIXOshFEpF2in
+ZLbSYowx92+9GzfjvdQ7fk0Q2ssg0zfScVa6FY8n019osz0SC3wcSd/qicdfecpu
+7oycpd9YDqk4lufE1qVMOsgE8OO4KXMrByz2f+T0p/bH9zdBa5HYylf1T7i60hIL
+kQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index cc32805f5ec5e61cd0419adfcb13f7eadadd4289..186239d3096b6a548b41d8bf0348e446986f3380 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -7,26 +7,26 @@ describe ApplicationController do
 
     it 'should redirect if the user is over their password expiry' do
       user.password_expires_at = Time.new(2002)
-      user.ldap_user?.should be_false
-      controller.stub(:current_user).and_return(user)
-      controller.should_receive(:redirect_to)
-      controller.should_receive(:new_profile_password_path)
+      expect(user.ldap_user?).to be_falsey
+      allow(controller).to receive(:current_user).and_return(user)
+      expect(controller).to receive(:redirect_to)
+      expect(controller).to receive(:new_profile_password_path)
       controller.send(:check_password_expiration)
     end
 
     it 'should not redirect if the user is under their password expiry' do
       user.password_expires_at = Time.now + 20010101
-      user.ldap_user?.should be_false
-      controller.stub(:current_user).and_return(user)
-      controller.should_not_receive(:redirect_to)
+      expect(user.ldap_user?).to be_falsey
+      allow(controller).to receive(:current_user).and_return(user)
+      expect(controller).not_to receive(:redirect_to)
       controller.send(:check_password_expiration)
     end
 
     it 'should not redirect if the user is over their password expiry but they are an ldap user' do
       user.password_expires_at = Time.new(2002)
-      user.stub(:ldap_user?).and_return(true)
-      controller.stub(:current_user).and_return(user)
-      controller.should_not_receive(:redirect_to)
+      allow(user).to receive(:ldap_user?).and_return(true)
+      allow(controller).to receive(:current_user).and_return(user)
+      expect(controller).not_to receive(:redirect_to)
       controller.send(:check_password_expiration)
     end
   end
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a0909cec3bd6f77f916aa1e86b9284441e1b8ecc
--- /dev/null
+++ b/spec/controllers/autocomplete_controller_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe AutocompleteController do
+  let!(:project) { create(:project) }
+  let!(:user)    { create(:user) }
+  let!(:user2)   { create(:user) }
+
+  context 'project members' do
+    before do
+      sign_in(user)
+      project.team << [user, :master]
+
+      get(:users, project_id: project.id)
+    end
+
+    let(:body) { JSON.parse(response.body) }
+
+    it { body.should be_kind_of(Array) }
+    it { body.size.should eq(1) }
+    it { body.first["username"].should == user.username }
+  end
+
+  context 'group members' do
+    let(:group) { create(:group) }
+
+    before do
+      sign_in(user)
+      group.add_owner(user)
+
+      get(:users, group_id: group.id)
+    end
+
+    let(:body) { JSON.parse(response.body) }
+
+    it { body.should be_kind_of(Array) }
+    it { body.size.should eq(1) }
+    it { body.first["username"].should == user.username }
+  end
+
+  context 'all users' do
+    before do
+      sign_in(user)
+      get(:users)
+    end
+
+    let(:body) { JSON.parse(response.body) }
+
+    it { body.should be_kind_of(Array) }
+    it { body.size.should eq(User.count) }
+  end
+end
diff --git a/spec/controllers/blob_controller_spec.rb b/spec/controllers/blob_controller_spec.rb
index 11d748ca77fc87741d9e631ace19612790808b8d..a1102f283406ca24dca53a0787ecdb3f48de08c2 100644
--- a/spec/controllers/blob_controller_spec.rb
+++ b/spec/controllers/blob_controller_spec.rb
@@ -9,29 +9,32 @@ describe Projects::BlobController do
 
     project.team << [user, :master]
 
-    project.stub(:branches).and_return(['master', 'foo/bar/baz'])
-    project.stub(:tags).and_return(['v1.0.0', 'v2.0.0'])
+    allow(project).to receive(:branches).and_return(['master', 'foo/bar/baz'])
+    allow(project).to receive(:tags).and_return(['v1.0.0', 'v2.0.0'])
     controller.instance_variable_set(:@project, project)
   end
 
   describe "GET show" do
     render_views
 
-    before { get :show, project_id: project.to_param, id: id }
+    before do
+      get(:show, namespace_id: project.namespace.to_param,
+          project_id: project.to_param, id: id)
+    end
 
     context "valid branch, valid file" do
       let(:id) { 'master/README.md' }
-      it { should respond_with(:success) }
+      it { is_expected.to respond_with(:success) }
     end
 
     context "valid branch, invalid file" do
       let(:id) { 'master/invalid-path.rb' }
-      it { should respond_with(:not_found) }
+      it { is_expected.to respond_with(:not_found) }
     end
 
     context "invalid branch, valid file" do
       let(:id) { 'invalid-branch/README.md' }
-      it { should respond_with(:not_found) }
+      it { is_expected.to respond_with(:not_found) }
     end
   end
 
@@ -39,13 +42,17 @@ describe Projects::BlobController do
     render_views
 
     before do
-      get :show, project_id: project.to_param, id: id
+      get(:show, namespace_id: project.namespace.to_param,
+          project_id: project.to_param, id: id)
       controller.instance_variable_set(:@blob, nil)
     end
 
     context 'redirect to tree' do
       let(:id) { 'markdown/doc' }
-      it { should redirect_to("/#{project.path_with_namespace}/tree/markdown/doc") }
+      it 'redirects' do
+        expect(subject).
+          to redirect_to("/#{project.path_with_namespace}/tree/markdown/doc")
+      end
     end
   end
 end
diff --git a/spec/controllers/branches_controller_spec.rb b/spec/controllers/branches_controller_spec.rb
index 610d7a84e31e5c9f72ddc61341c117b72fbbff4e..51397382cfbc107fc8cd4caf658195b078c4f631 100644
--- a/spec/controllers/branches_controller_spec.rb
+++ b/spec/controllers/branches_controller_spec.rb
@@ -9,8 +9,8 @@ describe Projects::BranchesController do
 
     project.team << [user, :master]
 
-    project.stub(:branches).and_return(['master', 'foo/bar/baz'])
-    project.stub(:tags).and_return(['v1.0.0', 'v2.0.0'])
+    allow(project).to receive(:branches).and_return(['master', 'foo/bar/baz'])
+    allow(project).to receive(:tags).and_return(['v1.0.0', 'v2.0.0'])
     controller.instance_variable_set(:@project, project)
   end
 
@@ -19,6 +19,7 @@ describe Projects::BranchesController do
 
     before {
       post :create,
+        namespace_id: project.namespace.to_param,
         project_id: project.to_param,
         branch_name: branch,
         ref: ref
@@ -27,25 +28,31 @@ describe Projects::BranchesController do
     context "valid branch name, valid source" do
       let(:branch) { "merge_branch" }
       let(:ref) { "master" }
-      it { should redirect_to("/#{project.path_with_namespace}/tree/merge_branch") }
+      it 'redirects' do
+        expect(subject).
+          to redirect_to("/#{project.path_with_namespace}/tree/merge_branch")
+      end
     end
 
     context "invalid branch name, valid ref" do
       let(:branch) { "<script>alert('merge');</script>" }
       let(:ref) { "master" }
-      it { should redirect_to("/#{project.path_with_namespace}/tree/alert('merge');") }
+      it 'redirects' do
+        expect(subject).
+          to redirect_to("/#{project.path_with_namespace}/tree/alert('merge');")
+      end
     end
 
     context "valid branch name, invalid ref" do
       let(:branch) { "merge_branch" }
       let(:ref) { "<script>alert('ref');</script>" }
-      it { should render_template("new") }
+      it { is_expected.to render_template('new') }
     end
 
     context "invalid branch name, invalid ref" do
       let(:branch) { "<script>alert('merge');</script>" }
       let(:ref) { "<script>alert('ref');</script>" }
-      it { should render_template("new") }
+      it { is_expected.to render_template('new') }
     end
   end
 end
diff --git a/spec/controllers/commit_controller_spec.rb b/spec/controllers/commit_controller_spec.rb
index f5822157ea4152f4af914e2edf165c8ffbcb0212..3394a1f863fa1f12477a2ea0466c186e14120a12 100644
--- a/spec/controllers/commit_controller_spec.rb
+++ b/spec/controllers/commit_controller_spec.rb
@@ -13,27 +13,32 @@ describe Projects::CommitController do
   describe "#show" do
     shared_examples "export as" do |format|
       it "should generally work" do
-        get :show, project_id: project.to_param, id: commit.id, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: commit.id, format: format)
 
         expect(response).to be_success
       end
 
       it "should generate it" do
-        Commit.any_instance.should_receive(:"to_#{format}")
+        expect_any_instance_of(Commit).to receive(:"to_#{format}")
 
-        get :show, project_id: project.to_param, id: commit.id, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: commit.id, format: format)
       end
 
       it "should render it" do
-        get :show, project_id: project.to_param, id: commit.id, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: commit.id, format: format)
 
         expect(response.body).to eq(commit.send(:"to_#{format}"))
       end
 
       it "should not escape Html" do
-        Commit.any_instance.stub(:"to_#{format}").and_return('HTML entities &<>" ')
+        allow_any_instance_of(Commit).to receive(:"to_#{format}").
+          and_return('HTML entities &<>" ')
 
-        get :show, project_id: project.to_param, id: commit.id, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: commit.id, format: format)
 
         expect(response.body).to_not include('&amp;')
         expect(response.body).to_not include('&gt;')
@@ -47,7 +52,8 @@ describe Projects::CommitController do
       let(:format) { :diff }
 
       it "should really only be a git diff" do
-        get :show, project_id: project.to_param, id: commit.id, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: commit.id, format: format)
 
         expect(response.body).to start_with("diff --git")
       end
@@ -58,16 +64,28 @@ describe Projects::CommitController do
       let(:format) { :patch }
 
       it "should really be a git email patch" do
-        get :show, project_id: project.to_param, id: commit.id, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: commit.id, format: format)
 
         expect(response.body).to start_with("From #{commit.id}")
       end
 
       it "should contain a git diff" do
-        get :show, project_id: project.to_param, id: commit.id, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: commit.id, format: format)
 
         expect(response.body).to match(/^diff --git/)
       end
     end
   end
+
+  describe "#branches" do
+    it "contains branch and tags information" do
+      get(:branches, namespace_id: project.namespace.to_param,
+          project_id: project.to_param, id: commit.id)
+
+      expect(assigns(:branches)).to include("master", "feature_conflict")
+      expect(assigns(:tags)).to include("v1.1.0")
+    end
+  end
 end
diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb
index 0c19d755eb188cbbc3029c1d17a8162fdd98fefe..2184b35152eadfb20740aba0b8a3908a9d09c37a 100644
--- a/spec/controllers/commits_controller_spec.rb
+++ b/spec/controllers/commits_controller_spec.rb
@@ -12,9 +12,10 @@ describe Projects::CommitsController do
   describe "GET show" do
     context "as atom feed" do
       it "should render as atom" do
-        get :show, project_id: project.to_param, id: "master", format: "atom"
-        response.should be_success
-        response.content_type.should == 'application/atom+xml'
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: "master", format: "atom")
+        expect(response).to be_success
+        expect(response.content_type).to eq('application/atom+xml')
       end
     end
   end
diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5dd4124061c746a2f892282757af43443446b403
--- /dev/null
+++ b/spec/controllers/import/bitbucket_controller_spec.rb
@@ -0,0 +1,78 @@
+require 'spec_helper'
+
+describe Import::BitbucketController do
+  let(:user) { create(:user, bitbucket_access_token: 'asd123', bitbucket_access_token_secret: "sekret") }
+
+  before do
+    sign_in(user)
+    controller.stub(:bitbucket_import_enabled?).and_return(true)
+  end
+
+  describe "GET callback" do
+    before do
+      session[:oauth_request_token] = {}
+    end
+    
+    it "updates access token" do
+      token = "asdasd12345"
+      secret = "sekrettt"
+      access_token = double(token: token, secret: secret)
+      Gitlab::BitbucketImport::Client.any_instance.stub(:get_token).and_return(access_token)
+      Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "bitbucket")
+
+      get :callback
+
+      expect(user.reload.bitbucket_access_token).to eq(token)
+      expect(user.reload.bitbucket_access_token_secret).to eq(secret)
+      expect(controller).to redirect_to(status_import_bitbucket_url)
+    end
+  end
+
+  describe "GET status" do
+    before do
+      @repo = OpenStruct.new(slug: 'vim', owner: 'asd')
+    end
+
+    it "assigns variables" do
+      @project = create(:project, import_type: 'bitbucket', creator_id: user.id)
+      controller.stub_chain(:client, :projects).and_return([@repo])
+
+      get :status
+
+      expect(assigns(:already_added_projects)).to eq([@project])
+      expect(assigns(:repos)).to eq([@repo])
+    end
+
+    it "does not show already added project" do
+      @project = create(:project, import_type: 'bitbucket', creator_id: user.id, import_source: 'asd/vim')
+      controller.stub_chain(:client, :projects).and_return([@repo])
+
+      get :status
+
+      expect(assigns(:already_added_projects)).to eq([@project])
+      expect(assigns(:repos)).to eq([])
+    end
+  end
+
+  describe "POST create" do
+    before do
+      @repo = {
+        slug: 'vim',
+        owner: "john"
+      }.with_indifferent_access
+    end
+
+    it "takes already existing namespace" do
+      namespace = create(:namespace, name: "john", owner: user)
+      expect(Gitlab::BitbucketImport::KeyAdder).
+        to receive(:new).with(@repo, user).
+        and_return(double(execute: true))
+      expect(Gitlab::BitbucketImport::ProjectCreator).
+        to receive(:new).with(@repo, namespace, user).
+        and_return(double(execute: true))
+      controller.stub_chain(:client, :project).and_return(@repo)
+
+      post :create, format: :js
+    end
+  end
+end
diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5b967bfcc0c1ac8c27517b1e8b7cbdcd64b47f52
--- /dev/null
+++ b/spec/controllers/import/github_controller_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe Import::GithubController do
+  let(:user) { create(:user, github_access_token: 'asd123') }
+
+  before do
+    sign_in(user)
+    controller.stub(:github_import_enabled?).and_return(true)
+  end
+
+  describe "GET callback" do
+    it "updates access token" do
+      token = "asdasd12345"
+      allow_any_instance_of(Gitlab::GithubImport::Client).
+        to receive(:get_token).and_return(token)
+      Gitlab.config.omniauth.providers << OpenStruct.new(app_id: 'asd123',
+                                                         app_secret: 'asd123',
+                                                         name: 'github')
+
+      get :callback
+
+      expect(user.reload.github_access_token).to eq(token)
+      expect(controller).to redirect_to(status_import_github_url)
+    end
+  end
+
+  describe "GET status" do
+    before do
+      @repo = OpenStruct.new(login: 'vim', full_name: 'asd/vim')
+      @org = OpenStruct.new(login: 'company')
+      @org_repo = OpenStruct.new(login: 'company', full_name: 'company/repo')
+    end
+
+    it "assigns variables" do
+      @project = create(:project, import_type: 'github', creator_id: user.id)
+      controller.stub_chain(:client, :repos).and_return([@repo])
+      controller.stub_chain(:client, :orgs).and_return([@org])
+      controller.stub_chain(:client, :org_repos).with(@org.login).and_return([@org_repo])
+
+      get :status
+
+      expect(assigns(:already_added_projects)).to eq([@project])
+      expect(assigns(:repos)).to eq([@repo, @org_repo])
+    end
+
+    it "does not show already added project" do
+      @project = create(:project, import_type: 'github', creator_id: user.id, import_source: 'asd/vim')
+      controller.stub_chain(:client, :repos).and_return([@repo])
+      controller.stub_chain(:client, :orgs).and_return([])
+
+      get :status
+
+      expect(assigns(:already_added_projects)).to eq([@project])
+      expect(assigns(:repos)).to eq([])
+    end
+  end
+
+  describe "POST create" do
+    before do
+      @repo = OpenStruct.new(login: 'vim', full_name: 'asd/vim', owner: OpenStruct.new(login: "john"))
+    end
+
+    it "takes already existing namespace" do
+      namespace = create(:namespace, name: "john", owner: user)
+      expect(Gitlab::GithubImport::ProjectCreator).
+        to receive(:new).with(@repo, namespace, user).
+        and_return(double(execute: true))
+      controller.stub_chain(:client, :repo).and_return(@repo)
+
+      post :create, format: :js
+    end
+  end
+end
diff --git a/spec/controllers/import/gitlab_controller_spec.rb b/spec/controllers/import/gitlab_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b6b86b1bceef0cd92fbb433f4c495c91738af687
--- /dev/null
+++ b/spec/controllers/import/gitlab_controller_spec.rb
@@ -0,0 +1,70 @@
+require 'spec_helper'
+
+describe Import::GitlabController do
+  let(:user) { create(:user, gitlab_access_token: 'asd123') }
+
+  before do
+    sign_in(user)
+    controller.stub(:gitlab_import_enabled?).and_return(true)
+  end
+
+  describe "GET callback" do
+    it "updates access token" do
+      token = "asdasd12345"
+      Gitlab::GitlabImport::Client.any_instance.stub_chain(:client, :auth_code, :get_token, :token).and_return(token)
+      Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "gitlab")
+
+      get :callback
+
+      expect(user.reload.gitlab_access_token).to eq(token)
+      expect(controller).to redirect_to(status_import_gitlab_url)
+    end
+  end
+
+  describe "GET status" do
+    before do
+      @repo = OpenStruct.new(path: 'vim', path_with_namespace: 'asd/vim')
+    end
+
+    it "assigns variables" do
+      @project = create(:project, import_type: 'gitlab', creator_id: user.id)
+      controller.stub_chain(:client, :projects).and_return([@repo])
+
+      get :status
+
+      expect(assigns(:already_added_projects)).to eq([@project])
+      expect(assigns(:repos)).to eq([@repo])
+    end
+
+    it "does not show already added project" do
+      @project = create(:project, import_type: 'gitlab', creator_id: user.id, import_source: 'asd/vim')
+      controller.stub_chain(:client, :projects).and_return([@repo])
+
+      get :status
+
+      expect(assigns(:already_added_projects)).to eq([@project])
+      expect(assigns(:repos)).to eq([])
+    end
+  end
+
+  describe "POST create" do
+    before do
+      @repo = {
+        path: 'vim',
+        path_with_namespace: 'asd/vim',
+        owner: {name: "john"},
+        namespace: {path: "john"}
+      }.with_indifferent_access
+    end
+
+    it "takes already existing namespace" do
+      namespace = create(:namespace, name: "john", owner: user)
+      expect(Gitlab::GitlabImport::ProjectCreator).
+        to receive(:new).with(@repo, namespace, user).
+        and_return(double(execute: true))
+      controller.stub_chain(:client, :project).and_return(@repo)
+
+      post :create, format: :js
+    end
+  end
+end
diff --git a/spec/controllers/import/gitorious_controller_spec.rb b/spec/controllers/import/gitorious_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..07c9484bf1a2fafa2e98ccb64b0546dbcb5718d4
--- /dev/null
+++ b/spec/controllers/import/gitorious_controller_spec.rb
@@ -0,0 +1,67 @@
+require 'spec_helper'
+
+describe Import::GitoriousController do
+  let(:user) { create(:user) }
+
+  before do
+    sign_in(user)
+  end
+
+  describe "GET new" do
+    it "redirects to import endpoint on gitorious.org" do
+      get :new
+
+      expect(controller).to redirect_to("https://gitorious.org/gitlab-import?callback_url=http://test.host/import/gitorious/callback")
+    end
+  end
+
+  describe "GET callback" do
+    it "stores repo list in session" do
+      get :callback, repos: 'foo/bar,baz/qux'
+
+      expect(session[:gitorious_repos]).to eq('foo/bar,baz/qux')
+    end
+  end
+
+  describe "GET status" do
+    before do
+      @repo = OpenStruct.new(full_name: 'asd/vim')
+    end
+
+    it "assigns variables" do
+      @project = create(:project, import_type: 'gitorious', creator_id: user.id)
+      controller.stub_chain(:client, :repos).and_return([@repo])
+
+      get :status
+
+      expect(assigns(:already_added_projects)).to eq([@project])
+      expect(assigns(:repos)).to eq([@repo])
+    end
+
+    it "does not show already added project" do
+      @project = create(:project, import_type: 'gitorious', creator_id: user.id, import_source: 'asd/vim')
+      controller.stub_chain(:client, :repos).and_return([@repo])
+
+      get :status
+
+      expect(assigns(:already_added_projects)).to eq([@project])
+      expect(assigns(:repos)).to eq([])
+    end
+  end
+
+  describe "POST create" do
+    before do
+      @repo = Gitlab::GitoriousImport::Repository.new('asd/vim')
+    end
+
+    it "takes already existing namespace" do
+      namespace = create(:namespace, name: "asd", owner: user)
+      expect(Gitlab::GitoriousImport::ProjectCreator).
+        to receive(:new).with(@repo, namespace, user).
+        and_return(double(execute: true))
+      controller.stub_chain(:client, :repo).and_return(@repo)
+
+      post :create, format: :js
+    end
+  end
+end
diff --git a/spec/controllers/merge_requests_controller_spec.rb b/spec/controllers/merge_requests_controller_spec.rb
index 300527e4ff2e7360259ccf54a5e845cc1368caf5..d6f56ed33d69ba73ff1d66049dbe815b794459c3 100644
--- a/spec/controllers/merge_requests_controller_spec.rb
+++ b/spec/controllers/merge_requests_controller_spec.rb
@@ -13,27 +13,32 @@ describe Projects::MergeRequestsController do
   describe "#show" do
     shared_examples "export merge as" do |format|
       it "should generally work" do
-        get :show, project_id: project.to_param, id: merge_request.iid, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: merge_request.iid, format: format)
 
         expect(response).to be_success
       end
 
       it "should generate it" do
-        MergeRequest.any_instance.should_receive(:"to_#{format}")
+        expect_any_instance_of(MergeRequest).to receive(:"to_#{format}")
 
-        get :show, project_id: project.to_param, id: merge_request.iid, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: merge_request.iid, format: format)
       end
 
       it "should render it" do
-        get :show, project_id: project.to_param, id: merge_request.iid, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: merge_request.iid, format: format)
 
         expect(response.body).to eq((merge_request.send(:"to_#{format}",user)).to_s)
       end
 
       it "should not escape Html" do
-        MergeRequest.any_instance.stub(:"to_#{format}").and_return('HTML entities &<>" ')
+        allow_any_instance_of(MergeRequest).to receive(:"to_#{format}").
+          and_return('HTML entities &<>" ')
 
-        get :show, project_id: project.to_param, id: merge_request.iid, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: merge_request.iid, format: format)
 
         expect(response.body).to_not include('&amp;')
         expect(response.body).to_not include('&gt;')
@@ -47,7 +52,8 @@ describe Projects::MergeRequestsController do
       let(:format) { :diff }
 
       it "should really only be a git diff" do
-        get :show, project_id: project.to_param, id: merge_request.iid, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: merge_request.iid, format: format)
 
         expect(response.body).to start_with("diff --git")
       end
@@ -58,13 +64,15 @@ describe Projects::MergeRequestsController do
       let(:format) { :patch }
 
       it "should really be a git email patch with commit" do
-        get :show, project_id: project.to_param, id: merge_request.iid, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: merge_request.iid, format: format)
 
         expect(response.body[0..100]).to start_with("From #{merge_request.commits.last.id}")
       end
 
       it "should contain git diffs" do
-        get :show, project_id: project.to_param, id: merge_request.iid, format: format
+        get(:show, namespace_id: project.namespace.to_param,
+            project_id: project.to_param, id: merge_request.iid, format: format)
 
         expect(response.body).to match(/^diff --git/)
       end
diff --git a/spec/controllers/projects/protected_branches_controller_spec.rb b/spec/controllers/projects/protected_branches_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..596d8d34b7c9a69045afda7cbcee09635c230eed
--- /dev/null
+++ b/spec/controllers/projects/protected_branches_controller_spec.rb
@@ -0,0 +1,10 @@
+require('spec_helper')
+
+describe Projects::ProtectedBranchesController do
+  describe "GET #index" do
+    let(:project) { create(:project_empty_repo, :public) }
+    it "redirect empty repo to projects page" do
+      get(:index, namespace_id: project.namespace.to_param, project_id: project.to_param)
+    end
+  end
+end
diff --git a/spec/controllers/projects/uploads_controller_spec.rb b/spec/controllers/projects/uploads_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..029f48b2d7a666ab62e317bbd12578e8693b9cb8
--- /dev/null
+++ b/spec/controllers/projects/uploads_controller_spec.rb
@@ -0,0 +1,57 @@
+require('spec_helper')
+
+describe Projects::UploadsController do
+  let(:project) { create(:project) }
+  let(:user)    { create(:user) }
+  let(:jpg)     { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') }
+  let(:txt)     { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') }
+
+  describe "POST #create" do
+    before do
+      sign_in(user)
+      project.team << [user, :developer]
+    end
+
+    context "without params['file']" do
+      it "returns an error" do
+        post :create, 
+          namespace_id: project.namespace.to_param,
+          project_id: project.to_param, 
+          format: :json
+        expect(response.status).to eq(422)
+      end
+    end
+
+    context 'with valid image' do
+      before do
+        post :create,
+          namespace_id: project.namespace.to_param,
+          project_id: project.to_param,
+          file: jpg,
+          format: :json
+      end
+
+      it 'returns a content with original filename, new link, and correct type.' do
+        expect(response.body).to match '\"alt\":\"rails_sample\"'
+        expect(response.body).to match "\"url\":\"http://localhost/#{project.path_with_namespace}/uploads"
+        expect(response.body).to match '\"is_image\":true'
+      end
+    end
+
+    context 'with valid non-image file' do
+      before do
+        post :create, 
+          namespace_id: project.namespace.to_param,
+          project_id: project.to_param, 
+          file: txt, 
+          format: :json
+      end
+
+      it 'returns a content with original filename, new link, and correct type.' do
+        expect(response.body).to match '\"alt\":\"doc_sample.txt\"'
+        expect(response.body).to match "\"url\":\"http://localhost/#{project.path_with_namespace}/uploads"
+        expect(response.body).to match '\"is_image\":false'
+      end
+    end
+  end
+end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 71bc49787cccdb42b00a3a1f999a2e7b04a7bb6f..a1b82a32150f7714c239b536e2d923331208292c 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -7,56 +7,41 @@ describe ProjectsController do
   let(:jpg)     { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') }
   let(:txt)     { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') }
 
-  describe "POST #upload_image" do
-    before do
-      sign_in(user)
-      project.team << [user, :developer]
-    end
+  describe "GET show" do
 
-    context "without params['markdown_img']" do
-      it "returns an error" do
-        post :upload_image, id: project.to_param, format: :json
-        expect(response.status).to eq(422)
-      end
-    end
+    context "when requested by `go get`" do
+      render_views
 
-    context "with invalid file" do
-      before do
-        post :upload_image, id: project.to_param, markdown_img: txt, format: :json
-      end
+      it "renders the go-import meta tag" do
+        get :show, "go-get" => "1", namespace_id: "bogus_namespace", id: "bogus_project"
 
-      it "returns an error" do
-        expect(response.status).to eq(422)
-      end
-    end
-
-    context "with valid file" do
-      before do
-        post :upload_image, id: project.to_param, markdown_img: jpg, format: :json
-      end
-
-      it "returns a content with original filename and new link." do
-        expect(response.body).to match "\"alt\":\"rails_sample\""
-        expect(response.body).to match "\"url\":\"http://test.host/uploads/#{project.path_with_namespace}"
+        expect(response.body).to include("name='go-import'")
+        
+        content = "localhost/bogus_namespace/bogus_project git http://localhost/bogus_namespace/bogus_project.git"
+        expect(response.body).to include("content='#{content}'")
       end
     end
   end
-
+  
   describe "POST #toggle_star" do
     it "toggles star if user is signed in" do
       sign_in(user)
-      expect(user.starred?(public_project)).to be_false
-      post :toggle_star, id: public_project.to_param
-      expect(user.starred?(public_project)).to be_true
-      post :toggle_star, id: public_project.to_param
-      expect(user.starred?(public_project)).to be_false
+      expect(user.starred?(public_project)).to be_falsey
+      post(:toggle_star, namespace_id: public_project.namespace.to_param,
+           id: public_project.to_param)
+      expect(user.starred?(public_project)).to be_truthy
+      post(:toggle_star, namespace_id: public_project.namespace.to_param,
+           id: public_project.to_param)
+      expect(user.starred?(public_project)).to be_falsey
     end
 
     it "does nothing if user is not signed in" do
-      post :toggle_star, id: public_project.to_param
-      expect(user.starred?(public_project)).to be_false
-      post :toggle_star, id: public_project.to_param
-      expect(user.starred?(public_project)).to be_false
+      post(:toggle_star, namespace_id: project.namespace.to_param,
+           id: public_project.to_param)
+      expect(user.starred?(public_project)).to be_falsey
+      post(:toggle_star, namespace_id: project.namespace.to_param,
+           id: public_project.to_param)
+      expect(user.starred?(public_project)).to be_falsey
     end
   end
 end
diff --git a/spec/controllers/tree_controller_spec.rb b/spec/controllers/tree_controller_spec.rb
index 8147fb0e6fba903c47b6b3c43202ece069169f0e..7b219819bbce79e4b6f44015c6a7f31b2eb4fb21 100644
--- a/spec/controllers/tree_controller_spec.rb
+++ b/spec/controllers/tree_controller_spec.rb
@@ -9,8 +9,8 @@ describe Projects::TreeController do
 
     project.team << [user, :master]
 
-    project.stub(:branches).and_return(['master', 'foo/bar/baz'])
-    project.stub(:tags).and_return(['v1.0.0', 'v2.0.0'])
+    allow(project).to receive(:branches).and_return(['master', 'foo/bar/baz'])
+    allow(project).to receive(:tags).and_return(['v1.0.0', 'v2.0.0'])
     controller.instance_variable_set(:@project, project)
   end
 
@@ -18,26 +18,29 @@ describe Projects::TreeController do
     # Make sure any errors accessing the tree in our views bubble up to this spec
     render_views
 
-    before { get :show, project_id: project.to_param, id: id }
+    before do
+      get(:show, namespace_id: project.namespace.to_param,
+          project_id: project.to_param, id: id)
+    end
 
     context "valid branch, no path" do
       let(:id) { 'master' }
-      it { should respond_with(:success) }
+      it { is_expected.to respond_with(:success) }
     end
 
     context "valid branch, valid path" do
       let(:id) { 'master/encoding/' }
-      it { should respond_with(:success) }
+      it { is_expected.to respond_with(:success) }
     end
 
     context "valid branch, invalid path" do
       let(:id) { 'master/invalid-path/' }
-      it { should respond_with(:not_found) }
+      it { is_expected.to respond_with(:not_found) }
     end
 
     context "invalid branch, valid path" do
       let(:id) { 'invalid-branch/encoding/' }
-      it { should respond_with(:not_found) }
+      it { is_expected.to respond_with(:not_found) }
     end
   end
 
@@ -45,12 +48,17 @@ describe Projects::TreeController do
     render_views
 
     before do
-      get :show, project_id: project.to_param, id: id
+      get(:show, namespace_id: project.namespace.to_param,
+          project_id: project.to_param, id: id)
     end
 
     context 'redirect to blob' do
       let(:id) { 'master/README.md' }
-      it { should redirect_to("/#{project.path_with_namespace}/blob/master/README.md") }
+      it 'redirects' do
+        redirect_url = "/#{project.path_with_namespace}/blob/master/README.md"
+        expect(subject).
+          to redirect_to(redirect_url)
+      end
     end
   end
 end
diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0f9780356b1b0920942b8788475205fa38d200e9
--- /dev/null
+++ b/spec/controllers/uploads_controller_spec.rb
@@ -0,0 +1,296 @@
+require 'spec_helper'
+
+describe UploadsController do
+  let!(:user) { create(:user, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) }
+
+  describe "GET show" do
+    context "when viewing a user avatar" do
+      context "when signed in" do
+        before do
+          sign_in(user)
+        end
+
+        context "when the user is blocked" do
+          before do
+            user.block
+          end
+
+          it "redirects to the sign in page" do
+            get :show, model: "user", mounted_as: "avatar", id: user.id, filename: "image.png"
+
+            expect(response).to redirect_to(new_user_session_path)
+          end
+        end
+
+        context "when the user isn't blocked" do
+          it "responds with status 200" do
+            get :show, model: "user", mounted_as: "avatar", id: user.id, filename: "image.png"
+
+            expect(response.status).to eq(200)
+          end
+        end
+      end
+      
+      context "when not signed in" do
+        it "responds with status 200" do
+          get :show, model: "user", mounted_as: "avatar", id: user.id, filename: "image.png"
+
+          expect(response.status).to eq(200)
+        end
+      end
+    end
+
+    context "when viewing a project avatar" do
+      let!(:project) { create(:project, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) }
+
+      context "when the project is public" do
+        before do
+          project.update_attribute(:visibility_level, Project::PUBLIC)
+        end
+
+        context "when not signed in" do
+          it "responds with status 200" do
+            get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png"
+
+            expect(response.status).to eq(200)
+          end
+        end
+
+        context "when signed in" do
+          before do
+            sign_in(user)
+          end
+
+          it "responds with status 200" do
+            get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png"
+
+            expect(response.status).to eq(200)
+          end
+        end
+      end
+
+      context "when the project is private" do
+        before do
+          project.update_attribute(:visibility_level, Project::PRIVATE)
+        end
+
+        context "when not signed in" do
+          it "redirects to the sign in page" do
+            get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png"
+
+            expect(response).to redirect_to(new_user_session_path)
+          end
+        end
+
+        context "when signed in" do
+          before do
+            sign_in(user)
+          end
+
+          context "when the user has access to the project" do
+            before do
+              project.team << [user, :master]
+            end
+
+            context "when the user is blocked" do
+              before do
+                user.block
+                project.team << [user, :master]
+              end
+
+              it "redirects to the sign in page" do
+                get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png"
+
+                expect(response).to redirect_to(new_user_session_path)
+              end
+            end
+
+            context "when the user isn't blocked" do
+              it "responds with status 200" do
+                get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png"
+
+                expect(response.status).to eq(200)
+              end
+            end
+          end
+
+          context "when the user doesn't have access to the project" do
+            it "responds with status 404" do
+              get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png"
+
+              expect(response.status).to eq(404)
+            end
+          end
+        end
+      end
+    end
+
+    context "when viewing a group avatar" do
+      let!(:group) { create(:group, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) }
+      let!(:project) { create(:project, namespace: group) }
+
+      context "when the group has public projects" do
+        before do
+          project.update_attribute(:visibility_level, Project::PUBLIC)
+        end
+
+        context "when not signed in" do
+          it "responds with status 200" do
+            get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png"
+
+            expect(response.status).to eq(200)
+          end
+        end
+
+        context "when signed in" do
+          before do
+            sign_in(user)
+          end
+
+          it "responds with status 200" do
+            get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png"
+
+            expect(response.status).to eq(200)
+          end
+        end
+      end
+
+      context "when the project doesn't have public projects" do
+        context "when not signed in" do
+          it "redirects to the sign in page" do
+            get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png"
+
+            expect(response).to redirect_to(new_user_session_path)
+          end
+        end
+
+        context "when signed in" do
+          before do
+            sign_in(user)
+          end
+
+          context "when the user has access to the project" do
+            before do
+              project.team << [user, :master]
+            end
+
+            context "when the user is blocked" do
+              before do
+                user.block
+                project.team << [user, :master]
+              end
+
+              it "redirects to the sign in page" do
+                get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png"
+
+                expect(response).to redirect_to(new_user_session_path)
+              end
+            end
+
+            context "when the user isn't blocked" do
+              it "responds with status 200" do
+                get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png"
+
+                expect(response.status).to eq(200)
+              end
+            end
+          end
+
+          context "when the user doesn't have access to the project" do
+            it "responds with status 404" do
+              get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png"
+
+              expect(response.status).to eq(404)
+            end
+          end
+        end
+      end
+    end
+
+    context "when viewing a note attachment" do
+      let!(:note) { create(:note, :with_attachment) }
+      let(:project) { note.project }
+
+      context "when the project is public" do
+        before do
+          project.update_attribute(:visibility_level, Project::PUBLIC)
+        end
+
+        context "when not signed in" do
+          it "responds with status 200" do
+            get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png"
+
+            expect(response.status).to eq(200)
+          end
+        end
+
+        context "when signed in" do
+          before do
+            sign_in(user)
+          end
+
+          it "responds with status 200" do
+            get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png"
+
+            expect(response.status).to eq(200)
+          end
+        end
+      end
+
+      context "when the project is private" do
+        before do
+          project.update_attribute(:visibility_level, Project::PRIVATE)
+        end
+
+        context "when not signed in" do
+          it "redirects to the sign in page" do
+            get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png"
+
+            expect(response).to redirect_to(new_user_session_path)
+          end
+        end
+
+        context "when signed in" do
+          before do
+            sign_in(user)
+          end
+
+          context "when the user has access to the project" do
+            before do
+              project.team << [user, :master]
+            end
+
+            context "when the user is blocked" do
+              before do
+                user.block
+                project.team << [user, :master]
+              end
+
+              it "redirects to the sign in page" do
+                get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png"
+
+                expect(response).to redirect_to(new_user_session_path)
+              end
+            end
+
+            context "when the user isn't blocked" do
+              it "responds with status 200" do
+                get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png"
+
+                expect(response.status).to eq(200)
+              end
+            end
+          end
+
+          context "when the user doesn't have access to the project" do
+            it "responds with status 404" do
+              get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png"
+
+              expect(response.status).to eq(404)
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d47a37914df78f8135fe66c08d92d61667e3587e
--- /dev/null
+++ b/spec/controllers/users_controller_spec.rb
@@ -0,0 +1,46 @@
+require 'spec_helper'
+
+describe UsersController do
+  let(:user)    { create(:user, username: 'user1', name: 'User 1', email: 'user1@gitlab.com') }
+
+  before do
+    sign_in(user)
+  end
+
+  describe 'GET #show' do
+    render_views
+
+    it 'renders the show template' do
+      get :show, username: user.username
+      expect(response.status).to eq(200)
+      expect(response).to render_template('show')
+    end
+  end
+
+  describe 'GET #calendar' do
+    it 'renders calendar' do
+      get :calendar, username: user.username
+      expect(response).to render_template('calendar')
+    end
+  end
+
+  describe 'GET #calendar_activities' do
+    let!(:project) { create(:project) }
+    let!(:user) { create(:user) }
+
+    before do
+      allow_any_instance_of(User).to receive(:contributed_projects_ids).and_return([project.id])
+      project.team << [user, :developer]
+    end
+
+    it 'assigns @calendar_date' do
+      get :calendar_activities, username: user.username, date: '2014-07-31'
+      expect(assigns(:calendar_date)).to eq(Date.parse('2014-07-31'))
+    end
+
+    it 'renders calendar_activities' do
+      get :calendar_activities, username: user.username
+      expect(response).to render_template('calendar_activities')
+    end
+  end
+end
diff --git a/spec/factories.rb b/spec/factories.rb
index 15899d8c3c47097de68576da3bad3978b0f629d1..fc103e5b1332b00a7833c4d9115a2c3f0d4dfdf1 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -5,10 +5,14 @@ FactoryGirl.define do
     Faker::Lorem.sentence
   end
 
-  sequence :name, aliases: [:file_name] do
+  sequence :name do
     Faker::Name.name
   end
 
+  sequence :file_name do
+    Faker::Internet.user_name
+  end
+
   sequence(:url) { Faker::Internet.uri('http') }
 
   factory :user, aliases: [:author, :assignee, :owner, :creator] do
@@ -16,7 +20,6 @@ FactoryGirl.define do
     name
     sequence(:username) { |n| "#{Faker::Internet.user_name}#{n}" }
     password "12345678"
-    password_confirmation { password }
     confirmed_at { Time.now }
     confirmation_token { nil }
 
@@ -24,9 +27,18 @@ FactoryGirl.define do
       admin true
     end
 
-    trait :ldap do
-      provider 'ldapmain'
-      extern_uid 'my-ldap-id'
+    factory :omniauth_user do
+      ignore do
+        extern_uid '123456'
+        provider 'ldapmain'
+      end
+
+      after(:create) do |user, evaluator|
+        user.identities << create(:identity,
+          provider: evaluator.provider,
+          extern_uid: evaluator.extern_uid
+        )
+      end
     end
 
     factory :admin, traits: [:admin]
@@ -182,4 +194,9 @@ FactoryGirl.define do
     deploy_key
     project
   end
+
+  factory :identity do
+    provider 'ldapmain'
+    extern_uid 'my-ldap-id'
+  end
 end
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index 0ae8ea5f878961e46f01e9fc7472b15d84893071..77cd37c22d93c0c85d7cf2fcfacca2d392396667 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -18,6 +18,7 @@
 #  iid               :integer
 #  description       :text
 #  position          :integer          default(0)
+#  locked_at         :datetime
 #
 
 FactoryGirl.define do
@@ -39,7 +40,7 @@ FactoryGirl.define do
     source_branch "master"
     target_branch "feature"
 
-    merge_status :can_be_merged
+    merge_status "can_be_merged"
 
     trait :with_diffs do
     end
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index 83d0cc62dbf9d5b86269264b7f22290f3714c752..f1c33461b55ee93bc294c4be19ed93f0154c49ef 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -30,6 +30,7 @@ FactoryGirl.define do
     factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note]
     factory :note_on_merge_request, traits: [:on_merge_request]
     factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff]
+    factory :note_on_project_snippet, traits: [:on_project_snippet]
 
     trait :on_commit do
       project factory: :project
@@ -52,6 +53,11 @@ FactoryGirl.define do
       noteable_type "Issue"
     end
 
+    trait :on_project_snippet do
+      noteable_id 1
+      noteable_type "Snippet"
+    end
+
     trait :with_attachment do
       attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "`/png") }
     end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 23314b3b1a4ac3129a04e89f043d3c89557d4870..0899a7603fcec5b2ffef6c0358e588268298700e 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -24,9 +24,16 @@
 #  import_status          :string(255)
 #  repository_size        :float            default(0.0)
 #  star_count             :integer          default(0), not null
+#  import_type            :string(255)
+#  import_source          :string(255)
+#  avatar                 :string(255)
 #
 
 FactoryGirl.define do
+  # Project without repository
+  #
+  # Project does not have bare repository.
+  # Use this factory if you dont need repository in tests
   factory :empty_project, class: 'Project' do
     sequence(:name) { |n| "project#{n}" }
     path { name.downcase.gsub(/\s/, '_') }
@@ -47,6 +54,20 @@ FactoryGirl.define do
     end
   end
 
+  # Project with empty repository
+  #
+  # This is a case when you just created a project
+  # but not pushed any code there yet
+  factory :project_empty_repo, parent: :empty_project do
+    after :create do |project|
+      project.create_repository
+    end
+  end
+
+  # Project with test repository
+  #
+  # Test repository source can be found at
+  # https://gitlab.com/gitlab-org/gitlab-test
   factory :project, parent: :empty_project do
     path { 'gitlabhq' }
 
@@ -56,7 +77,19 @@ FactoryGirl.define do
   end
 
   factory :redmine_project, parent: :project do
-    issues_tracker { "redmine" }
-    issues_tracker_id { "project_name_in_redmine" }
+    after :create do |project|
+      project.create_redmine_service(
+        active: true,
+        properties: {
+          'project_url' => 'http://redmine/projects/project_name_in_redmine',
+          'issues_url' => "http://redmine/#{project.id}/project_name_in_redmine/:id",
+          'new_issue_url' => 'http://redmine/projects/project_name_in_redmine/issues/new'
+        }
+      )
+    end
+    after :create do |project|
+      project.issues_tracker = 'redmine'
+      project.issues_tracker_id = 'project_name_in_redmine'
+    end
   end
 end
diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb
index 66bef0761c7329aae813d4d18e0bb5bd79e1ba90..c8e218d4d037459977b7dcd4616bd1909dc24c8b 100644
--- a/spec/factories_spec.rb
+++ b/spec/factories_spec.rb
@@ -9,7 +9,7 @@ FactoryGirl.factories.map(&:name).each do |factory_name|
   next if INVALID_FACTORIES.include?(factory_name)
   describe "#{factory_name} factory" do
     it 'should be valid' do
-      build(factory_name).should be_valid
+      expect(build(factory_name)).to be_valid
     end
   end
 end
diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb
index b557567bd047080cb8ef0dbbd755d735e619c014..25862614d2849e734a96ee8ef00e376fbe436763 100644
--- a/spec/features/admin/admin_hooks_spec.rb
+++ b/spec/features/admin/admin_hooks_spec.rb
@@ -12,15 +12,15 @@ describe "Admin::Hooks", feature: true do
   describe "GET /admin/hooks" do
     it "should be ok" do
       visit admin_root_path
-      within ".main-nav" do
+      within ".sidebar-wrapper" do
         click_on "Hooks"
       end
-      current_path.should == admin_hooks_path
+      expect(current_path).to eq(admin_hooks_path)
     end
 
     it "should have hooks list" do
       visit admin_hooks_path
-      page.should have_content(@system_hook.url)
+      expect(page).to have_content(@system_hook.url)
     end
   end
 
@@ -33,8 +33,8 @@ describe "Admin::Hooks", feature: true do
     end
 
     it "should open new hook popup" do
-      current_path.should == admin_hooks_path
-      page.should have_content(@url)
+      expect(current_path).to eq(admin_hooks_path)
+      expect(page).to have_content(@url)
     end
   end
 
@@ -45,7 +45,7 @@ describe "Admin::Hooks", feature: true do
       click_link "Test Hook"
     end
 
-    it { current_path.should == admin_hooks_path }
+    it { expect(current_path).to eq(admin_hooks_path) }
   end
 
 end
diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb
index 3b3d027ab75c6f440fcc017f8c4c97c4f2c3abb1..101d955d693c74d1ee29497fa0df828b03c37560 100644
--- a/spec/features/admin/admin_projects_spec.rb
+++ b/spec/features/admin/admin_projects_spec.rb
@@ -8,27 +8,27 @@ describe "Admin::Projects", feature: true  do
 
   describe "GET /admin/projects" do
     before do
-      visit admin_projects_path
+      visit admin_namespaces_projects_path
     end
 
     it "should be ok" do
-      current_path.should == admin_projects_path
+      expect(current_path).to eq(admin_namespaces_projects_path)
     end
 
     it "should have projects list" do
-      page.should have_content(@project.name)
+      expect(page).to have_content(@project.name)
     end
   end
 
   describe "GET /admin/projects/:id" do
     before do
-      visit admin_projects_path
+      visit admin_namespaces_projects_path
       click_link "#{@project.name}"
     end
 
     it "should have project info" do
-      page.should have_content(@project.path)
-      page.should have_content(@project.name)
+      expect(page).to have_content(@project.path)
+      expect(page).to have_content(@project.name)
     end
   end
 end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 82da19746f8618274e6825be36599de28e1bc8c1..f97b69713ceca6862bacafa3729342fa99a6fc78 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -9,12 +9,12 @@ describe "Admin::Users", feature: true  do
     end
 
     it "should be ok" do
-      current_path.should == admin_users_path
+      expect(current_path).to eq(admin_users_path)
     end
 
     it "should have users list" do
-      page.should have_content(@user.email)
-      page.should have_content(@user.name)
+      expect(page).to have_content(@user.email)
+      expect(page).to have_content(@user.name)
     end
   end
 
@@ -32,31 +32,33 @@ describe "Admin::Users", feature: true  do
 
     it "should apply defaults to user" do
       click_button "Create user"
-      user = User.last
-      user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
-      user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+      user = User.find_by(username: 'bang')
+      expect(user.projects_limit).
+        to eq(Gitlab.config.gitlab.default_projects_limit)
+      expect(user.can_create_group).
+        to eq(Gitlab.config.gitlab.default_can_create_group)
     end
 
     it "should create user with valid data" do
       click_button "Create user"
-      user = User.last
-      user.name.should ==  "Big Bang"
-      user.email.should == "bigbang@mail.com"
+      user = User.find_by(username: 'bang')
+      expect(user.name).to eq('Big Bang')
+      expect(user.email).to eq('bigbang@mail.com')
     end
 
     it "should call send mail" do
-      Notify.should_receive(:new_user_email)
+      expect(Notify).to receive(:new_user_email)
 
       click_button "Create user"
     end
 
     it "should send valid email to user with email & password" do
       click_button "Create user"
-      user = User.last
+      user = User.find_by(username: 'bang')
       email = ActionMailer::Base.deliveries.last
-      email.subject.should have_content("Account was created")
-      email.text_part.body.should have_content(user.email)
-      email.text_part.body.should have_content('password')
+      expect(email.subject).to have_content('Account was created')
+      expect(email.text_part.body).to have_content(user.email)
+      expect(email.text_part.body).to have_content('password')
     end
   end
 
@@ -67,8 +69,8 @@ describe "Admin::Users", feature: true  do
     end
 
     it "should have user info" do
-      page.should have_content(@user.email)
-      page.should have_content(@user.name)
+      expect(page).to have_content(@user.email)
+      expect(page).to have_content(@user.name)
     end
   end
 
@@ -80,8 +82,8 @@ describe "Admin::Users", feature: true  do
     end
 
     it "should have user edit page" do
-      page.should have_content("Name")
-      page.should have_content("Password")
+      expect(page).to have_content('Name')
+      expect(page).to have_content('Password')
     end
 
     describe "Update user" do
@@ -93,14 +95,14 @@ describe "Admin::Users", feature: true  do
       end
 
       it "should show page with  new data" do
-        page.should have_content("bigbang@mail.com")
-        page.should have_content("Big Bang")
+        expect(page).to have_content('bigbang@mail.com')
+        expect(page).to have_content('Big Bang')
       end
 
       it "should change user entry" do
         @simple_user.reload
-        @simple_user.name.should == "Big Bang"
-        @simple_user.is_admin?.should be_true
+        expect(@simple_user.name).to eq('Big Bang')
+        expect(@simple_user.is_admin?).to be_truthy
       end
     end
   end
diff --git a/spec/features/admin/security_spec.rb b/spec/features/admin/security_spec.rb
index 21b0d8b965eeff3dae60d04f5c5ecc8a12ae2b15..175fa9d4647fea1de2cbf57b327d7113efef3cc3 100644
--- a/spec/features/admin/security_spec.rb
+++ b/spec/features/admin/security_spec.rb
@@ -2,26 +2,26 @@ require 'spec_helper'
 
 describe "Admin::Projects", feature: true  do
   describe "GET /admin/projects" do
-    subject { admin_projects_path }
+    subject { admin_namespaces_projects_path }
 
-    it { should be_allowed_for :admin }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /admin/users" do
     subject { admin_users_path }
 
-    it { should be_allowed_for :admin }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /admin/hooks" do
     subject { admin_hooks_path }
 
-    it { should be_allowed_for :admin }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 end
diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb
index 187f2ffcffd5ede16143d2eb013c3db3644fc985..b710cb3c72ff33b85d85de20b73bb0d9e954e48f 100644
--- a/spec/features/atom/dashboard_issues_spec.rb
+++ b/spec/features/atom/dashboard_issues_spec.rb
@@ -17,12 +17,13 @@ describe "Dashboard Issues Feed", feature: true  do
       it "should render atom feed via private token" do
         visit issues_dashboard_path(:atom, private_token: user.private_token)
 
-        response_headers['Content-Type'].should have_content("application/atom+xml")
-        body.should have_selector("title", text: "#{user.name} issues")
-        body.should have_selector("author email", text: issue1.author_email)
-        body.should have_selector("entry summary", text: issue1.title)
-        body.should have_selector("author email", text: issue2.author_email)
-        body.should have_selector("entry summary", text: issue2.title)
+        expect(response_headers['Content-Type']).
+          to have_content('application/atom+xml')
+        expect(body).to have_selector('title', text: "#{user.name} issues")
+        expect(body).to have_selector('author email', text: issue1.author_email)
+        expect(body).to have_selector('entry summary', text: issue1.title)
+        expect(body).to have_selector('author email', text: issue2.author_email)
+        expect(body).to have_selector('entry summary', text: issue2.title)
       end
     end
   end
diff --git a/spec/features/atom/dashboard_spec.rb b/spec/features/atom/dashboard_spec.rb
index a7f87906b2ddcbcb8f936da6b25e60ef19de5bf6..ad157d742ff42f4d1fca3453f83daec6eb0cbbbb 100644
--- a/spec/features/atom/dashboard_spec.rb
+++ b/spec/features/atom/dashboard_spec.rb
@@ -2,12 +2,12 @@ require 'spec_helper'
 
 describe "Dashboard Feed", feature: true  do
   describe "GET /" do
-    let!(:user) { create(:user) }
+    let!(:user) { create(:user, name: "Jonh") }
 
     context "projects atom feed via private token" do
       it "should render projects atom feed" do
         visit dashboard_path(:atom, private_token: user.private_token)
-        body.should have_selector("feed title")
+        expect(body).to have_selector('feed title')
       end
     end
 
@@ -24,11 +24,12 @@ describe "Dashboard Feed", feature: true  do
       end
 
       it "should have issue opened event" do
-        body.should have_content("#{user.name} opened issue ##{issue.iid}")
+        expect(body).to have_content("#{user.name} opened issue ##{issue.iid}")
       end
 
       it "should have issue comment event" do
-        body.should have_content("#{user.name} commented on issue ##{issue.iid}")
+        expect(body).
+          to have_content("#{user.name} commented on issue ##{issue.iid}")
       end
     end
   end
diff --git a/spec/features/atom/issues_spec.rb b/spec/features/atom/issues_spec.rb
index 453dca69094cb12573d6cce9de03857f2056aef2..baa7814e96a017ab5cc74ae3c5a5e12586f14ab3 100644
--- a/spec/features/atom/issues_spec.rb
+++ b/spec/features/atom/issues_spec.rb
@@ -1,33 +1,36 @@
 require 'spec_helper'
 
-describe "Issues Feed", feature: true  do
-  describe "GET /issues" do
+describe 'Issues Feed', feature: true  do
+  describe 'GET /issues' do
     let!(:user)     { create(:user) }
     let!(:project)  { create(:project) }
     let!(:issue)    { create(:issue, author: user, project: project) }
 
     before { project.team << [user, :developer] }
 
-    context "when authenticated" do
-      it "should render atom feed" do
+    context 'when authenticated' do
+      it 'should render atom feed' do
         login_with user
-        visit project_issues_path(project, :atom)
+        visit namespace_project_issues_path(project.namespace, project, :atom)
 
-        response_headers['Content-Type'].should have_content("application/atom+xml")
-        body.should have_selector("title", text: "#{project.name} issues")
-        body.should have_selector("author email", text: issue.author_email)
-        body.should have_selector("entry summary", text: issue.title)
+        expect(response_headers['Content-Type']).
+          to have_content('application/atom+xml')
+        expect(body).to have_selector('title', text: "#{project.name} issues")
+        expect(body).to have_selector('author email', text: issue.author_email)
+        expect(body).to have_selector('entry summary', text: issue.title)
       end
     end
 
-    context "when authenticated via private token" do
-      it "should render atom feed" do
-        visit project_issues_path(project, :atom, private_token: user.private_token)
+    context 'when authenticated via private token' do
+      it 'should render atom feed' do
+        visit namespace_project_issues_path(project.namespace, project, :atom,
+                                            private_token: user.private_token)
 
-        response_headers['Content-Type'].should have_content("application/atom+xml")
-        body.should have_selector("title", text: "#{project.name} issues")
-        body.should have_selector("author email", text: issue.author_email)
-        body.should have_selector("entry summary", text: issue.title)
+        expect(response_headers['Content-Type']).
+          to have_content('application/atom+xml')
+        expect(body).to have_selector('title', text: "#{project.name} issues")
+        expect(body).to have_selector('author email', text: issue.author_email)
+        expect(body).to have_selector('entry summary', text: issue.title)
       end
     end
   end
diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..770ac04c2c57f49b68bb9d93e99d3bb41d253a5d
--- /dev/null
+++ b/spec/features/atom/users_spec.rb
@@ -0,0 +1,77 @@
+require 'spec_helper'
+
+describe "User Feed", feature: true  do
+  describe "GET /" do
+    let!(:user) { create(:user) }
+
+    context 'user atom feed via private token' do
+      it "should render user atom feed" do
+        visit user_path(user, :atom, private_token: user.private_token)
+        expect(body).to have_selector('feed title')
+      end
+    end
+
+    context 'feed content' do
+      let(:project) { create(:project) }
+      let(:issue) do
+        create(:issue, project: project,
+               author: user, description: "Houston, we have a bug!\n\n***\n\nI guess.")
+      end
+      let(:note) do
+        create(:note, noteable: issue, author: user,
+               note: 'Bug confirmed :+1:', project: project)
+      end
+      let(:merge_request) do
+        create(:merge_request,
+               title: 'Fix bug', author: user,
+               source_project: project, target_project: project,
+               description: "Here is the fix: ![an image](image.png)")
+      end
+
+      before do
+        project.team << [user, :master]
+        issue_event(issue, user)
+        note_event(note, user)
+        merge_request_event(merge_request, user)
+        visit user_path(user, :atom, private_token: user.private_token)
+      end
+
+      it 'should have issue opened event' do
+        expect(body).to have_content("#{safe_name} opened issue ##{issue.iid}")
+      end
+
+      it 'should have issue comment event' do
+        expect(body).
+          to have_content("#{safe_name} commented on issue ##{issue.iid}")
+      end
+
+      it 'should have XHTML summaries in issue descriptions' do
+        expect(body).to match /we have a bug!<\/p>\n\n<hr ?\/>\n\n<p>I guess/
+      end
+
+      it 'should have XHTML summaries in notes' do
+        expect(body).to match /Bug confirmed <img[^>]*\/>/
+      end
+
+      it 'should have XHTML summaries in merge request descriptions' do
+        expect(body).to match /Here is the fix: <img[^>]*\/>/
+      end
+    end
+  end
+
+  def issue_event(issue, user)
+    EventCreateService.new.open_issue(issue, user)
+  end
+
+  def note_event(note, user)
+    EventCreateService.new.leave_note(note, user)
+  end
+
+  def merge_request_event(request, user)
+    EventCreateService.new.open_mr(request, user)
+  end
+
+  def safe_name
+    html_escape(user.name)
+  end
+end
diff --git a/spec/features/gitlab_flavored_markdown_spec.rb b/spec/features/gitlab_flavored_markdown_spec.rb
index 9f50d1c97384666afbb7d0e8764258596788ae68..fca1a06eb88d3d0ec2dd397a5e95cf9aec723ef6 100644
--- a/spec/features/gitlab_flavored_markdown_spec.rb
+++ b/spec/features/gitlab_flavored_markdown_spec.rb
@@ -23,27 +23,27 @@ describe "GitLab Flavored Markdown", feature: true do
 
   describe "for commits" do
     it "should render title in commits#index" do
-      visit project_commits_path(project, 'master', limit: 1)
+      visit namespace_project_commits_path(project.namespace, project, 'master', limit: 1)
 
-      page.should have_link("##{issue.iid}")
+      expect(page).to have_link("##{issue.iid}")
     end
 
     it "should render title in commits#show" do
-      visit project_commit_path(project, commit)
+      visit namespace_project_commit_path(project.namespace, project, commit)
 
-      page.should have_link("##{issue.iid}")
+      expect(page).to have_link("##{issue.iid}")
     end
 
     it "should render description in commits#show" do
-      visit project_commit_path(project, commit)
+      visit namespace_project_commit_path(project.namespace, project, commit)
 
-      page.should have_link("@#{fred.username}")
+      expect(page).to have_link("@#{fred.username}")
     end
 
     it "should render title in repositories#branches" do
-      visit project_branches_path(project)
+      visit namespace_project_branches_path(project.namespace, project)
 
-      page.should have_link("##{issue.iid}")
+      expect(page).to have_link("##{issue.iid}")
     end
   end
 
@@ -62,21 +62,21 @@ describe "GitLab Flavored Markdown", feature: true do
     end
 
     it "should render subject in issues#index" do
-      visit project_issues_path(project)
+      visit namespace_project_issues_path(project.namespace, project)
 
-      page.should have_link("##{@other_issue.iid}")
+      expect(page).to have_link("##{@other_issue.iid}")
     end
 
     it "should render subject in issues#show" do
-      visit project_issue_path(project, @issue)
+      visit namespace_project_issue_path(project.namespace, project, @issue)
 
-      page.should have_link("##{@other_issue.iid}")
+      expect(page).to have_link("##{@other_issue.iid}")
     end
 
     it "should render details in issues#show" do
-      visit project_issue_path(project, @issue)
+      visit namespace_project_issue_path(project.namespace, project, @issue)
 
-      page.should have_link("@#{fred.username}")
+      expect(page).to have_link("@#{fred.username}")
     end
   end
 
@@ -87,15 +87,15 @@ describe "GitLab Flavored Markdown", feature: true do
     end
 
     it "should render title in merge_requests#index" do
-      visit project_merge_requests_path(project)
+      visit namespace_project_merge_requests_path(project.namespace, project)
 
-      page.should have_link("##{issue.iid}")
+      expect(page).to have_link("##{issue.iid}")
     end
 
     it "should render title in merge_requests#show" do
-      visit project_merge_request_path(project, @merge_request)
+      visit namespace_project_merge_request_path(project.namespace, project, @merge_request)
 
-      page.should have_link("##{issue.iid}")
+      expect(page).to have_link("##{issue.iid}")
     end
   end
 
@@ -109,21 +109,21 @@ describe "GitLab Flavored Markdown", feature: true do
     end
 
     it "should render title in milestones#index" do
-      visit project_milestones_path(project)
+      visit namespace_project_milestones_path(project.namespace, project)
 
-      page.should have_link("##{issue.iid}")
+      expect(page).to have_link("##{issue.iid}")
     end
 
     it "should render title in milestones#show" do
-      visit project_milestone_path(project, @milestone)
+      visit namespace_project_milestone_path(project.namespace, project, @milestone)
 
-      page.should have_link("##{issue.iid}")
+      expect(page).to have_link("##{issue.iid}")
     end
 
     it "should render description in milestones#show" do
-      visit project_milestone_path(project, @milestone)
+      visit namespace_project_milestone_path(project.namespace, project, @milestone)
 
-      page.should have_link("@#{fred.username}")
+      expect(page).to have_link("@#{fred.username}")
     end
   end
 end
diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..41088ce8271922233d38e1fcf24e49081e8aa8a5
--- /dev/null
+++ b/spec/features/help_pages_spec.rb
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe 'Help Pages', feature: true do
+  describe 'Show SSH page' do
+    before do
+      login_as :user
+    end
+    it 'replace the variable $your_email with the email of the user' do
+      visit help_page_path(category: 'ssh', file: 'README.md')
+      expect(page).to have_content("ssh-keygen -t rsa -C \"#{@user.email}\"")
+    end
+  end
+end
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 26607b0090c34bd427a8291fc7674898f7ab5609..e5f33d5a25acba8971b86f6cdbe7240875a43898 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -1,6 +1,8 @@
 require 'spec_helper'
 
-describe "Issues", feature: true do
+describe 'Issues', feature: true do
+  include SortingHelper
+
   let(:project) { create(:project) }
 
   before do
@@ -10,7 +12,7 @@ describe "Issues", feature: true do
     project.team << [[@user, user2], :developer]
   end
 
-  describe "Edit issue" do
+  describe 'Edit issue' do
     let!(:issue) do
       create(:issue,
              author: @user,
@@ -19,34 +21,38 @@ describe "Issues", feature: true do
     end
 
     before do
-      visit project_issues_path(project)
+      visit namespace_project_issues_path(project.namespace, project)
       click_link "Edit"
     end
 
-    it "should open new issue popup" do
-      page.should have_content("Issue ##{issue.iid}")
+    it 'should open new issue popup' do
+      expect(page).to have_content("Issue ##{issue.iid}")
     end
 
-    describe "fill in" do
+    describe 'fill in' do
       before do
-        fill_in "issue_title", with: "bug 345"
-        fill_in "issue_description", with: "bug description"
+        fill_in 'issue_title', with: 'bug 345'
+        fill_in 'issue_description', with: 'bug description'
       end
 
-      it { expect { click_button "Save changes" }.to_not change {Issue.count} }
+      it 'does not change issue count' do
+        expect {
+          click_button 'Save changes'
+        }.to_not change { Issue.count }
+      end
 
-      it "should update issue fields" do
-        click_button "Save changes"
+      it 'should update issue fields' do
+        click_button 'Save changes'
 
-        page.should have_content @user.name
-        page.should have_content "bug 345"
-        page.should have_content project.name
+        expect(page).to have_content @user.name
+        expect(page).to have_content 'bug 345'
+        expect(page).to have_content project.name
       end
     end
 
   end
 
-  describe "Editing issue assignee" do
+  describe 'Editing issue assignee' do
     let!(:issue) do
       create(:issue,
              author: @user,
@@ -54,23 +60,23 @@ describe "Issues", feature: true do
              project: project)
     end
 
-    it 'allows user to select unasigned', :js => true do
-      visit edit_project_issue_path(project, issue)
+    it 'allows user to select unasigned', js: true do
+      visit edit_namespace_project_issue_path(project.namespace, project, issue)
 
-      page.should have_content "Assign to #{@user.name}"
+      expect(page).to have_content "Assign to #{@user.name}"
 
       first('#s2id_issue_assignee_id').click
       sleep 2 # wait for ajax stuff to complete
       first('.user-result').click
 
-      click_button "Save changes"
+      click_button 'Save changes'
 
-      page.should have_content "Assignee: Select assignee"
-      issue.reload.assignee.should be_nil
+      expect(page).to have_content 'Assignee: none'
+      expect(issue.reload.assignee).to be_nil
     end
   end
 
-  describe "Filter issue" do
+  describe 'Filter issue' do
     before do
       ['foobar', 'barbaz', 'gitlab'].each do |title|
         create(:issue,
@@ -80,7 +86,7 @@ describe "Issues", feature: true do
                title: title)
       end
 
-      @issue = Issue.first # with title 'foobar'
+      @issue = Issue.find_by(title: 'foobar')
       @issue.milestone = create(:milestone, project: project)
       @issue.assignee = nil
       @issue.save
@@ -88,75 +94,79 @@ describe "Issues", feature: true do
 
     let(:issue) { @issue }
 
-    it "should allow filtering by issues with no specified milestone" do
-      visit project_issues_path(project, milestone_id: '0')
+    it 'should allow filtering by issues with no specified milestone' do
+      visit namespace_project_issues_path(project.namespace, project, milestone_id: IssuableFinder::NONE)
 
-      page.should_not have_content 'foobar'
-      page.should have_content 'barbaz'
-      page.should have_content 'gitlab'
+      expect(page).not_to have_content 'foobar'
+      expect(page).to have_content 'barbaz'
+      expect(page).to have_content 'gitlab'
     end
 
-    it "should allow filtering by a specified milestone" do
-      visit project_issues_path(project, milestone_id: issue.milestone.id)
+    it 'should allow filtering by a specified milestone' do
+      visit namespace_project_issues_path(project.namespace, project, milestone_id: issue.milestone.id)
 
-      page.should have_content 'foobar'
-      page.should_not have_content 'barbaz'
-      page.should_not have_content 'gitlab'
+      expect(page).to have_content 'foobar'
+      expect(page).not_to have_content 'barbaz'
+      expect(page).not_to have_content 'gitlab'
     end
 
-    it "should allow filtering by issues with no specified assignee" do
-      visit project_issues_path(project, assignee_id: '0')
+    it 'should allow filtering by issues with no specified assignee' do
+      visit namespace_project_issues_path(project.namespace, project, assignee_id: IssuableFinder::NONE)
 
-      page.should have_content 'foobar'
-      page.should_not have_content 'barbaz'
-      page.should_not have_content 'gitlab'
+      expect(page).to have_content 'foobar'
+      expect(page).not_to have_content 'barbaz'
+      expect(page).not_to have_content 'gitlab'
     end
 
-    it "should allow filtering by a specified assignee" do
-      visit project_issues_path(project, assignee_id: @user.id)
+    it 'should allow filtering by a specified assignee' do
+      visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id)
 
-      page.should_not have_content 'foobar'
-      page.should have_content 'barbaz'
-      page.should have_content 'gitlab'
+      expect(page).not_to have_content 'foobar'
+      expect(page).to have_content 'barbaz'
+      expect(page).to have_content 'gitlab'
     end
   end
 
   describe 'filter issue' do
     titles = ['foo','bar','baz']
     titles.each_with_index do |title, index|
-      let!(title.to_sym) { create(:issue, title: title, project: project, created_at: Time.now - (index * 60)) }
+      let!(title.to_sym) do
+        create(:issue, title: title,
+                       project: project,
+                       created_at: Time.now - (index * 60))
+      end
     end
     let(:newer_due_milestone) { create(:milestone, due_date: '2013-12-11') }
     let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') }
 
     it 'sorts by newest' do
-      visit project_issues_path(project, sort: 'newest')
+      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_created)
 
-      first_issue.should include("foo")
-      last_issue.should include("baz")
+      expect(first_issue).to include('foo')
+      expect(last_issue).to include('baz')
     end
 
     it 'sorts by oldest' do
-      visit project_issues_path(project, sort: 'oldest')
+      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_oldest_created)
 
-      first_issue.should include("baz")
-      last_issue.should include("foo")
+      expect(first_issue).to include('baz')
+      expect(last_issue).to include('foo')
     end
 
     it 'sorts by most recently updated' do
       baz.updated_at = Time.now + 100
       baz.save
-      visit project_issues_path(project, sort: 'recently_updated')
+      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_updated)
 
-      first_issue.should include("baz")
+      expect(first_issue).to include('baz')
     end
 
     it 'sorts by least recently updated' do
       baz.updated_at = Time.now - 100
       baz.save
-      visit project_issues_path(project, sort: 'last_updated')
+      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_oldest_updated)
 
-      first_issue.should include("baz")
+      expect(first_issue).to include('baz')
     end
 
     describe 'sorting by milestone' do
@@ -168,15 +178,15 @@ describe "Issues", feature: true do
       end
 
       it 'sorts by recently due milestone' do
-        visit project_issues_path(project, sort: 'milestone_due_soon')
+        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_soon)
 
-        first_issue.should include("foo")
+        expect(first_issue).to include('foo')
       end
 
       it 'sorts by least recently due milestone' do
-        visit project_issues_path(project, sort: 'milestone_due_later')
+        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_later)
 
-        first_issue.should include("bar")
+        expect(first_issue).to include('bar')
       end
     end
 
@@ -191,11 +201,13 @@ describe "Issues", feature: true do
       end
 
       it 'sorts with a filter applied' do
-        visit project_issues_path(project, sort: 'oldest', assignee_id: user2.id)
+        visit namespace_project_issues_path(project.namespace, project,
+                                            sort: sort_value_oldest_created,
+                                            assignee_id: user2.id)
 
-        first_issue.should include("bar")
-        last_issue.should include("foo")
-        page.should_not have_content 'baz'
+        expect(first_issue).to include('bar')
+        expect(last_issue).to include('foo')
+        expect(page).not_to have_content 'baz'
       end
     end
   end
@@ -206,13 +218,15 @@ describe "Issues", feature: true do
     context 'by autorized user' do
 
       it 'with dropdown menu' do
-        visit project_issue_path(project, issue)
+        visit namespace_project_issue_path(project.namespace, project, issue)
 
-        find('.edit-issue.inline-update #issue_assignee_id').set project.team.members.first.id
+        find('.edit-issue.inline-update #issue_assignee_id').
+          set project.team.members.first.id
         click_button 'Update Issue'
 
-        page.should have_content "Assignee:"
-        has_select?('issue_assignee_id', :selected => project.team.members.first.name)
+        expect(page).to have_content 'Assignee:'
+        has_select?('issue_assignee_id',
+                    selected: project.team.members.first.name)
       end
     end
 
@@ -226,12 +240,12 @@ describe "Issues", feature: true do
         issue.save
       end
 
-      it "shows assignee text", js: true do
+      it 'shows assignee text', js: true do
         logout
         login_with guest
 
-        visit project_issue_path(project, issue)
-        page.should have_content issue.assignee.name
+        visit namespace_project_issue_path(project.namespace, project, issue)
+        expect(page).to have_content issue.assignee.name
       end
     end
   end
@@ -243,13 +257,15 @@ describe "Issues", feature: true do
     context 'by authorized user' do
 
       it 'with dropdown menu' do
-        visit project_issue_path(project, issue)
+        visit namespace_project_issue_path(project.namespace, project, issue)
 
-        find('.edit-issue.inline-update').select(milestone.title, from: 'issue_milestone_id')
+        find('.edit-issue.inline-update').
+          select(milestone.title, from: 'issue_milestone_id')
         click_button 'Update Issue'
 
-        page.should have_content "Milestone changed to #{milestone.title}"
-        has_select?('issue_assignee_id', :selected => milestone.title)
+        expect(page).to have_content "Milestone changed to #{milestone.title}"
+        expect(page).to have_content "Milestone: #{milestone.title}"
+        has_select?('issue_assignee_id', selected: milestone.title)
       end
     end
 
@@ -262,12 +278,12 @@ describe "Issues", feature: true do
         issue.save
       end
 
-      it "shows milestone text", js: true do
+      it 'shows milestone text', js: true do
         logout
         login_with guest
 
-        visit project_issue_path(project, issue)
-        page.should have_content milestone.title
+        visit namespace_project_issue_path(project.namespace, project, issue)
+        expect(page).to have_content milestone.title
       end
     end
 
@@ -280,25 +296,25 @@ describe "Issues", feature: true do
       end
 
       it 'allows user to remove assignee', :js => true do
-        visit project_issue_path(project, issue)
-        page.should have_content "Assignee: #{user2.name}"
+        visit namespace_project_issue_path(project.namespace, project, issue)
+        expect(page).to have_content "Assignee: #{user2.name}"
 
         first('#s2id_issue_assignee_id').click
         sleep 2 # wait for ajax stuff to complete
         first('.user-result').click
 
-        page.should have_content "Assignee: Unassigned"
+        expect(page).to have_content 'Assignee: none'
         sleep 2 # wait for ajax stuff to complete
-        issue.reload.assignee.should be_nil
+        expect(issue.reload.assignee).to be_nil
       end
     end
   end
 
   def first_issue
-    all("ul.issues-list li").first.text
+    all('ul.issues-list li').first.text
   end
 
   def last_issue
-    all("ul.issues-list li").last.text
+    all('ul.issues-list li').last.text
   end
 end
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index 92f3a6c0929524ef942273303166a1561713402d..c47368b1fdaa13ff39c3e1740a443be7a12a11ec 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -3,197 +3,213 @@ require 'spec_helper'
 describe 'Comments' do
   include RepoHelpers
 
-  describe "On a merge request", js: true, feature: true do
+  describe 'On a merge request', js: true, feature: true do
     let!(:merge_request) { create(:merge_request) }
     let!(:project) { merge_request.source_project }
-    let!(:note) { create(:note_on_merge_request, :with_attachment, project: project) }
+    let!(:note) do
+      create(:note_on_merge_request, :with_attachment, project: project)
+    end
 
     before do
       login_as :admin
-      visit project_merge_request_path(project, merge_request)
+      visit namespace_project_merge_request_path(project.namespace, project, merge_request)
     end
 
     subject { page }
 
-    describe "the note form" do
+    describe 'the note form' do
       it 'should be valid' do
-        should have_css(".js-main-target-form", visible: true, count: 1)
-        find(".js-main-target-form input[type=submit]").value.should == "Add Comment"
-        within(".js-main-target-form") { should_not have_link("Cancel") }
-        within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) }
+        is_expected.to have_css('.js-main-target-form', visible: true, count: 1)
+        expect(find('.js-main-target-form input[type=submit]').value).
+          to eq('Add Comment')
+        within('.js-main-target-form') do
+          expect(page).not_to have_link('Cancel')
+        end
       end
 
-      describe "with text" do
+      describe 'with text' do
         before do
-          within(".js-main-target-form") do
-            fill_in "note[note]", with: "This is awesome"
+          within('.js-main-target-form') do
+            fill_in 'note[note]', with: 'This is awesome'
           end
         end
 
         it 'should have enable submit button and preview button' do
-          within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") }
-          within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) }
+          within('.js-main-target-form') do
+            expect(page).not_to have_css('.js-comment-button[disabled]')
+            expect(page).to have_css('.js-md-preview-button', visible: true)
+          end
         end
       end
     end
 
-    describe "when posting a note" do
+    describe 'when posting a note' do
       before do
-        within(".js-main-target-form") do
-          fill_in "note[note]", with: "This is awsome!"
-          find(".js-note-preview-button").trigger("click")
-          click_button "Add Comment"
+        within('.js-main-target-form') do
+          fill_in 'note[note]', with: 'This is awsome!'
+          find('.js-md-preview-button').click
+          click_button 'Add Comment'
         end
       end
 
       it 'should be added and form reset' do
-        should have_content("This is awsome!")
-        within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") }
-        within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) }
-        within(".js-main-target-form") { should have_css(".js-note-text", visible: true) }
+        is_expected.to have_content('This is awsome!')
+        within('.js-main-target-form') do
+          expect(page).to have_no_field('note[note]', with: 'This is awesome!')
+          expect(page).to have_css('.js-md-preview', visible: :hidden)
+        end
+        within('.js-main-target-form') do
+          is_expected.to have_css('.js-note-text', visible: true)
+        end
       end
     end
 
-    describe "when editing a note", js: true do
-      it "should contain the hidden edit form" do
-        within("#note_#{note.id}") { should have_css(".note-edit-form", visible: false) }
+    describe 'when editing a note', js: true do
+      it 'should contain the hidden edit form' do
+        within("#note_#{note.id}") do
+          is_expected.to have_css('.note-edit-form', visible: false)
+        end
       end
 
-      describe "editing the note" do
+      describe 'editing the note' do
         before do
           find('.note').hover
           find(".js-note-edit").click
         end
 
-        it "should show the note edit form and hide the note body" do
+        it 'should show the note edit form and hide the note body' do
           within("#note_#{note.id}") do
-            find(".note-edit-form", visible: true).should be_visible
-            find(".note-text", visible: false).should_not be_visible
-          end
-        end
-
-        it "should reset the edit note form textarea with the original content of the note if cancelled" do
-          find('.note').hover
-          find(".js-note-edit").click
-
-          within(".note-edit-form") do
-            fill_in "note[note]", with: "Some new content"
-            find(".btn-cancel").click
-            find(".js-note-text", visible: false).text.should == note.note
+            expect(find('.current-note-edit-form', visible: true)).to be_visible
+            expect(find('.note-edit-form', visible: true)).to be_visible
+            expect(find(:css, '.note-body > .note-text', visible: false)).not_to be_visible
           end
         end
 
-        it "appends the edited at time to the note" do
-          find('.note').hover
-          find(".js-note-edit").click
-
-          within(".note-edit-form") do
-            fill_in "note[note]", with: "Some new content"
-            find(".btn-save").click
+        # TODO: fix after 7.7 release
+        #it "should reset the edit note form textarea with the original content of the note if cancelled" do
+          #within(".current-note-edit-form") do
+            #fill_in "note[note]", with: "Some new content"
+            #find(".btn-cancel").click
+            #find(".js-note-text", visible: false).text.should == note.note
+          #end
+        #end
+
+        it 'appends the edited at time to the note' do
+          within('.current-note-edit-form') do
+            fill_in 'note[note]', with: 'Some new content'
+            find('.btn-save').click
           end
 
           within("#note_#{note.id}") do
-            should have_css(".note-last-update small")
-            find(".note-last-update small").text.should match(/Edited less than a minute ago/)
+            is_expected.to have_css('.note_edited_ago')
+            expect(find('.note_edited_ago').text).
+              to match(/less than a minute ago/)
           end
         end
       end
 
-      describe "deleting an attachment" do
+      describe 'deleting an attachment' do
         before do
           find('.note').hover
-          find(".js-note-edit").click
+          find('.js-note-edit').click
         end
 
-        it "shows the delete link" do
-          within(".note-attachment") do
-            should have_css(".js-note-attachment-delete")
+        it 'shows the delete link' do
+          within('.note-attachment') do
+            is_expected.to have_css('.js-note-attachment-delete')
           end
         end
 
-        it "removes the attachment div and resets the edit form" do
-          find(".js-note-attachment-delete").click
-          should_not have_css(".note-attachment")
-          find(".note-edit-form", visible: false).should_not be_visible
+        it 'removes the attachment div and resets the edit form' do
+          find('.js-note-attachment-delete').click
+          is_expected.not_to have_css('.note-attachment')
+          expect(find('.current-note-edit-form', visible: false)).
+            not_to be_visible
         end
       end
     end
   end
 
-  describe "On a merge request diff", js: true, feature: true do
+  describe 'On a merge request diff', js: true, feature: true do
     let(:merge_request) { create(:merge_request) }
     let(:project) { merge_request.source_project }
 
     before do
       login_as :admin
-      visit diffs_project_merge_request_path(project, merge_request)
+      visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)
     end
 
     subject { page }
 
-    describe "when adding a note" do
+    describe 'when adding a note' do
       before do
         click_diff_line
       end
 
-      describe "the notes holder" do
-        it { should have_css(".js-temp-notes-holder") }
+      describe 'the notes holder' do
+        it { is_expected.to have_css('.js-temp-notes-holder') }
 
-        it { within(".js-temp-notes-holder") { should have_css(".new_note") } }
+        it 'has .new_note css class' do
+          within('.js-temp-notes-holder') do
+            expect(subject).to have_css('.new_note')
+          end
+        end
       end
 
-      describe "the note form" do
+      describe 'the note form' do
         it "shouldn't add a second form for same row" do
           click_diff_line
 
-          should have_css("tr[id='#{line_code}'] + .js-temp-notes-holder form", count: 1)
+          is_expected.
+            to have_css("tr[id='#{line_code}'] + .js-temp-notes-holder form",
+                        count: 1)
         end
 
-        it "should be removed when canceled" do
+        it 'should be removed when canceled' do
           within(".diff-file form[rel$='#{line_code}']") do
-            find(".js-close-discussion-note-form").trigger("click")
+            find('.js-close-discussion-note-form').trigger('click')
           end
 
-          should have_no_css(".js-temp-notes-holder")
+          is_expected.to have_no_css('.js-temp-notes-holder')
         end
       end
     end
 
-    describe "with muliple note forms" do
+    describe 'with muliple note forms' do
       before do
         click_diff_line
         click_diff_line(line_code_2)
       end
 
-      it { should have_css(".js-temp-notes-holder", count: 2) }
+      it { is_expected.to have_css('.js-temp-notes-holder', count: 2) }
 
-      describe "previewing them separately" do
+      describe 'previewing them separately' do
         before do
           # add two separate texts and trigger previews on both
           within("tr[id='#{line_code}'] + .js-temp-notes-holder") do
-            fill_in "note[note]", with: "One comment on line 7"
-            find(".js-note-preview-button").trigger("click")
+            fill_in 'note[note]', with: 'One comment on line 7'
+            find('.js-md-preview-button').click
           end
           within("tr[id='#{line_code_2}'] + .js-temp-notes-holder") do
-            fill_in "note[note]", with: "Another comment on line 10"
-            find(".js-note-preview-button").trigger("click")
+            fill_in 'note[note]', with: 'Another comment on line 10'
+            find('.js-md-preview-button').click
           end
         end
       end
 
-      describe "posting a note" do
+      describe 'posting a note' do
         before do
           within("tr[id='#{line_code_2}'] + .js-temp-notes-holder") do
-            fill_in "note[note]", with: "Another comment on line 10"
-            click_button("Add Comment")
+            fill_in 'note[note]', with: 'Another comment on line 10'
+            click_button('Add Comment')
           end
         end
 
         it 'should be added as discussion' do
-          should have_content("Another comment on line 10")
-          should have_css(".notes_holder")
-          should have_css(".notes_holder .note", count: 1)
-          should have_button('Reply')
+          is_expected.to have_content('Another comment on line 10')
+          is_expected.to have_css('.notes_holder')
+          is_expected.to have_css('.notes_holder .note', count: 1)
+          is_expected.to have_button('Reply')
         end
       end
     end
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index bdf7b59114bc787f24948e3f161c5790f0999595..3d36a3c02d043cc989cfc682273d2c5c6b989e2d 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -1,35 +1,35 @@
 require 'spec_helper'
 
-describe "Profile account page", feature: true do
+describe 'Profile account page', feature: true do
   let(:user) { create(:user) }
 
   before do
     login_as :user
   end
 
-  describe "when signup is enabled" do
+  describe 'when signup is enabled' do
     before do
-      Gitlab.config.gitlab.stub(:signup_enabled).and_return(true)
+      ApplicationSetting.any_instance.stub(signup_enabled?: true)
       visit profile_account_path
     end
 
-    it { page.should have_content("Remove account") }
+    it { expect(page).to have_content('Remove account') }
 
-    it "should delete the account" do
-      expect { click_link "Delete account" }.to change {User.count}.by(-1)
-      current_path.should == new_user_session_path
+    it 'should delete the account' do
+      expect { click_link 'Delete account' }.to change { User.count }.by(-1)
+      expect(current_path).to eq(new_user_session_path)
     end
   end
 
-  describe "when signup is disabled" do
+  describe 'when signup is disabled' do
     before do
-      Gitlab.config.gitlab.stub(:signup_enabled).and_return(false)
+      ApplicationSetting.any_instance.stub(signup_enabled?: false)
       visit profile_account_path
     end
 
-    it "should not have option to remove account" do
-      page.should_not have_content("Remove account")
-      current_path.should == profile_account_path
+    it 'should not have option to remove account' do
+      expect(page).not_to have_content('Remove account')
+      expect(current_path).to eq(profile_account_path)
     end
   end
 end
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index d291621935b718f2593a42fa2ff25b9b18c6b36d..cae11be7cdd32b06c30738d919ae1e077e5ba681 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -7,7 +7,7 @@ describe "Projects", feature: true, js: true do
     before do
       @project = create(:project, namespace: @user.namespace)
       @project.team << [@user, :master]
-      visit edit_project_path(@project)
+      visit edit_namespace_project_path(@project.namespace, @project)
     end
 
     it "should remove project" do
diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb
index cce9f06cb690f302a8eaa98f4bf6cd222af1caec..73987739a7a5ea67d08b995bc53d5820fdbabf75 100644
--- a/spec/features/search_spec.rb
+++ b/spec/features/search_spec.rb
@@ -14,7 +14,7 @@ describe "Search", feature: true  do
   end
 
   it "should show project in search results" do
-    page.should have_content @project.name
+    expect(page).to have_content @project.name
   end
 end
 
diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb
index 1cca82cef64316f5fcf92b7030527667e18955a3..67238e3ab76029f1994bb9ddffeed26bb65fc291 100644
--- a/spec/features/security/dashboard_access_spec.rb
+++ b/spec/features/security/dashboard_access_spec.rb
@@ -4,52 +4,60 @@ describe "Dashboard access", feature: true  do
   describe "GET /dashboard" do
     subject { dashboard_path }
 
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /dashboard/issues" do
     subject { issues_dashboard_path }
 
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /dashboard/merge_requests" do
     subject { merge_requests_dashboard_path }
 
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
-  describe "GET /dashboard/projects" do
-    subject { projects_dashboard_path }
+  describe "GET /dashboard/projects/starred" do
+    subject { starred_dashboard_projects_path }
 
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /help" do
     subject { help_path }
 
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /projects/new" do
-    it { new_project_path.should be_allowed_for :admin }
-    it { new_project_path.should be_allowed_for :user }
-    it { new_project_path.should be_denied_for :visitor }
+    it { expect(new_project_path).to be_allowed_for :admin }
+    it { expect(new_project_path).to be_allowed_for :user }
+    it { expect(new_project_path).to be_denied_for :visitor }
   end
 
   describe "GET /groups/new" do
-    it { new_group_path.should be_allowed_for :admin }
-    it { new_group_path.should be_allowed_for :user }
-    it { new_group_path.should be_denied_for :visitor }
+    it { expect(new_group_path).to be_allowed_for :admin }
+    it { expect(new_group_path).to be_allowed_for :user }
+    it { expect(new_group_path).to be_denied_for :visitor }
+  end
+
+  describe "GET /profile/groups" do
+    subject { dashboard_groups_path }
+
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 end
diff --git a/spec/features/security/group/group_access_spec.rb b/spec/features/security/group/group_access_spec.rb
index 44de499e6d2985637219019acd3951546b02e6b4..63793149459ab2b4a01a164628f443ced51d0f06 100644
--- a/spec/features/security/group/group_access_spec.rb
+++ b/spec/features/security/group/group_access_spec.rb
@@ -2,9 +2,9 @@ require 'spec_helper'
 
 describe "Group access", feature: true  do
   describe "GET /projects/new" do
-    it { new_group_path.should be_allowed_for :admin }
-    it { new_group_path.should be_allowed_for :user }
-    it { new_group_path.should be_denied_for :visitor }
+    it { expect(new_group_path).to be_allowed_for :admin }
+    it { expect(new_group_path).to be_allowed_for :user }
+    it { expect(new_group_path).to be_denied_for :visitor }
   end
 
   describe "Group" do
@@ -26,73 +26,73 @@ describe "Group access", feature: true  do
     describe "GET /groups/:path" do
       subject { group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_denied_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
 
     describe "GET /groups/:path/issues" do
       subject { issues_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_denied_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
 
     describe "GET /groups/:path/merge_requests" do
       subject { merge_requests_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_denied_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
 
-    describe "GET /groups/:path/members" do
-      subject { members_group_path(group) }
+    describe "GET /groups/:path/group_members" do
+      subject { group_group_members_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_denied_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
 
     describe "GET /groups/:path/edit" do
       subject { edit_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_denied_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_denied_for master }
+      it { is_expected.to be_denied_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_denied_for guest }
+      it { is_expected.to be_denied_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
 
     describe "GET /groups/:path/projects" do
       subject { projects_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_denied_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_denied_for master }
+      it { is_expected.to be_denied_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_denied_for guest }
+      it { is_expected.to be_denied_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
   end
 end
diff --git a/spec/features/security/group/internal_group_access_spec.rb b/spec/features/security/group/internal_group_access_spec.rb
index da5c6eb4e911811ac6c6feaa07377f7c36075101..d17a7412e43874c3ea826e3520958d20f154b7b7 100644
--- a/spec/features/security/group/internal_group_access_spec.rb
+++ b/spec/features/security/group/internal_group_access_spec.rb
@@ -22,61 +22,61 @@ describe "Group with internal project access", feature: true  do
     describe "GET /groups/:path" do
       subject { group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
 
     describe "GET /groups/:path/issues" do
       subject { issues_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
 
     describe "GET /groups/:path/merge_requests" do
       subject { merge_requests_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
 
-    describe "GET /groups/:path/members" do
-      subject { members_group_path(group) }
+    describe "GET /groups/:path/group_members" do
+      subject { group_group_members_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
 
     describe "GET /groups/:path/edit" do
       subject { edit_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_denied_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_denied_for master }
+      it { is_expected.to be_denied_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_denied_for guest }
+      it { is_expected.to be_denied_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
   end
 end
diff --git a/spec/features/security/group/mixed_group_access_spec.rb b/spec/features/security/group/mixed_group_access_spec.rb
index c9889d99590c2f07febcf00f3b33812f97479fe2..b3db7b5dea4404337e9eba20df6d6a85f9395efd 100644
--- a/spec/features/security/group/mixed_group_access_spec.rb
+++ b/spec/features/security/group/mixed_group_access_spec.rb
@@ -23,61 +23,61 @@ describe "Group access", feature: true  do
     describe "GET /groups/:path" do
       subject { group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_allowed_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_allowed_for :visitor }
     end
 
     describe "GET /groups/:path/issues" do
       subject { issues_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_allowed_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_allowed_for :visitor }
     end
 
     describe "GET /groups/:path/merge_requests" do
       subject { merge_requests_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_allowed_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_allowed_for :visitor }
     end
 
-    describe "GET /groups/:path/members" do
-      subject { members_group_path(group) }
+    describe "GET /groups/:path/group_members" do
+      subject { group_group_members_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_allowed_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_allowed_for :visitor }
     end
 
     describe "GET /groups/:path/edit" do
       subject { edit_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_denied_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_denied_for master }
+      it { is_expected.to be_denied_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_denied_for guest }
+      it { is_expected.to be_denied_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
   end
 end
diff --git a/spec/features/security/group/public_group_access_spec.rb b/spec/features/security/group/public_group_access_spec.rb
index 2e76ab154ff13dec8d7ad65862ccc0657cf9a66f..c16f0c0d1e1d004c7276c426a9f49b01d2b381fb 100644
--- a/spec/features/security/group/public_group_access_spec.rb
+++ b/spec/features/security/group/public_group_access_spec.rb
@@ -22,61 +22,61 @@ describe "Group with public project access", feature: true  do
     describe "GET /groups/:path" do
       subject { group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_allowed_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_allowed_for :visitor }
     end
 
     describe "GET /groups/:path/issues" do
       subject { issues_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_allowed_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_allowed_for :visitor }
     end
 
     describe "GET /groups/:path/merge_requests" do
       subject { merge_requests_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_allowed_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_allowed_for :visitor }
     end
 
-    describe "GET /groups/:path/members" do
-      subject { members_group_path(group) }
+    describe "GET /groups/:path/group_members" do
+      subject { group_group_members_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_allowed_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_allowed_for master }
+      it { is_expected.to be_allowed_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_allowed_for guest }
+      it { is_expected.to be_allowed_for :user }
+      it { is_expected.to be_allowed_for :visitor }
     end
 
     describe "GET /groups/:path/edit" do
       subject { edit_group_path(group) }
 
-      it { should be_allowed_for owner }
-      it { should be_denied_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
+      it { is_expected.to be_allowed_for owner }
+      it { is_expected.to be_denied_for master }
+      it { is_expected.to be_denied_for reporter }
+      it { is_expected.to be_allowed_for :admin }
+      it { is_expected.to be_denied_for guest }
+      it { is_expected.to be_denied_for :user }
+      it { is_expected.to be_denied_for :visitor }
     end
   end
 end
diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb
index 4efc0ffdcd3844a9b1978a60acaa27413cd484a9..2512a9c0e3d414a36f920ab780b22ebaa63a091d 100644
--- a/spec/features/security/profile_access_spec.rb
+++ b/spec/features/security/profile_access_spec.rb
@@ -1,76 +1,65 @@
 require 'spec_helper'
 
-describe "Users Security", feature: true  do
-  describe "Project" do
-    before do
-      @u1 = create(:user)
-    end
-
-    describe "GET /login" do
-      it { new_user_session_path.should_not be_404_for :visitor }
-    end
-
-    describe "GET /profile/keys" do
-      subject { profile_keys_path }
+describe "Profile access", feature: true  do
+  before do
+    @u1 = create(:user)
+  end
 
-      it { should be_allowed_for @u1 }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
+  describe "GET /login" do
+    it { expect(new_user_session_path).not_to be_404_for :visitor }
+  end
 
-    describe "GET /profile" do
-      subject { profile_path }
+  describe "GET /profile/keys" do
+    subject { profile_keys_path }
 
-      it { should be_allowed_for @u1 }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
+    it { is_expected.to be_allowed_for @u1 }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
+  end
 
-    describe "GET /profile/account" do
-      subject { profile_account_path }
+  describe "GET /profile" do
+    subject { profile_path }
 
-      it { should be_allowed_for @u1 }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
+    it { is_expected.to be_allowed_for @u1 }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
+  end
 
-    describe "GET /profile/design" do
-      subject { design_profile_path }
+  describe "GET /profile/account" do
+    subject { profile_account_path }
 
-      it { should be_allowed_for @u1 }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
+    it { is_expected.to be_allowed_for @u1 }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
+  end
 
-    describe "GET /profile/history" do
-      subject { history_profile_path }
+  describe "GET /profile/design" do
+    subject { design_profile_path }
 
-      it { should be_allowed_for @u1 }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
+    it { is_expected.to be_allowed_for @u1 }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
+  end
 
-    describe "GET /profile/notifications" do
-      subject { profile_notifications_path }
+  describe "GET /profile/history" do
+    subject { history_profile_path }
 
-      it { should be_allowed_for @u1 }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
+    it { is_expected.to be_allowed_for @u1 }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
+  end
 
-    describe "GET /profile/groups" do
-      subject { profile_groups_path }
+  describe "GET /profile/notifications" do
+    subject { profile_notifications_path }
 
-      it { should be_allowed_for @u1 }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
+    it { is_expected.to be_allowed_for @u1 }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 end
diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb
index 598d554a946881b21963faead9d56359a08dffa9..8d1bfd2522337eef7eff0a7f7baf9b88755e8ff0 100644
--- a/spec/features/security/project/internal_access_spec.rb
+++ b/spec/features/security/project/internal_access_spec.rb
@@ -18,207 +18,210 @@ describe "Internal Project Access", feature: true  do
   describe "Project should be internal" do
     subject { project }
 
-    its(:internal?) { should be_true }
+    describe '#internal?' do
+      subject { super().internal? }
+      it { is_expected.to be_truthy }
+    end
   end
 
   describe "GET /:project_path" do
-    subject { project_path(project) }
+    subject { namespace_project_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/tree/master" do
-    subject { project_tree_path(project, project.repository.root_ref) }
+    subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/commits/master" do
-    subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
+    subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/commit/:sha" do
-    subject { project_commit_path(project, project.repository.commit) }
+    subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/compare" do
-    subject { project_compare_index_path(project) }
+    subject { namespace_project_compare_index_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
-  describe "GET /:project_path/team" do
-    subject { project_team_index_path(project) }
+  describe "GET /:project_path/project_members" do
+    subject { namespace_project_project_members_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/blob" do
     before do
       commit = project.repository.commit
       path = '.gitignore'
-      @blob_path = project_blob_path(project, File.join(commit.id, path))
+      @blob_path = namespace_project_blob_path(project.namespace, project, File.join(commit.id, path))
     end
 
-    it { @blob_path.should be_allowed_for master }
-    it { @blob_path.should be_allowed_for reporter }
-    it { @blob_path.should be_allowed_for :admin }
-    it { @blob_path.should be_allowed_for guest }
-    it { @blob_path.should be_allowed_for :user }
-    it { @blob_path.should be_denied_for :visitor }
+    it { expect(@blob_path).to be_allowed_for master }
+    it { expect(@blob_path).to be_allowed_for reporter }
+    it { expect(@blob_path).to be_allowed_for :admin }
+    it { expect(@blob_path).to be_allowed_for guest }
+    it { expect(@blob_path).to be_allowed_for :user }
+    it { expect(@blob_path).to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/edit" do
-    subject { edit_project_path(project) }
+    subject { edit_namespace_project_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/deploy_keys" do
-    subject { project_deploy_keys_path(project) }
+    subject { namespace_project_deploy_keys_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/issues" do
-    subject { project_issues_path(project) }
+    subject { namespace_project_issues_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/snippets" do
-    subject { project_snippets_path(project) }
+    subject { namespace_project_snippets_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/snippets/new" do
-    subject { new_project_snippet_path(project) }
+    subject { new_namespace_project_snippet_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/merge_requests" do
-    subject { project_merge_requests_path(project) }
+    subject { namespace_project_merge_requests_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/merge_requests/new" do
-    subject { new_project_merge_request_path(project) }
+    subject { new_namespace_project_merge_request_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/branches" do
-    subject { project_branches_path(project) }
+    subject { namespace_project_branches_path(project.namespace, project) }
 
     before do
       # Speed increase
-      Project.any_instance.stub(:branches).and_return([])
+      allow_any_instance_of(Project).to receive(:branches).and_return([])
     end
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/tags" do
-    subject { project_tags_path(project) }
+    subject { namespace_project_tags_path(project.namespace, project) }
 
     before do
       # Speed increase
-      Project.any_instance.stub(:tags).and_return([])
+      allow_any_instance_of(Project).to receive(:tags).and_return([])
     end
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/hooks" do
-    subject { project_hooks_path(project) }
-
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    subject { namespace_project_hooks_path(project.namespace, project) }
+
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 end
diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb
index b1d4c79e05bd9fb58c7ace0111f178be6a1eee9c..9021ff331868772b533d7485235fd786e1d3ecb7 100644
--- a/spec/features/security/project/private_access_spec.rb
+++ b/spec/features/security/project/private_access_spec.rb
@@ -18,185 +18,188 @@ describe "Private Project Access", feature: true  do
   describe "Project should be private" do
     subject { project }
 
-    its(:private?) { should be_true }
+    describe '#private?' do
+      subject { super().private? }
+      it { is_expected.to be_truthy }
+    end
   end
 
   describe "GET /:project_path" do
-    subject { project_path(project) }
+    subject { namespace_project_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/tree/master" do
-    subject { project_tree_path(project, project.repository.root_ref) }
+    subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/commits/master" do
-    subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
+    subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/commit/:sha" do
-    subject { project_commit_path(project, project.repository.commit) }
+    subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/compare" do
-    subject { project_compare_index_path(project) }
+    subject { namespace_project_compare_index_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
-  describe "GET /:project_path/team" do
-    subject { project_team_index_path(project) }
+  describe "GET /:project_path/project_members" do
+    subject { namespace_project_project_members_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/blob" do
     before do
       commit = project.repository.commit
       path = '.gitignore'
-      @blob_path = project_blob_path(project, File.join(commit.id, path))
+      @blob_path = namespace_project_blob_path(project.namespace, project, File.join(commit.id, path))
     end
 
-    it { @blob_path.should be_allowed_for master }
-    it { @blob_path.should be_allowed_for reporter }
-    it { @blob_path.should be_allowed_for :admin }
-    it { @blob_path.should be_denied_for guest }
-    it { @blob_path.should be_denied_for :user }
-    it { @blob_path.should be_denied_for :visitor }
+    it { expect(@blob_path).to be_allowed_for master }
+    it { expect(@blob_path).to be_allowed_for reporter }
+    it { expect(@blob_path).to be_allowed_for :admin }
+    it { expect(@blob_path).to be_denied_for guest }
+    it { expect(@blob_path).to be_denied_for :user }
+    it { expect(@blob_path).to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/edit" do
-    subject { edit_project_path(project) }
+    subject { edit_namespace_project_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/deploy_keys" do
-    subject { project_deploy_keys_path(project) }
+    subject { namespace_project_deploy_keys_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/issues" do
-    subject { project_issues_path(project) }
+    subject { namespace_project_issues_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/snippets" do
-    subject { project_snippets_path(project) }
+    subject { namespace_project_snippets_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/merge_requests" do
-    subject { project_merge_requests_path(project) }
+    subject { namespace_project_merge_requests_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/branches" do
-    subject { project_branches_path(project) }
+    subject { namespace_project_branches_path(project.namespace, project) }
 
     before do
       # Speed increase
-      Project.any_instance.stub(:branches).and_return([])
+      allow_any_instance_of(Project).to receive(:branches).and_return([])
     end
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/tags" do
-    subject { project_tags_path(project) }
+    subject { namespace_project_tags_path(project.namespace, project) }
 
     before do
       # Speed increase
-      Project.any_instance.stub(:tags).and_return([])
+      allow_any_instance_of(Project).to receive(:tags).and_return([])
     end
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/hooks" do
-    subject { project_hooks_path(project) }
-
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    subject { namespace_project_hooks_path(project.namespace, project) }
+
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 end
diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb
index a4c8a2be25ab2b19b1b1ee3cf8f1a08ead82230c..6ec190ed777e81a323a5c966777eecae8ad991b1 100644
--- a/spec/features/security/project/public_access_spec.rb
+++ b/spec/features/security/project/public_access_spec.rb
@@ -23,207 +23,210 @@ describe "Public Project Access", feature: true  do
   describe "Project should be public" do
     subject { project }
 
-    its(:public?) { should be_true }
+    describe '#public?' do
+      subject { super().public? }
+      it { is_expected.to be_truthy }
+    end
   end
 
   describe "GET /:project_path" do
-    subject { project_path(project) }
+    subject { namespace_project_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_allowed_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :visitor }
   end
 
   describe "GET /:project_path/tree/master" do
-    subject { project_tree_path(project, project.repository.root_ref) }
+    subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_allowed_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :visitor }
   end
 
   describe "GET /:project_path/commits/master" do
-    subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
+    subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_allowed_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :visitor }
   end
 
   describe "GET /:project_path/commit/:sha" do
-    subject { project_commit_path(project, project.repository.commit) }
+    subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_allowed_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :visitor }
   end
 
   describe "GET /:project_path/compare" do
-    subject { project_compare_index_path(project) }
+    subject { namespace_project_compare_index_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_allowed_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :visitor }
   end
 
-  describe "GET /:project_path/team" do
-    subject { project_team_index_path(project) }
+  describe "GET /:project_path/project_members" do
+    subject { namespace_project_project_members_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/blob" do
     before do
       commit = project.repository.commit
       path = '.gitignore'
-      @blob_path = project_blob_path(project, File.join(commit.id, path))
+      @blob_path = namespace_project_blob_path(project.namespace, project, File.join(commit.id, path))
     end
 
-    it { @blob_path.should be_allowed_for master }
-    it { @blob_path.should be_allowed_for reporter }
-    it { @blob_path.should be_allowed_for :admin }
-    it { @blob_path.should be_allowed_for guest }
-    it { @blob_path.should be_allowed_for :user }
-    it { @blob_path.should be_allowed_for :visitor }
+    it { expect(@blob_path).to be_allowed_for master }
+    it { expect(@blob_path).to be_allowed_for reporter }
+    it { expect(@blob_path).to be_allowed_for :admin }
+    it { expect(@blob_path).to be_allowed_for guest }
+    it { expect(@blob_path).to be_allowed_for :user }
+    it { expect(@blob_path).to be_allowed_for :visitor }
   end
 
   describe "GET /:project_path/edit" do
-    subject { edit_project_path(project) }
+    subject { edit_namespace_project_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/deploy_keys" do
-    subject { project_deploy_keys_path(project) }
+    subject { namespace_project_deploy_keys_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/issues" do
-    subject { project_issues_path(project) }
+    subject { namespace_project_issues_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_allowed_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :visitor }
   end
 
   describe "GET /:project_path/snippets" do
-    subject { project_snippets_path(project) }
+    subject { namespace_project_snippets_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_allowed_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :visitor }
   end
 
   describe "GET /:project_path/snippets/new" do
-    subject { new_project_snippet_path(project) }
+    subject { new_namespace_project_snippet_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/merge_requests" do
-    subject { project_merge_requests_path(project) }
+    subject { namespace_project_merge_requests_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_allowed_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :visitor }
   end
 
   describe "GET /:project_path/merge_requests/new" do
-    subject { new_project_merge_request_path(project) }
+    subject { new_namespace_project_merge_request_path(project.namespace, project) }
 
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 
   describe "GET /:project_path/branches" do
-    subject { project_branches_path(project) }
+    subject { namespace_project_branches_path(project.namespace, project) }
 
     before do
       # Speed increase
-      Project.any_instance.stub(:branches).and_return([])
+      allow_any_instance_of(Project).to receive(:branches).and_return([])
     end
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_allowed_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :visitor }
   end
 
   describe "GET /:project_path/tags" do
-    subject { project_tags_path(project) }
+    subject { namespace_project_tags_path(project.namespace, project) }
 
     before do
       # Speed increase
-      Project.any_instance.stub(:tags).and_return([])
+      allow_any_instance_of(Project).to receive(:tags).and_return([])
     end
 
-    it { should be_allowed_for master }
-    it { should be_allowed_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_allowed_for guest }
-    it { should be_allowed_for :user }
-    it { should be_allowed_for :visitor }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :visitor }
   end
 
   describe "GET /:project_path/hooks" do
-    subject { project_hooks_path(project) }
-
-    it { should be_allowed_for master }
-    it { should be_denied_for reporter }
-    it { should be_allowed_for :admin }
-    it { should be_denied_for guest }
-    it { should be_denied_for :user }
-    it { should be_denied_for :visitor }
+    subject { namespace_project_hooks_path(project.namespace, project) }
+
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_denied_for reporter }
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :visitor }
   end
 end
diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb
index a1206989d39fbaf97e6e6c42eae0f32a3beb7cf4..21a3a4bf937c7f90f5c8e8ce6676f93565209c48 100644
--- a/spec/features/users_spec.rb
+++ b/spec/features/users_spec.rb
@@ -1,19 +1,14 @@
 require 'spec_helper'
 
 describe 'Users', feature: true do
-  describe "GET /users/sign_up" do
-    before do
-      Gitlab.config.gitlab.stub(:signup_enabled).and_return(true)
-    end
-
+  describe "GET /users/sign_in" do
     it "should create a new user account" do
-      visit new_user_registration_path
+      visit new_user_session_path
       fill_in "user_name", with: "Name Surname"
       fill_in "user_username", with: "Great"
       fill_in "user_email", with: "name@mail.com"
       fill_in "user_password_sign_up", with: "password1234"
-      fill_in "user_password_confirmation", with: "password1234"
-      expect { click_button "Sign up" }.to change {User.count}.by(1)
+      expect { click_button "Sign up" }.to change { User.count }.by(1)
     end
   end
 end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 7489e56f423e2326996dbdaffbdef3ae7b8c9922..479fa950387abfbb1e8921f71e5b6c3da9a0940d 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -5,9 +5,10 @@ describe IssuesFinder do
   let(:user2) { create :user }
   let(:project1) { create(:project) }
   let(:project2) { create(:project) }
-  let(:issue1) { create(:issue, assignee: user, project: project1) }
-  let(:issue2) { create(:issue, assignee: user, project: project2) }
-  let(:issue3) { create(:issue, assignee: user2, project: project2) }
+  let(:milestone) { create(:milestone, project: project1) }
+  let(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone) }
+  let(:issue2) { create(:issue, author: user, assignee: user, project: project2) }
+  let(:issue3) { create(:issue, author: user2, assignee: user2, project: project2) }
 
   before do
     project1.team << [user, :master]
@@ -22,37 +23,59 @@ describe IssuesFinder do
       issue3
     end
 
-    it 'should filter by all' do
-      params = { scope: "all", state: 'opened' }
-      issues = IssuesFinder.new.execute(user, params)
-      issues.size.should == 3
-    end
+    context 'scope: all' do
+      it 'should filter by all' do
+        params = { scope: "all", state: 'opened' }
+        issues = IssuesFinder.new.execute(user, params)
+        expect(issues.size).to eq(3)
+      end
 
-    it 'should filter by assignee' do
-      params = { scope: "assigned-to-me", state: 'opened' }
-      issues = IssuesFinder.new.execute(user, params)
-      issues.size.should == 2
-    end
+      it 'should filter by assignee id' do
+        params = { scope: "all", assignee_id: user.id, state: 'opened' }
+        issues = IssuesFinder.new.execute(user, params)
+        expect(issues.size).to eq(2)
+      end
 
-    it 'should filter by project' do
-      params = { scope: "assigned-to-me", state: 'opened', project_id: project1.id }
-      issues = IssuesFinder.new.execute(user, params)
-      issues.size.should == 1
-    end
+      it 'should filter by author id' do
+        params = { scope: "all", author_id: user2.id, state: 'opened' }
+        issues = IssuesFinder.new.execute(user, params)
+        expect(issues).to eq([issue3])
+      end
 
-    it 'should be empty for unauthorized user' do
-      params = { scope: "all", state: 'opened' }
-      issues = IssuesFinder.new.execute(nil, params)
-      issues.size.should be_zero
+      it 'should filter by milestone id' do
+        params = { scope: "all", milestone_id: milestone.id, state: 'opened' }
+        issues = IssuesFinder.new.execute(user, params)
+        expect(issues).to eq([issue1])
+      end
+
+      it 'should be empty for unauthorized user' do
+        params = { scope: "all", state: 'opened' }
+        issues = IssuesFinder.new.execute(nil, params)
+        expect(issues.size).to be_zero
+      end
+
+      it 'should not include unauthorized issues' do
+        params = { scope: "all", state: 'opened' }
+        issues = IssuesFinder.new.execute(user2, params)
+        expect(issues.size).to eq(2)
+        expect(issues).not_to include(issue1)
+        expect(issues).to include(issue2)
+        expect(issues).to include(issue3)
+      end
     end
 
-    it 'should not include unauthorized issues' do
-      params = { scope: "all", state: 'opened' }
-      issues = IssuesFinder.new.execute(user2, params)
-      issues.size.should == 2
-      issues.should_not include(issue1)
-      issues.should include(issue2)
-      issues.should include(issue3)
+    context 'personal scope' do
+      it 'should filter by assignee' do
+        params = { scope: "assigned-to-me", state: 'opened' }
+        issues = IssuesFinder.new.execute(user, params)
+        expect(issues.size).to eq(2)
+      end
+
+      it 'should filter by project' do
+        params = { scope: "assigned-to-me", state: 'opened', project_id: project1.id }
+        issues = IssuesFinder.new.execute(user, params)
+        expect(issues.size).to eq(1)
+      end
     end
   end
 end
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 94b4d4c4ff4247aad62cee7366ea464c1bea6664..8536377a7f079b534fd8ea9e728ee728e003ce86 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -21,13 +21,13 @@ describe MergeRequestsFinder do
     it 'should filter by scope' do
       params = { scope: 'authored', state: 'opened' }
       merge_requests = MergeRequestsFinder.new.execute(user, params)
-      merge_requests.size.should == 2
+      expect(merge_requests.size).to eq(2)
     end
 
     it 'should filter by project' do
       params = { project_id: project1.id, scope: 'authored', state: 'opened' }
       merge_requests = MergeRequestsFinder.new.execute(user, params)
-      merge_requests.size.should == 1
+      expect(merge_requests.size).to eq(1)
     end
   end
 end
diff --git a/spec/finders/notes_finder_spec.rb b/spec/finders/notes_finder_spec.rb
index 4f8a5f909df1207545e28be2e1296b77b0e54a85..c83824b900de0678ce22ebbe70be1bc237005113 100644
--- a/spec/finders/notes_finder_spec.rb
+++ b/spec/finders/notes_finder_spec.rb
@@ -21,7 +21,7 @@ describe NotesFinder do
 
     it 'should find all notes' do
       notes = NotesFinder.new.execute(project, user, params)
-      notes.size.should eq(2)
+      expect(notes.size).to eq(2)
     end
 
     it 'should raise an exception for an invalid target_type' do
@@ -32,7 +32,7 @@ describe NotesFinder do
     it 'filters out old notes' do
       note2.update_attribute(:updated_at, 2.hours.ago)
       notes = NotesFinder.new.execute(project, user, params)
-      notes.should eq([note1])
+      expect(notes).to eq([note1])
     end
   end
 end
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index 6e3ae4d615b087a7634c8d213fddd191cd0b1a00..2ab71b05968f81d20bc997f6ed2199e261dcad91 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -12,19 +12,19 @@ describe ProjectsFinder do
   context 'non authenticated' do
     subject { ProjectsFinder.new.execute(nil, group: group) }
 
-    it { should include(project1) }
-    it { should_not include(project2) }
-    it { should_not include(project3) }
-    it { should_not include(project4) }
+    it { is_expected.to include(project1) }
+    it { is_expected.not_to include(project2) }
+    it { is_expected.not_to include(project3) }
+    it { is_expected.not_to include(project4) }
   end
 
   context 'authenticated' do
     subject { ProjectsFinder.new.execute(user, group: group) }
 
-    it { should include(project1) }
-    it { should include(project2) }
-    it { should_not include(project3) }
-    it { should_not include(project4) }
+    it { is_expected.to include(project1) }
+    it { is_expected.to include(project2) }
+    it { is_expected.not_to include(project3) }
+    it { is_expected.not_to include(project4) }
   end
 
   context 'authenticated, project member' do
@@ -32,10 +32,10 @@ describe ProjectsFinder do
 
     subject { ProjectsFinder.new.execute(user, group: group) }
 
-    it { should include(project1) }
-    it { should include(project2) }
-    it { should include(project3) }
-    it { should_not include(project4) }
+    it { is_expected.to include(project1) }
+    it { is_expected.to include(project2) }
+    it { is_expected.to include(project3) }
+    it { is_expected.not_to include(project4) }
   end
 
   context 'authenticated, group member' do
@@ -43,9 +43,9 @@ describe ProjectsFinder do
 
     subject { ProjectsFinder.new.execute(user, group: group) }
 
-    it { should include(project1) }
-    it { should include(project2) }
-    it { should include(project3) }
-    it { should include(project4) }
+    it { is_expected.to include(project1) }
+    it { is_expected.to include(project2) }
+    it { is_expected.to include(project3) }
+    it { is_expected.to include(project4) }
   end
 end
diff --git a/spec/finders/snippets_finder_spec.rb b/spec/finders/snippets_finder_spec.rb
index c645cbc964ccc466c323a60f0d7ad1500d72cbf5..1b4ffc2d7176e1fa2ef6d896c467c747c00f1323 100644
--- a/spec/finders/snippets_finder_spec.rb
+++ b/spec/finders/snippets_finder_spec.rb
@@ -18,14 +18,14 @@ describe SnippetsFinder do
 
     it "returns all private and internal snippets" do
       snippets = SnippetsFinder.new.execute(user, filter: :all)
-      snippets.should include(@snippet2, @snippet3)
-      snippets.should_not include(@snippet1)
+      expect(snippets).to include(@snippet2, @snippet3)
+      expect(snippets).not_to include(@snippet1)
     end
 
     it "returns all public snippets" do
       snippets = SnippetsFinder.new.execute(nil, filter: :all)
-      snippets.should include(@snippet3)
-      snippets.should_not include(@snippet1, @snippet2)
+      expect(snippets).to include(@snippet3)
+      expect(snippets).not_to include(@snippet1, @snippet2)
     end
   end
 
@@ -38,37 +38,37 @@ describe SnippetsFinder do
 
     it "returns all public and internal snippets" do
       snippets = SnippetsFinder.new.execute(user1, filter: :by_user, user: user)
-      snippets.should include(@snippet2, @snippet3)
-      snippets.should_not include(@snippet1)
+      expect(snippets).to include(@snippet2, @snippet3)
+      expect(snippets).not_to include(@snippet1)
     end
 
     it "returns internal snippets" do
       snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_internal")
-      snippets.should include(@snippet2)
-      snippets.should_not include(@snippet1, @snippet3)
+      expect(snippets).to include(@snippet2)
+      expect(snippets).not_to include(@snippet1, @snippet3)
     end
 
     it "returns private snippets" do
       snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_private")
-      snippets.should include(@snippet1)
-      snippets.should_not include(@snippet2, @snippet3)
+      expect(snippets).to include(@snippet1)
+      expect(snippets).not_to include(@snippet2, @snippet3)
     end
 
     it "returns public snippets" do
       snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_public")
-      snippets.should include(@snippet3)
-      snippets.should_not include(@snippet1, @snippet2)
+      expect(snippets).to include(@snippet3)
+      expect(snippets).not_to include(@snippet1, @snippet2)
     end
 
     it "returns all snippets" do
       snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user)
-      snippets.should include(@snippet1, @snippet2, @snippet3)
+      expect(snippets).to include(@snippet1, @snippet2, @snippet3)
     end
 
     it "returns only public snippets if unauthenticated user" do
       snippets = SnippetsFinder.new.execute(nil, filter: :by_user, user: user)
-      snippets.should include(@snippet3)
-      snippets.should_not include(@snippet2, @snippet1)
+      expect(snippets).to include(@snippet3)
+      expect(snippets).not_to include(@snippet2, @snippet1)
     end
 
   end
@@ -82,20 +82,20 @@ describe SnippetsFinder do
 
     it "returns public snippets for unauthorized user" do
       snippets = SnippetsFinder.new.execute(nil, filter: :by_project, project: project1)
-      snippets.should include(@snippet3)
-      snippets.should_not include(@snippet1, @snippet2)
+      expect(snippets).to include(@snippet3)
+      expect(snippets).not_to include(@snippet1, @snippet2)
     end
 
     it "returns public and internal snippets for none project members" do
       snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1)
-      snippets.should include(@snippet2, @snippet3)
-      snippets.should_not include(@snippet1)
+      expect(snippets).to include(@snippet2, @snippet3)
+      expect(snippets).not_to include(@snippet1)
     end
 
     it "returns all snippets for project members" do
       project1.team << [user, :developer] 
       snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1)
-      snippets.should include(@snippet1, @snippet2, @snippet3)
+      expect(snippets).to include(@snippet1, @snippet2, @snippet3)
     end
   end
 end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 2db67cfdf95e11c9d9947c99b0d3f5805a9ab74b..4c11709ed6e716f2326ae4137ca56a6d5faaa7ce 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -3,20 +3,20 @@ require 'spec_helper'
 describe ApplicationHelper do
   describe 'current_controller?' do
     before do
-      controller.stub(:controller_name).and_return('foo')
+      allow(controller).to receive(:controller_name).and_return('foo')
     end
 
-    it "returns true when controller matches argument" do
-      current_controller?(:foo).should be_true
+    it 'returns true when controller matches argument' do
+      expect(current_controller?(:foo)).to be_truthy
     end
 
-    it "returns false when controller does not match argument" do
-      current_controller?(:bar).should_not be_true
+    it 'returns false when controller does not match argument' do
+      expect(current_controller?(:bar)).not_to be_truthy
     end
 
-    it "should take any number of arguments" do
-      current_controller?(:baz, :bar).should_not be_true
-      current_controller?(:baz, :bar, :foo).should be_true
+    it 'should take any number of arguments' do
+      expect(current_controller?(:baz, :bar)).not_to be_truthy
+      expect(current_controller?(:baz, :bar, :foo)).to be_truthy
     end
   end
 
@@ -25,99 +25,124 @@ describe ApplicationHelper do
       allow(self).to receive(:action_name).and_return('foo')
     end
 
-    it "returns true when action matches argument" do
-      current_action?(:foo).should be_true
+    it 'returns true when action matches argument' do
+      expect(current_action?(:foo)).to be_truthy
     end
 
-    it "returns false when action does not match argument" do
-      current_action?(:bar).should_not be_true
+    it 'returns false when action does not match argument' do
+      expect(current_action?(:bar)).not_to be_truthy
     end
 
-    it "should take any number of arguments" do
-      current_action?(:baz, :bar).should_not be_true
-      current_action?(:baz, :bar, :foo).should be_true
+    it 'should take any number of arguments' do
+      expect(current_action?(:baz, :bar)).not_to be_truthy
+      expect(current_action?(:baz, :bar, :foo)).to be_truthy
     end
   end
 
-  describe "group_icon" do
+  describe 'project_icon' do
     avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png')
 
-    it "should return an url for the avatar" do
-      group = create(:group)
-      group.avatar = File.open(avatar_file_path)
-      group.save!
-      group_icon(group.path).to_s.should match("/uploads/group/avatar/#{ group.id }/gitlab_logo.png")
+    it 'should return an url for the avatar' do
+      project = create(:project)
+      project.avatar = File.open(avatar_file_path)
+      project.save!
+      avatar_url = "http://localhost/uploads/project/avatar/#{ project.id }/gitlab_logo.png"
+      expect(project_icon("#{project.namespace.to_param}/#{project.to_param}").to_s).to eq(
+        "<img alt=\"Gitlab logo\" src=\"#{avatar_url}\" />"
+      )
     end
 
-    it "should give default avatar_icon when no avatar is present" do
-      group = create(:group)
-      group.save!
-      group_icon(group.path).should match("group_avatar.png")
+    it 'should give uploaded icon when present' do
+      project = create(:project)
+      project.save!
+
+      allow_any_instance_of(Project).to receive(:avatar_in_git).and_return(true)
+
+      avatar_url = 'http://localhost' + namespace_project_avatar_path(project.namespace, project)
+      expect(project_icon("#{project.namespace.to_param}/#{project.to_param}").to_s).to match(
+        image_tag(avatar_url))
     end
   end
 
-  describe "avatar_icon" do
+  describe 'avatar_icon' do
     avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png')
 
-    it "should return an url for the avatar" do
+    it 'should return an url for the avatar' do
+      user = create(:user)
+      user.avatar = File.open(avatar_file_path)
+      user.save!
+      expect(avatar_icon(user.email).to_s).
+        to match("/uploads/user/avatar/#{ user.id }/gitlab_logo.png")
+    end
+
+    it 'should return an url for the avatar with relative url' do
+      Gitlab.config.gitlab.stub(relative_url_root: '/gitlab')
+      Gitlab.config.gitlab.stub(url: Settings.send(:build_gitlab_url))
+
       user = create(:user)
       user.avatar = File.open(avatar_file_path)
       user.save!
-      avatar_icon(user.email).to_s.should match("/uploads/user/avatar/#{ user.id }/gitlab_logo.png")
+      expect(avatar_icon(user.email).to_s).
+        to match("/gitlab/uploads/user/avatar/#{ user.id }/gitlab_logo.png")
     end
 
-    it "should call gravatar_icon when no avatar is present" do
+    it 'should call gravatar_icon when no avatar is present' do
       user = create(:user, email: 'test@example.com')
       user.save!
-      avatar_icon(user.email).to_s.should == "http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s=40&d=identicon"
+      expect(avatar_icon(user.email).to_s).to eq('http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s=40&d=identicon')
     end
   end
 
-  describe "gravatar_icon" do
+  describe 'gravatar_icon' do
     let(:user_email) { 'user@email.com' }
 
-    it "should return a generic avatar path when Gravatar is disabled" do
-      Gitlab.config.gravatar.stub(:enabled).and_return(false)
-      gravatar_icon(user_email).should match('no_avatar.png')
+    it 'should return a generic avatar path when Gravatar is disabled' do
+      ApplicationSetting.any_instance.stub(gravatar_enabled?: false)
+      expect(gravatar_icon(user_email)).to match('no_avatar.png')
     end
 
-    it "should return a generic avatar path when email is blank" do
-      gravatar_icon('').should match('no_avatar.png')
+    it 'should return a generic avatar path when email is blank' do
+      expect(gravatar_icon('')).to match('no_avatar.png')
     end
 
-    it "should return default gravatar url" do
+    it 'should return default gravatar url' do
       Gitlab.config.gitlab.stub(https: false)
-      gravatar_icon(user_email).should match('http://www.gravatar.com/avatar/b58c6f14d292556214bd64909bcdb118')
+      url = 'http://www.gravatar.com/avatar/b58c6f14d292556214bd64909bcdb118'
+      expect(gravatar_icon(user_email)).to match(url)
     end
 
-    it "should use SSL when appropriate" do
+    it 'should use SSL when appropriate' do
       Gitlab.config.gitlab.stub(https: true)
-      gravatar_icon(user_email).should match('https://secure.gravatar.com')
+      expect(gravatar_icon(user_email)).to match('https://secure.gravatar.com')
     end
 
-    it "should return custom gravatar path when gravatar_url is set" do
+    it 'should return custom gravatar path when gravatar_url is set' do
       allow(self).to receive(:request).and_return(double(:ssl? => false))
-      Gitlab.config.gravatar.stub(:plain_url).and_return('http://example.local/?s=%{size}&hash=%{hash}')
-      gravatar_icon(user_email, 20).should == 'http://example.local/?s=20&hash=b58c6f14d292556214bd64909bcdb118'
+      allow(Gitlab.config.gravatar).
+        to receive(:plain_url).
+        and_return('http://example.local/?s=%{size}&hash=%{hash}')
+      url = 'http://example.local/?s=20&hash=b58c6f14d292556214bd64909bcdb118'
+      expect(gravatar_icon(user_email, 20)).to eq(url)
     end
 
-    it "should accept a custom size" do
+    it 'should accept a custom size' do
       allow(self).to receive(:request).and_return(double(:ssl? => false))
-      gravatar_icon(user_email, 64).should match(/\?s=64/)
+      expect(gravatar_icon(user_email, 64)).to match(/\?s=64/)
     end
 
-    it "should use default size when size is wrong" do
+    it 'should use default size when size is wrong' do
       allow(self).to receive(:request).and_return(double(:ssl? => false))
-      gravatar_icon(user_email, nil).should match(/\?s=40/)
+      expect(gravatar_icon(user_email, nil)).to match(/\?s=40/)
     end
 
-    it "should be case insensitive" do
+    it 'should be case insensitive' do
       allow(self).to receive(:request).and_return(double(:ssl? => false))
-      gravatar_icon(user_email).should == gravatar_icon(user_email.upcase + " ")
+      expect(gravatar_icon(user_email)).
+        to eq(gravatar_icon(user_email.upcase + ' '))
     end
   end
 
-  describe "grouped_options_refs" do
+  describe 'grouped_options_refs' do
     # Override Rails' grouped_options_for_select helper since HTML is harder to work with
     def grouped_options_for_select(options, *args)
       options
@@ -130,90 +155,94 @@ describe ApplicationHelper do
       @project = create(:project)
     end
 
-    it "includes a list of branch names" do
-      options[0][0].should == 'Branches'
-      options[0][1].should include('master', 'feature')
+    it 'includes a list of branch names' do
+      expect(options[0][0]).to eq('Branches')
+      expect(options[0][1]).to include('master', 'feature')
     end
 
-    it "includes a list of tag names" do
-      options[1][0].should == 'Tags'
-      options[1][1].should include('v1.0.0','v1.1.0')
+    it 'includes a list of tag names' do
+      expect(options[1][0]).to eq('Tags')
+      expect(options[1][1]).to include('v1.0.0', 'v1.1.0')
     end
 
-    it "includes a specific commit ref if defined" do
+    it 'includes a specific commit ref if defined' do
       # Must be an instance variable
       @ref = '2ed06dc41dbb5936af845b87d79e05bbf24c73b8'
 
-      options[2][0].should == 'Commit'
-      options[2][1].should == [@ref]
+      expect(options[2][0]).to eq('Commit')
+      expect(options[2][1]).to eq([@ref])
     end
 
-    it "sorts tags in a natural order" do
+    it 'sorts tags in a natural order' do
       # Stub repository.tag_names to make sure we get some valid testing data
-      expect(@project.repository).to receive(:tag_names).and_return(["v1.0.9", "v1.0.10", "v2.0", "v3.1.4.2", "v1.0.9a"])
+      expect(@project.repository).to receive(:tag_names).
+        and_return(['v1.0.9', 'v1.0.10', 'v2.0', 'v3.1.4.2', 'v2.0rc1¿',
+                    'v1.0.9a', 'v2.0-rc1', 'v2.0rc2'])
 
-      options[1][1].should == ["v3.1.4.2", "v2.0", "v1.0.10", "v1.0.9a", "v1.0.9"]
+      expect(options[1][1]).
+        to eq(['v3.1.4.2', 'v2.0', 'v2.0rc2', 'v2.0rc1¿', 'v2.0-rc1', 'v1.0.10',
+               'v1.0.9', 'v1.0.9a'])
     end
   end
 
-  describe "user_color_scheme_class" do
-    context "with current_user is nil" do
-      it "should return a string" do
+  describe 'user_color_scheme_class' do
+    context 'with current_user is nil' do
+      it 'should return a string' do
         allow(self).to receive(:current_user).and_return(nil)
-        user_color_scheme_class.should be_kind_of(String)
+        expect(user_color_scheme_class).to be_kind_of(String)
       end
     end
 
-    context "with a current_user" do
+    context 'with a current_user' do
       (1..5).each do |color_scheme_id|
         context "with color_scheme_id == #{color_scheme_id}" do
-          it "should return a string" do
+          it 'should return a string' do
             current_user = double(:color_scheme_id => color_scheme_id)
             allow(self).to receive(:current_user).and_return(current_user)
-            user_color_scheme_class.should be_kind_of(String)
+            expect(user_color_scheme_class).to be_kind_of(String)
           end
         end
       end
     end
   end
 
-  describe "simple_sanitize" do
+  describe 'simple_sanitize' do
     let(:a_tag) { '<a href="#">Foo</a>' }
 
-    it "allows the a tag" do
-      simple_sanitize(a_tag).should == a_tag
+    it 'allows the a tag' do
+      expect(simple_sanitize(a_tag)).to eq(a_tag)
     end
 
-    it "allows the span tag" do
+    it 'allows the span tag' do
       input = '<span class="foo">Bar</span>'
-      simple_sanitize(input).should == input
+      expect(simple_sanitize(input)).to eq(input)
     end
 
-    it "disallows other tags" do
+    it 'disallows other tags' do
       input = "<strike><b>#{a_tag}</b></strike>"
-      simple_sanitize(input).should == a_tag
+      expect(simple_sanitize(input)).to eq(a_tag)
     end
   end
 
-  describe "link_to" do
+  describe 'link_to' do
 
-    it "should not include rel=nofollow for internal links" do
-      expect(link_to("Home", root_path)).to eq("<a href=\"/\">Home</a>")
+    it 'should not include rel=nofollow for internal links' do
+      expect(link_to('Home', root_path)).to eq("<a href=\"/\">Home</a>")
     end
 
-    it "should include rel=nofollow for external links" do
-      expect(link_to("Example", "http://www.example.com")).to eq("<a href=\"http://www.example.com\" rel=\"nofollow\">Example</a>")
+    it 'should include rel=nofollow for external links' do
+      expect(link_to('Example', 'http://www.example.com')).to eq("<a href=\"http://www.example.com\" rel=\"nofollow\">Example</a>")
     end
 
-    it "should include re=nofollow for external links and honor existing html_options" do
+    it 'should include re=nofollow for external links and honor existing html_options' do
       expect(
-        link_to("Example", "http://www.example.com", class: "toggle", data: {toggle: "dropdown"})
+        link_to('Example', 'http://www.example.com', class: 'toggle', data: {toggle: 'dropdown'})
       ).to eq("<a class=\"toggle\" data-toggle=\"dropdown\" href=\"http://www.example.com\" rel=\"nofollow\">Example</a>")
     end
 
-    it "should include rel=nofollow for external links and preserver other rel values" do
+    it 'should include rel=nofollow for external links and preserver other rel values' do
       expect(
-        link_to("Example", "http://www.example.com", rel: "noreferrer")
+        link_to('Example', 'http://www.example.com', rel: 'noreferrer')
       ).to eq("<a href=\"http://www.example.com\" rel=\"noreferrer nofollow\">Example</a>")
     end
   end
@@ -222,7 +251,7 @@ describe ApplicationHelper do
     let(:content) { 'Noël' }
 
     it 'should preserve encoding' do
-      content.encoding.name.should == 'UTF-8'
+      expect(content.encoding.name).to eq('UTF-8')
       expect(render_markup('foo.rst', content).encoding.name).to eq('UTF-8')
     end
   end
diff --git a/spec/helpers/broadcast_messages_helper_spec.rb b/spec/helpers/broadcast_messages_helper_spec.rb
index 1338ce4873d61d0ff77d29402a688ce6c3c2b05e..f6df12662bb1a78a44d1647823d8f538979274c6 100644
--- a/spec/helpers/broadcast_messages_helper_spec.rb
+++ b/spec/helpers/broadcast_messages_helper_spec.rb
@@ -6,7 +6,7 @@ describe BroadcastMessagesHelper do
 
     context "default style" do
       it "should have no style" do
-        broadcast_styling(broadcast_message).should match('')
+        expect(broadcast_styling(broadcast_message)).to match('')
       end
     end
 
@@ -14,7 +14,8 @@ describe BroadcastMessagesHelper do
       before { broadcast_message.stub(color: "#f2dede", font: "#b94a48") }
 
       it "should have a customized style" do
-        broadcast_styling(broadcast_message).should match('background-color:#f2dede;color:#b94a48')
+        expect(broadcast_styling(broadcast_message)).
+          to match('background-color:#f2dede;color:#b94a48')
       end
     end
   end
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index b07742a6ee2ac9dd4960c76f7694e0f5d2875aab..5bd09793b11dac1209da4d095263dc0b728d1181 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -10,58 +10,61 @@ describe DiffHelper do
 
   describe 'diff_hard_limit_enabled?' do
     it 'should return true if param is provided' do
-      controller.stub(:params).and_return { { :force_show_diff => true } }
-      diff_hard_limit_enabled?.should be_true
+      allow(controller).to receive(:params) { { force_show_diff: true } }
+      expect(diff_hard_limit_enabled?).to be_truthy
     end
 
     it 'should return false if param is not provided' do
-      diff_hard_limit_enabled?.should be_false
+      expect(diff_hard_limit_enabled?).to be_falsey
     end
   end
 
   describe 'allowed_diff_size' do
     it 'should return hard limit for a diff if force diff is true' do
-      controller.stub(:params).and_return { { :force_show_diff => true } }
-      allowed_diff_size.should eq(1000)
+      allow(controller).to receive(:params) { { force_show_diff: true } }
+      expect(allowed_diff_size).to eq(1000)
     end
 
     it 'should return safe limit for a diff if force diff is false' do
-      allowed_diff_size.should eq(100)
+      expect(allowed_diff_size).to eq(100)
     end
   end
 
   describe 'parallel_diff' do
     it 'should return an array of arrays containing the parsed diff' do
-      parallel_diff(diff_file, 0).should match_array(parallel_diff_result_array)
+      expect(parallel_diff(diff_file, 0)).
+        to match_array(parallel_diff_result_array)
     end
   end
 
   describe 'generate_line_code' do
     it 'should generate correct line code' do
-      generate_line_code(diff_file.file_path, diff_file.diff_lines.first).should == '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6'
+      expect(generate_line_code(diff_file.file_path, diff_file.diff_lines.first)).
+        to eq('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6')
     end
   end
 
   describe 'unfold_bottom_class' do
     it 'should return empty string when bottom line shouldnt be unfolded' do
-      unfold_bottom_class(false).should == ''
+      expect(unfold_bottom_class(false)).to eq('')
     end
 
     it 'should return js class when bottom lines should be unfolded' do
-      unfold_bottom_class(true).should == 'js-unfold-bottom'
+      expect(unfold_bottom_class(true)).to eq('js-unfold-bottom')
     end
   end
 
   describe 'diff_line_content' do
 
     it 'should return non breaking space when line is empty' do
-      diff_line_content(nil).should eq(" &nbsp;")
+      expect(diff_line_content(nil)).to eq(' &nbsp;')
     end
 
     it 'should return the line itself' do
-      diff_line_content(diff_file.diff_lines.first.text).should eq("@@ -6,12 +6,18 @@ module Popen")
-      diff_line_content(diff_file.diff_lines.first.type).should eq("match")
-      diff_line_content(diff_file.diff_lines.first.new_pos).should eq(6)
+      expect(diff_line_content(diff_file.diff_lines.first.text)).
+        to eq('@@ -6,12 +6,18 @@ module Popen')
+      expect(diff_line_content(diff_file.diff_lines.first.type)).to eq('match')
+      expect(diff_line_content(diff_file.diff_lines.first.new_pos)).to eq(6)
     end
   end
 
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index 4de54d291f247242699c88a1b12cf7db90e417d3..b392371deb4c427d6deb16b472462f8a0b4786e5 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -4,6 +4,8 @@ describe EventsHelper do
   include ApplicationHelper
   include GitlabMarkdownHelper
 
+  let(:current_user) { create(:user, email: "current@email.com") }
+
   it 'should display one line of plain text without alteration' do
     input = 'A short, plain note'
     expect(event_note(input)).to match(input)
@@ -26,7 +28,8 @@ describe EventsHelper do
 
   it 'should display the first line of a code block' do
     input = "```\nCode block\nwith two lines\n```"
-    expected = '<pre><code class="">Code block...</code></pre>'
+    expected = '<pre class="code highlight white plaintext"><code>' \
+               'Code block...</code></pre>'
 
     expect(event_note(input)).to match(expected)
   end
@@ -49,4 +52,14 @@ describe EventsHelper do
     expect(event_note(input)).to match(link_url)
     expect(event_note(input)).to match(expected_link_text)
   end
+
+  it 'should preserve code color scheme' do
+    input = "```ruby\ndef test\n  'hello world'\nend\n```"
+    expected = '<pre class="code highlight white ruby">' \
+      "<code><span class=\"k\">def</span> <span class=\"nf\">test</span>\n" \
+      "  <span class=\"s1\">\'hello world\'</span>\n" \
+      "<span class=\"k\">end</span>\n" \
+      '</code></pre>'
+    expect(event_note(input)).to eq(expected)
+  end
 end
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
index 3c636b747d1d978f21f9e77c8b0e16667e71445c..c631acc591dd1febbc925140f9df6864c6b9aee7 100644
--- a/spec/helpers/gitlab_markdown_helper_spec.rb
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -1,4 +1,4 @@
-require "spec_helper"
+require 'spec_helper'
 
 describe GitlabMarkdownHelper do
   include ApplicationHelper
@@ -9,6 +9,7 @@ describe GitlabMarkdownHelper do
 
   let(:user)          { create(:user, username: 'gfm') }
   let(:commit)        { project.repository.commit }
+  let(:earlier_commit){ project.repository.commit("HEAD~2") }
   let(:issue)         { create(:issue, project: project) }
   let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
   let(:snippet)       { create(:project_snippet, project: project) }
@@ -23,71 +24,120 @@ describe GitlabMarkdownHelper do
     @project = project
     @ref = 'markdown'
     @repository = project.repository
+    @request.host = Gitlab.config.gitlab.host
   end
 
   describe "#gfm" do
     it "should return unaltered text if project is nil" do
       actual = "Testing references: ##{issue.iid}"
 
-      gfm(actual).should_not == actual
+      expect(gfm(actual)).not_to eq(actual)
 
       @project = nil
-      gfm(actual).should == actual
+      expect(gfm(actual)).to eq(actual)
     end
 
     it "should not alter non-references" do
       actual = expected = "_Please_ *stop* 'helping' and all the other b*$#%' you do."
-      gfm(actual).should == expected
+      expect(gfm(actual)).to eq(expected)
     end
 
     it "should not touch HTML entities" do
-      @project.issues.stub(:where).with(id: '39').and_return([issue])
+      allow(@project.issues).to receive(:where).
+        with(id: '39').and_return([issue])
       actual = 'We&#39;ll accept good pull requests.'
-      gfm(actual).should == "We'll accept good pull requests."
+      expect(gfm(actual)).to eq("We'll accept good pull requests.")
     end
 
     it "should forward HTML options to links" do
-      gfm("Fixed in #{commit.id}", @project, class: 'foo').
-          should have_selector('a.gfm.foo')
+      expect(gfm("Fixed in #{commit.id}", @project, class: 'foo')).
+          to have_selector('a.gfm.foo')
+    end
+
+    describe "referencing a commit range" do
+      let(:expected) { namespace_project_compare_path(project.namespace, project, from: earlier_commit.id, to: commit.id) }
+
+      it "should link using a full id" do
+        actual = "What happened in #{earlier_commit.id}...#{commit.id}"
+        expect(gfm(actual)).to match(expected)
+      end
+
+      it "should link using a short id" do
+        actual = "What happened in #{earlier_commit.short_id}...#{commit.short_id}"
+        expected = namespace_project_compare_path(project.namespace, project, from: earlier_commit.short_id, to: commit.short_id)
+        expect(gfm(actual)).to match(expected)
+      end
+
+      it "should link inclusively" do
+        actual = "What happened in #{earlier_commit.id}..#{commit.id}"
+        expected = namespace_project_compare_path(project.namespace, project, from: "#{earlier_commit.id}^", to: commit.id)
+        expect(gfm(actual)).to match(expected)
+      end
+
+      it "should link with adjacent text" do
+        actual = "(see #{earlier_commit.id}...#{commit.id})"
+        expect(gfm(actual)).to match(expected)
+      end
+
+      it "should keep whitespace intact" do
+        actual   = "Changes #{earlier_commit.id}...#{commit.id} dramatically"
+        expected = /Changes <a.+>#{earlier_commit.id}...#{commit.id}<\/a> dramatically/
+        expect(gfm(actual)).to match(expected)
+      end
+
+      it "should not link with an invalid id" do
+        actual = expected = "What happened in #{earlier_commit.id.reverse}...#{commit.id.reverse}"
+        expect(gfm(actual)).to eq(expected)
+      end
+
+      it "should include a title attribute" do
+        actual = "What happened in #{earlier_commit.id}...#{commit.id}"
+        expect(gfm(actual)).to match(/title="Commits #{earlier_commit.id} through #{commit.id}"/)
+      end
+
+      it "should include standard gfm classes" do
+        actual = "What happened in #{earlier_commit.id}...#{commit.id}"
+        expect(gfm(actual)).to match(/class="\s?gfm gfm-commit_range\s?"/)
+      end
     end
 
     describe "referencing a commit" do
-      let(:expected) { project_commit_path(project, commit) }
+      let(:expected) { namespace_project_commit_path(project.namespace, project, commit) }
 
       it "should link using a full id" do
         actual = "Reverts #{commit.id}"
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should link using a short id" do
         actual = "Backported from #{commit.short_id}"
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should link with adjacent text" do
         actual = "Reverted (see #{commit.id})"
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should keep whitespace intact" do
         actual   = "Changes #{commit.id} dramatically"
         expected = /Changes <a.+>#{commit.id}<\/a> dramatically/
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should not link with an invalid id" do
         actual = expected = "What happened in #{commit.id.reverse}"
-        gfm(actual).should == expected
+        expect(gfm(actual)).to eq(expected)
       end
 
       it "should include a title attribute" do
         actual = "Reverts #{commit.id}"
-        gfm(actual).should match(/title="#{commit.link_title}"/)
+        expect(gfm(actual)).to match(/title="#{commit.link_title}"/)
       end
 
       it "should include standard gfm classes" do
         actual = "Reverts #{commit.id}"
-        gfm(actual).should match(/class="\s?gfm gfm-commit\s?"/)
+        expect(gfm(actual)).to match(/class="\s?gfm gfm-commit\s?"/)
       end
     end
 
@@ -100,37 +150,37 @@ describe GitlabMarkdownHelper do
       end
 
       it "should link using a simple name" do
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should link using a name with dots" do
         user.update_attributes(name: "alphA.Beta")
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should link using name with underscores" do
         user.update_attributes(name: "ping_pong_king")
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should link with adjacent text" do
         actual = "Mail the admin (@#{user.username})"
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should keep whitespace intact" do
         actual   = "Yes, @#{user.username} is right."
         expected = /Yes, <a.+>@#{user.username}<\/a> is right/
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should not link with an invalid id" do
         actual = expected = "@#{user.username.reverse} you are right."
-        gfm(actual).should == expected
+        expect(gfm(actual)).to eq(expected)
       end
 
       it "should include standard gfm classes" do
-        gfm(actual).should match(/class="\s?gfm gfm-team_member\s?"/)
+        expect(gfm(actual)).to match(/class="\s?gfm gfm-project_member\s?"/)
       end
     end
 
@@ -144,40 +194,41 @@ describe GitlabMarkdownHelper do
     # Currently limited to Snippets, Issues and MergeRequests
     shared_examples 'referenced object' do
       let(:actual)   { "Reference to #{reference}" }
-      let(:expected) { polymorphic_path([project, object]) }
+      let(:expected) { polymorphic_path([project.namespace, project, object]) }
 
       it "should link using a valid id" do
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should link with adjacent text" do
         # Wrap the reference in parenthesis
-        gfm(actual.gsub(reference, "(#{reference})")).should match(expected)
+        expect(gfm(actual.gsub(reference, "(#{reference})"))).to match(expected)
 
         # Append some text to the end of the reference
-        gfm(actual.gsub(reference, "#{reference}, right?")).should match(expected)
+        expect(gfm(actual.gsub(reference, "#{reference}, right?"))).
+          to match(expected)
       end
 
       it "should keep whitespace intact" do
         actual   = "Referenced #{reference} already."
         expected = /Referenced <a.+>[^\s]+<\/a> already/
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should not link with an invalid id" do
         # Modify the reference string so it's still parsed, but is invalid
         reference.gsub!(/^(.)(\d+)$/, '\1' + ('\2' * 2))
-        gfm(actual).should == actual
+        expect(gfm(actual)).to eq(actual)
       end
 
       it "should include a title attribute" do
         title = "#{object.class.to_s.titlecase}: #{object.title}"
-        gfm(actual).should match(/title="#{title}"/)
+        expect(gfm(actual)).to match(/title="#{title}"/)
       end
 
       it "should include standard gfm classes" do
         css = object.class.to_s.underscore
-        gfm(actual).should match(/class="\s?gfm gfm-#{css}\s?"/)
+        expect(gfm(actual)).to match(/class="\s?gfm gfm-#{css}\s?"/)
       end
     end
 
@@ -196,34 +247,33 @@ describe GitlabMarkdownHelper do
       let(:actual)   { "Reference to #{full_reference}" }
       let(:expected) do
         if object.is_a?(Commit)
-          project_commit_path(@other_project, object)
+          namespace_project_commit_path(@other_project.namespace, @other_project, object)
         else
-          polymorphic_path([@other_project, object])
+          polymorphic_path([@other_project.namespace, @other_project, object])
         end
       end
 
       it 'should link using a valid id' do
-        gfm(actual).should match(
+        expect(gfm(actual)).to match(
           /#{expected}.*#{Regexp.escape(full_reference)}/
         )
       end
 
       it 'should link with adjacent text' do
         # Wrap the reference in parenthesis
-        gfm(actual.gsub(full_reference, "(#{full_reference})")).should(
+        expect(gfm(actual.gsub(full_reference, "(#{full_reference})"))).to(
           match(expected)
         )
 
         # Append some text to the end of the reference
-        gfm(actual.gsub(full_reference, "#{full_reference}, right?")).should(
-          match(expected)
-        )
+        expect(gfm(actual.gsub(full_reference, "#{full_reference}, right?"))).
+          to(match(expected))
       end
 
       it 'should keep whitespace intact' do
         actual   = "Referenced #{full_reference} already."
         expected = /Referenced <a.+>[^\s]+<\/a> already/
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it 'should not link with an invalid id' do
@@ -233,7 +283,7 @@ describe GitlabMarkdownHelper do
         else
           reference.gsub!(/^(.)(\d+)$/, '\1' + ('\2' * 2))
         end
-        gfm(actual).should == actual
+        expect(gfm(actual)).to eq(actual)
       end
 
       it 'should include a title attribute' do
@@ -242,12 +292,12 @@ describe GitlabMarkdownHelper do
         else
           title = "#{object.class.to_s.titlecase}: #{object.title}"
         end
-        gfm(actual).should match(/title="#{title}"/)
+        expect(gfm(actual)).to match(/title="#{title}"/)
       end
 
       it 'should include standard gfm classes' do
         css = object.class.to_s.underscore
-        gfm(actual).should match(/class="\s?gfm gfm-#{css}\s?"/)
+        expect(gfm(actual)).to match(/class="\s?gfm gfm-#{css}\s?"/)
       end
     end
 
@@ -296,43 +346,47 @@ describe GitlabMarkdownHelper do
       let(:reference) { "JIRA-#{issue.iid}" }
 
       before do
-        issue_tracker_config = { "jira" => { "title" => "JIRA tracker", "issues_url" => "http://jira.example/browse/:id" } }
-        Gitlab.config.stub(:issues_tracker).and_return(issue_tracker_config)
-        @project.stub(:issues_tracker).and_return("jira")
-        @project.stub(:issues_tracker_id).and_return("JIRA")
+        jira = @project.create_jira_service if @project.jira_service.nil?
+        properties = {"title"=>"JIRA tracker", "project_url"=>"http://jira.example/issues/?jql=project=A", "issues_url"=>"http://jira.example/browse/:id", "new_issue_url"=>"http://jira.example/secure/CreateIssue.jspa"}
+        jira.update_attributes(properties: properties, active: true)
+      end
+
+      after do
+        @project.jira_service.destroy! unless @project.jira_service.nil?
       end
 
       it "should link using a valid id" do
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should link with adjacent text" do
         # Wrap the reference in parenthesis
-        gfm(actual.gsub(reference, "(#{reference})")).should match(expected)
+        expect(gfm(actual.gsub(reference, "(#{reference})"))).to match(expected)
 
         # Append some text to the end of the reference
-        gfm(actual.gsub(reference, "#{reference}, right?")).should match(expected)
+        expect(gfm(actual.gsub(reference, "#{reference}, right?"))).
+          to match(expected)
       end
 
       it "should keep whitespace intact" do
         actual   = "Referenced #{reference} already."
         expected = /Referenced <a.+>[^\s]+<\/a> already/
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should not link with an invalid id" do
         # Modify the reference string so it's still parsed, but is invalid
         invalid_reference = actual.gsub(/(\d+)$/, "r45")
-        gfm(invalid_reference).should == invalid_reference
+        expect(gfm(invalid_reference)).to eq(invalid_reference)
       end
 
       it "should include a title attribute" do
         title = "Issue in JIRA tracker"
-        gfm(actual).should match(/title="#{title}"/)
+        expect(gfm(actual)).to match(/title="#{title}"/)
       end
 
       it "should include standard gfm classes" do
-        gfm(actual).should match(/class="\s?gfm gfm-issue\s?"/)
+        expect(gfm(actual)).to match(/class="\s?gfm gfm-issue\s?"/)
       end
     end
 
@@ -347,40 +401,40 @@ describe GitlabMarkdownHelper do
       let(:object)    { snippet }
       let(:reference) { "$#{snippet.id}" }
       let(:actual)   { "Reference to #{reference}" }
-      let(:expected) { project_snippet_path(project, object) }
+      let(:expected) { namespace_project_snippet_path(project.namespace, project, object) }
 
       it "should link using a valid id" do
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should link with adjacent text" do
         # Wrap the reference in parenthesis
-        gfm(actual.gsub(reference, "(#{reference})")).should match(expected)
+        expect(gfm(actual.gsub(reference, "(#{reference})"))).to match(expected)
 
         # Append some text to the end of the reference
-        gfm(actual.gsub(reference, "#{reference}, right?")).should match(expected)
+        expect(gfm(actual.gsub(reference, "#{reference}, right?"))).to match(expected)
       end
 
       it "should keep whitespace intact" do
         actual   = "Referenced #{reference} already."
         expected = /Referenced <a.+>[^\s]+<\/a> already/
-        gfm(actual).should match(expected)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should not link with an invalid id" do
         # Modify the reference string so it's still parsed, but is invalid
         reference.gsub!(/^(.)(\d+)$/, '\1' + ('\2' * 2))
-        gfm(actual).should == actual
+        expect(gfm(actual)).to eq(actual)
       end
 
       it "should include a title attribute" do
         title = "Snippet: #{object.title}"
-        gfm(actual).should match(/title="#{title}"/)
+        expect(gfm(actual)).to match(/title="#{title}"/)
       end
 
       it "should include standard gfm classes" do
         css = object.class.to_s.underscore
-        gfm(actual).should match(/class="\s?gfm gfm-snippet\s?"/)
+        expect(gfm(actual)).to match(/class="\s?gfm gfm-snippet\s?"/)
       end
 
     end
@@ -389,70 +443,70 @@ describe GitlabMarkdownHelper do
       let(:actual) { "!#{merge_request.iid} -> #{commit.id} -> ##{issue.iid}" }
 
       it "should link to the merge request" do
-        expected = project_merge_request_path(project, merge_request)
-        gfm(actual).should match(expected)
+        expected = namespace_project_merge_request_path(project.namespace, project, merge_request)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should link to the commit" do
-        expected = project_commit_path(project, commit)
-        gfm(actual).should match(expected)
+        expected = namespace_project_commit_path(project.namespace, project, commit)
+        expect(gfm(actual)).to match(expected)
       end
 
       it "should link to the issue" do
-        expected = project_issue_path(project, issue)
-        gfm(actual).should match(expected)
+        expected = namespace_project_issue_path(project.namespace, project, issue)
+        expect(gfm(actual)).to match(expected)
       end
     end
 
     describe "emoji" do
       it "matches at the start of a string" do
-        gfm(":+1:").should match(/<img/)
+        expect(gfm(":+1:")).to match(/<img/)
       end
 
       it "matches at the end of a string" do
-        gfm("This gets a :-1:").should match(/<img/)
+        expect(gfm("This gets a :-1:")).to match(/<img/)
       end
 
       it "matches with adjacent text" do
-        gfm("+1 (:+1:)").should match(/<img/)
+        expect(gfm("+1 (:+1:)")).to match(/<img/)
       end
 
       it "has a title attribute" do
-        gfm(":-1:").should match(/title=":-1:"/)
+        expect(gfm(":-1:")).to match(/title=":-1:"/)
       end
 
       it "has an alt attribute" do
-        gfm(":-1:").should match(/alt=":-1:"/)
+        expect(gfm(":-1:")).to match(/alt=":-1:"/)
       end
 
       it "has an emoji class" do
-        gfm(":+1:").should match('class="emoji"')
+        expect(gfm(":+1:")).to match('class="emoji"')
       end
 
       it "sets height and width" do
         actual = gfm(":+1:")
-        actual.should match(/width="20"/)
-        actual.should match(/height="20"/)
+        expect(actual).to match(/width="20"/)
+        expect(actual).to match(/height="20"/)
       end
 
       it "keeps whitespace intact" do
-        gfm('This deserves a :+1: big time.').
-          should match(/deserves a <img.+> big time/)
+        expect(gfm('This deserves a :+1: big time.')).
+          to match(/deserves a <img.+> big time/)
       end
 
       it "ignores invalid emoji" do
-        gfm(":invalid-emoji:").should_not match(/<img/)
+        expect(gfm(":invalid-emoji:")).not_to match(/<img/)
       end
 
       it "should work independent of reference links (i.e. without @project being set)" do
         @project = nil
-        gfm(":+1:").should match(/<img/)
+        expect(gfm(":+1:")).to match(/<img/)
       end
     end
   end
 
   describe "#link_to_gfm" do
-    let(:commit_path) { project_commit_path(project, commit) }
+    let(:commit_path) { namespace_project_commit_path(project.namespace, project, commit) }
     let(:issues)      { create_list(:issue, 2, project: project) }
 
     it "should handle references nested in links with all the text" do
@@ -463,60 +517,67 @@ describe GitlabMarkdownHelper do
       groups = actual.split("</a>")
 
       # Leading commit link
-      groups[0].should match(/href="#{commit_path}"/)
-      groups[0].should match(/This should finally fix $/)
+      expect(groups[0]).to match(/href="#{commit_path}"/)
+      expect(groups[0]).to match(/This should finally fix $/)
 
       # First issue link
-      groups[1].should match(/href="#{project_issue_url(project, issues[0])}"/)
-      groups[1].should match(/##{issues[0].iid}$/)
+      expect(groups[1]).
+        to match(/href="#{namespace_project_issue_path(project.namespace, project, issues[0])}"/)
+      expect(groups[1]).to match(/##{issues[0].iid}$/)
 
       # Internal commit link
-      groups[2].should match(/href="#{commit_path}"/)
-      groups[2].should match(/ and /)
+      expect(groups[2]).to match(/href="#{commit_path}"/)
+      expect(groups[2]).to match(/ and /)
 
       # Second issue link
-      groups[3].should match(/href="#{project_issue_url(project, issues[1])}"/)
-      groups[3].should match(/##{issues[1].iid}$/)
+      expect(groups[3]).
+        to match(/href="#{namespace_project_issue_path(project.namespace, project, issues[1])}"/)
+      expect(groups[3]).to match(/##{issues[1].iid}$/)
 
       # Trailing commit link
-      groups[4].should match(/href="#{commit_path}"/)
-      groups[4].should match(/ for real$/)
+      expect(groups[4]).to match(/href="#{commit_path}"/)
+      expect(groups[4]).to match(/ for real$/)
     end
 
     it "should forward HTML options" do
       actual = link_to_gfm("Fixed in #{commit.id}", commit_path, class: 'foo')
-      actual.should have_selector 'a.gfm.gfm-commit.foo'
+      expect(actual).to have_selector 'a.gfm.gfm-commit.foo'
     end
 
     it "escapes HTML passed in as the body" do
       actual = "This is a <h1>test</h1> - see ##{issues[0].iid}"
-      link_to_gfm(actual, commit_path).should match('&lt;h1&gt;test&lt;/h1&gt;')
+      expect(link_to_gfm(actual, commit_path)).
+        to match('&lt;h1&gt;test&lt;/h1&gt;')
     end
   end
 
   describe "#markdown" do
     it "should handle references in paragraphs" do
       actual = "\n\nLorem ipsum dolor sit amet. #{commit.id} Nam pulvinar sapien eget.\n"
-      expected = project_commit_path(project, commit)
-      markdown(actual).should match(expected)
+      expected = namespace_project_commit_path(project.namespace, project, commit)
+      expect(markdown(actual)).to match(expected)
     end
 
     it "should handle references in headers" do
       actual = "\n# Working around ##{issue.iid}\n## Apply !#{merge_request.iid}"
 
-      markdown(actual, {no_header_anchors:true}).should match(%r{<h1[^<]*>Working around <a.+>##{issue.iid}</a></h1>})
-      markdown(actual, {no_header_anchors:true}).should match(%r{<h2[^<]*>Apply <a.+>!#{merge_request.iid}</a></h2>})
+      expect(markdown(actual, no_header_anchors: true)).
+        to match(%r{<h1[^<]*>Working around <a.+>##{issue.iid}</a></h1>})
+      expect(markdown(actual, no_header_anchors: true)).
+        to match(%r{<h2[^<]*>Apply <a.+>!#{merge_request.iid}</a></h2>})
     end
 
     it "should add ids and links to headers" do
       # Test every rule except nested tags.
       text = '..Ab_c-d. e..'
       id = 'ab_c-d-e'
-      markdown("# #{text}").should match(%r{<h1 id="#{id}">#{text}<a href="[^"]*##{id}"></a></h1>})
-      markdown("# #{text}", {no_header_anchors:true}).should == "<h1>#{text}</h1>"
+      expect(markdown("# #{text}")).
+        to match(%r{<h1 id="#{id}">#{text}<a href="[^"]*##{id}"></a></h1>})
+      expect(markdown("# #{text}", {no_header_anchors:true})).
+      to eq("<h1>#{text}</h1>")
 
       id = 'link-text'
-      markdown("# [link text](url) ![img alt](url)").should match(
+      expect(markdown("# [link text](url) ![img alt](url)")).to match(
         %r{<h1 id="#{id}"><a href="[^"]*url">link text</a> <img[^>]*><a href="[^"]*##{id}"></a></h1>}
       )
     end
@@ -526,32 +587,37 @@ describe GitlabMarkdownHelper do
 
       actual = "\n* dark: ##{issue.iid}\n* light by @#{member.user.username}"
 
-      markdown(actual).should match(%r{<li>dark: <a.+>##{issue.iid}</a></li>})
-      markdown(actual).should match(%r{<li>light by <a.+>@#{member.user.username}</a></li>})
+      expect(markdown(actual)).
+        to match(%r{<li>dark: <a.+>##{issue.iid}</a></li>})
+      expect(markdown(actual)).
+        to match(%r{<li>light by <a.+>@#{member.user.username}</a></li>})
     end
 
     it "should not link the apostrophe to issue 39" do
       project.team << [user, :master]
-      project.issues.stub(:where).with(iid: '39').and_return([issue])
+      allow(project.issues).
+        to receive(:where).with(iid: '39').and_return([issue])
 
       actual   = "Yes, it is @#{member.user.username}'s task."
       expected = /Yes, it is <a.+>@#{member.user.username}<\/a>'s task/
-      markdown(actual).should match(expected)
+      expect(markdown(actual)).to match(expected)
     end
 
     it "should not link the apostrophe to issue 39 in code blocks" do
       project.team << [user, :master]
-      project.issues.stub(:where).with(iid: '39').and_return([issue])
+      allow(project.issues).
+        to receive(:where).with(iid: '39').and_return([issue])
 
       actual   = "Yes, `it is @#{member.user.username}'s task.`"
       expected = /Yes, <code>it is @gfm\'s task.<\/code>/
-      markdown(actual).should match(expected)
+      expect(markdown(actual)).to match(expected)
     end
 
     it "should handle references in <em>" do
       actual = "Apply _!#{merge_request.iid}_ ASAP"
 
-      markdown(actual).should match(%r{Apply <em><a.+>!#{merge_request.iid}</a></em>})
+      expect(markdown(actual)).
+        to match(%r{Apply <em><a.+>!#{merge_request.iid}</a></em>})
     end
 
     it "should handle tables" do
@@ -560,91 +626,136 @@ describe GitlabMarkdownHelper do
 | cell 1   | cell 2   |
 | cell 3   | cell 4   |}
 
-      markdown(actual).should match(/\A<table/)
+      expect(markdown(actual)).to match(/\A<table/)
     end
 
     it "should leave code blocks untouched" do
-      helper.stub(:user_color_scheme_class).and_return(:white)
+      allow(helper).to receive(:user_color_scheme_class).and_return(:white)
 
-      target_html = "\n<div class=\"highlighted-data white\">\n  <div class=\"highlight\">\n    <pre><code class=\"\">some code from $#{snippet.id}\nhere too\n</code></pre>\n  </div>\n</div>\n\n"
+      target_html = "<pre class=\"code highlight white plaintext\"><code>some code from $#{snippet.id}\nhere too\n</code></pre>\n"
 
-      helper.markdown("\n    some code from $#{snippet.id}\n    here too\n").should == target_html
-      helper.markdown("\n```\nsome code from $#{snippet.id}\nhere too\n```\n").should == target_html
+      expect(helper.markdown("\n    some code from $#{snippet.id}\n    here too\n")).
+        to eq(target_html)
+      expect(helper.markdown("\n```\nsome code from $#{snippet.id}\nhere too\n```\n")).
+        to eq(target_html)
     end
 
     it "should leave inline code untouched" do
-      markdown("\nDon't use `$#{snippet.id}` here.\n").should ==
+      expect(markdown("\nDon't use `$#{snippet.id}` here.\n")).to eq(
         "<p>Don't use <code>$#{snippet.id}</code> here.</p>\n"
+      )
     end
 
     it "should leave ref-like autolinks untouched" do
-      markdown("look at http://example.tld/#!#{merge_request.iid}").should == "<p>look at <a href=\"http://example.tld/#!#{merge_request.iid}\">http://example.tld/#!#{merge_request.iid}</a></p>\n"
+      expect(markdown("look at http://example.tld/#!#{merge_request.iid}")).to eq("<p>look at <a href=\"http://example.tld/#!#{merge_request.iid}\">http://example.tld/#!#{merge_request.iid}</a></p>\n")
     end
 
     it "should leave ref-like href of 'manual' links untouched" do
-      markdown("why not [inspect !#{merge_request.iid}](http://example.tld/#!#{merge_request.iid})").should == "<p>why not <a href=\"http://example.tld/#!#{merge_request.iid}\">inspect </a><a class=\"gfm gfm-merge_request \" href=\"#{project_merge_request_url(project, merge_request)}\" title=\"Merge Request: #{merge_request.title}\">!#{merge_request.iid}</a><a href=\"http://example.tld/#!#{merge_request.iid}\"></a></p>\n"
+      expect(markdown("why not [inspect !#{merge_request.iid}](http://example.tld/#!#{merge_request.iid})")).to eq("<p>why not <a href=\"http://example.tld/#!#{merge_request.iid}\">inspect </a><a class=\"gfm gfm-merge_request \" href=\"#{namespace_project_merge_request_url(project.namespace, project, merge_request)}\" title=\"Merge Request: #{merge_request.title}\">!#{merge_request.iid}</a><a href=\"http://example.tld/#!#{merge_request.iid}\"></a></p>\n")
     end
 
     it "should leave ref-like src of images untouched" do
-      markdown("screen shot: ![some image](http://example.tld/#!#{merge_request.iid})").should == "<p>screen shot: <img src=\"http://example.tld/#!#{merge_request.iid}\" alt=\"some image\"></p>\n"
+      expect(markdown("screen shot: ![some image](http://example.tld/#!#{merge_request.iid})")).to eq("<p>screen shot: <img src=\"http://example.tld/#!#{merge_request.iid}\" alt=\"some image\"></p>\n")
     end
 
     it "should generate absolute urls for refs" do
-      markdown("##{issue.iid}").should include(project_issue_url(project, issue))
+      expect(markdown("##{issue.iid}")).to include(namespace_project_issue_path(project.namespace, project, issue))
     end
 
     it "should generate absolute urls for emoji" do
-      markdown(':smile:').should(
-        include(%(src="#{Gitlab.config.gitlab.url}/assets/emoji/smile.png))
+      expect(markdown(':smile:')).to(
+        include(%(src="#{Gitlab.config.gitlab.url}/assets/emoji/#{Emoji.emoji_filename('smile')}.png))
       )
     end
 
     it "should generate absolute urls for emoji if relative url is present" do
-      Gitlab.config.gitlab.stub(:url).and_return('http://localhost/gitlab/root')
-      markdown(":smile:").should include("src=\"http://localhost/gitlab/root/assets/emoji/smile.png")
+      allow(Gitlab.config.gitlab).to receive(:url).and_return('http://localhost/gitlab/root')
+      expect(markdown(":smile:")).to include("src=\"http://localhost/gitlab/root/assets/emoji/#{Emoji.emoji_filename('smile')}.png")
     end
 
     it "should generate absolute urls for emoji if asset_host is present" do
-      Gitlab::Application.config.stub(:asset_host).and_return("https://cdn.example.com")
+      allow(Gitlab::Application.config).to receive(:asset_host).and_return("https://cdn.example.com")
       ActionView::Base.any_instance.stub_chain(:config, :asset_host).and_return("https://cdn.example.com")
-      markdown(":smile:").should include("src=\"https://cdn.example.com/assets/emoji/smile.png")
+      expect(markdown(":smile:")).to include("src=\"https://cdn.example.com/assets/emoji/#{Emoji.emoji_filename('smile')}.png")
     end
 
 
     it "should handle relative urls for a file in master" do
       actual = "[GitLab API doc](doc/api/README.md)\n"
       expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md\">GitLab API doc</a></p>\n"
-      markdown(actual).should match(expected)
+      expect(markdown(actual)).to match(expected)
+    end
+
+    it "should handle relative urls for a file in master with an anchor" do
+      actual = "[GitLab API doc](doc/api/README.md#section)\n"
+      expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md#section\">GitLab API doc</a></p>\n"
+      expect(markdown(actual)).to match(expected)
+    end
+
+    it "should not handle relative urls for the current file with an anchor" do
+      actual = "[GitLab API doc](#section)\n"
+      expected = "<p><a href=\"#section\">GitLab API doc</a></p>\n"
+      expect(markdown(actual)).to match(expected)
     end
 
     it "should handle relative urls for a directory in master" do
       actual = "[GitLab API doc](doc/api)\n"
       expected = "<p><a href=\"/#{project.path_with_namespace}/tree/#{@ref}/doc/api\">GitLab API doc</a></p>\n"
-      markdown(actual).should match(expected)
+      expect(markdown(actual)).to match(expected)
     end
 
     it "should handle absolute urls" do
       actual = "[GitLab](https://www.gitlab.com)\n"
       expected = "<p><a href=\"https://www.gitlab.com\">GitLab</a></p>\n"
-      markdown(actual).should match(expected)
+      expect(markdown(actual)).to match(expected)
     end
 
     it "should handle relative urls in reference links for a file in master" do
       actual = "[GitLab API doc][GitLab readme]\n [GitLab readme]: doc/api/README.md\n"
       expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md\">GitLab API doc</a></p>\n"
-      markdown(actual).should match(expected)
+      expect(markdown(actual)).to match(expected)
     end
 
     it "should handle relative urls in reference links for a directory in master" do
       actual = "[GitLab API doc directory][GitLab readmes]\n [GitLab readmes]: doc/api/\n"
       expected = "<p><a href=\"/#{project.path_with_namespace}/tree/#{@ref}/doc/api\">GitLab API doc directory</a></p>\n"
-      markdown(actual).should match(expected)
+      expect(markdown(actual)).to match(expected)
     end
 
      it "should not handle malformed relative urls in reference links for a file in master" do
       actual = "[GitLab readme]: doc/api/README.md\n"
       expected = ""
-      markdown(actual).should match(expected)
+      expect(markdown(actual)).to match(expected)
+    end
+
+    it 'should allow whitelisted HTML tags from the user' do
+      actual = '<dl><dt>Term</dt><dd>Definition</dd></dl>'
+      expect(markdown(actual)).to match(actual)
+    end
+
+    it 'should sanitize tags that are not whitelisted' do
+      actual = '<textarea>no inputs allowed</textarea> <blink>no blinks</blink>'
+      expected = 'no inputs allowed no blinks'
+      expect(markdown(actual)).to match(expected)
+      expect(markdown(actual)).not_to match('<.textarea>')
+      expect(markdown(actual)).not_to match('<.blink>')
+    end
+
+    it 'should allow whitelisted tag attributes from the user' do
+      actual = '<a class="custom">link text</a>'
+      expect(markdown(actual)).to match(actual)
+    end
+
+    it 'should sanitize tag attributes that are not whitelisted' do
+      actual = '<a href="http://example.com/bar.html" foo="bar">link text</a>'
+      expected = '<a href="http://example.com/bar.html">link text</a>'
+      expect(markdown(actual)).to match(expected)
+    end
+
+    it 'should sanitize javascript in attributes' do
+      actual = %q(<a href="javascript:alert('foo')">link text</a>)
+      expected = '<a>link text</a>'
+      expect(markdown(actual)).to match(expected)
     end
   end
 
@@ -657,29 +768,29 @@ describe GitlabMarkdownHelper do
     it "should not touch relative urls" do
       actual = "[GitLab API doc][GitLab readme]\n [GitLab readme]: doc/api/README.md\n"
       expected = "<p><a href=\"doc/api/README.md\">GitLab API doc</a></p>\n"
-      markdown(actual).should match(expected)
+      expect(markdown(actual)).to match(expected)
     end
   end
 
   describe "#render_wiki_content" do
     before do
       @wiki = double('WikiPage')
-      @wiki.stub(:content).and_return('wiki content')
+      allow(@wiki).to receive(:content).and_return('wiki content')
     end
 
     it "should use GitLab Flavored Markdown for markdown files" do
-      @wiki.stub(:format).and_return(:markdown)
+      allow(@wiki).to receive(:format).and_return(:markdown)
 
-      helper.should_receive(:markdown).with('wiki content')
+      expect(helper).to receive(:markdown).with('wiki content')
 
       helper.render_wiki_content(@wiki)
     end
 
     it "should use the Gollum renderer for all other file types" do
-      @wiki.stub(:format).and_return(:rdoc)
+      allow(@wiki).to receive(:format).and_return(:rdoc)
       formatted_content_stub = double('formatted_content')
-      formatted_content_stub.should_receive(:html_safe)
-      @wiki.stub(:formatted_content).and_return(formatted_content_stub)
+      expect(formatted_content_stub).to receive(:html_safe)
+      allow(@wiki).to receive(:formatted_content).and_return(formatted_content_stub)
 
       helper.render_wiki_content(@wiki)
     end
@@ -736,6 +847,17 @@ EOT
       )
     end
 
+    it 'should render checkboxes for nested tasks' do
+      rendered_text = markdown(@source_text_asterisk, parse_tasks: true)
+
+      expect(rendered_text).to match(
+        /<input.*checkbox.*valid unchecked nested task/
+      )
+      expect(rendered_text).to match(
+        /<input.*checkbox.*valid checked nested task/
+      )
+    end
+
     it 'should not be confused by whitespace before bullets' do
       rendered_text_asterisk = markdown(@source_text_asterisk,
                                         parse_tasks: true)
diff --git a/spec/helpers/groups_helper.rb b/spec/helpers/groups_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3e99ab84ec93312b8579d297b5de3d220be1ae35
--- /dev/null
+++ b/spec/helpers/groups_helper.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe GroupsHelper do
+  describe 'group_icon' do
+    avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png')
+
+    it 'should return an url for the avatar' do
+      group = create(:group)
+      group.avatar = File.open(avatar_file_path)
+      group.save!
+      expect(group_icon(group.path).to_s).
+        to match("/uploads/group/avatar/#{ group.id }/gitlab_logo.png")
+    end
+
+    it 'should give default avatar_icon when no avatar is present' do
+      group = create(:group)
+      group.save!
+      expect(group_icon(group.path)).to match('group_avatar.png')
+    end
+  end
+end
diff --git a/spec/helpers/icons_helper_spec.rb b/spec/helpers/icons_helper_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0b1cf07b7b083cd23f912a7569daeba11fde8a2f
--- /dev/null
+++ b/spec/helpers/icons_helper_spec.rb
@@ -0,0 +1,109 @@
+require 'spec_helper'
+
+describe IconsHelper do
+  describe 'file_type_icon_class' do
+    it 'returns folder class' do
+      expect(file_type_icon_class('folder', 0, 'folder_name')).to eq 'folder'
+    end
+
+    it 'returns share class' do
+      expect(file_type_icon_class('file', 0120000, 'link')).to eq 'share'
+    end
+
+    it 'returns file-pdf-o class with .pdf' do
+      expect(file_type_icon_class('file', 0, 'filename.pdf')).to eq 'file-pdf-o'
+    end
+
+    it 'returns file-image-o class with .jpg' do
+      expect(file_type_icon_class('file', 0, 'filename.jpg')).to eq 'file-image-o'
+    end
+
+    it 'returns file-image-o class with .JPG' do
+      expect(file_type_icon_class('file', 0, 'filename.JPG')).to eq 'file-image-o'
+    end
+
+    it 'returns file-image-o class with .png' do
+      expect(file_type_icon_class('file', 0, 'filename.png')).to eq 'file-image-o'
+    end
+
+    it 'returns file-archive-o class with .tar' do
+      expect(file_type_icon_class('file', 0, 'filename.tar')).to eq 'file-archive-o'
+    end
+
+    it 'returns file-archive-o class with .TAR' do
+      expect(file_type_icon_class('file', 0, 'filename.TAR')).to eq 'file-archive-o'
+    end
+
+    it 'returns file-archive-o class with .tar.gz' do
+      expect(file_type_icon_class('file', 0, 'filename.tar.gz')).to eq 'file-archive-o'
+    end
+
+    it 'returns file-audio-o class with .mp3' do
+      expect(file_type_icon_class('file', 0, 'filename.mp3')).to eq 'file-audio-o'
+    end
+
+    it 'returns file-audio-o class with .MP3' do
+      expect(file_type_icon_class('file', 0, 'filename.MP3')).to eq 'file-audio-o'
+    end
+
+    it 'returns file-audio-o class with .wav' do
+      expect(file_type_icon_class('file', 0, 'filename.wav')).to eq 'file-audio-o'
+    end
+
+    it 'returns file-video-o class with .avi' do
+      expect(file_type_icon_class('file', 0, 'filename.avi')).to eq 'file-video-o'
+    end
+
+    it 'returns file-video-o class with .AVI' do
+      expect(file_type_icon_class('file', 0, 'filename.AVI')).to eq 'file-video-o'
+    end
+
+    it 'returns file-video-o class with .mp4' do
+      expect(file_type_icon_class('file', 0, 'filename.mp4')).to eq 'file-video-o'
+    end
+
+    it 'returns file-word-o class with .doc' do
+      expect(file_type_icon_class('file', 0, 'filename.doc')).to eq 'file-word-o'
+    end
+
+    it 'returns file-word-o class with .DOC' do
+      expect(file_type_icon_class('file', 0, 'filename.DOC')).to eq 'file-word-o'
+    end
+
+    it 'returns file-word-o class with .docx' do
+      expect(file_type_icon_class('file', 0, 'filename.docx')).to eq 'file-word-o'
+    end
+
+    it 'returns file-excel-o class with .xls' do
+      expect(file_type_icon_class('file', 0, 'filename.xls')).to eq 'file-excel-o'
+    end
+
+    it 'returns file-excel-o class with .XLS' do
+      expect(file_type_icon_class('file', 0, 'filename.XLS')).to eq 'file-excel-o'
+    end
+
+    it 'returns file-excel-o class with .xlsx' do
+      expect(file_type_icon_class('file', 0, 'filename.xlsx')).to eq 'file-excel-o'
+    end
+
+    it 'returns file-excel-o class with .ppt' do
+      expect(file_type_icon_class('file', 0, 'filename.ppt')).to eq 'file-powerpoint-o'
+    end
+
+    it 'returns file-excel-o class with .PPT' do
+      expect(file_type_icon_class('file', 0, 'filename.PPT')).to eq 'file-powerpoint-o'
+    end
+
+    it 'returns file-excel-o class with .pptx' do
+      expect(file_type_icon_class('file', 0, 'filename.pptx')).to eq 'file-powerpoint-o'
+    end
+
+    it 'returns file-text-o class with .unknow' do
+      expect(file_type_icon_class('file', 0, 'filename.unknow')).to eq 'file-text-o'
+    end
+
+    it 'returns file-text-o class with no extension' do
+      expect(file_type_icon_class('file', 0, 'CHANGELOG')).to eq 'file-text-o'
+    end
+  end
+end
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index 9c95bc044f3dbf7f21c0815b0e6fecd08758b05b..54dd8d4aa64dd87686e982499c9e3940f2c8f740 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -5,133 +5,132 @@ describe IssuesHelper do
   let(:issue) { create :issue, project: project }
   let(:ext_project) { create :redmine_project }
 
-  describe :title_for_issue do
+  describe "title_for_issue" do
     it "should return issue title if used internal tracker" do
       @project = project
-      title_for_issue(issue.iid).should eq issue.title
+      expect(title_for_issue(issue.iid)).to eq issue.title
     end
 
     it "should always return empty string if used external tracker" do
       @project = ext_project
-      title_for_issue(rand(100)).should eq ""
+      expect(title_for_issue(rand(100))).to eq ""
     end
 
     it "should always return empty string if project nil" do
       @project = nil
 
-      title_for_issue(rand(100)).should eq ""
+      expect(title_for_issue(rand(100))).to eq ""
     end
   end
 
-  describe :url_for_project_issues do
-    let(:project_url) { Gitlab.config.issues_tracker.redmine.project_url}
+  describe "url_for_project_issues" do
+    let(:project_url) { ext_project.external_issue_tracker.project_url }
     let(:ext_expected) do
       project_url.gsub(':project_id', ext_project.id.to_s)
                  .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s)
     end
-    let(:int_expected) { polymorphic_path([project]) }
+    let(:int_expected) { polymorphic_path([@project.namespace, project]) }
 
     it "should return internal path if used internal tracker" do
       @project = project
-      url_for_project_issues.should match(int_expected)
+      expect(url_for_project_issues).to match(int_expected)
     end
 
     it "should return path to external tracker" do
       @project = ext_project
 
-      url_for_project_issues.should match(ext_expected)
+      expect(url_for_project_issues).to match(ext_expected)
     end
 
     it "should return empty string if project nil" do
       @project = nil
 
-      url_for_project_issues.should eq ""
+      expect(url_for_project_issues).to eq ""
     end
 
     describe "when external tracker was enabled and then config removed" do
       before do
         @project = ext_project
-        Gitlab.config.stub(:issues_tracker).and_return(nil)
+        allow(Gitlab.config).to receive(:issues_tracker).and_return(nil)
       end
 
-      it "should return path to internal tracker" do
-        url_for_project_issues.should match(polymorphic_path([@project]))
+      it "should return path to external tracker" do
+        expect(url_for_project_issues).to match(ext_expected)
       end
     end
   end
 
-  describe :url_for_issue do
-    let(:issue_id) { 3 }
-    let(:issues_url) { Gitlab.config.issues_tracker.redmine.issues_url}
+  describe "url_for_issue" do
+    let(:issues_url) { ext_project.external_issue_tracker.issues_url}
     let(:ext_expected) do
-      issues_url.gsub(':id', issue_id.to_s)
+      issues_url.gsub(':id', issue.iid.to_s)
         .gsub(':project_id', ext_project.id.to_s)
         .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s)
     end
-    let(:int_expected) { polymorphic_path([project, issue]) }
+    let(:int_expected) { polymorphic_path([@project.namespace, project, issue]) }
 
     it "should return internal path if used internal tracker" do
       @project = project
-      url_for_issue(issue.iid).should match(int_expected)
+      expect(url_for_issue(issue.iid)).to match(int_expected)
     end
 
     it "should return path to external tracker" do
       @project = ext_project
 
-      url_for_issue(issue_id).should match(ext_expected)
+      expect(url_for_issue(issue.iid)).to match(ext_expected)
     end
 
     it "should return empty string if project nil" do
       @project = nil
 
-      url_for_issue(issue.iid).should eq ""
+      expect(url_for_issue(issue.iid)).to eq ""
     end
 
     describe "when external tracker was enabled and then config removed" do
       before do
         @project = ext_project
-        Gitlab.config.stub(:issues_tracker).and_return(nil)
+        allow(Gitlab.config).to receive(:issues_tracker).and_return(nil)
       end
 
-      it "should return internal path" do
-        url_for_issue(issue.iid).should match(polymorphic_path([@project, issue]))
+      it "should return external path" do
+        expect(url_for_issue(issue.iid)).to match(ext_expected)
       end
     end
   end
 
-  describe :url_for_new_issue do
-    let(:issues_url) { Gitlab.config.issues_tracker.redmine.new_issue_url}
+  describe '#url_for_new_issue' do
+    let(:issues_url) { ext_project.external_issue_tracker.new_issue_url }
     let(:ext_expected) do
       issues_url.gsub(':project_id', ext_project.id.to_s)
         .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s)
     end
-    let(:int_expected) { new_project_issue_path(project) }
+    let(:int_expected) { new_namespace_project_issue_path(project.namespace, project) }
 
     it "should return internal path if used internal tracker" do
       @project = project
-      url_for_new_issue.should match(int_expected)
+      expect(url_for_new_issue).to match(int_expected)
     end
 
     it "should return path to external tracker" do
       @project = ext_project
 
-      url_for_new_issue.should match(ext_expected)
+      expect(url_for_new_issue).to match(ext_expected)
     end
 
     it "should return empty string if project nil" do
       @project = nil
 
-      url_for_new_issue.should eq ""
+      expect(url_for_new_issue).to eq ""
     end
 
     describe "when external tracker was enabled and then config removed" do
       before do
         @project = ext_project
-        Gitlab.config.stub(:issues_tracker).and_return(nil)
+        allow(Gitlab.config).to receive(:issues_tracker).and_return(nil)
       end
 
       it "should return internal path" do
-        url_for_new_issue.should match(new_project_issue_path(@project))
+        expect(url_for_new_issue).to match(ext_expected)
       end
     end
   end
diff --git a/spec/helpers/merge_requests_helper.rb b/spec/helpers/merge_requests_helper.rb
index 5a317c4886bcad66df2ea37d75b15c200bb3dd4c..5262d64404814c8dc164d2cc8ee2d7cc96335f86 100644
--- a/spec/helpers/merge_requests_helper.rb
+++ b/spec/helpers/merge_requests_helper.rb
@@ -7,6 +7,6 @@ describe MergeRequestsHelper do
       [build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)]
     end
 
-    it { should eq('#1, #2, and #3') }
+    it { is_expected.to eq('#1, #2, and #3') }
   end
 end
diff --git a/spec/helpers/nav_helper_spec.rb b/spec/helpers/nav_helper_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e4d18d8bfc6f2421286ed9b7a37a382b41c8760d
--- /dev/null
+++ b/spec/helpers/nav_helper_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the NavHelper. For example:
+#
+# describe NavHelper do
+#   describe "string concat" do
+#     it "concats two strings with spaces" do
+#       expect(helper.concat_strings("this","that")).to eq("this that")
+#     end
+#   end
+# end
+describe NavHelper do
+  describe '#nav_menu_collapsed?' do
+    it 'returns true when the nav is collapsed in the cookie' do
+      helper.request.cookies[:collapsed_nav] = 'true'
+      expect(helper.nav_menu_collapsed?).to eq true
+    end
+
+    it 'returns false when the nav is not collapsed in the cookie' do
+      helper.request.cookies[:collapsed_nav] = 'false'
+      expect(helper.nav_menu_collapsed?).to eq false
+    end
+  end
+end
diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb
index 31ecdacf28e5523e2d2d8197bbd9a7b62511bc95..482cb33e94ff1f39d8e39365e769abb652a09f08 100644
--- a/spec/helpers/notifications_helper_spec.rb
+++ b/spec/helpers/notifications_helper_spec.rb
@@ -1,6 +1,9 @@
 require 'spec_helper'
 
 describe NotificationsHelper do
+  include FontAwesome::Rails::IconHelper
+  include IconsHelper
+
   describe 'notification_icon' do
     let(:notification) { double(disabled?: false, participating?: false, watch?: false) }
 
@@ -8,7 +11,7 @@ describe NotificationsHelper do
       before { notification.stub(disabled?: true) }
 
       it "has a red icon" do
-        notification_icon(notification).should match('class="fa fa-volume-off ns-mute"')
+        expect(notification_icon(notification)).to match('class="fa fa-volume-off ns-mute"')
       end
     end
 
@@ -16,7 +19,7 @@ describe NotificationsHelper do
       before { notification.stub(participating?: true) }
 
       it "has a blue icon" do
-        notification_icon(notification).should match('class="fa fa-volume-down ns-part"')
+        expect(notification_icon(notification)).to match('class="fa fa-volume-down ns-part"')
       end
     end
 
@@ -24,12 +27,12 @@ describe NotificationsHelper do
       before { notification.stub(watch?: true) }
 
       it "has a green icon" do
-        notification_icon(notification).should match('class="fa fa-volume-up ns-watch"')
+        expect(notification_icon(notification)).to match('class="fa fa-volume-up ns-watch"')
       end
     end
 
     it "has a blue icon" do
-      notification_icon(notification).should match('class="fa fa-circle-o ns-default"')
+      expect(notification_icon(notification)).to match('class="fa fa-circle-o ns-default"')
     end
   end
 end
diff --git a/spec/helpers/oauth_helper_spec.rb b/spec/helpers/oauth_helper_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..088c342fa13c7b34742261cf980256c5dea6be54
--- /dev/null
+++ b/spec/helpers/oauth_helper_spec.rb
@@ -0,0 +1,20 @@
+require "spec_helper"
+
+describe OauthHelper do
+  describe "additional_providers" do
+    it 'returns all enabled providers' do
+      allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :github] }
+      expect(helper.additional_providers).to include(*[:twitter, :github])
+    end
+
+    it 'does not return ldap provider' do
+      allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :ldapmain] }
+      expect(helper.additional_providers).to include(:twitter)
+    end
+
+    it 'returns empty array' do
+      allow(helper).to receive(:enabled_oauth_providers) { [] }
+      expect(helper.additional_providers).to eq([])
+    end
+  end
+end
\ No newline at end of file
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 114058e3095ef6bfc29dc476a5527dd5a1b872ca..0f78725e3d9f1a410075617941555f695b6fcece 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -1,23 +1,11 @@
 require 'spec_helper'
 
 describe ProjectsHelper do
-  describe '#project_issues_trackers' do
-    it "returns the correct issues trackers available" do
-      project_issues_trackers.should ==
-          "<option value=\"redmine\">Redmine</option>\n" \
-          "<option value=\"gitlab\">GitLab</option>"
-    end
-
-    it "returns the correct issues trackers available with current tracker 'gitlab' selected" do
-      project_issues_trackers('gitlab').should ==
-          "<option value=\"redmine\">Redmine</option>\n" \
-          "<option selected=\"selected\" value=\"gitlab\">GitLab</option>"
-    end
-
-    it "returns the correct issues trackers available with current tracker 'redmine' selected" do
-      project_issues_trackers('redmine').should ==
-          "<option selected=\"selected\" value=\"redmine\">Redmine</option>\n" \
-          "<option value=\"gitlab\">GitLab</option>"
+  describe "#project_status_css_class" do
+    it "returns appropriate class" do
+      expect(project_status_css_class("started")).to eq("active")
+      expect(project_status_css_class("failed")).to eq("danger")
+      expect(project_status_css_class("finished")).to eq("success")
     end
   end
 end
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 733f2754727329d401f795036c0bd3f2559b3840..b327f4f911a96d29dc78d6df6dae9ae4ee3c8313 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -13,7 +13,7 @@ describe SearchHelper do
       end
 
       it "it returns nil" do
-        search_autocomplete_opts("q").should be_nil
+        expect(search_autocomplete_opts("q")).to be_nil
       end
     end
 
@@ -25,29 +25,29 @@ describe SearchHelper do
       end
 
       it "includes Help sections" do
-        search_autocomplete_opts("hel").size.should == 9
+        expect(search_autocomplete_opts("hel").size).to eq(9)
       end
 
       it "includes default sections" do
-        search_autocomplete_opts("adm").size.should == 1
+        expect(search_autocomplete_opts("adm").size).to eq(1)
       end
 
       it "includes the user's groups" do
         create(:group).add_owner(user)
-        search_autocomplete_opts("gro").size.should == 1
+        expect(search_autocomplete_opts("gro").size).to eq(1)
       end
 
       it "includes the user's projects" do
         project = create(:project, namespace: create(:namespace, owner: user))
-        search_autocomplete_opts(project.name).size.should == 1
+        expect(search_autocomplete_opts(project.name).size).to eq(1)
       end
 
       context "with a current project" do
         before { @project = create(:project) }
 
         it "includes project-specific sections" do
-          search_autocomplete_opts("Files").size.should == 1
-          search_autocomplete_opts("Commits").size.should == 1
+          expect(search_autocomplete_opts("Files").size).to eq(1)
+          expect(search_autocomplete_opts("Commits").size).to eq(1)
         end
       end
     end
diff --git a/spec/helpers/submodule_helper_spec.rb b/spec/helpers/submodule_helper_spec.rb
index 41c9f038c266a5adeefa55cbdb75f77a675593a3..aef1108e3337843117948d52c36277d8115c260e 100644
--- a/spec/helpers/submodule_helper_spec.rb
+++ b/spec/helpers/submodule_helper_spec.rb
@@ -19,28 +19,28 @@ describe SubmoduleHelper do
         Gitlab.config.gitlab_shell.stub(ssh_port: 22) # set this just to be sure
         Gitlab.config.gitlab_shell.stub(ssh_path_prefix: Settings.send(:build_gitlab_shell_ssh_path_prefix))
         stub_url([ config.user, '@', config.host, ':gitlab-org/gitlab-ce.git' ].join(''))
-        submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ]
+        expect(submodule_links(submodule_item)).to eq([ namespace_project_path('gitlab-org', 'gitlab-ce'), namespace_project_tree_path('gitlab-org', 'gitlab-ce', 'hash') ])
       end
 
       it 'should detect ssh on non-standard port' do
         Gitlab.config.gitlab_shell.stub(ssh_port: 2222)
         Gitlab.config.gitlab_shell.stub(ssh_path_prefix: Settings.send(:build_gitlab_shell_ssh_path_prefix))
         stub_url([ 'ssh://', config.user, '@', config.host, ':2222/gitlab-org/gitlab-ce.git' ].join(''))
-        submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ]
+        expect(submodule_links(submodule_item)).to eq([ namespace_project_path('gitlab-org', 'gitlab-ce'), namespace_project_tree_path('gitlab-org', 'gitlab-ce', 'hash') ])
       end
 
       it 'should detect http on standard port' do
         Gitlab.config.gitlab.stub(port: 80)
         Gitlab.config.gitlab.stub(url: Settings.send(:build_gitlab_url))
         stub_url([ 'http://', config.host, '/gitlab-org/gitlab-ce.git' ].join(''))
-        submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ]
+        expect(submodule_links(submodule_item)).to eq([ namespace_project_path('gitlab-org', 'gitlab-ce'), namespace_project_tree_path('gitlab-org', 'gitlab-ce', 'hash') ])
       end
 
       it 'should detect http on non-standard port' do
         Gitlab.config.gitlab.stub(port: 3000)
         Gitlab.config.gitlab.stub(url: Settings.send(:build_gitlab_url))
         stub_url([ 'http://', config.host, ':3000/gitlab-org/gitlab-ce.git' ].join(''))
-        submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ]
+        expect(submodule_links(submodule_item)).to eq([ namespace_project_path('gitlab-org', 'gitlab-ce'), namespace_project_tree_path('gitlab-org', 'gitlab-ce', 'hash') ])
       end
 
       it 'should work with relative_url_root' do
@@ -48,67 +48,67 @@ describe SubmoduleHelper do
         Gitlab.config.gitlab.stub(relative_url_root: '/gitlab/root')
         Gitlab.config.gitlab.stub(url: Settings.send(:build_gitlab_url))
         stub_url([ 'http://', config.host, '/gitlab/root/gitlab-org/gitlab-ce.git' ].join(''))
-        submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ]
+        expect(submodule_links(submodule_item)).to eq([ namespace_project_path('gitlab-org', 'gitlab-ce'), namespace_project_tree_path('gitlab-org', 'gitlab-ce', 'hash') ])
       end
     end
 
     context 'submodule on github.com' do
       it 'should detect ssh' do
         stub_url('git@github.com:gitlab-org/gitlab-ce.git')
-        submodule_links(submodule_item).should == [ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ]
+        expect(submodule_links(submodule_item)).to eq([ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ])
       end
 
       it 'should detect http' do
         stub_url('http://github.com/gitlab-org/gitlab-ce.git')
-        submodule_links(submodule_item).should == [ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ]
+        expect(submodule_links(submodule_item)).to eq([ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ])
       end
 
       it 'should detect https' do
         stub_url('https://github.com/gitlab-org/gitlab-ce.git')
-        submodule_links(submodule_item).should == [ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ]
+        expect(submodule_links(submodule_item)).to eq([ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ])
       end
 
       it 'should return original with non-standard url' do
         stub_url('http://github.com/gitlab-org/gitlab-ce')
-        submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ]
+        expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ])
 
         stub_url('http://github.com/another/gitlab-org/gitlab-ce.git')
-        submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ]
+        expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ])
       end
     end
 
     context 'submodule on gitlab.com' do
       it 'should detect ssh' do
         stub_url('git@gitlab.com:gitlab-org/gitlab-ce.git')
-        submodule_links(submodule_item).should == [ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ]
+        expect(submodule_links(submodule_item)).to eq([ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ])
       end
 
       it 'should detect http' do
         stub_url('http://gitlab.com/gitlab-org/gitlab-ce.git')
-        submodule_links(submodule_item).should == [ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ]
+        expect(submodule_links(submodule_item)).to eq([ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ])
       end
 
       it 'should detect https' do
         stub_url('https://gitlab.com/gitlab-org/gitlab-ce.git')
-        submodule_links(submodule_item).should == [ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ]
+        expect(submodule_links(submodule_item)).to eq([ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ])
       end
 
       it 'should return original with non-standard url' do
         stub_url('http://gitlab.com/gitlab-org/gitlab-ce')
-        submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ]
+        expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ])
 
         stub_url('http://gitlab.com/another/gitlab-org/gitlab-ce.git')
-        submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ]
+        expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ])
       end
     end
 
     context 'submodule on unsupported' do
       it 'should return original' do
         stub_url('http://mygitserver.com/gitlab-org/gitlab-ce')
-        submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ]
+        expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ])
 
         stub_url('http://mygitserver.com/gitlab-org/gitlab-ce.git')
-        submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ]
+        expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ])
       end
     end
   end
diff --git a/spec/helpers/tab_helper_spec.rb b/spec/helpers/tab_helper_spec.rb
index fa8a3f554f75c892009d621a924eab1343415812..fc0ceecfbe7d8a10ca3b18710c80a29a3ba895bb 100644
--- a/spec/helpers/tab_helper_spec.rb
+++ b/spec/helpers/tab_helper_spec.rb
@@ -5,40 +5,40 @@ describe TabHelper do
 
   describe 'nav_link' do
     before do
-      controller.stub(:controller_name).and_return('foo')
+      allow(controller).to receive(:controller_name).and_return('foo')
       allow(self).to receive(:action_name).and_return('foo')
     end
 
     it "captures block output" do
-      nav_link { "Testing Blocks" }.should match(/Testing Blocks/)
+      expect(nav_link { "Testing Blocks" }).to match(/Testing Blocks/)
     end
 
     it "performs checks on the current controller" do
-      nav_link(controller: :foo).should match(/<li class="active">/)
-      nav_link(controller: :bar).should_not match(/active/)
-      nav_link(controller: [:foo, :bar]).should match(/active/)
+      expect(nav_link(controller: :foo)).to match(/<li class="active">/)
+      expect(nav_link(controller: :bar)).not_to match(/active/)
+      expect(nav_link(controller: [:foo, :bar])).to match(/active/)
     end
 
     it "performs checks on the current action" do
-      nav_link(action: :foo).should match(/<li class="active">/)
-      nav_link(action: :bar).should_not match(/active/)
-      nav_link(action: [:foo, :bar]).should match(/active/)
+      expect(nav_link(action: :foo)).to match(/<li class="active">/)
+      expect(nav_link(action: :bar)).not_to match(/active/)
+      expect(nav_link(action: [:foo, :bar])).to match(/active/)
     end
 
     it "performs checks on both controller and action when both are present" do
-      nav_link(controller: :bar, action: :foo).should_not match(/active/)
-      nav_link(controller: :foo, action: :bar).should_not match(/active/)
-      nav_link(controller: :foo, action: :foo).should match(/active/)
+      expect(nav_link(controller: :bar, action: :foo)).not_to match(/active/)
+      expect(nav_link(controller: :foo, action: :bar)).not_to match(/active/)
+      expect(nav_link(controller: :foo, action: :foo)).to match(/active/)
     end
 
     it "accepts a path shorthand" do
-      nav_link(path: 'foo#bar').should_not match(/active/)
-      nav_link(path: 'foo#foo').should match(/active/)
+      expect(nav_link(path: 'foo#bar')).not_to match(/active/)
+      expect(nav_link(path: 'foo#foo')).to match(/active/)
     end
 
     it "passes extra html options to the list element" do
-      nav_link(action: :foo, html_options: {class: 'home'}).should match(/<li class="home active">/)
-      nav_link(html_options: {class: 'active'}).should match(/<li class="active">/)
+      expect(nav_link(action: :foo, html_options: {class: 'home'})).to match(/<li class="home active">/)
+      expect(nav_link(html_options: {class: 'active'})).to match(/<li class="active">/)
     end
   end
 end
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8271e00f41b24f03669224eaf86cc7d2653efa71
--- /dev/null
+++ b/spec/helpers/tree_helper_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe TreeHelper do
+  describe 'flatten_tree' do
+    let(:project) { create(:project) }
+
+    before {
+      @repository = project.repository
+      @commit = project.repository.commit("e56497bb")
+    }
+
+    context "on a directory containing more than one file/directory" do
+      let(:tree_item) { double(name: "files", path: "files") }
+
+      it "should return the directory name" do
+        expect(flatten_tree(tree_item)).to match('files')
+      end
+    end
+
+    context "on a directory containing only one directory" do
+      let(:tree_item) { double(name: "foo", path: "foo") }
+
+      it "should return the flattened path" do
+        expect(flatten_tree(tree_item)).to match('foo/bar')
+      end
+    end
+  end
+end
diff --git a/spec/lib/disable_email_interceptor_spec.rb b/spec/lib/disable_email_interceptor_spec.rb
index 8bf6ee2ed50851d2c37746442366da96d0f539e6..06d5450688baf556d40bec2390f8f93878e6690e 100644
--- a/spec/lib/disable_email_interceptor_spec.rb
+++ b/spec/lib/disable_email_interceptor_spec.rb
@@ -6,7 +6,7 @@ describe DisableEmailInterceptor do
   end
 
   it 'should not send emails' do
-    Gitlab.config.gitlab.stub(:email_enabled).and_return(false)
+    allow(Gitlab.config.gitlab).to receive(:email_enabled).and_return(false)
     expect {
       deliver_mail
     }.not_to change(ActionMailer::Base.deliveries, :count)
diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb
index 7b3818ea5c8754962a922629b7844d1c0b06d576..ac602eac154bce6b5992dfe8a9149ff445fe2130 100644
--- a/spec/lib/extracts_path_spec.rb
+++ b/spec/lib/extracts_path_spec.rb
@@ -14,44 +14,46 @@ describe ExtractsPath do
   describe '#extract_ref' do
     it "returns an empty pair when no @project is set" do
       @project = nil
-      extract_ref('master/CHANGELOG').should == ['', '']
+      expect(extract_ref('master/CHANGELOG')).to eq(['', ''])
     end
 
     context "without a path" do
       it "extracts a valid branch" do
-        extract_ref('master').should == ['master', '']
+        expect(extract_ref('master')).to eq(['master', ''])
       end
 
       it "extracts a valid tag" do
-        extract_ref('v2.0.0').should == ['v2.0.0', '']
+        expect(extract_ref('v2.0.0')).to eq(['v2.0.0', ''])
       end
 
       it "extracts a valid commit ref without a path" do
-        extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062').should ==
+        expect(extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062')).to eq(
           ['f4b14494ef6abf3d144c28e4af0c20143383e062', '']
+        )
       end
 
       it "falls back to a primitive split for an invalid ref" do
-        extract_ref('stable').should == ['stable', '']
+        expect(extract_ref('stable')).to eq(['stable', ''])
       end
     end
 
     context "with a path" do
       it "extracts a valid branch" do
-        extract_ref('foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG']
+        expect(extract_ref('foo/bar/baz/CHANGELOG')).to eq(['foo/bar/baz', 'CHANGELOG'])
       end
 
       it "extracts a valid tag" do
-        extract_ref('v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG']
+        expect(extract_ref('v2.0.0/CHANGELOG')).to eq(['v2.0.0', 'CHANGELOG'])
       end
 
       it "extracts a valid commit SHA" do
-        extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should ==
+        expect(extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG')).to eq(
           ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG']
+        )
       end
 
       it "falls back to a primitive split for an invalid ref" do
-        extract_ref('stable/CHANGELOG').should == ['stable', 'CHANGELOG']
+        expect(extract_ref('stable/CHANGELOG')).to eq(['stable', 'CHANGELOG'])
       end
     end
   end
diff --git a/spec/lib/git_ref_validator_spec.rb b/spec/lib/git_ref_validator_spec.rb
index b2469c18395edab10b10724374ade915e0c0d9cc..4633b6f3934b9ddf7e00c1cf3ea35e10d3da9f57 100644
--- a/spec/lib/git_ref_validator_spec.rb
+++ b/spec/lib/git_ref_validator_spec.rb
@@ -1,20 +1,20 @@
 require 'spec_helper'
 
 describe Gitlab::GitRefValidator do
-  it { Gitlab::GitRefValidator.validate('feature/new').should be_true }
-  it { Gitlab::GitRefValidator.validate('implement_@all').should be_true }
-  it { Gitlab::GitRefValidator.validate('my_new_feature').should be_true }
-  it { Gitlab::GitRefValidator.validate('#1').should be_true }
-  it { Gitlab::GitRefValidator.validate('feature/~new/').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature/^new/').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature/:new/').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature/?new/').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature/*new/').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature/[new/').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature/new/').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature/new.').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature\@{').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature\new').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature//new').should be_false }
-  it { Gitlab::GitRefValidator.validate('feature new').should be_false }
+  it { expect(Gitlab::GitRefValidator.validate('feature/new')).to be_truthy }
+  it { expect(Gitlab::GitRefValidator.validate('implement_@all')).to be_truthy }
+  it { expect(Gitlab::GitRefValidator.validate('my_new_feature')).to be_truthy }
+  it { expect(Gitlab::GitRefValidator.validate('#1')).to be_truthy }
+  it { expect(Gitlab::GitRefValidator.validate('feature/~new/')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature/^new/')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature/:new/')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature/?new/')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature/*new/')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature/[new/')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature/new/')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature/new.')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature\@{')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature\new')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature//new')).to be_falsey }
+  it { expect(Gitlab::GitRefValidator.validate('feature new')).to be_falsey }
 end
diff --git a/spec/lib/gitlab/backend/grack_auth_spec.rb b/spec/lib/gitlab/backend/grack_auth_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d0aad54f677fa11e79a95c897a2689e91ae4de44
--- /dev/null
+++ b/spec/lib/gitlab/backend/grack_auth_spec.rb
@@ -0,0 +1,196 @@
+require "spec_helper"
+
+describe Grack::Auth do
+  let(:user)    { create(:user) }
+  let(:project) { create(:project) }
+
+  let(:app)   { lambda { |env| [200, {}, "Success!"] } }
+  let!(:auth) { Grack::Auth.new(app) }
+  let(:env) {
+    {
+      "rack.input" => "",
+      "REQUEST_METHOD" => "GET",
+      "QUERY_STRING" => "service=git-upload-pack"
+    }
+  }
+  let(:status) { auth.call(env).first }
+
+  describe "#call" do
+    context "when the project doesn't exist" do
+      before do
+        env["PATH_INFO"] = "doesnt/exist.git"
+      end
+
+      context "when no authentication is provided" do
+        it "responds with status 401" do
+          expect(status).to eq(401)
+        end
+      end
+
+      context "when username and password are provided" do
+        context "when authentication fails" do
+          before do
+            env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, "nope")
+          end
+
+          it "responds with status 401" do
+            expect(status).to eq(401)
+          end
+        end
+
+        context "when authentication succeeds" do
+          before do
+            env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password)
+          end
+
+          it "responds with status 404" do
+            expect(status).to eq(404)
+          end
+        end
+      end
+    end
+
+    context "when the project exists" do
+      before do
+        env["PATH_INFO"] = project.path_with_namespace + ".git"
+      end
+
+      context "when the project is public" do
+        before do
+          project.update_attribute(:visibility_level, Project::PUBLIC)
+        end
+
+        it "responds with status 200" do
+          expect(status).to eq(200)
+        end
+      end
+
+      context "when the project is private" do
+        before do
+          project.update_attribute(:visibility_level, Project::PRIVATE)
+        end
+
+        context "when no authentication is provided" do
+          it "responds with status 401" do
+            expect(status).to eq(401)
+          end
+        end
+
+        context "when username and password are provided" do
+          context "when authentication fails" do
+            before do
+              env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, "nope")
+            end
+
+            it "responds with status 401" do
+              expect(status).to eq(401)
+            end
+
+            context "when the user is IP banned" do
+              before do
+                expect(Rack::Attack::Allow2Ban).to receive(:filter).and_return(true)
+                allow_any_instance_of(Rack::Request).to receive(:ip).and_return('1.2.3.4')
+              end
+
+              it "responds with status 401" do
+                expect(status).to eq(401)
+              end
+            end
+          end
+
+          context "when authentication succeeds" do
+            before do
+              env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password)
+            end
+
+            context "when the user has access to the project" do
+              before do
+                project.team << [user, :master]
+              end
+
+              context "when the user is blocked" do
+                before do
+                  user.block
+                  project.team << [user, :master]
+                end
+
+                it "responds with status 404" do
+                  expect(status).to eq(404)
+                end
+              end
+
+              context "when the user isn't blocked" do
+                before do
+                 expect(Rack::Attack::Allow2Ban).to receive(:reset)
+                end
+
+                it "responds with status 200" do
+                  expect(status).to eq(200)
+                end
+              end
+
+              context "when blank password attempts follow a valid login" do
+                let(:options) { Gitlab.config.rack_attack.git_basic_auth }
+                let(:maxretry) { options[:maxretry] - 1 }
+                let(:ip) { '1.2.3.4' }
+
+                before do
+                  allow_any_instance_of(Rack::Request).to receive(:ip).and_return(ip)
+                  Rack::Attack::Allow2Ban.reset(ip, options)
+                end
+
+                after do
+                  Rack::Attack::Allow2Ban.reset(ip, options)
+                end
+
+                def attempt_login(include_password)
+                  password = include_password ? user.password : ""
+                  env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, password)
+                  Grack::Auth.new(app)
+                  auth.call(env).first
+                end
+
+                it "repeated attempts followed by successful attempt" do
+                  for n in 0..maxretry do
+                    expect(attempt_login(false)).to eq(401)
+                  end
+
+                  expect(attempt_login(true)).to eq(200)
+                  expect(Rack::Attack::Allow2Ban.send(:banned?, ip)).to eq(nil)
+
+                  for n in 0..maxretry do
+                    expect(attempt_login(false)).to eq(401)
+                  end
+                end
+              end
+            end
+
+            context "when the user doesn't have access to the project" do
+              it "responds with status 404" do
+                expect(status).to eq(404)
+              end
+            end
+          end
+        end
+
+        context "when a gitlab ci token is provided" do
+          let(:token) { "123" }
+
+          before do
+            gitlab_ci_service = project.build_gitlab_ci_service
+            gitlab_ci_service.active = true
+            gitlab_ci_service.token = token
+            gitlab_ci_service.project_url = "http://google.com"
+            gitlab_ci_service.save
+
+            env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials("gitlab-ci-token", token)
+          end
+
+          it "responds with status 200" do
+            expect(status).to eq(200)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/backend/rack_attack_helpers_spec.rb b/spec/lib/gitlab/backend/rack_attack_helpers_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2ac496fd669a62cb3b48b0dd9377d580a6df8bbf
--- /dev/null
+++ b/spec/lib/gitlab/backend/rack_attack_helpers_spec.rb
@@ -0,0 +1,35 @@
+require "spec_helper"
+
+describe 'RackAttackHelpers' do
+  describe 'reset' do
+    let(:discriminator) { 'test-key'}
+    let(:maxretry) { 5 }
+    let(:period) { 1.minute }
+    let(:options) { { findtime: period, bantime: 60, maxretry: maxretry } }
+
+    def do_filter
+      for i in 1..maxretry - 1 do
+        status = Rack::Attack::Allow2Ban.filter(discriminator, options) { true }
+        expect(status).to eq(false)
+      end
+    end
+
+    def do_reset
+      Rack::Attack::Allow2Ban.reset(discriminator, options)
+    end
+
+    before do
+      do_reset
+    end
+
+    after do
+      do_reset
+    end
+
+    it 'user is not banned after n - 1 retries' do
+      do_filter
+      do_reset
+      do_filter
+    end
+  end
+end
diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb
index f00ec0fa401504350dc1a0e155aeabf19e6230c5..27279465c1aece0b6f00bccfac48a57520386e9c 100644
--- a/spec/lib/gitlab/backend/shell_spec.rb
+++ b/spec/lib/gitlab/backend/shell_spec.rb
@@ -8,11 +8,11 @@ describe Gitlab::Shell do
     Project.stub(find: project)
   end
 
-  it { should respond_to :add_key }
-  it { should respond_to :remove_key }
-  it { should respond_to :add_repository }
-  it { should respond_to :remove_repository }
-  it { should respond_to :fork_repository }
+  it { is_expected.to respond_to :add_key }
+  it { is_expected.to respond_to :remove_key }
+  it { is_expected.to respond_to :add_repository }
+  it { is_expected.to respond_to :remove_repository }
+  it { is_expected.to respond_to :fork_repository }
 
-  it { gitlab_shell.url_to_repo('diaspora').should == Gitlab.config.gitlab_shell.ssh_path_prefix + "diaspora.git" }
+  it { expect(gitlab_shell.url_to_repo('diaspora')).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + "diaspora.git") }
 end
diff --git a/spec/lib/gitlab/bitbucket_import/client_spec.rb b/spec/lib/gitlab/bitbucket_import/client_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dd450e9967b338f0b0ffb2929fb1afd1749272c2
--- /dev/null
+++ b/spec/lib/gitlab/bitbucket_import/client_spec.rb
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe Gitlab::BitbucketImport::Client do
+  let(:token) { '123456' }
+  let(:secret) { 'secret' }
+  let(:client) { Gitlab::BitbucketImport::Client.new(token, secret) }
+
+  before do
+    Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "bitbucket")
+  end
+
+  it 'all OAuth client options are symbols' do
+    client.consumer.options.keys.each do |key|
+      expect(key).to be_kind_of(Symbol)
+    end
+  end
+end
diff --git a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f5523105848ced4551c48735d640ae8a49183ad1
--- /dev/null
+++ b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe Gitlab::BitbucketImport::ProjectCreator do
+  let(:user) { create(:user, bitbucket_access_token: "asdffg", bitbucket_access_token_secret: "sekret") }
+  let(:repo) { {
+    name: 'Vim',
+    slug: 'vim',
+    is_private: true,
+    owner: "asd"}.with_indifferent_access
+  }
+  let(:namespace){ create(:namespace) }
+
+  it 'creates project' do
+    allow_any_instance_of(Project).to receive(:add_import_job)
+    
+    project_creator = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, user)
+    project = project_creator.execute
+    
+    expect(project.import_url).to eq("ssh://git@bitbucket.org/asd/vim.git")
+    expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+  end
+end
diff --git a/spec/lib/gitlab/closing_issue_extractor_spec.rb b/spec/lib/gitlab/closing_issue_extractor_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c96ee78e5fdaea6801eed2e3c322d30045a7e054
--- /dev/null
+++ b/spec/lib/gitlab/closing_issue_extractor_spec.rb
@@ -0,0 +1,174 @@
+require 'spec_helper'
+
+describe Gitlab::ClosingIssueExtractor do
+  let(:project) { create(:project) }
+  let(:issue) { create(:issue, project: project) }
+  let(:iid1) { issue.iid }
+
+  describe :closed_by_message_in_project do
+    context 'with a single reference' do
+      it do
+        message = "Awesome commit (Closes ##{iid1})"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Awesome commit (closes ##{iid1})"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Closed ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "closed ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Closing ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "closing ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Close ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "close ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Awesome commit (Fixes ##{iid1})"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Awesome commit (fixes ##{iid1})"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Fixed ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "fixed ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Fixing ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "fixing ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Fix ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "fix ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Awesome commit (Resolves ##{iid1})"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Awesome commit (resolves ##{iid1})"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Resolved ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "resolved ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Resolving ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "resolving ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "Resolve ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+
+      it do
+        message = "resolve ##{iid1}"
+        expect(subject.closed_by_message_in_project(message, project)).to eq([issue])
+      end
+    end
+
+    context 'with multiple references' do
+      let(:other_issue) { create(:issue, project: project) }
+      let(:third_issue) { create(:issue, project: project) }
+      let(:iid2) { other_issue.iid }
+      let(:iid3) { third_issue.iid }
+
+      it 'fetches issues in single line message' do
+        message = "Closes ##{iid1} and fix ##{iid2}"
+
+        expect(subject.closed_by_message_in_project(message, project)).
+            to eq([issue, other_issue])
+      end
+
+      it 'fetches comma-separated issues references in single line message' do
+        message = "Closes ##{iid1}, closes ##{iid2}"
+
+        expect(subject.closed_by_message_in_project(message, project)).
+            to eq([issue, other_issue])
+      end
+
+      it 'fetches comma-separated issues numbers in single line message' do
+        message = "Closes ##{iid1}, ##{iid2} and ##{iid3}"
+
+        expect(subject.closed_by_message_in_project(message, project)).
+            to eq([issue, other_issue, third_issue])
+      end
+
+      it 'fetches issues in multi-line message' do
+        message = "Awesome commit (closes ##{iid1})\nAlso fixes ##{iid2}"
+
+        expect(subject.closed_by_message_in_project(message, project)).
+            to eq([issue, other_issue])
+      end
+
+      it 'fetches issues in hybrid message' do
+        message = "Awesome commit (closes ##{iid1})\n"\
+                  "Also fixing issues ##{iid2}, ##{iid3} and #4"
+
+        expect(subject.closed_by_message_in_project(message, project)).
+            to eq([issue, other_issue, third_issue])
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index cf0b5c282c1d7a75195dbb921f7708d497e68180..40eb45e37cafd9348b73200e5893312c01889672 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -11,11 +11,11 @@ describe Gitlab::Diff::File do
   describe :diff_lines do
     let(:diff_lines) { diff_file.diff_lines }
 
-    it { diff_lines.size.should == 30 }
-    it { diff_lines.first.should be_kind_of(Gitlab::Diff::Line) }
+    it { expect(diff_lines.size).to eq(30) }
+    it { expect(diff_lines.first).to be_kind_of(Gitlab::Diff::Line) }
   end
 
   describe :mode_changed? do
-    it { diff_file.mode_changed?.should be_false }
+    it { expect(diff_file.mode_changed?).to be_falsey }
   end
 end
diff --git a/spec/lib/gitlab/diff/parser_spec.rb b/spec/lib/gitlab/diff/parser_spec.rb
index 35b78260acd75eb6fddcc7f312ffb2e6b802bbba..918f6d0ead4f11b408d30f4fb06918558cdcdd30 100644
--- a/spec/lib/gitlab/diff/parser_spec.rb
+++ b/spec/lib/gitlab/diff/parser_spec.rb
@@ -50,43 +50,43 @@ eos
       @lines = parser.parse(diff.lines)
     end
 
-    it { @lines.size.should == 30 }
+    it { expect(@lines.size).to eq(30) }
 
     describe 'lines' do
       describe 'first line' do
         let(:line) { @lines.first }
 
-        it { line.type.should == 'match' }
-        it { line.old_pos.should == 6 }
-        it { line.new_pos.should == 6 }
-        it { line.text.should == '@@ -6,12 +6,18 @@ module Popen' }
+        it { expect(line.type).to eq('match') }
+        it { expect(line.old_pos).to eq(6) }
+        it { expect(line.new_pos).to eq(6) }
+        it { expect(line.text).to eq('@@ -6,12 +6,18 @@ module Popen') }
       end
 
       describe 'removal line' do
         let(:line) { @lines[10] }
 
-        it { line.type.should == 'old' }
-        it { line.old_pos.should == 14 }
-        it { line.new_pos.should == 13 }
-        it { line.text.should == '-    options = { chdir: path }' }
+        it { expect(line.type).to eq('old') }
+        it { expect(line.old_pos).to eq(14) }
+        it { expect(line.new_pos).to eq(13) }
+        it { expect(line.text).to eq('-    options = { chdir: path }') }
       end
 
       describe 'addition line' do
         let(:line) { @lines[16] }
 
-        it { line.type.should == 'new' }
-        it { line.old_pos.should == 15 }
-        it { line.new_pos.should == 18 }
-        it { line.text.should == '+    options = {' }
+        it { expect(line.type).to eq('new') }
+        it { expect(line.old_pos).to eq(15) }
+        it { expect(line.new_pos).to eq(18) }
+        it { expect(line.text).to eq('+    options = {') }
       end
 
       describe 'unchanged line' do
         let(:line) { @lines.last }
 
-        it { line.type.should == nil }
-        it { line.old_pos.should == 24 }
-        it { line.new_pos.should == 31 }
-        it { line.text.should == '       @cmd_output &lt;&lt; stderr.read' }
+        it { expect(line.type).to eq(nil) }
+        it { expect(line.old_pos).to eq(24) }
+        it { expect(line.new_pos).to eq(31) }
+        it { expect(line.text).to eq('       @cmd_output &lt;&lt; stderr.read') }
       end
     end
   end
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index fe0a6bbdabb2d951025c024b0f2f763da67ca1f2..39be9d646442c761595f5ef28952d97315558515 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -1,18 +1,81 @@
 require 'spec_helper'
 
 describe Gitlab::GitAccess do
-  let(:access) { Gitlab::GitAccess.new }
+  let(:access) { Gitlab::GitAccess.new(actor, project) }
   let(:project) { create(:project) }
   let(:user) { create(:user) }
+  let(:actor) { user }
 
-  describe 'download_allowed?' do
+  describe 'can_push_to_branch?' do
+    describe 'push to none protected branch' do
+      it "returns true if user is a master" do
+        project.team << [user, :master]
+        expect(access.can_push_to_branch?("random_branch")).to be_truthy
+      end
+
+      it "returns true if user is a developer" do
+        project.team << [user, :developer]
+        expect(access.can_push_to_branch?("random_branch")).to be_truthy
+      end
+
+      it "returns false if user is a reporter" do
+        project.team << [user, :reporter]
+        expect(access.can_push_to_branch?("random_branch")).to be_falsey
+      end
+    end
+
+    describe 'push to protected branch' do
+      before do
+        @branch = create :protected_branch, project: project
+      end
+      
+      it "returns true if user is a master" do
+        project.team << [user, :master]
+        expect(access.can_push_to_branch?(@branch.name)).to be_truthy
+      end
+
+      it "returns false if user is a developer" do
+        project.team << [user, :developer]
+        expect(access.can_push_to_branch?(@branch.name)).to be_falsey
+      end
+
+      it "returns false if user is a reporter" do
+        project.team << [user, :reporter]
+        expect(access.can_push_to_branch?(@branch.name)).to be_falsey
+      end
+    end
+
+    describe 'push to protected branch if allowed for developers' do
+      before do
+        @branch = create :protected_branch, project: project, developers_can_push: true
+      end
+      
+      it "returns true if user is a master" do
+        project.team << [user, :master]
+        expect(access.can_push_to_branch?(@branch.name)).to be_truthy
+      end
+
+      it "returns true if user is a developer" do
+        project.team << [user, :developer]
+        expect(access.can_push_to_branch?(@branch.name)).to be_truthy
+      end
+
+      it "returns false if user is a reporter" do
+        project.team << [user, :reporter]
+        expect(access.can_push_to_branch?(@branch.name)).to be_falsey
+      end
+    end
+
+  end
+
+  describe 'download_access_check' do
     describe 'master permissions' do
       before { project.team << [user, :master] }
 
       context 'pull code' do
-        subject { access.download_allowed?(user, project) }
+        subject { access.download_access_check }
 
-        it { should be_true }
+        it { expect(subject.allowed?).to be_truthy }
       end
     end
 
@@ -20,9 +83,9 @@ describe Gitlab::GitAccess do
       before { project.team << [user, :guest] }
 
       context 'pull code' do
-        subject { access.download_allowed?(user, project) }
+        subject { access.download_access_check }
 
-        it { should be_false }
+        it { expect(subject.allowed?).to be_falsey }
       end
     end
 
@@ -33,22 +96,42 @@ describe Gitlab::GitAccess do
       end
 
       context 'pull code' do
-        subject { access.download_allowed?(user, project) }
+        subject { access.download_access_check }
 
-        it { should be_false }
+        it { expect(subject.allowed?).to be_falsey }
       end
     end
 
     describe 'without acccess to project' do
       context 'pull code' do
-        subject { access.download_allowed?(user, project) }
+        subject { access.download_access_check }
+
+        it { expect(subject.allowed?).to be_falsey }
+      end
+    end
+
+    describe 'deploy key permissions' do
+      let(:key) { create(:deploy_key) }
+      let(:actor) { key }
+
+      context 'pull code' do
+        context 'allowed' do
+          before { key.projects << project }
+          subject { access.download_access_check }
+
+          it { expect(subject.allowed?).to be_truthy }
+        end
+
+        context 'denied' do
+          subject { access.download_access_check }
 
-        it { should be_false }
+          it { expect(subject.allowed?).to be_falsey }
+        end
       end
     end
   end
 
-  describe 'push_allowed?' do
+  describe 'push_access_check' do
     def protect_feature_branch
       create(:protected_branch, name: 'feature', project: project)
     end
@@ -110,6 +193,13 @@ describe Gitlab::GitAccess do
       }
     end
 
+    def self.updated_permissions_matrix
+      updated_permissions_matrix = permissions_matrix.dup
+      updated_permissions_matrix[:developer][:push_protected_branch] = true
+      updated_permissions_matrix[:developer][:push_all] = true
+      updated_permissions_matrix
+    end
+
     permissions_matrix.keys.each do |role|
       describe "#{role} access" do
         before { protect_feature_branch }
@@ -117,9 +207,26 @@ describe Gitlab::GitAccess do
 
         permissions_matrix[role].each do |action, allowed|
           context action do
-            subject { access.push_allowed?(user, project, changes[action]) }
+            subject { access.push_access_check(changes[action]) }
+
+            it { expect(subject.allowed?).to allowed ? be_truthy : be_falsey }
+          end
+        end
+      end
+    end
+
+    context "with enabled developers push to protected branches " do
+      updated_permissions_matrix.keys.each do |role|
+        describe "#{role} access" do
+          before { create(:protected_branch, name: 'feature', developers_can_push: true, project: project) }
+          before { project.team << [user, role] }
+
+          updated_permissions_matrix[role].each do |action, allowed|
+            context action do
+              subject { access.push_access_check(changes[action]) }
 
-            it { should allowed ? be_true : be_false }
+              it { expect(subject.allowed?).to allowed ? be_truthy : be_falsey }
+            end
           end
         end
       end
diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb
index ed5785b31e6828d6514d96634fb9032638f4dd1a..4cb91094cb3bf0bda9ff4352a3a4237e9c90d089 100644
--- a/spec/lib/gitlab/git_access_wiki_spec.rb
+++ b/spec/lib/gitlab/git_access_wiki_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
 describe Gitlab::GitAccessWiki do
-  let(:access) { Gitlab::GitAccessWiki.new }
+  let(:access) { Gitlab::GitAccessWiki.new(user, project) }
   let(:project) { create(:project) }
   let(:user) { create(:user) }
 
@@ -11,9 +11,9 @@ describe Gitlab::GitAccessWiki do
       project.team << [user, :developer]
     end
 
-    subject { access.push_allowed?(user, project, changes) }
+    subject { access.push_access_check(changes) }
 
-    it { should be_true }
+    it { expect(subject.allowed?).to be_truthy }
   end
 
   def changes
diff --git a/spec/lib/gitlab/github_import/client_spec.rb b/spec/lib/gitlab/github_import/client_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..26618120316ace4d5aef3ddf6eab3f5b7d546a21
--- /dev/null
+++ b/spec/lib/gitlab/github_import/client_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe Gitlab::GithubImport::Client do
+  let(:token) { '123456' }
+  let(:client) { Gitlab::GithubImport::Client.new(token) }
+
+  before do
+    Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "github")
+  end
+
+  it 'all OAuth2 client options are symbols' do
+    client.client.options.keys.each do |key|
+      expect(key).to be_kind_of(Symbol)
+    end
+  end
+end
diff --git a/spec/lib/gitlab/github_import/project_creator_spec.rb b/spec/lib/gitlab/github_import/project_creator_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8d594a112d4646378651e51af0c3d9691e248903
--- /dev/null
+++ b/spec/lib/gitlab/github_import/project_creator_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe Gitlab::GithubImport::ProjectCreator do
+  let(:user) { create(:user, github_access_token: "asdffg") }
+  let(:repo) { OpenStruct.new(
+    login: 'vim',
+    name: 'vim',
+    private: true,
+    full_name: 'asd/vim',
+    clone_url: "https://gitlab.com/asd/vim.git",
+    owner: OpenStruct.new(login: "john"))
+  }
+  let(:namespace){ create(:namespace) }
+
+  it 'creates project' do
+    allow_any_instance_of(Project).to receive(:add_import_job)
+    
+    project_creator = Gitlab::GithubImport::ProjectCreator.new(repo, namespace, user)
+    project = project_creator.execute
+    
+    expect(project.import_url).to eq("https://asdffg@gitlab.com/asd/vim.git")
+    expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+  end
+end
diff --git a/spec/lib/gitlab/gitlab_import/client_spec.rb b/spec/lib/gitlab/gitlab_import/client_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c511c51547409ac98519b97c4b4de59159c4d139
--- /dev/null
+++ b/spec/lib/gitlab/gitlab_import/client_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe Gitlab::GitlabImport::Client do
+  let(:token) { '123456' }
+  let(:client) { Gitlab::GitlabImport::Client.new(token) }
+
+  before do
+    Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "gitlab")
+  end
+
+  it 'all OAuth2 client options are symbols' do
+    client.client.options.keys.each do |key|
+      expect(key).to be_kind_of(Symbol)
+    end
+  end
+end
diff --git a/spec/lib/gitlab/gitlab_import/project_creator_spec.rb b/spec/lib/gitlab/gitlab_import/project_creator_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4c0d64ed1389930388a41b9d0384bddb2422dc65
--- /dev/null
+++ b/spec/lib/gitlab/gitlab_import/project_creator_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe Gitlab::GitlabImport::ProjectCreator do
+  let(:user) { create(:user, gitlab_access_token: "asdffg") }
+  let(:repo) { {
+    name: 'vim',
+    path: 'vim',
+    visibility_level: Gitlab::VisibilityLevel::PRIVATE,
+    path_with_namespace: 'asd/vim',
+    http_url_to_repo: "https://gitlab.com/asd/vim.git",
+    owner: {name: "john"}}.with_indifferent_access
+  }
+  let(:namespace){ create(:namespace) }
+
+  it 'creates project' do
+    allow_any_instance_of(Project).to receive(:add_import_job)
+    
+    project_creator = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, user)
+    project = project_creator.execute
+    
+    expect(project.import_url).to eq("https://oauth2:asdffg@gitlab.com/asd/vim.git")
+    expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+  end
+end
diff --git a/spec/lib/gitlab/gitlab_markdown_helper_spec.rb b/spec/lib/gitlab/gitlab_markdown_helper_spec.rb
index 540618a560305b1ed8650a9915e7459a28475af8..ab613193f41de7f355312961204c7aafc1d8074f 100644
--- a/spec/lib/gitlab/gitlab_markdown_helper_spec.rb
+++ b/spec/lib/gitlab/gitlab_markdown_helper_spec.rb
@@ -5,24 +5,24 @@ describe Gitlab::MarkdownHelper do
     %w(textile rdoc org creole wiki
        mediawiki rst adoc asciidoc asc).each do |type|
       it "returns true for #{type} files" do
-        Gitlab::MarkdownHelper.markup?("README.#{type}").should be_true
+        expect(Gitlab::MarkdownHelper.markup?("README.#{type}")).to be_truthy
       end
     end
 
     it 'returns false when given a non-markup filename' do
-      Gitlab::MarkdownHelper.markup?('README.rb').should_not be_true
+      expect(Gitlab::MarkdownHelper.markup?('README.rb')).not_to be_truthy
     end
   end
 
   describe '#gitlab_markdown?' do
     %w(mdown md markdown).each do |type|
       it "returns true for #{type} files" do
-        Gitlab::MarkdownHelper.gitlab_markdown?("README.#{type}").should be_true
+        expect(Gitlab::MarkdownHelper.gitlab_markdown?("README.#{type}")).to be_truthy
       end
     end
 
     it 'returns false when given a non-markdown filename' do
-      Gitlab::MarkdownHelper.gitlab_markdown?('README.rb').should_not be_true
+      expect(Gitlab::MarkdownHelper.gitlab_markdown?('README.rb')).not_to be_truthy
     end
   end
 end
diff --git a/spec/lib/gitlab/gitorious_import/project_creator.rb b/spec/lib/gitlab/gitorious_import/project_creator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cf2318bb3a2e6764600e2679a18ad388de0ea686
--- /dev/null
+++ b/spec/lib/gitlab/gitorious_import/project_creator.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe Gitlab::GitoriousImport::ProjectCreator do
+  let(:user) { create(:user) }
+  let(:repo) { Gitlab::GitoriousImport::Repository.new('foo/bar-baz-qux') }
+  let(:namespace){ create(:namespace) }
+
+  it 'creates project' do
+    allow_any_instance_of(Project).to receive(:add_import_job)
+
+    project_creator = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, user)
+    project_creator.execute
+    project = Project.last
+
+    expect(project.name).to eq("Bar Baz Qux")
+    expect(project.path).to eq("bar-baz-qux")
+    expect(project.namespace).to eq(namespace)
+    expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
+    expect(project.import_type).to eq("gitorious")
+    expect(project.import_source).to eq("foo/bar-baz-qux")
+    expect(project.import_url).to eq("https://gitorious.org/foo/bar-baz-qux.git")
+  end
+end
diff --git a/spec/lib/gitlab/ldap/access_spec.rb b/spec/lib/gitlab/ldap/access_spec.rb
index f4d5a9273968f736e2296c5edb0a58f13123b797..707a0521ab3a0a670c0ba5156ca7ad1d2f4b5aab 100644
--- a/spec/lib/gitlab/ldap/access_spec.rb
+++ b/spec/lib/gitlab/ldap/access_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
 
 describe Gitlab::LDAP::Access do
   let(:access) { Gitlab::LDAP::Access.new user }
-  let(:user) { create(:user, :ldap) }
+  let(:user) { create(:omniauth_user) }
 
   describe :allowed? do
     subject { access.allowed? }
@@ -10,7 +10,7 @@ describe Gitlab::LDAP::Access do
     context 'when the user cannot be found' do
       before { Gitlab::LDAP::Person.stub(find_by_dn: nil) }
 
-      it { should be_false }
+      it { is_expected.to be_falsey }
     end
 
     context 'when the user is found' do
@@ -19,13 +19,27 @@ describe Gitlab::LDAP::Access do
       context 'and the user is diabled via active directory' do
         before { Gitlab::LDAP::Person.stub(disabled_via_active_directory?: true) }
 
-        it { should be_false }
+        it { is_expected.to be_falsey }
+
+        it "should block user in GitLab" do
+          access.allowed?
+          user.should be_blocked
+        end
       end
 
       context 'and has no disabled flag in active diretory' do
-        before { Gitlab::LDAP::Person.stub(disabled_via_active_directory?: false) }
+        before do
+          user.block
+          
+          Gitlab::LDAP::Person.stub(disabled_via_active_directory?: false)
+        end
+
+        it { is_expected.to be_truthy }
 
-        it { should be_true }
+        it "should unblock user in GitLab" do
+          access.allowed?
+          user.should_not be_blocked
+        end
       end
 
       context 'without ActiveDirectory enabled' do
@@ -34,8 +48,8 @@ describe Gitlab::LDAP::Access do
           Gitlab::LDAP::Config.any_instance.stub(active_directory: false)
         end
 
-        it { should be_true }
+        it { is_expected.to be_truthy }
       end
     end
   end
-end
\ No newline at end of file
+end
diff --git a/spec/lib/gitlab/ldap/adapter_spec.rb b/spec/lib/gitlab/ldap/adapter_spec.rb
index 19347e47378c60b88e55369b90f1c6b5f09e895f..b609e4b38f21c28c21445bded0723288922e1906 100644
--- a/spec/lib/gitlab/ldap/adapter_spec.rb
+++ b/spec/lib/gitlab/ldap/adapter_spec.rb
@@ -12,20 +12,20 @@ describe Gitlab::LDAP::Adapter do
       context "and the result is non-empty" do
         before { ldap.stub(search: [:foo]) }
 
-        it { should be_true }
+        it { is_expected.to be_truthy }
       end
 
       context "and the result is empty" do
         before { ldap.stub(search: []) }
 
-        it { should be_false }
+        it { is_expected.to be_falsey }
       end
     end
 
     context "when the search encounters an error" do
       before { ldap.stub(search: nil, get_operation_result: double(code: 1, message: 'some error')) }
 
-      it { should be_false }
+      it { is_expected.to be_falsey }
     end
   end
 end
diff --git a/spec/lib/gitlab/ldap/authentication_spec.rb b/spec/lib/gitlab/ldap/authentication_spec.rb
index 0eb7c443b8bb60ca9d6452f43216b0f53699e830..8afc2b21f467ac848fadfea567ff32f3a2f27c39 100644
--- a/spec/lib/gitlab/ldap/authentication_spec.rb
+++ b/spec/lib/gitlab/ldap/authentication_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
 
 describe Gitlab::LDAP::Authentication do
   let(:klass) { Gitlab::LDAP::Authentication }
-  let(:user) { create(:user, :ldap, extern_uid: dn) }
+  let(:user) { create(:omniauth_user, extern_uid: dn) }
   let(:dn) { 'uid=john,ou=people,dc=example,dc=com' }
   let(:login) { 'john' }
   let(:password) { 'password' }
@@ -19,7 +19,7 @@ describe Gitlab::LDAP::Authentication do
       klass.any_instance.stub(adapter: double(:adapter,
         bind_as: double(:ldap_user, dn: dn)
       ))
-      expect(klass.login(login, password)).to be_true
+      expect(klass.login(login, password)).to be_truthy
     end
 
     it "is false if the user does not exist" do
@@ -27,27 +27,27 @@ describe Gitlab::LDAP::Authentication do
       klass.any_instance.stub(adapter: double(:adapter,
         bind_as: double(:ldap_user, dn: dn)
       ))
-      expect(klass.login(login, password)).to be_false
+      expect(klass.login(login, password)).to be_falsey
     end
 
     it "is false if authentication fails" do
       user
       # try only to fake the LDAP call
       klass.any_instance.stub(adapter: double(:adapter, bind_as: nil))
-      expect(klass.login(login, password)).to be_false
+      expect(klass.login(login, password)).to be_falsey
     end
 
     it "fails if ldap is disabled" do
       Gitlab::LDAP::Config.stub(enabled?: false)
-      expect(klass.login(login, password)).to be_false
+      expect(klass.login(login, password)).to be_falsey
     end
 
     it "fails if no login is supplied" do
-      expect(klass.login('', password)).to be_false
+      expect(klass.login('', password)).to be_falsey
     end
 
     it "fails if no password is supplied" do
-      expect(klass.login(login, '')).to be_false
+      expect(klass.login(login, '')).to be_falsey
     end
   end
 end
\ No newline at end of file
diff --git a/spec/lib/gitlab/ldap/config_spec.rb b/spec/lib/gitlab/ldap/config_spec.rb
index 3ebb8aae243a4e260dfd98db46c4d2408e91d30e..2df2beca7a601cd58cc17dd2da135cb3fe1a63e7 100644
--- a/spec/lib/gitlab/ldap/config_spec.rb
+++ b/spec/lib/gitlab/ldap/config_spec.rb
@@ -4,7 +4,7 @@ describe Gitlab::LDAP::Config do
   let(:config) { Gitlab::LDAP::Config.new provider }
   let(:provider) { 'ldapmain' }
 
-  describe :initalize do
+  describe '#initalize' do
     it 'requires a provider' do
       expect{ Gitlab::LDAP::Config.new }.to raise_error ArgumentError
     end
diff --git a/spec/lib/gitlab/ldap/user_spec.rb b/spec/lib/gitlab/ldap/user_spec.rb
index 726c9764e3d23ebf0faea6217fac03866e570531..4f93545feb699eb2d8903f045419653f0e9d7872 100644
--- a/spec/lib/gitlab/ldap/user_spec.rb
+++ b/spec/lib/gitlab/ldap/user_spec.rb
@@ -13,20 +13,37 @@ describe Gitlab::LDAP::User do
     double(uid: 'my-uid', provider: 'ldapmain', info: double(info))
   end
 
+  describe :changed? do
+    it "marks existing ldap user as changed" do
+      existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain')
+      expect(gl_user.changed?).to be_truthy
+    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_truthy
+    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_falsey
+    end
+  end
+
   describe :find_or_create do
     it "finds the user if already existing" do
-      existing_user = create(:user, extern_uid: 'my-uid', provider: 'ldapmain')
+      existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain')
 
       expect{ gl_user.save }.to_not change{ User.count }
     end
 
     it "connects to existing non-ldap user if the email matches" do
-      existing_user = create(:user, email: 'john@example.com')
+      existing_user = create(:omniauth_user, email: 'john@example.com', provider: "twitter")
       expect{ gl_user.save }.to_not change{ User.count }
 
       existing_user.reload
-      expect(existing_user.extern_uid).to eql 'my-uid'
-      expect(existing_user.provider).to eql 'ldapmain'
+      expect(existing_user.ldap_identity.extern_uid).to eql 'my-uid'
+      expect(existing_user.ldap_identity.provider).to eql 'ldapmain'
     end
 
     it "creates a new user if not found" do
diff --git a/spec/lib/gitlab/note_data_builder_spec.rb b/spec/lib/gitlab/note_data_builder_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..448cd0c6880dcd58c23174cc62de6deec7453c2a
--- /dev/null
+++ b/spec/lib/gitlab/note_data_builder_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe 'Gitlab::NoteDataBuilder' do
+  let(:project) { create(:project) }
+  let(:user) { create(:user) }
+  let(:data) { Gitlab::NoteDataBuilder.build(note, user) }
+  let(:note_url) { Gitlab::UrlBuilder.new(:note).build(note.id) }
+  let(:fixed_time) { Time.at(1425600000) } # Avoid time precision errors
+
+  before(:each) do
+    expect(data).to have_key(:object_attributes)
+    expect(data[:object_attributes]).to have_key(:url)
+    expect(data[:object_attributes][:url]).to eq(note_url)
+    expect(data[:object_kind]).to eq('note')
+    expect(data[:user]).to eq(user.hook_attrs)
+  end
+
+  describe 'When asking for a note on commit' do
+    let(:note) { create(:note_on_commit) }
+
+    it 'returns the note and commit-specific data' do
+      expect(data).to have_key(:commit)
+    end
+  end
+
+  describe 'When asking for a note on commit diff' do
+    let(:note) { create(:note_on_commit_diff) }
+
+    it 'returns the note and commit-specific data' do
+      expect(data).to have_key(:commit)
+    end
+  end
+
+  describe 'When asking for a note on issue' do
+    let(:issue) { create(:issue, created_at: fixed_time, updated_at: fixed_time) }
+    let(:note) { create(:note_on_issue, noteable_id: issue.id) }
+
+    it 'returns the note and issue-specific data' do
+      expect(data).to have_key(:issue)
+      expect(data[:issue]).to eq(issue.hook_attrs)
+    end
+  end
+
+  describe 'When asking for a note on merge request' do
+    let(:merge_request) { create(:merge_request, created_at: fixed_time, updated_at: fixed_time) }
+    let(:note) { create(:note_on_merge_request, noteable_id: merge_request.id) }
+
+    it 'returns the note and merge request data' do
+      expect(data).to have_key(:merge_request)
+      expect(data[:merge_request]).to eq(merge_request.hook_attrs)
+    end
+  end
+
+  describe 'When asking for a note on merge request diff' do
+    let(:merge_request) { create(:merge_request, created_at: fixed_time, updated_at: fixed_time) }
+    let(:note) { create(:note_on_merge_request_diff, noteable_id: merge_request.id) }
+
+    it 'returns the note and merge request diff data' do
+      expect(data).to have_key(:merge_request)
+      expect(data[:merge_request]).to eq(merge_request.hook_attrs)
+    end
+  end
+
+  describe 'When asking for a note on project snippet' do
+    let!(:snippet) { create(:project_snippet, created_at: fixed_time, updated_at: fixed_time) }
+    let!(:note) { create(:note_on_project_snippet, noteable_id: snippet.id) }
+
+    it 'returns the note and project snippet data' do
+      expect(data).to have_key(:snippet)
+      expect(data[:snippet]).to eq(snippet.hook_attrs)
+    end
+  end
+end
diff --git a/spec/lib/gitlab/oauth/user_spec.rb b/spec/lib/gitlab/oauth/user_spec.rb
index 8a83a1b25880130091bccd3402a54978ba1a16d9..44cdd1e4fab191ee3d8f90166c3e6274b5131e9d 100644
--- a/spec/lib/gitlab/oauth/user_spec.rb
+++ b/spec/lib/gitlab/oauth/user_spec.rb
@@ -8,23 +8,23 @@ describe Gitlab::OAuth::User do
   let(:auth_hash) { double(uid: uid, provider: provider, info: double(info_hash)) }
   let(:info_hash) do
     {
-      nickname: 'john',
+      nickname: '-john+gitlab-ETC%.git@gmail.com',
       name: 'John',
       email: 'john@mail.com'
     }
   end
 
   describe :persisted? do
-    let!(:existing_user) { create(:user, extern_uid: 'my-uid', provider: 'my-provider') }
+    let!(:existing_user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') }
 
     it "finds an existing user based on uid and provider (facebook)" do
       auth = double(info: double(name: 'John'), uid: 'my-uid', provider: 'my-provider')
-      expect( oauth_user.persisted? ).to be_true
+      expect( oauth_user.persisted? ).to be_truthy
     end
 
     it "returns false if use is not found in database" do
       auth_hash.stub(uid: 'non-existing')
-      expect( oauth_user.persisted? ).to be_false
+      expect( oauth_user.persisted? ).to be_falsey
     end
   end
 
@@ -39,8 +39,9 @@ describe Gitlab::OAuth::User do
           oauth_user.save
 
           expect(gl_user).to be_valid
-          expect(gl_user.extern_uid).to eql uid
-          expect(gl_user.provider).to eql 'twitter'
+          identity = gl_user.identities.first
+          expect(identity.extern_uid).to eql uid
+          expect(identity.provider).to eql 'twitter'
         end
       end
 
@@ -61,8 +62,8 @@ describe Gitlab::OAuth::User do
 
           it do
             oauth_user.save
-            gl_user.should be_valid
-            gl_user.should_not be_blocked
+            expect(gl_user).to be_valid
+            expect(gl_user).not_to be_blocked
           end
         end
 
@@ -71,8 +72,8 @@ describe Gitlab::OAuth::User do
 
           it do
             oauth_user.save
-            gl_user.should be_valid
-            gl_user.should be_blocked
+            expect(gl_user).to be_valid
+            expect(gl_user).to be_blocked
           end
         end
       end
@@ -88,8 +89,8 @@ describe Gitlab::OAuth::User do
 
           it do
             oauth_user.save
-            gl_user.should be_valid
-            gl_user.should_not be_blocked
+            expect(gl_user).to be_valid
+            expect(gl_user).not_to be_blocked
           end
         end
 
@@ -98,8 +99,8 @@ describe Gitlab::OAuth::User do
 
           it do
             oauth_user.save
-            gl_user.should be_valid
-            gl_user.should_not be_blocked
+            expect(gl_user).to be_valid
+            expect(gl_user).not_to be_blocked
           end
         end
       end
diff --git a/spec/lib/gitlab/popen_spec.rb b/spec/lib/gitlab/popen_spec.rb
index 76d506eb3c0bf385fbba06d42e3f935f90e9bef1..cd9d0456b25c29b51ad8ceceed11dc67d00af87c 100644
--- a/spec/lib/gitlab/popen_spec.rb
+++ b/spec/lib/gitlab/popen_spec.rb
@@ -13,8 +13,8 @@ describe 'Gitlab::Popen', no_db: true do
       @output, @status = @klass.new.popen(%W(ls), path)
     end
 
-    it { @status.should be_zero }
-    it { @output.should include('cache') }
+    it { expect(@status).to be_zero }
+    it { expect(@output).to include('cache') }
   end
 
   context 'non-zero status' do
@@ -22,8 +22,8 @@ describe 'Gitlab::Popen', no_db: true do
       @output, @status = @klass.new.popen(%W(cat NOTHING), path)
     end
 
-    it { @status.should == 1 }
-    it { @output.should include('No such file or directory') }
+    it { expect(@status).to eq(1) }
+    it { expect(@output).to include('No such file or directory') }
   end
 
   context 'unsafe string command' do
@@ -37,8 +37,8 @@ describe 'Gitlab::Popen', no_db: true do
       @output, @status = @klass.new.popen(%W(ls))
     end
 
-    it { @status.should be_zero }
-    it { @output.should include('spec') }
+    it { expect(@status).to be_zero }
+    it { expect(@output).to include('spec') }
   end
 
 end
diff --git a/spec/lib/gitlab/push_data_builder_spec.rb b/spec/lib/gitlab/push_data_builder_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1b8ba7b4d4333d300f62845d8bfccaf1060ced1a
--- /dev/null
+++ b/spec/lib/gitlab/push_data_builder_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe 'Gitlab::PushDataBuilder' do
+  let(:project) { create(:project) }
+  let(:user) { create(:user) }
+
+
+  describe :build_sample do
+    let(:data) { Gitlab::PushDataBuilder.build_sample(project, user) }
+
+    it { expect(data).to be_a(Hash) }
+    it { expect(data[:before]).to eq('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
+    it { expect(data[:after]).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
+    it { expect(data[:ref]).to eq('refs/heads/master') }
+    it { expect(data[:commits].size).to eq(3) }
+    it { expect(data[:repository][:git_http_url]).to eq(project.http_url_to_repo) }
+    it { expect(data[:repository][:git_ssh_url]).to eq(project.ssh_url_to_repo) }
+    it { expect(data[:repository][:visibility_level]).to eq(project.visibility_level) }
+    it { expect(data[:total_commits_count]).to eq(3) }
+  end
+
+  describe :build do
+    let(:data) do
+      Gitlab::PushDataBuilder.build(project,
+                                    user,
+                                    Gitlab::Git::BLANK_SHA,
+                                    '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b',
+                                    'refs/tags/v1.1.0')
+    end
+
+    it { expect(data).to be_a(Hash) }
+    it { expect(data[:before]).to eq(Gitlab::Git::BLANK_SHA) }
+    it { expect(data[:checkout_sha]).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
+    it { expect(data[:after]).to eq('8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b') }
+    it { expect(data[:ref]).to eq('refs/tags/v1.1.0') }
+    it { expect(data[:commits]).to be_empty }
+    it { expect(data[:total_commits_count]).to be_zero }
+  end
+end
diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb
index 23867df39dda8f7e7f32e452eecd830863308c1c..b3f4bb5aeda9137c09206e1409bd0f37da8dd8c8 100644
--- a/spec/lib/gitlab/reference_extractor_spec.rb
+++ b/spec/lib/gitlab/reference_extractor_spec.rb
@@ -3,52 +3,76 @@ require 'spec_helper'
 describe Gitlab::ReferenceExtractor do
   it 'extracts username references' do
     subject.analyze('this contains a @user reference', nil)
-    subject.users.should == [{ project: nil, id: 'user' }]
+    expect(subject.users).to eq([{ project: nil, id: 'user' }])
   end
 
   it 'extracts issue references' do
     subject.analyze('this one talks about issue #1234', nil)
-    subject.issues.should == [{ project: nil, id: '1234' }]
+    expect(subject.issues).to eq([{ project: nil, id: '1234' }])
   end
 
   it 'extracts JIRA issue references' do
-    Gitlab.config.gitlab.stub(:issues_tracker).and_return('jira')
     subject.analyze('this one talks about issue JIRA-1234', nil)
-    subject.issues.should == [{ project: nil, id: 'JIRA-1234' }]
+    expect(subject.issues).to eq([{ project: nil, id: 'JIRA-1234' }])
   end
 
   it 'extracts merge request references' do
     subject.analyze("and here's !43, a merge request", nil)
-    subject.merge_requests.should == [{ project: nil, id: '43' }]
+    expect(subject.merge_requests).to eq([{ project: nil, id: '43' }])
   end
 
   it 'extracts snippet ids' do
     subject.analyze('snippets like $12 get extracted as well', nil)
-    subject.snippets.should == [{ project: nil, id: '12' }]
+    expect(subject.snippets).to eq([{ project: nil, id: '12' }])
   end
 
   it 'extracts commit shas' do
     subject.analyze('commit shas 98cf0ae3 are pulled out as Strings', nil)
-    subject.commits.should == [{ project: nil, id: '98cf0ae3' }]
+    expect(subject.commits).to eq([{ project: nil, id: '98cf0ae3' }])
+  end
+
+  it 'extracts commit ranges' do
+    subject.analyze('here you go, a commit range: 98cf0ae3...98cf0ae4', nil)
+    expect(subject.commit_ranges).to eq([{ project: nil, id: '98cf0ae3...98cf0ae4' }])
   end
 
   it 'extracts multiple references and preserves their order' do
     subject.analyze('@me and @you both care about this', nil)
-    subject.users.should == [
+    expect(subject.users).to eq([
       { project: nil, id: 'me' },
       { project: nil, id: 'you' }
-    ]
+    ])
   end
 
   it 'leaves the original note unmodified' do
     text = 'issue #123 is just the worst, @user'
     subject.analyze(text, nil)
-    text.should == 'issue #123 is just the worst, @user'
+    expect(text).to eq('issue #123 is just the worst, @user')
+  end
+
+  it 'extracts no references for <pre>..</pre> blocks' do
+    subject.analyze("<pre>def puts '#1 issue'\nend\n</pre>```", nil)
+    expect(subject.issues).to be_blank
+  end
+
+  it 'extracts no references for <code>..</code> blocks' do
+    subject.analyze("<code>def puts '!1 request'\nend\n</code>```", nil)
+    expect(subject.merge_requests).to be_blank
+  end
+
+  it 'extracts no references for code blocks with language' do
+    subject.analyze("this code:\n```ruby\ndef puts '#1 issue'\nend\n```", nil)
+    expect(subject.issues).to be_blank
+  end
+
+  it 'extracts issue references for invalid code blocks' do
+    subject.analyze('test: ```this one talks about issue #1234```', nil)
+    expect(subject.issues).to eq([{ project: nil, id: '1234' }])
   end
 
   it 'handles all possible kinds of references' do
     accessors = Gitlab::Markdown::TYPES.map { |t| "#{t}s".to_sym }
-    subject.should respond_to(*accessors)
+    expect(subject).to respond_to(*accessors)
   end
 
   context 'with a project' do
@@ -63,7 +87,7 @@ describe Gitlab::ReferenceExtractor do
       project.team << [@u_bar, :guest]
 
       subject.analyze('@foo, @baduser, @bar, and @offteam', project)
-      subject.users_for(project).should == [@u_foo, @u_bar]
+      expect(subject.users_for(project)).to eq([@u_foo, @u_bar])
     end
 
     it 'accesses valid issue objects' do
@@ -71,7 +95,7 @@ describe Gitlab::ReferenceExtractor do
       @i1 = create(:issue, project: project)
 
       subject.analyze("##{@i0.iid}, ##{@i1.iid}, and #999.", project)
-      subject.issues_for(project).should == [@i0, @i1]
+      expect(subject.issues_for(project)).to eq([@i0, @i1])
     end
 
     it 'accesses valid merge requests' do
@@ -79,7 +103,7 @@ describe Gitlab::ReferenceExtractor do
       @m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'bbb')
 
       subject.analyze("!999, !#{@m1.iid}, and !#{@m0.iid}.", project)
-      subject.merge_requests_for(project).should == [@m1, @m0]
+      expect(subject.merge_requests_for(project)).to eq([@m1, @m0])
     end
 
     it 'accesses valid snippets' do
@@ -88,7 +112,7 @@ describe Gitlab::ReferenceExtractor do
       @s2 = create(:project_snippet)
 
       subject.analyze("$#{@s0.id}, $999, $#{@s2.id}, $#{@s1.id}", project)
-      subject.snippets_for(project).should == [@s0, @s1]
+      expect(subject.snippets_for(project)).to eq([@s0, @s1])
     end
 
     it 'accesses valid commits' do
@@ -97,9 +121,37 @@ describe Gitlab::ReferenceExtractor do
       subject.analyze("this references commits #{commit.sha[0..6]} and 012345",
                       project)
       extracted = subject.commits_for(project)
-      extracted.should have(1).item
-      extracted[0].sha.should == commit.sha
-      extracted[0].message.should == commit.message
+      expect(extracted.size).to eq(1)
+      expect(extracted[0].sha).to eq(commit.sha)
+      expect(extracted[0].message).to eq(commit.message)
     end
+
+    it 'accesses valid commit ranges' do
+      commit = project.repository.commit('master')
+      earlier_commit = project.repository.commit('master~2')
+
+      subject.analyze("this references commits #{earlier_commit.sha[0..6]}...#{commit.sha[0..6]}",
+                      project)
+      extracted = subject.commit_ranges_for(project)
+      expect(extracted.size).to eq(1)
+      expect(extracted[0][0].sha).to eq(earlier_commit.sha)
+      expect(extracted[0][0].message).to eq(earlier_commit.message)
+      expect(extracted[0][1].sha).to eq(commit.sha)
+      expect(extracted[0][1].message).to eq(commit.message)
+    end
+  end
+
+  context 'with a project with an underscore' do
+    let(:project) { create(:project, path: 'test_project') }
+    let(:issue) { create(:issue, project: project) }
+
+    it 'handles project issue references' do
+      subject.analyze("this refers issue #{project.path_with_namespace}##{issue.iid}",
+          project)
+      extracted = subject.issues_for(project)
+      expect(extracted.size).to eq(1)
+      expect(extracted).to eq([issue])
+    end
+
   end
 end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index a3aae7771bdef18065cb6e7c03b4a227273d022b..1db9f15b790f2ffd815b5202b46c7f0e06810f81 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -2,20 +2,20 @@ require 'spec_helper'
 
 describe Gitlab::Regex do
   describe 'path regex' do
-    it { 'gitlab-ce'.should match(Gitlab::Regex.path_regex) }
-    it { 'gitlab_git'.should match(Gitlab::Regex.path_regex) }
-    it { '_underscore.js'.should match(Gitlab::Regex.path_regex) }
-    it { '100px.com'.should match(Gitlab::Regex.path_regex) }
-    it { '?gitlab'.should_not match(Gitlab::Regex.path_regex) }
-    it { 'git lab'.should_not match(Gitlab::Regex.path_regex) }
-    it { 'gitlab.git'.should_not match(Gitlab::Regex.path_regex) }
+    it { expect('gitlab-ce').to match(Gitlab::Regex.path_regex) }
+    it { expect('gitlab_git').to match(Gitlab::Regex.path_regex) }
+    it { expect('_underscore.js').to match(Gitlab::Regex.path_regex) }
+    it { expect('100px.com').to match(Gitlab::Regex.path_regex) }
+    it { expect('?gitlab').not_to match(Gitlab::Regex.path_regex) }
+    it { expect('git lab').not_to match(Gitlab::Regex.path_regex) }
+    it { expect('gitlab.git').not_to match(Gitlab::Regex.path_regex) }
   end
 
   describe 'project name regex' do
-    it { 'gitlab-ce'.should match(Gitlab::Regex.project_name_regex) }
-    it { 'GitLab CE'.should match(Gitlab::Regex.project_name_regex) }
-    it { '100 lines'.should match(Gitlab::Regex.project_name_regex) }
-    it { 'gitlab.git'.should match(Gitlab::Regex.project_name_regex) }
-    it { '?gitlab'.should_not match(Gitlab::Regex.project_name_regex) }
+    it { expect('gitlab-ce').to match(Gitlab::Regex.project_name_regex) }
+    it { expect('GitLab CE').to match(Gitlab::Regex.project_name_regex) }
+    it { expect('100 lines').to match(Gitlab::Regex.project_name_regex) }
+    it { expect('gitlab.git').to match(Gitlab::Regex.project_name_regex) }
+    it { expect('?gitlab').not_to match(Gitlab::Regex.project_name_regex) }
   end
 end
diff --git a/spec/lib/gitlab/satellite/action_spec.rb b/spec/lib/gitlab/satellite/action_spec.rb
index 3eb1258d67ea61fd0872f2348c60cf51d3a27a4f..28e3d64ee2be0528484216f6dac785cd74de7339 100644
--- a/spec/lib/gitlab/satellite/action_spec.rb
+++ b/spec/lib/gitlab/satellite/action_spec.rb
@@ -6,7 +6,7 @@ describe 'Gitlab::Satellite::Action' do
 
   describe '#prepare_satellite!' do
     it 'should be able to fetch timeout from conf' do
-      Gitlab::Satellite::Action::DEFAULT_OPTIONS[:git_timeout].should == 30.seconds
+      expect(Gitlab::Satellite::Action::DEFAULT_OPTIONS[:git_timeout]).to eq(30.seconds)
     end
 
     it 'create a repository with a parking branch and one remote: origin' do
@@ -15,22 +15,22 @@ describe 'Gitlab::Satellite::Action' do
       #now lets dirty it up
 
       starting_remote_count = repo.git.list_remotes.size
-      starting_remote_count.should >= 1
+      expect(starting_remote_count).to be >= 1
       #kind of hookey way to add a second remote
       origin_uri = repo.git.remote({v: true}).split(" ")[1]
     begin
       repo.git.remote({raise: true}, 'add', 'another-remote', origin_uri)
       repo.git.branch({raise: true}, 'a-new-branch')
 
-      repo.heads.size.should > (starting_remote_count)
-      repo.git.remote().split(" ").size.should > (starting_remote_count)
+      expect(repo.heads.size).to be > (starting_remote_count)
+      expect(repo.git.remote().split(" ").size).to be > (starting_remote_count)
     rescue
     end
 
       repo.git.config({}, "user.name", "#{user.name} -- foo")
       repo.git.config({}, "user.email", "#{user.email} -- foo")
-      repo.config['user.name'].should =="#{user.name} -- foo"
-      repo.config['user.email'].should =="#{user.email} -- foo"
+      expect(repo.config['user.name']).to eq("#{user.name} -- foo")
+      expect(repo.config['user.email']).to eq("#{user.email} -- foo")
 
 
       #These must happen in the context of the satellite directory...
@@ -42,13 +42,13 @@ describe 'Gitlab::Satellite::Action' do
 
       #verify it's clean
       heads = repo.heads.map(&:name)
-      heads.size.should == 1
-      heads.include?(Gitlab::Satellite::Satellite::PARKING_BRANCH).should == true
+      expect(heads.size).to eq(1)
+      expect(heads.include?(Gitlab::Satellite::Satellite::PARKING_BRANCH)).to eq(true)
       remotes = repo.git.remote().split(' ')
-      remotes.size.should == 1
-      remotes.include?('origin').should == true
-      repo.config['user.name'].should ==user.name
-      repo.config['user.email'].should ==user.email
+      expect(remotes.size).to eq(1)
+      expect(remotes.include?('origin')).to eq(true)
+      expect(repo.config['user.name']).to eq(user.name)
+      expect(repo.config['user.email']).to eq(user.email)
     end
   end
 
@@ -61,16 +61,16 @@ describe 'Gitlab::Satellite::Action' do
       #set assumptions
       FileUtils.rm_f(project.satellite.lock_file)
 
-      File.exists?(project.satellite.lock_file).should be_false
+      expect(File.exists?(project.satellite.lock_file)).to be_falsey
 
       satellite_action = Gitlab::Satellite::Action.new(user, project)
       satellite_action.send(:in_locked_and_timed_satellite) do |sat_repo|
-        repo.should == sat_repo
-        (File.exists? project.satellite.lock_file).should be_true
+        expect(repo).to eq(sat_repo)
+        expect(File.exists? project.satellite.lock_file).to be_truthy
         called = true
       end
 
-      called.should be_true
+      expect(called).to be_truthy
 
     end
 
@@ -80,19 +80,19 @@ describe 'Gitlab::Satellite::Action' do
 
       # Set base assumptions
       if File.exists? project.satellite.lock_file
-        FileLockStatusChecker.new(project.satellite.lock_file).flocked?.should be_false
+        expect(FileLockStatusChecker.new(project.satellite.lock_file).flocked?).to be_falsey
       end
 
       satellite_action = Gitlab::Satellite::Action.new(user, project)
       satellite_action.send(:in_locked_and_timed_satellite) do |sat_repo|
         called = true
-        repo.should == sat_repo
-        (File.exists? project.satellite.lock_file).should be_true
-        FileLockStatusChecker.new(project.satellite.lock_file).flocked?.should be_true
+        expect(repo).to eq(sat_repo)
+        expect(File.exists? project.satellite.lock_file).to be_truthy
+        expect(FileLockStatusChecker.new(project.satellite.lock_file).flocked?).to be_truthy
       end
 
-      called.should be_true
-      FileLockStatusChecker.new(project.satellite.lock_file).flocked?.should be_false
+      expect(called).to be_truthy
+      expect(FileLockStatusChecker.new(project.satellite.lock_file).flocked?).to be_falsey
 
     end
 
diff --git a/spec/lib/gitlab/satellite/merge_action_spec.rb b/spec/lib/gitlab/satellite/merge_action_spec.rb
index 479a73a10817ed817efb7b7712f01dcdd02b3150..915e3ff0e5167219787780ca4b7f994fb1e2cb59 100644
--- a/spec/lib/gitlab/satellite/merge_action_spec.rb
+++ b/spec/lib/gitlab/satellite/merge_action_spec.rb
@@ -13,9 +13,9 @@ describe 'Gitlab::Satellite::MergeAction' do
 
   describe '#commits_between' do
     def verify_commits(commits, first_commit_sha, last_commit_sha)
-      commits.each { |commit| commit.class.should == Gitlab::Git::Commit }
-      commits.first.id.should == first_commit_sha
-      commits.last.id.should == last_commit_sha
+      commits.each { |commit| expect(commit.class).to eq(Gitlab::Git::Commit) }
+      expect(commits.first.id).to eq(first_commit_sha)
+      expect(commits.last.id).to eq(last_commit_sha)
     end
 
     context 'on fork' do
@@ -35,7 +35,7 @@ describe 'Gitlab::Satellite::MergeAction' do
   describe '#format_patch' do
     def verify_content(patch)
       sample_compare.commits.each do |commit|
-        patch.include?(commit).should be_true
+        expect(patch.include?(commit)).to be_truthy
       end
     end
 
@@ -57,11 +57,11 @@ describe 'Gitlab::Satellite::MergeAction' do
   describe '#diffs_between_satellite tested against diff_in_satellite' do
     def is_a_matching_diff(diff, diffs)
       diff_count = diff.scan('diff --git').size
-      diff_count.should >= 1
-      diffs.size.should == diff_count
+      expect(diff_count).to be >= 1
+      expect(diffs.size).to eq(diff_count)
       diffs.each do |a_diff|
-        a_diff.class.should == Gitlab::Git::Diff
-        (diff.include? a_diff.diff).should be_true
+        expect(a_diff.class).to eq(Gitlab::Git::Diff)
+        expect(diff.include? a_diff.diff).to be_truthy
       end
     end
 
@@ -82,23 +82,23 @@ describe 'Gitlab::Satellite::MergeAction' do
 
   describe '#can_be_merged?' do
     context 'on fork' do
-      it { Gitlab::Satellite::MergeAction.new(
+      it { expect(Gitlab::Satellite::MergeAction.new(
         merge_request_fork.author,
-        merge_request_fork).can_be_merged?.should be_true }
+        merge_request_fork).can_be_merged?).to be_truthy }
 
-      it { Gitlab::Satellite::MergeAction.new(
+      it { expect(Gitlab::Satellite::MergeAction.new(
         merge_request_fork_with_conflict.author,
-        merge_request_fork_with_conflict).can_be_merged?.should be_false }
+        merge_request_fork_with_conflict).can_be_merged?).to be_falsey }
     end
 
     context 'between branches' do
-      it { Gitlab::Satellite::MergeAction.new(
+      it { expect(Gitlab::Satellite::MergeAction.new(
         merge_request.author,
-        merge_request).can_be_merged?.should be_true }
+        merge_request).can_be_merged?).to be_truthy }
 
-      it { Gitlab::Satellite::MergeAction.new(
+      it { expect(Gitlab::Satellite::MergeAction.new(
         merge_request_with_conflict.author,
-        merge_request_with_conflict).can_be_merged?.should be_false }
+        merge_request_with_conflict).can_be_merged?).to be_falsey }
     end
   end
 end
diff --git a/spec/lib/gitlab/upgrader_spec.rb b/spec/lib/gitlab/upgrader_spec.rb
index 2b254d6b3a6791ae748d629d13cc507b211ec432..ce3ea6c260aa66659caa758c328cb00f8a3a9fcf 100644
--- a/spec/lib/gitlab/upgrader_spec.rb
+++ b/spec/lib/gitlab/upgrader_spec.rb
@@ -5,20 +5,20 @@ describe Gitlab::Upgrader do
   let(:current_version) { Gitlab::VERSION }
 
   describe 'current_version_raw' do
-    it { upgrader.current_version_raw.should == current_version }
+    it { expect(upgrader.current_version_raw).to eq(current_version) }
   end
 
   describe 'latest_version?' do
     it 'should be true if newest version' do
       upgrader.stub(latest_version_raw: current_version)
-      upgrader.latest_version?.should be_true
+      expect(upgrader.latest_version?).to be_truthy
     end
   end
 
   describe 'latest_version_raw' do
     it 'should be latest version for GitLab 5' do
       upgrader.stub(current_version_raw: "5.3.0")
-      upgrader.latest_version_raw.should == "v5.4.2"
+      expect(upgrader.latest_version_raw).to eq("v5.4.2")
     end
   end
 end
diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb
index eb47bee8336b6141c84c4eb4a99e37c779fce225..5153ed15af3f865fed83d30545d9d99a82685639 100644
--- a/spec/lib/gitlab/url_builder_spec.rb
+++ b/spec/lib/gitlab/url_builder_spec.rb
@@ -5,7 +5,73 @@ describe Gitlab::UrlBuilder do
     it 'returns the issue url' do
       issue = create(:issue)
       url = Gitlab::UrlBuilder.new(:issue).build(issue.id)
-      expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.to_param}/issues/#{issue.iid}"
+      expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}"
+    end
+  end
+
+  describe 'When asking for an merge request' do
+    it 'returns the merge request url' do
+      merge_request = create(:merge_request)
+      url = Gitlab::UrlBuilder.new(:merge_request).build(merge_request.id)
+      expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}"
+    end
+  end
+
+  describe 'When asking for a note on commit' do
+    let(:note) { create(:note_on_commit) }
+    let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) }
+
+    it 'returns the note url' do
+      expect(url).to eq "#{Settings.gitlab['url']}/#{note.project.path_with_namespace}/commit/#{note.commit_id}#note_#{note.id}"
+    end
+  end
+
+  describe 'When asking for a note on commit diff' do
+    let(:note) { create(:note_on_commit_diff) }
+    let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) }
+
+    it 'returns the note url' do
+      expect(url).to eq "#{Settings.gitlab['url']}/#{note.project.path_with_namespace}/commit/#{note.commit_id}#note_#{note.id}"
+    end
+  end
+
+  describe 'When asking for a note on issue' do
+    let(:issue) { create(:issue) }
+    let(:note) { create(:note_on_issue, noteable_id: issue.id) }
+    let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) }
+
+    it 'returns the note url' do
+      expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}#note_#{note.id}"
+    end
+  end
+
+  describe 'When asking for a note on merge request' do
+    let(:merge_request) { create(:merge_request) }
+    let(:note) { create(:note_on_merge_request, noteable_id: merge_request.id) }
+    let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) }
+
+    it 'returns the note url' do
+      expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}#note_#{note.id}"
+    end
+  end
+
+  describe 'When asking for a note on merge request diff' do
+    let(:merge_request) { create(:merge_request) }
+    let(:note) { create(:note_on_merge_request_diff, noteable_id: merge_request.id) }
+    let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) }
+
+    it 'returns the note url' do
+      expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}#note_#{note.id}"
+    end
+  end
+
+  describe 'When asking for a note on project snippet' do
+    let(:snippet) { create(:project_snippet) }
+    let(:note) { create(:note_on_project_snippet, noteable_id: snippet.id) }
+    let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) }
+
+    it 'returns the note url' do
+      expect(url).to eq "#{Settings.gitlab['url']}/#{snippet.project.path_with_namespace}/snippets/#{note.noteable_id}#note_#{note.id}"
     end
   end
 end
diff --git a/spec/lib/gitlab/version_info_spec.rb b/spec/lib/gitlab/version_info_spec.rb
index 94dccf7a4e5aeb59509855d1e2ea5f1921d3dad7..5afeb1c1ec3048de7691da7e2f8f0991200b7187 100644
--- a/spec/lib/gitlab/version_info_spec.rb
+++ b/spec/lib/gitlab/version_info_spec.rb
@@ -12,58 +12,58 @@ describe 'Gitlab::VersionInfo', no_db: true do
   end
 
   context '>' do
-    it { @v2_0_0.should > @v1_1_0 }
-    it { @v1_1_0.should > @v1_0_1 }
-    it { @v1_0_1.should > @v1_0_0 }
-    it { @v1_0_0.should > @v0_1_0 }
-    it { @v0_1_0.should > @v0_0_1 }
+    it { expect(@v2_0_0).to be > @v1_1_0 }
+    it { expect(@v1_1_0).to be > @v1_0_1 }
+    it { expect(@v1_0_1).to be > @v1_0_0 }
+    it { expect(@v1_0_0).to be > @v0_1_0 }
+    it { expect(@v0_1_0).to be > @v0_0_1 }
   end
 
   context '>=' do
-    it { @v2_0_0.should >= Gitlab::VersionInfo.new(2, 0, 0) }
-    it { @v2_0_0.should >= @v1_1_0 }
+    it { expect(@v2_0_0).to be >= Gitlab::VersionInfo.new(2, 0, 0) }
+    it { expect(@v2_0_0).to be >= @v1_1_0 }
   end
 
   context '<' do
-    it { @v0_0_1.should < @v0_1_0 }
-    it { @v0_1_0.should < @v1_0_0 }
-    it { @v1_0_0.should < @v1_0_1 }
-    it { @v1_0_1.should < @v1_1_0 }
-    it { @v1_1_0.should < @v2_0_0 }
+    it { expect(@v0_0_1).to be < @v0_1_0 }
+    it { expect(@v0_1_0).to be < @v1_0_0 }
+    it { expect(@v1_0_0).to be < @v1_0_1 }
+    it { expect(@v1_0_1).to be < @v1_1_0 }
+    it { expect(@v1_1_0).to be < @v2_0_0 }
   end
 
   context '<=' do
-    it { @v0_0_1.should <= Gitlab::VersionInfo.new(0, 0, 1) }
-    it { @v0_0_1.should <= @v0_1_0 }
+    it { expect(@v0_0_1).to be <= Gitlab::VersionInfo.new(0, 0, 1) }
+    it { expect(@v0_0_1).to be <= @v0_1_0 }
   end
 
   context '==' do
-    it { @v0_0_1.should == Gitlab::VersionInfo.new(0, 0, 1) }
-    it { @v0_1_0.should == Gitlab::VersionInfo.new(0, 1, 0) }
-    it { @v1_0_0.should == Gitlab::VersionInfo.new(1, 0, 0) }
+    it { expect(@v0_0_1).to eq(Gitlab::VersionInfo.new(0, 0, 1)) }
+    it { expect(@v0_1_0).to eq(Gitlab::VersionInfo.new(0, 1, 0)) }
+    it { expect(@v1_0_0).to eq(Gitlab::VersionInfo.new(1, 0, 0)) }
   end
 
   context '!=' do
-    it { @v0_0_1.should_not == @v0_1_0 }
+    it { expect(@v0_0_1).not_to eq(@v0_1_0) }
   end
 
   context 'unknown' do
-    it { @unknown.should_not be @v0_0_1 }
-    it { @unknown.should_not be Gitlab::VersionInfo.new }
+    it { expect(@unknown).not_to be @v0_0_1 }
+    it { expect(@unknown).not_to be Gitlab::VersionInfo.new }
     it { expect{@unknown > @v0_0_1}.to raise_error(ArgumentError) }
     it { expect{@unknown < @v0_0_1}.to raise_error(ArgumentError) }
   end
 
   context 'parse' do
-    it { Gitlab::VersionInfo.parse("1.0.0").should == @v1_0_0 }
-    it { Gitlab::VersionInfo.parse("1.0.0.1").should == @v1_0_0 }
-    it { Gitlab::VersionInfo.parse("git 1.0.0b1").should == @v1_0_0 }
-    it { Gitlab::VersionInfo.parse("git 1.0b1").should_not be_valid }
+    it { expect(Gitlab::VersionInfo.parse("1.0.0")).to eq(@v1_0_0) }
+    it { expect(Gitlab::VersionInfo.parse("1.0.0.1")).to eq(@v1_0_0) }
+    it { expect(Gitlab::VersionInfo.parse("git 1.0.0b1")).to eq(@v1_0_0) }
+    it { expect(Gitlab::VersionInfo.parse("git 1.0b1")).not_to be_valid }
   end
 
   context 'to_s' do
-    it { @v1_0_0.to_s.should == "1.0.0" }
-    it { @unknown.to_s.should == "Unknown" }
+    it { expect(@v1_0_0.to_s).to eq("1.0.0") }
+    it { expect(@unknown.to_s).to eq("Unknown") }
   end
 end
 
diff --git a/spec/lib/repository_cache_spec.rb b/spec/lib/repository_cache_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..af399f3a7319795710c5052736f1413f2c36baa7
--- /dev/null
+++ b/spec/lib/repository_cache_spec.rb
@@ -0,0 +1,34 @@
+require 'rspec'
+require_relative '../../lib/repository_cache'
+
+describe RepositoryCache do
+  let(:backend) { double('backend').as_null_object }
+  let(:cache) { RepositoryCache.new('example', backend) }
+
+  describe '#cache_key' do
+    it 'includes the namespace' do
+      expect(cache.cache_key(:foo)).to eq 'foo:example'
+    end
+  end
+
+  describe '#expire' do
+    it 'expires the given key from the cache' do
+      cache.expire(:foo)
+      expect(backend).to have_received(:delete).with('foo:example')
+    end
+  end
+
+  describe '#fetch' do
+    it 'fetches the given key from the cache' do
+      cache.fetch(:bar)
+      expect(backend).to have_received(:fetch).with('bar:example')
+    end
+
+    it 'accepts a block' do
+      p = -> {}
+
+      cache.fetch(:baz, &p)
+      expect(backend).to have_received(:fetch).with('baz:example', &p)
+    end
+  end
+end
diff --git a/spec/lib/votes_spec.rb b/spec/lib/votes_spec.rb
index a3c353d5eab64c2fb8e2190adff9382bee5d78db..df243a26008dca1ab7fafe6907b95d21fc49717a 100644
--- a/spec/lib/votes_spec.rb
+++ b/spec/lib/votes_spec.rb
@@ -5,132 +5,181 @@ describe Issue, 'Votes' do
 
   describe "#upvotes" do
     it "with no notes has a 0/0 score" do
-      issue.upvotes.should == 0
+      expect(issue.upvotes).to eq(0)
     end
 
     it "should recognize non-+1 notes" do
       add_note "No +1 here"
-      issue.should have(1).note
-      issue.notes.first.upvote?.should be_false
-      issue.upvotes.should == 0
+      expect(issue.notes.size).to eq(1)
+      expect(issue.notes.first.upvote?).to be_falsey
+      expect(issue.upvotes).to eq(0)
     end
 
     it "should recognize a single +1 note" do
       add_note "+1 This is awesome"
-      issue.upvotes.should == 1
+      expect(issue.upvotes).to eq(1)
     end
 
-    it "should recognize multiple +1 notes" do
-      add_note "+1 This is awesome"
-      add_note "+1 I want this"
-      issue.upvotes.should == 2
+    it 'should recognize multiple +1 notes' do
+      add_note '+1 This is awesome', create(:user)
+      add_note '+1 I want this', create(:user)
+      expect(issue.upvotes).to eq(2)
+    end
+
+    it 'should not count 2 +1 votes from the same user' do
+      add_note '+1 This is awesome'
+      add_note '+1 I want this'
+      expect(issue.upvotes).to eq(1)
     end
   end
 
   describe "#downvotes" do
     it "with no notes has a 0/0 score" do
-      issue.downvotes.should == 0
+      expect(issue.downvotes).to eq(0)
     end
 
     it "should recognize non--1 notes" do
       add_note "Almost got a -1"
-      issue.should have(1).note
-      issue.notes.first.downvote?.should be_false
-      issue.downvotes.should == 0
+      expect(issue.notes.size).to eq(1)
+      expect(issue.notes.first.downvote?).to be_falsey
+      expect(issue.downvotes).to eq(0)
     end
 
     it "should recognize a single -1 note" do
       add_note "-1 This is bad"
-      issue.downvotes.should == 1
+      expect(issue.downvotes).to eq(1)
     end
 
     it "should recognize multiple -1 notes" do
-      add_note "-1 This is bad"
-      add_note "-1 Away with this"
-      issue.downvotes.should == 2
+      add_note('-1 This is bad', create(:user))
+      add_note('-1 Away with this', create(:user))
+      expect(issue.downvotes).to eq(2)
     end
   end
 
   describe "#votes_count" do
     it "with no notes has a 0/0 score" do
-      issue.votes_count.should == 0
+      expect(issue.votes_count).to eq(0)
     end
 
     it "should recognize non notes" do
       add_note "No +1 here"
-      issue.should have(1).note
-      issue.votes_count.should == 0
+      expect(issue.notes.size).to eq(1)
+      expect(issue.votes_count).to eq(0)
     end
 
     it "should recognize a single +1 note" do
       add_note "+1 This is awesome"
-      issue.votes_count.should == 1
+      expect(issue.votes_count).to eq(1)
     end
 
     it "should recognize a single -1 note" do
       add_note "-1 This is bad"
-      issue.votes_count.should == 1
+      expect(issue.votes_count).to eq(1)
     end
 
     it "should recognize multiple notes" do
-      add_note "+1 This is awesome"
-      add_note "-1 This is bad"
-      add_note "+1 I want this"
-      issue.votes_count.should == 3
+      add_note('+1 This is awesome', create(:user))
+      add_note('-1 This is bad', create(:user))
+      add_note('+1 I want this', create(:user))
+      expect(issue.votes_count).to eq(3)
+    end
+
+    it 'should not count 2 -1 votes from the same user' do
+      add_note '-1 This is suspicious'
+      add_note '-1 This is bad'
+      expect(issue.votes_count).to eq(1)
     end
   end
 
   describe "#upvotes_in_percent" do
     it "with no notes has a 0% score" do
-      issue.upvotes_in_percent.should == 0
+      expect(issue.upvotes_in_percent).to eq(0)
     end
 
     it "should count a single 1 note as 100%" do
       add_note "+1 This is awesome"
-      issue.upvotes_in_percent.should == 100
+      expect(issue.upvotes_in_percent).to eq(100)
     end
 
-    it "should count multiple +1 notes as 100%" do
-      add_note "+1 This is awesome"
-      add_note "+1 I want this"
-      issue.upvotes_in_percent.should == 100
+    it 'should count multiple +1 notes as 100%' do
+      add_note('+1 This is awesome', create(:user))
+      add_note('+1 I want this', create(:user))
+      expect(issue.upvotes_in_percent).to eq(100)
     end
 
-    it "should count fractions for multiple +1 and -1 notes correctly" do
-      add_note "+1 This is awesome"
-      add_note "+1 I want this"
-      add_note "-1 This is bad"
-      add_note "+1 me too"
-      issue.upvotes_in_percent.should == 75
+    it 'should count fractions for multiple +1 and -1 notes correctly' do
+      add_note('+1 This is awesome', create(:user))
+      add_note('+1 I want this', create(:user))
+      add_note('-1 This is bad', create(:user))
+      add_note('+1 me too', create(:user))
+      expect(issue.upvotes_in_percent).to eq(75)
     end
   end
 
   describe "#downvotes_in_percent" do
     it "with no notes has a 0% score" do
-      issue.downvotes_in_percent.should == 0
+      expect(issue.downvotes_in_percent).to eq(0)
     end
 
     it "should count a single -1 note as 100%" do
       add_note "-1 This is bad"
-      issue.downvotes_in_percent.should == 100
+      expect(issue.downvotes_in_percent).to eq(100)
     end
 
-    it "should count multiple -1 notes as 100%" do
-      add_note "-1 This is bad"
-      add_note "-1 Away with this"
-      issue.downvotes_in_percent.should == 100
+    it 'should count multiple -1 notes as 100%' do
+      add_note('-1 This is bad', create(:user))
+      add_note('-1 Away with this', create(:user))
+      expect(issue.downvotes_in_percent).to eq(100)
     end
 
-    it "should count fractions for multiple +1 and -1 notes correctly" do
-      add_note "+1 This is awesome"
-      add_note "+1 I want this"
-      add_note "-1 This is bad"
-      add_note "+1 me too"
-      issue.downvotes_in_percent.should == 25
+    it 'should count fractions for multiple +1 and -1 notes correctly' do
+      add_note('+1 This is awesome', create(:user))
+      add_note('+1 I want this', create(:user))
+      add_note('-1 This is bad', create(:user))
+      add_note('+1 me too', create(:user))
+      expect(issue.downvotes_in_percent).to eq(25)
+    end
+  end
+
+  describe '#filter_superceded_votes' do
+
+    it 'should count a users vote only once amongst multiple votes' do
+      add_note('-1 This needs work before I will accept it')
+      add_note('+1 I want this', create(:user))
+      add_note('+1 This is is awesome', create(:user))
+      add_note('+1 this looks good now')
+      add_note('+1 This is awesome', create(:user))
+      add_note('+1 me too', create(:user))
+      expect(issue.downvotes).to eq(0)
+      expect(issue.upvotes).to eq(5)
     end
+
+    it 'should count each users vote only once' do
+      add_note '-1 This needs work before it will be accepted'
+      add_note '+1 I like this'
+      add_note '+1 I still like this'
+      add_note '+1 I really like this'
+      add_note '+1 Give me this now!!!!'
+      expect(issue.downvotes).to eq(0)
+      expect(issue.upvotes).to eq(1)
+    end
+
+    it 'should count a users vote only once without caring about comments' do
+      add_note '-1 This needs work before it will be accepted'
+      add_note 'Comment 1'
+      add_note 'Another comment'
+      add_note '+1 vote'
+      add_note 'final comment'
+      expect(issue.downvotes).to eq(0)
+      expect(issue.upvotes).to eq(1)
+    end
+
   end
 
-  def add_note(text)
-    issue.notes << create(:note, note: text, project: issue.project)
+  def add_note(text, author = issue.author)
+    created_at = Time.now - 1.hour + Note.count.seconds
+    issue.notes << create(:note, note: text, project: issue.project,
+                          author_id: author.id, created_at: created_at)
   end
 end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index e06e8826e5c437544a78fe2aa86f257db4ba8c14..ba42f9e5c706589e144dac1f0f1b69dc96665ed0 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -5,38 +5,46 @@ describe Notify do
   include EmailSpec::Matchers
   include RepoHelpers
 
+  let(:gitlab_sender_display_name) { Gitlab.config.gitlab.email_display_name }
   let(:gitlab_sender) { Gitlab.config.gitlab.email_from }
   let(:recipient) { create(:user, email: 'recipient@example.com') }
   let(:project) { create(:project) }
 
+  before(:each) do
+    email = recipient.emails.create(email: "notifications@example.com")
+    recipient.update_attribute(:notification_email, email.email)
+  end
+
   shared_examples 'a multiple recipients email' do
     it 'is sent to the given recipient' do
-      should deliver_to recipient.email
+      is_expected.to deliver_to recipient.notification_email
     end
   end
 
   shared_examples 'an email sent from GitLab' do
     it 'is sent from GitLab' do
       sender = subject.header[:from].addrs[0]
-      sender.display_name.should eq('GitLab')
-      sender.address.should eq(gitlab_sender)
+      expect(sender.display_name).to eq(gitlab_sender_display_name)
+      expect(sender.address).to eq(gitlab_sender)
     end
   end
 
   shared_examples 'an email starting a new thread' do |message_id_prefix|
     it 'has a discussion identifier' do
-      should have_header 'Message-ID',  /<#{message_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
+      is_expected.to have_header 'Message-ID',  /<#{message_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
+      is_expected.to have_header 'X-GitLab-Project', /#{project.name}/
     end
   end
 
   shared_examples 'an answer to an existing thread' do |thread_id_prefix|
     it 'has a subject that begins with Re: ' do
-      should have_subject /^Re: /
+      is_expected.to have_subject /^Re: /
     end
 
     it 'has headers that reference an existing thread' do
-      should have_header 'References',  /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
-      should have_header 'In-Reply-To', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
+      is_expected.to have_header 'References',  /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
+      is_expected.to have_header 'In-Reply-To', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
+      is_expected.to have_header 'X-GitLab-Project', /#{project.name}/
     end
   end
 
@@ -46,35 +54,35 @@ describe Notify do
 
     token = 'kETLwRaayvigPq_x3SNM'
 
-    subject { Notify.new_user_email(new_user.id, new_user.password, token) }
+    subject { Notify.new_user_email(new_user.id, token) }
 
     it_behaves_like 'an email sent from GitLab'
 
     it 'is sent to the new user' do
-      should deliver_to new_user.email
+      is_expected.to deliver_to new_user.email
     end
 
     it 'has the correct subject' do
-      should have_subject /^Account was created for you$/i
+      is_expected.to have_subject /^Account was created for you$/i
     end
 
     it 'contains the new user\'s login name' do
-      should have_body_text /#{new_user.email}/
+      is_expected.to have_body_text /#{new_user.email}/
     end
 
     it 'contains the password text' do
-      should have_body_text /Click here to set your password/
+      is_expected.to have_body_text /Click here to set your password/
     end
 
     it 'includes a link for user to set password' do
       params = "reset_password_token=#{token}"
-      should have_body_text(
+      is_expected.to have_body_text(
         %r{http://localhost(:\d+)?/users/password/edit\?#{params}}
       )
     end
 
     it 'includes a link to the site' do
-      should have_body_text /#{example_site_path}/
+      is_expected.to have_body_text /#{example_site_path}/
     end
   end
 
@@ -83,28 +91,28 @@ describe Notify do
     let(:example_site_path) { root_path }
     let(:new_user) { create(:user, email: 'newguy@example.com', password: "securePassword") }
 
-    subject { Notify.new_user_email(new_user.id, new_user.password) }
+    subject { Notify.new_user_email(new_user.id) }
 
     it_behaves_like 'an email sent from GitLab'
 
     it 'is sent to the new user' do
-      should deliver_to new_user.email
+      is_expected.to deliver_to new_user.email
     end
 
     it 'has the correct subject' do
-      should have_subject /^Account was created for you$/i
+      is_expected.to have_subject /^Account was created for you$/i
     end
 
     it 'contains the new user\'s login name' do
-      should have_body_text /#{new_user.email}/
+      is_expected.to have_body_text /#{new_user.email}/
     end
 
     it 'should not contain the new user\'s password' do
-      should_not have_body_text /password/
+      is_expected.not_to have_body_text /password/
     end
 
     it 'includes a link to the site' do
-      should have_body_text /#{example_site_path}/
+      is_expected.to have_body_text /#{example_site_path}/
     end
   end
 
@@ -116,19 +124,19 @@ describe Notify do
     it_behaves_like 'an email sent from GitLab'
 
     it 'is sent to the new user' do
-      should deliver_to key.user.email
+      is_expected.to deliver_to key.user.email
     end
 
     it 'has the correct subject' do
-      should have_subject /^SSH key was added to your account$/i
+      is_expected.to have_subject /^SSH key was added to your account$/i
     end
 
     it 'contains the new ssh key title' do
-      should have_body_text /#{key.title}/
+      is_expected.to have_body_text /#{key.title}/
     end
 
     it 'includes a link to ssh keys page' do
-      should have_body_text /#{profile_keys_path}/
+      is_expected.to have_body_text /#{profile_keys_path}/
     end
   end
 
@@ -138,19 +146,19 @@ describe Notify do
     subject { Notify.new_email_email(email.id) }
 
     it 'is sent to the new user' do
-      should deliver_to email.user.email
+      is_expected.to deliver_to email.user.email
     end
 
     it 'has the correct subject' do
-      should have_subject /^Email was added to your account$/i
+      is_expected.to have_subject /^Email was added to your account$/i
     end
 
     it 'contains the new email address' do
-      should have_body_text /#{email.email}/
+      is_expected.to have_body_text /#{email.email}/
     end
 
     it 'includes a link to emails page' do
-      should have_body_text /#{profile_emails_path}/
+      is_expected.to have_body_text /#{profile_emails_path}/
     end
   end
 
@@ -163,18 +171,25 @@ describe Notify do
       shared_examples 'an assignee email' do
         it 'is sent as the author' do
           sender = subject.header[:from].addrs[0]
-          sender.display_name.should eq(current_user.name)
-          sender.address.should eq(gitlab_sender)
+          expect(sender.display_name).to eq(current_user.name)
+          expect(sender.address).to eq(gitlab_sender)
         end
 
         it 'is sent to the assignee' do
-          should deliver_to assignee.email
+          is_expected.to deliver_to assignee.email
         end
       end
 
       context 'for issues' do
         let(:issue) { create(:issue, author: current_user, assignee: assignee, project: project) }
         let(:issue_with_description) { create(:issue, author: current_user, assignee: assignee, project: project, description: Faker::Lorem.sentence) }
+        let(:issue_with_image) do
+          create(:issue,
+                 author: current_user,
+                 assignee: assignee,
+                 project: project,
+                 description: "![test](#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/12345/test.jpg)")
+        end
 
         describe 'that are new' do
           subject { Notify.new_issue_email(issue.assignee_id, issue.id) }
@@ -183,11 +198,11 @@ describe Notify do
           it_behaves_like 'an email starting a new thread', 'issue'
 
           it 'has the correct subject' do
-            should have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/
+            is_expected.to have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/
           end
 
           it 'contains a link to the new issue' do
-            should have_body_text /#{project_issue_path project, issue}/
+            is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
           end
         end
 
@@ -195,7 +210,23 @@ describe Notify do
           subject { Notify.new_issue_email(issue_with_description.assignee_id, issue_with_description.id) }
 
           it 'contains the description' do
-            should have_body_text /#{issue_with_description.description}/
+            is_expected.to have_body_text /#{issue_with_description.description}/
+          end
+        end
+
+        describe 'that contain images' do
+          let(:png) { File.read("#{Rails.root}/spec/fixtures/dk.png") }
+          let(:png_encoded) { Base64::encode64(png) }
+
+          before :each do
+            file_path = File.join(Rails.root, 'public', 'uploads', issue_with_image.project.path_with_namespace, '12345/test.jpg')
+            allow(File).to receive(:file?).with(file_path).and_return(true)
+            allow(File).to receive(:read).with(file_path).and_return(png)
+          end
+
+          subject { Notify.new_issue_email(issue_with_image.assignee_id, issue_with_image.id) }
+          it 'replaces attached images with inline images' do
+            is_expected.to have_body_text URI.encode(png_encoded)
           end
         end
 
@@ -207,24 +238,24 @@ describe Notify do
 
           it 'is sent as the author' do
             sender = subject.header[:from].addrs[0]
-            sender.display_name.should eq(current_user.name)
-            sender.address.should eq(gitlab_sender)
+            expect(sender.display_name).to eq(current_user.name)
+            expect(sender.address).to eq(gitlab_sender)
           end
 
           it 'has the correct subject' do
-            should have_subject /#{issue.title} \(##{issue.iid}\)/
+            is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/
           end
 
           it 'contains the name of the previous assignee' do
-            should have_body_text /#{previous_assignee.name}/
+            is_expected.to have_body_text /#{previous_assignee.name}/
           end
 
           it 'contains the name of the new assignee' do
-            should have_body_text /#{assignee.name}/
+            is_expected.to have_body_text /#{assignee.name}/
           end
 
           it 'contains a link to the issue' do
-            should have_body_text /#{project_issue_path project, issue}/
+            is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
           end
         end
 
@@ -236,24 +267,24 @@ describe Notify do
 
           it 'is sent as the author' do
             sender = subject.header[:from].addrs[0]
-            sender.display_name.should eq(current_user.name)
-            sender.address.should eq(gitlab_sender)
+            expect(sender.display_name).to eq(current_user.name)
+            expect(sender.address).to eq(gitlab_sender)
           end
 
           it 'has the correct subject' do
-            should have_subject /#{issue.title} \(##{issue.iid}\)/i
+            is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/i
           end
 
           it 'contains the new status' do
-            should have_body_text /#{status}/i
+            is_expected.to have_body_text /#{status}/i
           end
 
           it 'contains the user name' do
-            should have_body_text /#{current_user.name}/i
+            is_expected.to have_body_text /#{current_user.name}/i
           end
 
           it 'contains a link to the issue' do
-            should have_body_text /#{project_issue_path project, issue}/
+            is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
           end
         end
 
@@ -263,6 +294,14 @@ describe Notify do
         let(:merge_author) { create(:user) }
         let(:merge_request) { create(:merge_request, author: current_user, assignee: assignee, source_project: project, target_project: project) }
         let(:merge_request_with_description) { create(:merge_request, author: current_user, assignee: assignee, source_project: project, target_project: project, description: Faker::Lorem.sentence) }
+        let(:merge_request_with_image) do
+           create(:merge_request,
+                  author: current_user,
+                  assignee: assignee,
+                  source_project: project,
+                  target_project: project,
+                  description: "![test](#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/12345/test.jpg)")
+         end
 
         describe 'that are new' do
           subject { Notify.new_merge_request_email(merge_request.assignee_id, merge_request.id) }
@@ -271,23 +310,23 @@ describe Notify do
           it_behaves_like 'an email starting a new thread', 'merge_request'
 
           it 'has the correct subject' do
-            should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
+            is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
           end
 
           it 'contains a link to the new merge request' do
-            should have_body_text /#{project_merge_request_path(project, merge_request)}/
+            is_expected.to have_body_text /#{namespace_project_merge_request_path(project.namespace, project, merge_request)}/
           end
 
           it 'contains the source branch for the merge request' do
-            should have_body_text /#{merge_request.source_branch}/
+            is_expected.to have_body_text /#{merge_request.source_branch}/
           end
 
           it 'contains the target branch for the merge request' do
-            should have_body_text /#{merge_request.target_branch}/
+            is_expected.to have_body_text /#{merge_request.target_branch}/
           end
 
           it 'has the correct message-id set' do
-            should have_header 'Message-ID', "<merge_request_#{merge_request.id}@#{Gitlab.config.gitlab.host}>"
+            is_expected.to have_header 'Message-ID', "<merge_request_#{merge_request.id}@#{Gitlab.config.gitlab.host}>"
           end
         end
 
@@ -295,7 +334,23 @@ describe Notify do
           subject { Notify.new_merge_request_email(merge_request_with_description.assignee_id, merge_request_with_description.id) }
 
           it 'contains the description' do
-            should have_body_text /#{merge_request_with_description.description}/
+            is_expected.to have_body_text /#{merge_request_with_description.description}/
+          end
+        end
+
+        describe 'that are new and contain contain images in the description' do
+          let(:png) {File.read("#{Rails.root}/spec/fixtures/dk.png")}
+          let(:png_encoded) { Base64::encode64(png) }
+
+          before :each do
+            file_path = File.join(Rails.root, 'public', 'uploads', merge_request_with_image.project.path_with_namespace, '/12345/test.jpg')
+            allow(File).to receive(:file?).with(file_path).and_return(true)
+            allow(File).to receive(:read).with(file_path).and_return(png)
+          end
+
+          subject { Notify.new_merge_request_email(merge_request_with_image.assignee_id, merge_request_with_image.id) }
+          it 'replaces attached images with inline images' do
+            is_expected.to have_body_text URI.encode(png_encoded)
           end
         end
 
@@ -307,24 +362,24 @@ describe Notify do
 
           it 'is sent as the author' do
             sender = subject.header[:from].addrs[0]
-            sender.display_name.should eq(current_user.name)
-            sender.address.should eq(gitlab_sender)
+            expect(sender.display_name).to eq(current_user.name)
+            expect(sender.address).to eq(gitlab_sender)
           end
 
           it 'has the correct subject' do
-            should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
+            is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
           end
 
           it 'contains the name of the previous assignee' do
-            should have_body_text /#{previous_assignee.name}/
+            is_expected.to have_body_text /#{previous_assignee.name}/
           end
 
           it 'contains the name of the new assignee' do
-            should have_body_text /#{assignee.name}/
+            is_expected.to have_body_text /#{assignee.name}/
           end
 
           it 'contains a link to the merge request' do
-            should have_body_text /#{project_merge_request_path project, merge_request}/
+            is_expected.to have_body_text /#{namespace_project_merge_request_path project.namespace, project, merge_request}/
           end
         end
 
@@ -336,24 +391,24 @@ describe Notify do
 
           it 'is sent as the author' do
             sender = subject.header[:from].addrs[0]
-            sender.display_name.should eq(current_user.name)
-            sender.address.should eq(gitlab_sender)
+            expect(sender.display_name).to eq(current_user.name)
+            expect(sender.address).to eq(gitlab_sender)
           end
 
           it 'has the correct subject' do
-            should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/i
+            is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/i
           end
 
           it 'contains the new status' do
-            should have_body_text /#{status}/i
+            is_expected.to have_body_text /#{status}/i
           end
 
           it 'contains the user name' do
-            should have_body_text /#{current_user.name}/i
+            is_expected.to have_body_text /#{current_user.name}/i
           end
 
           it 'contains a link to the merge request' do
-            should have_body_text /#{project_merge_request_path project, merge_request}/
+            is_expected.to have_body_text /#{namespace_project_merge_request_path project.namespace, project, merge_request}/
           end
         end
 
@@ -365,20 +420,20 @@ describe Notify do
 
           it 'is sent as the merge author' do
             sender = subject.header[:from].addrs[0]
-            sender.display_name.should eq(merge_author.name)
-            sender.address.should eq(gitlab_sender)
+            expect(sender.display_name).to eq(merge_author.name)
+            expect(sender.address).to eq(gitlab_sender)
           end
 
           it 'has the correct subject' do
-            should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
+            is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
           end
 
           it 'contains the new status' do
-            should have_body_text /merged/i
+            is_expected.to have_body_text /merged/i
           end
 
           it 'contains a link to the merge request' do
-            should have_body_text /#{project_merge_request_path project, merge_request}/
+            is_expected.to have_body_text /#{namespace_project_merge_request_path project.namespace, project, merge_request}/
           end
         end
       end
@@ -392,36 +447,39 @@ describe Notify do
       it_behaves_like 'an email sent from GitLab'
 
       it 'has the correct subject' do
-        should have_subject /Project was moved/
+        is_expected.to have_subject /Project was moved/
       end
 
       it 'contains name of project' do
-        should have_body_text /#{project.name_with_namespace}/
+        is_expected.to have_body_text /#{project.name_with_namespace}/
       end
 
       it 'contains new user role' do
-        should have_body_text /#{project.ssh_url_to_repo}/
+        is_expected.to have_body_text /#{project.ssh_url_to_repo}/
       end
     end
 
     describe 'project access changed' do
       let(:project) { create(:project) }
       let(:user) { create(:user) }
-      let(:project_member) { create(:project_member,
-                                   project: project,
-                                   user: user) }
+      let(:project_member) do
+        create(:project_member,
+               project: project,
+               user: user)
+      end
+
       subject { Notify.project_access_granted_email(project_member.id) }
 
       it_behaves_like 'an email sent from GitLab'
 
       it 'has the correct subject' do
-        should have_subject /Access to project was granted/
+        is_expected.to have_subject /Access to project was granted/
       end
       it 'contains name of project' do
-        should have_body_text /#{project.name}/
+        is_expected.to have_body_text /#{project.name}/
       end
       it 'contains new user role' do
-        should have_body_text /#{project_member.human_access}/
+        is_expected.to have_body_text /#{project_member.human_access}/
       end
     end
 
@@ -430,29 +488,55 @@ describe Notify do
       let(:note) { create(:note, project: project, author: note_author) }
 
       before :each do
-        Note.stub(:find).with(note.id).and_return(note)
+        allow(Note).to receive(:find).with(note.id).and_return(note)
       end
 
       shared_examples 'a note email' do
         it 'is sent as the author' do
           sender = subject.header[:from].addrs[0]
-          sender.display_name.should eq(note_author.name)
-          sender.address.should eq(gitlab_sender)
+          expect(sender.display_name).to eq(note_author.name)
+          expect(sender.address).to eq(gitlab_sender)
         end
 
         it 'is sent to the given recipient' do
-          should deliver_to recipient.email
+          is_expected.to deliver_to recipient.notification_email
         end
 
         it 'contains the message from the note' do
-          should have_body_text /#{note.note}/
+          is_expected.to have_body_text /#{note.note}/
+        end
+      end
+
+      describe 'on a commit that contains an image' do
+        let(:commit) { project.repository.commit }
+        let(:note_with_image) do
+          create(:note,
+                 project: project,
+                 author: note_author,
+                 note: "![test](#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/12345/test.jpg)")
+        end
+
+        let(:png) {File.read("#{Rails.root}/spec/fixtures/dk.png")}
+        let(:png_encoded) { Base64::encode64(png) }
+
+        before :each do
+          file_path = File.join(Rails.root, 'public', 'uploads', note_with_image.project.path_with_namespace, '12345/test.jpg')
+          allow(File).to receive(:file?).with(file_path).and_return(true)
+          allow(File).to receive(:read).with(file_path).and_return(png)
+          allow(Note).to receive(:find).with(note_with_image.id).and_return(note_with_image)
+          allow(note_with_image).to receive(:noteable).and_return(commit)
+        end
+
+        subject { Notify.note_commit_email(recipient.id, note_with_image.id) }
+        it 'replaces attached images with inline images' do
+          is_expected.to have_body_text URI.encode(png_encoded)
         end
       end
 
       describe 'on a commit' do
         let(:commit) { project.repository.commit }
 
-        before(:each) { note.stub(:noteable).and_return(commit) }
+        before(:each) { allow(note).to receive(:noteable).and_return(commit) }
 
         subject { Notify.note_commit_email(recipient.id, note.id) }
 
@@ -460,18 +544,18 @@ describe Notify do
         it_behaves_like 'an answer to an existing thread', 'commits'
 
         it 'has the correct subject' do
-          should have_subject /#{commit.title} \(#{commit.short_id}\)/
+          is_expected.to have_subject /#{commit.title} \(#{commit.short_id}\)/
         end
 
         it 'contains a link to the commit' do
-          should have_body_text commit.short_id
+          is_expected.to have_body_text commit.short_id
         end
       end
 
       describe 'on a merge request' do
         let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
-        let(:note_on_merge_request_path) { project_merge_request_path(project, merge_request, anchor: "note_#{note.id}") }
-        before(:each) { note.stub(:noteable).and_return(merge_request) }
+        let(:note_on_merge_request_path) { namespace_project_merge_request_path(project.namespace, project, merge_request, anchor: "note_#{note.id}") }
+        before(:each) { allow(note).to receive(:noteable).and_return(merge_request) }
 
         subject { Notify.note_merge_request_email(recipient.id, note.id) }
 
@@ -479,18 +563,18 @@ describe Notify do
         it_behaves_like 'an answer to an existing thread', 'merge_request'
 
         it 'has the correct subject' do
-          should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
+          is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
         end
 
         it 'contains a link to the merge request note' do
-          should have_body_text /#{note_on_merge_request_path}/
+          is_expected.to have_body_text /#{note_on_merge_request_path}/
         end
       end
 
       describe 'on an issue' do
         let(:issue) { create(:issue, project: project) }
-        let(:note_on_issue_path) { project_issue_path(project, issue, anchor: "note_#{note.id}") }
-        before(:each) { note.stub(:noteable).and_return(issue) }
+        let(:note_on_issue_path) { namespace_project_issue_path(project.namespace, project, issue, anchor: "note_#{note.id}") }
+        before(:each) { allow(note).to receive(:noteable).and_return(issue) }
 
         subject { Notify.note_issue_email(recipient.id, note.id) }
 
@@ -498,11 +582,11 @@ describe Notify do
         it_behaves_like 'an answer to an existing thread', 'issue'
 
         it 'has the correct subject' do
-          should have_subject /#{issue.title} \(##{issue.iid}\)/
+          is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/
         end
 
         it 'contains a link to the issue note' do
-          should have_body_text /#{note_on_issue_path}/
+          is_expected.to have_body_text /#{note_on_issue_path}/
         end
       end
     end
@@ -518,15 +602,15 @@ describe Notify do
     it_behaves_like 'an email sent from GitLab'
 
     it 'has the correct subject' do
-      should have_subject /Access to group was granted/
+      is_expected.to have_subject /Access to group was granted/
     end
 
     it 'contains name of project' do
-      should have_body_text /#{group.name}/
+      is_expected.to have_body_text /#{group.name}/
     end
 
     it 'contains new user role' do
-      should have_body_text /#{membership.human_access}/
+      is_expected.to have_body_text /#{membership.human_access}/
     end
   end
 
@@ -544,15 +628,109 @@ describe Notify do
     it_behaves_like 'an email sent from GitLab'
 
     it 'is sent to the new user' do
-      should deliver_to 'new-email@mail.com'
+      is_expected.to deliver_to 'new-email@mail.com'
     end
 
     it 'has the correct subject' do
-      should have_subject "Confirmation instructions"
+      is_expected.to have_subject "Confirmation instructions"
     end
 
     it 'includes a link to the site' do
-      should have_body_text /#{example_site_path}/
+      is_expected.to have_body_text /#{example_site_path}/
+    end
+  end
+
+  describe 'email on push for a created branch' do
+    let(:example_site_path) { root_path }
+    let(:user) { create(:user) }
+    let(:tree_path) { namespace_project_tree_path(project.namespace, project, "master") }
+
+    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :create) }
+
+    it 'is sent as the author' do
+      sender = subject.header[:from].addrs[0]
+      expect(sender.display_name).to eq(user.name)
+      expect(sender.address).to eq(gitlab_sender)
+    end
+
+    it 'is sent to recipient' do
+      is_expected.to deliver_to 'devs@company.name'
+    end
+
+    it 'has the correct subject' do
+      is_expected.to have_subject /Pushed new branch master/
+    end
+
+    it 'contains a link to the branch' do
+      is_expected.to have_body_text /#{tree_path}/
+    end
+  end
+
+  describe 'email on push for a created tag' do
+    let(:example_site_path) { root_path }
+    let(:user) { create(:user) }
+    let(:tree_path) { namespace_project_tree_path(project.namespace, project, "v1.0") }
+
+    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :create) }
+
+    it 'is sent as the author' do
+      sender = subject.header[:from].addrs[0]
+      expect(sender.display_name).to eq(user.name)
+      expect(sender.address).to eq(gitlab_sender)
+    end
+
+    it 'is sent to recipient' do
+      is_expected.to deliver_to 'devs@company.name'
+    end
+
+    it 'has the correct subject' do
+      is_expected.to have_subject /Pushed new tag v1\.0/
+    end
+
+    it 'contains a link to the tag' do
+      is_expected.to have_body_text /#{tree_path}/
+    end
+  end
+
+  describe 'email on push for a deleted branch' do
+    let(:example_site_path) { root_path }
+    let(:user) { create(:user) }
+
+    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :delete) }
+
+    it 'is sent as the author' do
+      sender = subject.header[:from].addrs[0]
+      expect(sender.display_name).to eq(user.name)
+      expect(sender.address).to eq(gitlab_sender)
+    end
+
+    it 'is sent to recipient' do
+      is_expected.to deliver_to 'devs@company.name'
+    end
+
+    it 'has the correct subject' do
+      is_expected.to have_subject /Deleted branch master/
+    end
+  end
+
+  describe 'email on push for a deleted tag' do
+    let(:example_site_path) { root_path }
+    let(:user) { create(:user) }
+
+    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) }
+
+    it 'is sent as the author' do
+      sender = subject.header[:from].addrs[0]
+      expect(sender.display_name).to eq(user.name)
+      expect(sender.address).to eq(gitlab_sender)
+    end
+
+    it 'is sent to recipient' do
+      is_expected.to deliver_to 'devs@company.name'
+    end
+
+    it 'has the correct subject' do
+      is_expected.to have_subject /Deleted tag v1\.0/
     end
   end
 
@@ -561,34 +739,87 @@ describe Notify do
     let(:user) { create(:user) }
     let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_image_commit.id, sample_commit.id) }
     let(:commits) { Commit.decorate(compare.commits) }
-    let(:diff_path) { project_compare_path(project, from: commits.first, to: commits.last) }
+    let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base), to: Commit.new(compare.head)) }
+    let(:send_from_committer_email) { false }
 
-    subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'master', compare) }
+    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, send_from_committer_email: send_from_committer_email) }
 
     it 'is sent as the author' do
       sender = subject.header[:from].addrs[0]
-      sender.display_name.should eq(user.name)
-      sender.address.should eq(gitlab_sender)
+      expect(sender.display_name).to eq(user.name)
+      expect(sender.address).to eq(gitlab_sender)
     end
 
     it 'is sent to recipient' do
-      should deliver_to 'devs@company.name'
+      is_expected.to deliver_to 'devs@company.name'
     end
 
     it 'has the correct subject' do
-      should have_subject /#{commits.length} new commits pushed to repository/
+      is_expected.to have_subject /\[#{project.path_with_namespace}\]\[master\] #{commits.length} commits:/
     end
 
     it 'includes commits list' do
-      should have_body_text /Change some files/
+      is_expected.to have_body_text /Change some files/
     end
 
     it 'includes diffs' do
-      should have_body_text /def archive_formats_regex/
+      is_expected.to have_body_text /def archive_formats_regex/
     end
 
     it 'contains a link to the diff' do
-      should have_body_text /#{diff_path}/
+      is_expected.to have_body_text /#{diff_path}/
+    end
+
+    it 'doesn not contain the misleading footer' do
+      is_expected.not_to have_body_text /you are a member of/
+    end
+
+    context "when set to send from committer email if domain matches" do
+
+      let(:send_from_committer_email) { true }
+
+      before do
+        allow(Gitlab.config.gitlab).to receive(:host).and_return("gitlab.corp.company.com")
+      end
+
+      context "when the committer email domain is within the GitLab domain" do
+
+        before do
+          user.update_attribute(:email, "user@company.com")
+          user.confirm!
+        end
+
+        it "is sent from the committer email" do
+          sender = subject.header[:from].addrs[0]
+          expect(sender.address).to eq(user.email)
+        end
+      end
+
+      context "when the committer email domain is not completely within the GitLab domain" do
+
+        before do
+          user.update_attribute(:email, "user@something.company.com")
+          user.confirm!
+        end
+
+        it "is sent from the default email" do
+          sender = subject.header[:from].addrs[0]
+          expect(sender.address).to eq(gitlab_sender)
+        end
+      end
+
+      context "when the committer email domain is outside the GitLab domain" do
+
+        before do
+          user.update_attribute(:email, "user@mpany.com")
+          user.confirm!
+        end
+
+        it "is sent from the default email" do
+          sender = subject.header[:from].addrs[0]
+          expect(sender.address).to eq(gitlab_sender)
+        end
+      end
     end
   end
 
@@ -597,34 +828,34 @@ describe Notify do
     let(:user) { create(:user) }
     let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_commit.parent_id, sample_commit.id) }
     let(:commits) { Commit.decorate(compare.commits) }
-    let(:diff_path) { project_commit_path(project, commits.first) }
+    let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) }
 
-    subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'master', compare) }
+    subject { Notify.repository_push_email(project.id, 'devs@company.name', author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare) }
 
     it 'is sent as the author' do
       sender = subject.header[:from].addrs[0]
-      sender.display_name.should eq(user.name)
-      sender.address.should eq(gitlab_sender)
+      expect(sender.display_name).to eq(user.name)
+      expect(sender.address).to eq(gitlab_sender)
     end
 
     it 'is sent to recipient' do
-      should deliver_to 'devs@company.name'
+      is_expected.to deliver_to 'devs@company.name'
     end
 
     it 'has the correct subject' do
-      should have_subject /#{commits.first.title}/
+      is_expected.to have_subject /#{commits.first.title}/
     end
 
     it 'includes commits list' do
-      should have_body_text /Change some files/
+      is_expected.to have_body_text /Change some files/
     end
 
     it 'includes diffs' do
-      should have_body_text /def archive_formats_regex/
+      is_expected.to have_body_text /def archive_formats_regex/
     end
 
     it 'contains a link to the diff' do
-      should have_body_text /#{diff_path}/
+      is_expected.to have_body_text /#{diff_path}/
     end
   end
 end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b4f0b2c201aba6f638f0a3d6762a0efd9c1dff25
--- /dev/null
+++ b/spec/models/application_setting_spec.rb
@@ -0,0 +1,24 @@
+# == Schema Information
+#
+# Table name: application_settings
+#
+#  id                           :integer          not null, primary key
+#  default_projects_limit       :integer
+#  default_branch_protection    :integer
+#  signup_enabled               :boolean
+#  signin_enabled               :boolean
+#  gravatar_enabled             :boolean
+#  sign_in_text                 :text
+#  created_at                   :datetime
+#  updated_at                   :datetime
+#  home_page_url                :string(255)
+#  default_branch_protection    :integer          default(2)
+#  twitter_sharing_enabled      :boolean          default(TRUE)
+#  restricted_visibility_levels :text
+#
+
+require 'spec_helper'
+
+describe ApplicationSetting, models: true do
+  it { expect(ApplicationSetting.create_from_defaults).to be_valid }
+end
diff --git a/spec/models/assembla_service_spec.rb b/spec/models/assembla_service_spec.rb
deleted file mode 100644
index 4300090eb13ed4c2a03a861d32e9df7627840680..0000000000000000000000000000000000000000
--- a/spec/models/assembla_service_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# == Schema Information
-#
-# Table name: services
-#
-#  id         :integer          not null, primary key
-#  type       :string(255)
-#  title      :string(255)
-#  project_id :integer          not null
-#  created_at :datetime
-#  updated_at :datetime
-#  active     :boolean          default(FALSE), not null
-#  properties :text
-#
-
-require 'spec_helper'
-
-describe AssemblaService, models: true do
-  describe "Associations" do
-    it { should belong_to :project }
-    it { should have_one :service_hook }
-  end
-
-  describe "Execute" do
-    let(:user)    { create(:user) }
-    let(:project) { create(:project) }
-
-    before do
-      @assembla_service = AssemblaService.new
-      @assembla_service.stub(
-        project_id: project.id,
-        project: project,
-        service_hook: true,
-        token: 'verySecret',
-        subdomain: 'project_name'
-      )
-      @sample_data = GitPushService.new.sample_data(project, user)
-      @api_url = 'https://atlas.assembla.com/spaces/project_name/github_tool?secret_key=verySecret'
-      WebMock.stub_request(:post, @api_url)
-    end
-
-    it "should call Assembla API" do
-      @assembla_service.execute(@sample_data)
-      WebMock.should have_requested(:post, @api_url).with(
-        body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/
-      ).once
-    end
-  end
-end
diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb
index 0f31c407c90d3b2a7d6d82846c426a12e79a34e6..8ab72151a690b1e37b60cffe94e0742955907f48 100644
--- a/spec/models/broadcast_message_spec.rb
+++ b/spec/models/broadcast_message_spec.rb
@@ -18,22 +18,22 @@ require 'spec_helper'
 describe BroadcastMessage do
   subject { create(:broadcast_message) }
 
-  it { should be_valid }
+  it { is_expected.to be_valid }
 
   describe :current do
     it "should return last message if time match" do
       broadcast_message = create(:broadcast_message, starts_at: Time.now.yesterday, ends_at: Time.now.tomorrow)
-      BroadcastMessage.current.should == broadcast_message
+      expect(BroadcastMessage.current).to eq(broadcast_message)
     end
 
     it "should return nil if time not come" do
       broadcast_message = create(:broadcast_message, starts_at: Time.now.tomorrow, ends_at: Time.now + 2.days)
-      BroadcastMessage.current.should be_nil
+      expect(BroadcastMessage.current).to be_nil
     end
 
     it "should return nil if time has passed" do
       broadcast_message = create(:broadcast_message, starts_at: Time.now - 2.days, ends_at: Time.now.yesterday)
-      BroadcastMessage.current.should be_nil
+      expect(BroadcastMessage.current).to be_nil
     end
   end
 end
diff --git a/spec/models/buildbox_service_spec.rb b/spec/models/buildbox_service_spec.rb
deleted file mode 100644
index 1d9ca51be16138ab31c50db3bd4a72cf4b4a1149..0000000000000000000000000000000000000000
--- a/spec/models/buildbox_service_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# == Schema Information
-#
-# Table name: services
-#
-#  id         :integer          not null, primary key
-#  type       :string(255)
-#  title      :string(255)
-#  project_id :integer          not null
-#  created_at :datetime
-#  updated_at :datetime
-#  active     :boolean          default(FALSE), not null
-#  properties :text
-#
-
-require 'spec_helper'
-
-describe BuildboxService do
-  describe 'Associations' do
-    it { should belong_to :project }
-    it { should have_one :service_hook }
-  end
-
-  describe 'commits methods' do
-    before do
-      @project = Project.new
-      @project.stub(
-        default_branch: 'default-brancho'
-      )
-
-      @service = BuildboxService.new
-      @service.stub(
-        project: @project,
-        service_hook: true,
-        project_url: 'https://buildbox.io/account-name/example-project',
-        token: 'secret-sauce-webhook-token:secret-sauce-status-token'
-      )
-    end
-
-    describe :webhook_url do
-      it 'returns the webhook url' do
-        @service.webhook_url.should ==
-          'https://webhook.buildbox.io/deliver/secret-sauce-webhook-token'
-      end
-    end
-
-    describe :commit_status_path do
-      it 'returns the correct status page' do
-        @service.commit_status_path('2ab7834c').should ==
-          'https://gitlab.buildbox.io/status/secret-sauce-status-token.json?commit=2ab7834c'
-      end
-    end
-
-    describe :build_page do
-      it 'returns the correct build page' do
-        @service.build_page('2ab7834c').should ==
-          'https://buildbox.io/account-name/example-project/builds?commit=2ab7834c'
-      end
-    end
-
-    describe :builds_page do
-      it 'returns the correct path to the builds page' do
-        @service.builds_path.should ==
-          'https://buildbox.io/account-name/example-project/builds?branch=default-brancho'
-      end
-    end
-
-    describe :status_img_path do
-      it 'returns the correct path to the status image' do
-        @service.status_img_path.should == 'https://badge.buildbox.io/secret-sauce-status-token.svg'
-      end
-    end
-  end
-end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index a6ec44da4be170a709341991f3c7b3c0e24c8bd0..8b3d88640da75479752fce7553b3ecce851d3196 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -6,22 +6,22 @@ describe Commit do
 
   describe '#title' do
     it "returns no_commit_message when safe_message is blank" do
-      commit.stub(:safe_message).and_return('')
-      commit.title.should == "--no commit message"
+      allow(commit).to receive(:safe_message).and_return('')
+      expect(commit.title).to eq("--no commit message")
     end
 
     it "truncates a message without a newline at 80 characters" do
       message = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit. Vivamus egestas lacinia lacus, sed rutrum mauris.'
 
-      commit.stub(:safe_message).and_return(message)
-      commit.title.should == "#{message[0..79]}&hellip;"
+      allow(commit).to receive(:safe_message).and_return(message)
+      expect(commit.title).to eq("#{message[0..79]}&hellip;")
     end
 
     it "truncates a message with a newline before 80 characters at the newline" do
       message = commit.safe_message.split(" ").first
 
-      commit.stub(:safe_message).and_return(message + "\n" + message)
-      commit.title.should == message
+      allow(commit).to receive(:safe_message).and_return(message + "\n" + message)
+      expect(commit.title).to eq(message)
     end
 
     it "does not truncates a message with a newline after 80 but less 100 characters" do
@@ -30,25 +30,25 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis
 Vivamus egestas lacinia lacus, sed rutrum mauris.
 eos
 
-      commit.stub(:safe_message).and_return(message)
-      commit.title.should == message.split("\n").first
+      allow(commit).to receive(:safe_message).and_return(message)
+      expect(commit.title).to eq(message.split("\n").first)
     end
   end
 
   describe "delegation" do
     subject { commit }
 
-    it { should respond_to(:message) }
-    it { should respond_to(:authored_date) }
-    it { should respond_to(:committed_date) }
-    it { should respond_to(:committer_email) }
-    it { should respond_to(:author_email) }
-    it { should respond_to(:parents) }
-    it { should respond_to(:date) }
-    it { should respond_to(:diffs) }
-    it { should respond_to(:tree) }
-    it { should respond_to(:id) }
-    it { should respond_to(:to_patch) }
+    it { is_expected.to respond_to(:message) }
+    it { is_expected.to respond_to(:authored_date) }
+    it { is_expected.to respond_to(:committed_date) }
+    it { is_expected.to respond_to(:committer_email) }
+    it { is_expected.to respond_to(:author_email) }
+    it { is_expected.to respond_to(:parents) }
+    it { is_expected.to respond_to(:date) }
+    it { is_expected.to respond_to(:diffs) }
+    it { is_expected.to respond_to(:tree) }
+    it { is_expected.to respond_to(:id) }
+    it { is_expected.to respond_to(:to_patch) }
   end
 
   describe '#closes_issues' do
@@ -57,18 +57,14 @@ eos
     let(:other_issue) { create :issue, project: other_project }
 
     it 'detects issues that this commit is marked as closing' do
-      stub_const('Gitlab::ClosingIssueExtractor::ISSUE_CLOSING_REGEX',
-                 /Fixes #\d+/)
       commit.stub(safe_message: "Fixes ##{issue.iid}")
-      commit.closes_issues(project).should == [issue]
+      expect(commit.closes_issues(project)).to eq([issue])
     end
 
     it 'does not detect issues from other projects' do
       ext_ref = "#{other_project.path_with_namespace}##{other_issue.iid}"
-      stub_const('Gitlab::ClosingIssueExtractor::ISSUE_CLOSING_REGEX',
-                 /^([Cc]loses|[Ff]ixes)/)
       commit.stub(safe_message: "Fixes #{ext_ref}")
-      commit.closes_issues(project).should be_empty
+      expect(commit.closes_issues(project)).to be_empty
     end
   end
 
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 9cbc899067689d4f92056367995f8e92d9cc92df..557c71b4d2cecc2c8a28f2a57633fee4ef7051f3 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -4,63 +4,63 @@ describe Issue, "Issuable" do
   let(:issue) { create(:issue) }
 
   describe "Associations" do
-    it { should belong_to(:project) }
-    it { should belong_to(:author) }
-    it { should belong_to(:assignee) }
-    it { should have_many(:notes).dependent(:destroy) }
+    it { is_expected.to belong_to(:project) }
+    it { is_expected.to belong_to(:author) }
+    it { is_expected.to belong_to(:assignee) }
+    it { is_expected.to have_many(:notes).dependent(:destroy) }
   end
 
   describe "Validation" do
     before { subject.stub(set_iid: false) }
-    it { should validate_presence_of(:project) }
-    it { should validate_presence_of(:iid) }
-    it { should validate_presence_of(:author) }
-    it { should validate_presence_of(:title) }
-    it { should ensure_length_of(:title).is_at_least(0).is_at_most(255) }
+    it { is_expected.to validate_presence_of(:project) }
+    it { is_expected.to validate_presence_of(:iid) }
+    it { is_expected.to validate_presence_of(:author) }
+    it { is_expected.to validate_presence_of(:title) }
+    it { is_expected.to ensure_length_of(:title).is_at_least(0).is_at_most(255) }
   end
 
   describe "Scope" do
-    it { described_class.should respond_to(:opened) }
-    it { described_class.should respond_to(:closed) }
-    it { described_class.should respond_to(:assigned) }
+    it { expect(described_class).to respond_to(:opened) }
+    it { expect(described_class).to respond_to(:closed) }
+    it { expect(described_class).to respond_to(:assigned) }
   end
 
   describe ".search" do
     let!(:searchable_issue) { create(:issue, title: "Searchable issue") }
 
     it "matches by title" do
-      described_class.search('able').should == [searchable_issue]
+      expect(described_class.search('able')).to eq([searchable_issue])
     end
   end
 
   describe "#today?" do
     it "returns true when created today" do
       # Avoid timezone differences and just return exactly what we want
-      Date.stub(:today).and_return(issue.created_at.to_date)
-      issue.today?.should be_true
+      allow(Date).to receive(:today).and_return(issue.created_at.to_date)
+      expect(issue.today?).to be_truthy
     end
 
     it "returns false when not created today" do
-      Date.stub(:today).and_return(Date.yesterday)
-      issue.today?.should be_false
+      allow(Date).to receive(:today).and_return(Date.yesterday)
+      expect(issue.today?).to be_falsey
     end
   end
 
   describe "#new?" do
     it "returns true when created today and record hasn't been updated" do
-      issue.stub(:today?).and_return(true)
-      issue.new?.should be_true
+      allow(issue).to receive(:today?).and_return(true)
+      expect(issue.new?).to be_truthy
     end
 
     it "returns false when not created today" do
-      issue.stub(:today?).and_return(false)
-      issue.new?.should be_false
+      allow(issue).to receive(:today?).and_return(false)
+      expect(issue.new?).to be_falsey
     end
 
     it "returns false when record has been updated" do
-      issue.stub(:today?).and_return(true)
+      allow(issue).to receive(:today?).and_return(true)
       issue.touch
-      issue.new?.should be_false
+      expect(issue.new?).to be_falsey
     end
   end
 end
diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb
index ca6f11b2a4dcb9295b33a282e0eccf614d01635f..eadb941a3fa8780eb5789e890760c9661295c89d 100644
--- a/spec/models/concerns/mentionable_spec.rb
+++ b/spec/models/concerns/mentionable_spec.rb
@@ -8,7 +8,7 @@ describe Issue, "Mentionable" do
 
     subject { issue.mentioned_users }
 
-    it { should include(user) }
-    it { should_not include(user2) }
+    it { is_expected.to include(user) }
+    it { is_expected.not_to include(user2) }
   end
 end
diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb
index adbbbac875fa5199a4fbf76e2a8640f578c008e7..b32be8d7a7cb45199703192cf0c8d2f4fbcd8d55 100644
--- a/spec/models/deploy_key_spec.rb
+++ b/spec/models/deploy_key_spec.rb
@@ -19,7 +19,7 @@ describe DeployKey do
   let(:deploy_key) { create(:deploy_key, projects: [project]) }
 
   describe "Associations" do
-    it { should have_many(:deploy_keys_projects) }
-    it { should have_many(:projects) }
+    it { is_expected.to have_many(:deploy_keys_projects) }
+    it { is_expected.to have_many(:projects) }
   end
 end
diff --git a/spec/models/deploy_keys_project_spec.rb b/spec/models/deploy_keys_project_spec.rb
index 3e0e25ee39aff4d4804ce8db4da89c61959aa8e4..f351aab923831598f2bc1785aa85ffe264919833 100644
--- a/spec/models/deploy_keys_project_spec.rb
+++ b/spec/models/deploy_keys_project_spec.rb
@@ -13,12 +13,45 @@ require 'spec_helper'
 
 describe DeployKeysProject do
   describe "Associations" do
-    it { should belong_to(:deploy_key) }
-    it { should belong_to(:project) }
+    it { is_expected.to belong_to(:deploy_key) }
+    it { is_expected.to belong_to(:project) }
   end
 
   describe "Validation" do
-    it { should validate_presence_of(:project_id) }
-    it { should validate_presence_of(:deploy_key_id) }
+    it { is_expected.to validate_presence_of(:project_id) }
+    it { is_expected.to validate_presence_of(:deploy_key_id) }
+  end
+
+  describe "Destroying" do
+    let(:project)     { create(:project) }
+    subject           { create(:deploy_keys_project, project: project) }
+    let(:deploy_key)  { subject.deploy_key }
+
+    context "when the deploy key is only used by this project" do
+      it "destroys the deploy key" do
+        subject.destroy
+
+        expect {
+          deploy_key.reload
+        }.to raise_error(ActiveRecord::RecordNotFound)
+      end
+    end
+
+    context "when the deploy key is used by more than one project" do
+
+      let!(:other_project) { create(:project) }
+
+      before do
+        other_project.deploy_keys << deploy_key
+      end
+
+      it "doesn't destroy the deploy key" do
+        subject.destroy
+
+        expect {
+          deploy_key.reload
+        }.not_to raise_error(ActiveRecord::RecordNotFound)
+      end
+    end
   end
 end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 204ae9da7042bc89fe1dc4b6863d3e0d16f57e50..0f32f162a104b70ff3d124b0cf9fcece128b6b94 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -18,16 +18,16 @@ require 'spec_helper'
 
 describe Event do
   describe "Associations" do
-    it { should belong_to(:project) }
-    it { should belong_to(:target) }
+    it { is_expected.to belong_to(:project) }
+    it { is_expected.to belong_to(:target) }
   end
 
   describe "Respond to" do
-    it { should respond_to(:author_name) }
-    it { should respond_to(:author_email) }
-    it { should respond_to(:issue_title) }
-    it { should respond_to(:merge_request_title) }
-    it { should respond_to(:commits) }
+    it { is_expected.to respond_to(:author_name) }
+    it { is_expected.to respond_to(:author_email) }
+    it { is_expected.to respond_to(:issue_title) }
+    it { is_expected.to respond_to(:merge_request_title) }
+    it { is_expected.to respond_to(:commits) }
   end
 
   describe "Push event" do
@@ -58,10 +58,10 @@ describe Event do
       )
     end
 
-    it { @event.push?.should be_true }
-    it { @event.proper?.should be_true }
-    it { @event.tag?.should be_false }
-    it { @event.branch_name.should == "master" }
-    it { @event.author.should == @user }
+    it { expect(@event.push?).to be_truthy }
+    it { expect(@event.proper?).to be_truthy }
+    it { expect(@event.tag?).to be_falsey }
+    it { expect(@event.branch_name).to eq("master") }
+    it { expect(@event.author).to eq(@user) }
   end
 end
diff --git a/spec/models/external_wiki_service_spec.rb b/spec/models/external_wiki_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..78ef687d29cbeec644b45d8cc267e782939ae802
--- /dev/null
+++ b/spec/models/external_wiki_service_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe ExternalWikiService do
+  include ExternalWikiHelper
+  describe "Associations" do
+    it { should belong_to :project }
+    it { should have_one :service_hook }
+  end
+
+  describe "Validations" do
+    context "active" do
+      before do
+        subject.active = true
+      end
+
+      it { should validate_presence_of :external_wiki_url }
+    end
+  end
+
+  describe 'External wiki' do
+    let(:project) { create(:project) }
+
+    context 'when it is active' do
+      before do
+        properties = { 'external_wiki_url' => 'https://gitlab.com' }
+        @service = project.create_external_wiki_service(active: true, properties: properties)
+      end
+
+      after do
+        @service.destroy!
+      end
+
+      it 'should replace the wiki url' do
+        wiki_path = get_project_wiki_path(project)
+        wiki_path.should match('https://gitlab.com')
+      end
+    end
+  end
+end
diff --git a/spec/models/flowdock_service_spec.rb b/spec/models/flowdock_service_spec.rb
deleted file mode 100644
index 5540f0fa988809b0d384cda283a0502d275d31f5..0000000000000000000000000000000000000000
--- a/spec/models/flowdock_service_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# == Schema Information
-#
-# Table name: services
-#
-#  id         :integer          not null, primary key
-#  type       :string(255)
-#  title      :string(255)
-#  project_id :integer          not null
-#  created_at :datetime
-#  updated_at :datetime
-#  active     :boolean          default(FALSE), not null
-#  properties :text
-#
-
-require 'spec_helper'
-
-describe FlowdockService do
-  describe "Associations" do
-    it { should belong_to :project }
-    it { should have_one :service_hook }
-  end
-
-  describe "Execute" do
-    let(:user)    { create(:user) }
-    let(:project) { create(:project) }
-
-    before do
-      @flowdock_service = FlowdockService.new
-      @flowdock_service.stub(
-        project_id: project.id,
-        project: project,
-        service_hook: true,
-        token: 'verySecret'
-      )
-      @sample_data = GitPushService.new.sample_data(project, user)
-      @api_url = 'https://api.flowdock.com/v1/git/verySecret'
-      WebMock.stub_request(:post, @api_url)
-    end
-
-    it "should call FlowDock API" do
-      @flowdock_service.execute(@sample_data)
-      WebMock.should have_requested(:post, @api_url).with(
-        body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/
-      ).once
-    end
-  end
-end
diff --git a/spec/models/forked_project_link_spec.rb b/spec/models/forked_project_link_spec.rb
index 1845c6103f5a4efc33dda69224995ba379d0a49b..7d0ad44a92c2ad1f4c072d6c3bc4bc81df6d3097 100644
--- a/spec/models/forked_project_link_spec.rb
+++ b/spec/models/forked_project_link_spec.rb
@@ -21,11 +21,11 @@ describe ForkedProjectLink, "add link on fork" do
   end
 
   it "project_to should know it is forked" do
-    @project_to.forked?.should be_true
+    expect(@project_to.forked?).to be_truthy
   end
 
   it "project should know who it is forked from" do
-    @project_to.forked_from_project.should == project_from
+    expect(@project_to.forked_from_project).to eq(project_from)
   end
 end
 
@@ -43,15 +43,15 @@ describe :forked_from_project do
 
 
   it "project_to should know it is forked" do
-    project_to.forked?.should be_true
+    expect(project_to.forked?).to be_truthy
   end
 
   it "project_from should not be forked" do
-    project_from.forked?.should be_false
+    expect(project_from.forked?).to be_falsey
   end
 
   it "project_to.destroy should destroy fork_link" do
-    forked_project_link.should_receive(:destroy)
+    expect(forked_project_link).to receive(:destroy)
     project_to.destroy
   end
 
diff --git a/spec/models/gemnasium_service_spec.rb b/spec/models/gemnasium_service_spec.rb
deleted file mode 100644
index 60ffa6f8b05766f225d755d0b7bdfa7e0e6521b4..0000000000000000000000000000000000000000
--- a/spec/models/gemnasium_service_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# == Schema Information
-#
-# Table name: services
-#
-#  id         :integer          not null, primary key
-#  type       :string(255)
-#  title      :string(255)
-#  project_id :integer          not null
-#  created_at :datetime
-#  updated_at :datetime
-#  active     :boolean          default(FALSE), not null
-#  properties :text
-#
-
-require 'spec_helper'
-
-describe GemnasiumService do
-  describe "Associations" do
-    it { should belong_to :project }
-    it { should have_one :service_hook }
-  end
-
-  describe "Execute" do
-    let(:user)    { create(:user) }
-    let(:project) { create(:project) }
-
-    before do
-      @gemnasium_service = GemnasiumService.new
-      @gemnasium_service.stub(
-        project_id: project.id,
-        project: project,
-        service_hook: true,
-        token: 'verySecret',
-        api_key: 'GemnasiumUserApiKey'
-      )
-      @sample_data = GitPushService.new.sample_data(project, user)
-    end
-    it "should call Gemnasium service" do
-      Gemnasium::GitlabService.should_receive(:execute).with(an_instance_of(Hash)).once
-      @gemnasium_service.execute(@sample_data)
-    end
-  end
-end
diff --git a/spec/models/gitlab_ci_service_spec.rb b/spec/models/gitlab_ci_service_spec.rb
deleted file mode 100644
index 83277058fbb183a838d3fc96a564a5c6feb68b51..0000000000000000000000000000000000000000
--- a/spec/models/gitlab_ci_service_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# == Schema Information
-#
-# Table name: services
-#
-#  id         :integer          not null, primary key
-#  type       :string(255)
-#  title      :string(255)
-#  project_id :integer          not null
-#  created_at :datetime
-#  updated_at :datetime
-#  active     :boolean          default(FALSE), not null
-#  properties :text
-#
-
-require 'spec_helper'
-
-describe GitlabCiService do
-  describe "Associations" do
-    it { should belong_to :project }
-    it { should have_one :service_hook }
-  end
-
-  describe "Mass assignment" do
-  end
-
-  describe 'commits methods' do
-    before do
-      @service = GitlabCiService.new
-      @service.stub(
-        service_hook: true,
-        project_url: 'http://ci.gitlab.org/projects/2',
-        token: 'verySecret'
-      )
-    end
-
-    describe :commit_status_path do
-      it { @service.commit_status_path("2ab7834c").should == "http://ci.gitlab.org/projects/2/commits/2ab7834c/status.json?token=verySecret"}
-    end
-
-    describe :build_page do
-      it { @service.build_page("2ab7834c").should == "http://ci.gitlab.org/projects/2/commits/2ab7834c"}
-    end
-  end
-end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 1d4ba8a2b850cdae3075518d52749828e7a9246a..9428224a64f9eba52a98ba773663002d1f4b3c0c 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -19,29 +19,29 @@ describe Group do
   let!(:group) { create(:group) }
 
   describe "Associations" do
-    it { should have_many :projects }
-    it { should have_many :group_members }
+    it { is_expected.to have_many :projects }
+    it { is_expected.to have_many :group_members }
   end
 
-  it { should validate_presence_of :name }
-  it { should validate_uniqueness_of(:name) }
-  it { should validate_presence_of :path }
-  it { should validate_uniqueness_of(:path) }
-  it { should_not validate_presence_of :owner }
+  it { is_expected.to validate_presence_of :name }
+  it { is_expected.to validate_uniqueness_of(:name) }
+  it { is_expected.to validate_presence_of :path }
+  it { is_expected.to validate_uniqueness_of(:path) }
+  it { is_expected.not_to validate_presence_of :owner }
 
   describe :users do
-    it { group.users.should == group.owners }
+    it { expect(group.users).to eq(group.owners) }
   end
 
   describe :human_name do
-    it { group.human_name.should == group.name }
+    it { expect(group.human_name).to eq(group.name) }
   end
 
   describe :add_users do
     let(:user) { create(:user) }
     before { group.add_user(user, GroupMember::MASTER) }
 
-    it { group.group_members.masters.map(&:user).should include(user) }
+    it { expect(group.group_members.masters.map(&:user)).to include(user) }
   end
 
   describe :add_users do
@@ -49,10 +49,10 @@ describe Group do
     before { group.add_users([user.id], GroupMember::GUEST) }
 
     it "should update the group permission" do
-      group.group_members.guests.map(&:user).should include(user)
+      expect(group.group_members.guests.map(&:user)).to include(user)
       group.add_users([user.id], GroupMember::DEVELOPER)
-      group.group_members.developers.map(&:user).should include(user)
-      group.group_members.guests.map(&:user).should_not include(user)
+      expect(group.group_members.developers.map(&:user)).to include(user)
+      expect(group.group_members.guests.map(&:user)).not_to include(user)
     end
   end
 
@@ -62,12 +62,12 @@ describe Group do
 
     it "should be true if avatar is image" do
       group.update_attribute(:avatar, 'uploads/avatar.png')
-      group.avatar_type.should be_true
+      expect(group.avatar_type).to be_truthy
     end
 
     it "should be false if avatar is html page" do
       group.update_attribute(:avatar, 'uploads/avatar.html')
-      group.avatar_type.should == ["only images allowed"]
+      expect(group.avatar_type).to eq(["only images allowed"])
     end
   end
 end
diff --git a/spec/models/project_hook_spec.rb b/spec/models/hooks/project_hook_spec.rb
similarity index 100%
rename from spec/models/project_hook_spec.rb
rename to spec/models/hooks/project_hook_spec.rb
diff --git a/spec/models/service_hook_spec.rb b/spec/models/hooks/service_hook_spec.rb
similarity index 94%
rename from spec/models/service_hook_spec.rb
rename to spec/models/hooks/service_hook_spec.rb
index 6ec82438dfe6bae49bb759df5c936a9fa899cf7a..96bf74d45da7589495953ae9ca71598c8cd0d66d 100644
--- a/spec/models/service_hook_spec.rb
+++ b/spec/models/hooks/service_hook_spec.rb
@@ -19,6 +19,6 @@ require "spec_helper"
 
 describe ServiceHook do
   describe "Associations" do
-    it { should belong_to :service }
+    it { is_expected.to belong_to :service }
   end
 end
diff --git a/spec/models/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb
similarity index 50%
rename from spec/models/system_hook_spec.rb
rename to spec/models/hooks/system_hook_spec.rb
index 4ab5261dc9d1397e4044973e823575c966e26a01..810b311a40bbc24d60af228bf9a4aa57ec34d375 100644
--- a/spec/models/system_hook_spec.rb
+++ b/spec/models/hooks/system_hook_spec.rb
@@ -26,32 +26,32 @@ describe SystemHook do
 
     it "project_create hook" do
       Projects::CreateService.new(create(:user), name: 'empty').execute
-      WebMock.should have_requested(:post, @system_hook.url).with(body: /project_create/).once
+      expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /project_create/).once
     end
 
     it "project_destroy hook" do
       user = create(:user)
       project = create(:empty_project, namespace: user.namespace)
       Projects::DestroyService.new(project, user, {}).execute
-      WebMock.should have_requested(:post, @system_hook.url).with(body: /project_destroy/).once
+      expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /project_destroy/).once
     end
 
     it "user_create hook" do
       create(:user)
-      WebMock.should have_requested(:post, @system_hook.url).with(body: /user_create/).once
+      expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /user_create/).once
     end
 
     it "user_destroy hook" do
       user = create(:user)
       user.destroy
-      WebMock.should have_requested(:post, @system_hook.url).with(body: /user_destroy/).once
+      expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /user_destroy/).once
     end
 
     it "project_create hook" do
       user = create(:user)
       project = create(:project)
       project.team << [user, :master]
-      WebMock.should have_requested(:post, @system_hook.url).with(body: /user_add_to_team/).once
+      expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /user_add_to_team/).once
     end
 
     it "project_destroy hook" do
@@ -59,7 +59,42 @@ describe SystemHook do
       project = create(:project)
       project.team << [user, :master]
       project.project_members.destroy_all
-      WebMock.should have_requested(:post, @system_hook.url).with(body: /user_remove_from_team/).once
+      expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /user_remove_from_team/).once
     end
+
+    it 'group create hook' do
+      create(:group)
+      expect(WebMock).to have_requested(:post, @system_hook.url).with(
+        body: /group_create/
+      ).once
+    end
+
+    it 'group destroy hook' do
+      group = create(:group)
+      group.destroy
+      expect(WebMock).to have_requested(:post, @system_hook.url).with(
+        body: /group_destroy/
+      ).once
+    end
+
+    it 'group member create hook' do
+      group = create(:group)
+      user = create(:user)
+      group.add_user(user, Gitlab::Access::MASTER)
+      expect(WebMock).to have_requested(:post, @system_hook.url).with(
+        body: /user_add_to_group/
+      ).once
+    end
+
+    it 'group member destroy hook' do
+      group = create(:group)
+      user = create(:user)
+      group.add_user(user, Gitlab::Access::MASTER)
+      group.group_members.destroy_all
+      expect(WebMock).to have_requested(:post, @system_hook.url).with(
+        body: /user_remove_from_group/
+      ).once
+    end
+
   end
 end
diff --git a/spec/models/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
similarity index 59%
rename from spec/models/web_hook_spec.rb
rename to spec/models/hooks/web_hook_spec.rb
index e9c04ee89cbb1f3c453de5e788a2230592b6a29b..67ec9193ad7db5daa111c11a1fbcfca249bd1567 100644
--- a/spec/models/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -19,25 +19,25 @@ require 'spec_helper'
 
 describe ProjectHook do
   describe "Associations" do
-    it { should belong_to :project }
+    it { is_expected.to belong_to :project }
   end
 
   describe "Mass assignment" do
   end
 
   describe "Validations" do
-    it { should validate_presence_of(:url) }
+    it { is_expected.to validate_presence_of(:url) }
 
     context "url format" do
-      it { should allow_value("http://example.com").for(:url) }
-      it { should allow_value("https://excample.com").for(:url) }
-      it { should allow_value("http://test.com/api").for(:url) }
-      it { should allow_value("http://test.com/api?key=abc").for(:url) }
-      it { should allow_value("http://test.com/api?key=abc&type=def").for(:url) }
+      it { is_expected.to allow_value("http://example.com").for(:url) }
+      it { is_expected.to allow_value("https://excample.com").for(:url) }
+      it { is_expected.to allow_value("http://test.com/api").for(:url) }
+      it { is_expected.to allow_value("http://test.com/api?key=abc").for(:url) }
+      it { is_expected.to allow_value("http://test.com/api?key=abc&type=def").for(:url) }
 
-      it { should_not allow_value("example.com").for(:url) }
-      it { should_not allow_value("ftp://example.com").for(:url) }
-      it { should_not allow_value("herp-and-derp").for(:url) }
+      it { is_expected.not_to allow_value("example.com").for(:url) }
+      it { is_expected.not_to allow_value("ftp://example.com").for(:url) }
+      it { is_expected.not_to allow_value("herp-and-derp").for(:url) }
     end
   end
 
@@ -53,22 +53,22 @@ describe ProjectHook do
 
     it "POSTs to the web hook URL" do
       @project_hook.execute(@data)
-      WebMock.should have_requested(:post, @project_hook.url).once
+      expect(WebMock).to have_requested(:post, @project_hook.url).once
     end
 
     it "POSTs the data as JSON" do
       json = @data.to_json
 
       @project_hook.execute(@data)
-      WebMock.should have_requested(:post, @project_hook.url).with(body: json).once
+      expect(WebMock).to have_requested(:post, @project_hook.url).with(body: json).once
     end
 
     it "catches exceptions" do
-      WebHook.should_receive(:post).and_raise("Some HTTP Post error")
+      expect(WebHook).to receive(:post).and_raise("Some HTTP Post error")
 
-      lambda {
+      expect {
         @project_hook.execute(@data)
-      }.should raise_error
+      }.to raise_error
     end
   end
 end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 6b6efe832e5ebe8edb5c5fe179fc3aa09902eaa7..087e40c3d840e86faa9ca49049282d6d2cc1d0b3 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -21,14 +21,14 @@ require 'spec_helper'
 
 describe Issue do
   describe "Associations" do
-    it { should belong_to(:milestone) }
+    it { is_expected.to belong_to(:milestone) }
   end
 
   describe "Mass assignment" do
   end
 
   describe 'modules' do
-    it { should include_module(Issuable) }
+    it { is_expected.to include_module(Issuable) }
   end
 
   subject { create(:issue) }
@@ -36,10 +36,10 @@ describe Issue do
   describe '#is_being_reassigned?' do
     it 'returns true if the issue assignee has changed' do
       subject.assignee = create(:user)
-      subject.is_being_reassigned?.should be_true
+      expect(subject.is_being_reassigned?).to be_truthy
     end
     it 'returns false if the issue assignee has not changed' do
-      subject.is_being_reassigned?.should be_false
+      expect(subject.is_being_reassigned?).to be_falsey
     end
   end
 
@@ -51,7 +51,7 @@ describe Issue do
         issue = create :issue, assignee: user
       end
 
-      Issue.open_for(user).count.should eq 2
+      expect(Issue.open_for(user).count).to eq 2
     end
   end
 
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 95c0aed0ffe50da9b089546cd6e8211b0460a3f2..a212b95a7d6e9c5a645dd8bafdbf34e12bd26e1f 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -16,67 +16,67 @@ require 'spec_helper'
 
 describe Key do
   describe "Associations" do
-    it { should belong_to(:user) }
+    it { is_expected.to belong_to(:user) }
   end
 
   describe "Mass assignment" do
   end
 
   describe "Validation" do
-    it { should validate_presence_of(:title) }
-    it { should validate_presence_of(:key) }
-    it { should ensure_length_of(:title).is_within(0..255) }
-    it { should ensure_length_of(:key).is_within(0..5000) }
+    it { is_expected.to validate_presence_of(:title) }
+    it { is_expected.to validate_presence_of(:key) }
+    it { is_expected.to ensure_length_of(:title).is_within(0..255) }
+    it { is_expected.to ensure_length_of(:key).is_within(0..5000) }
   end
 
   describe "Methods" do
-    it { should respond_to :projects }
+    it { is_expected.to respond_to :projects }
   end
 
   context "validation of uniqueness" do
     let(:user) { create(:user) }
 
     it "accepts the key once" do
-      build(:key, user: user).should be_valid
+      expect(build(:key, user: user)).to be_valid
     end
 
     it "does not accept the exact same key twice" do
       create(:key, user: user)
-      build(:key, user: user).should_not be_valid
+      expect(build(:key, user: user)).not_to be_valid
     end
 
     it "does not accept a duplicate key with a different comment" do
       create(:key, user: user)
       duplicate = build(:key, user: user)
       duplicate.key << ' extra comment'
-      duplicate.should_not be_valid
+      expect(duplicate).not_to be_valid
     end
   end
 
   context "validate it is a fingerprintable key" do
     it "accepts the fingerprintable key" do
-      build(:key).should be_valid
+      expect(build(:key)).to be_valid
     end
 
     it "rejects the unfingerprintable key (contains space in middle)" do
-      build(:key_with_a_space_in_the_middle).should_not be_valid
+      expect(build(:key_with_a_space_in_the_middle)).not_to be_valid
     end
 
     it "rejects the unfingerprintable key (not a key)" do
-      build(:invalid_key).should_not be_valid
+      expect(build(:invalid_key)).not_to be_valid
     end
   end
 
   context 'callbacks' do
     it 'should add new key to authorized_file' do
       @key = build(:personal_key, id: 7)
-      GitlabShellWorker.should_receive(:perform_async).with(:add_key, @key.shell_id, @key.key)
+      expect(GitlabShellWorker).to receive(:perform_async).with(:add_key, @key.shell_id, @key.key)
       @key.save
     end
 
     it 'should remove key from authorized_file' do
       @key = create(:personal_key)
-      GitlabShellWorker.should_receive(:perform_async).with(:remove_key, @key.shell_id, @key.key)
+      expect(GitlabShellWorker).to receive(:perform_async).with(:remove_key, @key.shell_id, @key.key)
       @key.destroy
     end
   end
diff --git a/spec/models/label_link_spec.rb b/spec/models/label_link_spec.rb
index 0db60432ad37744c4c24db9c47d50367e72e5cbd..8c240826582807ad8614fc75602e4d9e7f2a0f9b 100644
--- a/spec/models/label_link_spec.rb
+++ b/spec/models/label_link_spec.rb
@@ -14,8 +14,8 @@ require 'spec_helper'
 
 describe LabelLink do
   let(:label) { create(:label_link) }
-  it { label.should be_valid }
+  it { expect(label).to be_valid }
 
-  it { should belong_to(:label) }
-  it { should belong_to(:target) }
+  it { is_expected.to belong_to(:label) }
+  it { is_expected.to belong_to(:target) }
 end
diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb
index 31634648f0418d45713e4ebd7fce8b5d55be3f97..8644ac46605af0a17c6e4c43e3254a510d9f971b 100644
--- a/spec/models/label_spec.rb
+++ b/spec/models/label_spec.rb
@@ -14,30 +14,30 @@ require 'spec_helper'
 
 describe Label do
   let(:label) { create(:label) }
-  it { label.should be_valid }
+  it { expect(label).to be_valid }
 
-  it { should belong_to(:project) }
+  it { is_expected.to belong_to(:project) }
 
   describe 'Validation' do
     it 'should validate color code' do
-      build(:label, color: 'G-ITLAB').should_not be_valid
-      build(:label, color: 'AABBCC').should_not be_valid
-      build(:label, color: '#AABBCCEE').should_not be_valid
-      build(:label, color: '#GGHHII').should_not be_valid
-      build(:label, color: '#').should_not be_valid
-      build(:label, color: '').should_not be_valid
+      expect(build(:label, color: 'G-ITLAB')).not_to be_valid
+      expect(build(:label, color: 'AABBCC')).not_to be_valid
+      expect(build(:label, color: '#AABBCCEE')).not_to be_valid
+      expect(build(:label, color: '#GGHHII')).not_to be_valid
+      expect(build(:label, color: '#')).not_to be_valid
+      expect(build(:label, color: '')).not_to be_valid
 
-      build(:label, color: '#AABBCC').should be_valid
+      expect(build(:label, color: '#AABBCC')).to be_valid
     end
 
     it 'should validate title' do
-      build(:label, title: 'G,ITLAB').should_not be_valid
-      build(:label, title: 'G?ITLAB').should_not be_valid
-      build(:label, title: 'G&ITLAB').should_not be_valid
-      build(:label, title: '').should_not be_valid
+      expect(build(:label, title: 'G,ITLAB')).not_to be_valid
+      expect(build(:label, title: 'G?ITLAB')).not_to be_valid
+      expect(build(:label, title: 'G&ITLAB')).not_to be_valid
+      expect(build(:label, title: '')).not_to be_valid
 
-      build(:label, title: 'GITLAB').should be_valid
-      build(:label, title: 'gitlab').should be_valid
+      expect(build(:label, title: 'GITLAB')).to be_valid
+      expect(build(:label, title: 'gitlab')).to be_valid
     end
   end
 end
diff --git a/spec/models/group_member_spec.rb b/spec/models/members/group_member_spec.rb
similarity index 67%
rename from spec/models/group_member_spec.rb
rename to spec/models/members/group_member_spec.rb
index 38657de6793be7af5a2ca230607d2a2ae422c4b5..e206c11f33ae43bb117f1d899307cd60de1a8e08 100644
--- a/spec/models/group_member_spec.rb
+++ b/spec/models/members/group_member_spec.rb
@@ -21,25 +21,25 @@ describe GroupMember do
       it "should send email to user" do
         membership = build(:group_member)
         membership.stub(notification_service: double('NotificationService').as_null_object)
-        membership.should_receive(:notification_service)
+        expect(membership).to receive(:notification_service)
         membership.save
       end
     end
 
     describe "#after_update" do
       before do
-        @membership = create :group_member
-        @membership.stub(notification_service: double('NotificationService').as_null_object)
+        @group_member = create :group_member
+        @group_member.stub(notification_service: double('NotificationService').as_null_object)
       end
 
       it "should send email to user" do
-        @membership.should_receive(:notification_service)
-        @membership.update_attribute(:access_level, GroupMember::MASTER)
+        expect(@group_member).to receive(:notification_service)
+        @group_member.update_attribute(:access_level, GroupMember::MASTER)
       end
 
       it "does not send an email when the access level has not changed" do
-        @membership.should_not_receive(:notification_service)
-        @membership.update_attribute(:access_level, GroupMember::OWNER)
+        expect(@group_member).not_to receive(:notification_service)
+        @group_member.update_attribute(:access_level, GroupMember::OWNER)
       end
     end
   end
diff --git a/spec/models/project_member_spec.rb b/spec/models/members/project_member_spec.rb
similarity index 69%
rename from spec/models/project_member_spec.rb
rename to spec/models/members/project_member_spec.rb
index 9b5f89b6d7d472f6deca96bbb26cd4f863ac0bbf..521721f3577ee2cba82abdc7c9b4a88fe3131ee7 100644
--- a/spec/models/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -33,19 +33,19 @@ describe ProjectMember do
       @status = @project_2.team.import(@project_1)
     end
 
-    it { @status.should be_true }
+    it { expect(@status).to be_truthy }
 
     describe 'project 2 should get user 1 as developer. user_2 should not be changed' do
-      it { @project_2.users.should include(@user_1) }
-      it { @project_2.users.should include(@user_2) }
+      it { expect(@project_2.users).to include(@user_1) }
+      it { expect(@project_2.users).to include(@user_2) }
 
-      it { @abilities.allowed?(@user_1, :write_project, @project_2).should be_true }
-      it { @abilities.allowed?(@user_2, :read_project, @project_2).should be_true }
+      it { expect(@abilities.allowed?(@user_1, :write_project, @project_2)).to be_truthy }
+      it { expect(@abilities.allowed?(@user_2, :read_project, @project_2)).to be_truthy }
     end
 
     describe 'project 1 should not be changed' do
-      it { @project_1.users.should include(@user_1) }
-      it { @project_1.users.should_not include(@user_2) }
+      it { expect(@project_1.users).to include(@user_1) }
+      it { expect(@project_1.users).not_to include(@user_2) }
     end
   end
 
@@ -64,12 +64,12 @@ describe ProjectMember do
       )
     end
 
-    it { @project_1.users.should include(@user_1) }
-    it { @project_1.users.should include(@user_2) }
+    it { expect(@project_1.users).to include(@user_1) }
+    it { expect(@project_1.users).to include(@user_2) }
 
 
-    it { @project_2.users.should include(@user_1) }
-    it { @project_2.users.should include(@user_2) }
+    it { expect(@project_2.users).to include(@user_1) }
+    it { expect(@project_2.users).to include(@user_2) }
   end
 
   describe :truncate_teams do
@@ -86,7 +86,7 @@ describe ProjectMember do
       ProjectMember.truncate_teams([@project_1.id, @project_2.id])
     end
 
-    it { @project_1.users.should be_empty }
-    it { @project_2.users.should be_empty }
+    it { expect(@project_1.users).to be_empty }
+    it { expect(@project_2.users).to be_empty }
   end
 end
diff --git a/spec/models/members_spec.rb b/spec/models/members_spec.rb
index 6866c4794c28b9c8774077c005b9ed73ac8cc57e..dfd3f7feb6b17a4b71caac66b0f3c1415bc4f8b1 100644
--- a/spec/models/members_spec.rb
+++ b/spec/models/members_spec.rb
@@ -2,19 +2,19 @@ require 'spec_helper'
 
 describe Member do
   describe "Associations" do
-    it { should belong_to(:user) }
+    it { is_expected.to belong_to(:user) }
   end
 
   describe "Validation" do
     subject { Member.new(access_level: Member::GUEST) }
 
-    it { should validate_presence_of(:user) }
-    it { should validate_presence_of(:source) }
-    it { should ensure_inclusion_of(:access_level).in_array(Gitlab::Access.values) }
+    it { is_expected.to validate_presence_of(:user) }
+    it { is_expected.to validate_presence_of(:source) }
+    it { is_expected.to validate_inclusion_of(:access_level).in_array(Gitlab::Access.values) }
   end
 
   describe "Delegate methods" do
-    it { should respond_to(:user_name) }
-    it { should respond_to(:user_email) }
+    it { is_expected.to respond_to(:user_name) }
+    it { is_expected.to respond_to(:user_email) }
   end
 end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 7b0d261d72feaf880304b5a78b9225e554238f48..d40503d791cad7a6c6f8ab9a8b4fbd18a933020b 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -18,41 +18,42 @@
 #  iid               :integer
 #  description       :text
 #  position          :integer          default(0)
+#  locked_at         :datetime
 #
 
 require 'spec_helper'
 
 describe MergeRequest do
   describe "Validation" do
-    it { should validate_presence_of(:target_branch) }
-    it { should validate_presence_of(:source_branch) }
+    it { is_expected.to validate_presence_of(:target_branch) }
+    it { is_expected.to validate_presence_of(:source_branch) }
   end
 
   describe "Mass assignment" do
   end
 
   describe "Respond to" do
-    it { should respond_to(:unchecked?) }
-    it { should respond_to(:can_be_merged?) }
-    it { should respond_to(:cannot_be_merged?) }
+    it { is_expected.to respond_to(:unchecked?) }
+    it { is_expected.to respond_to(:can_be_merged?) }
+    it { is_expected.to respond_to(:cannot_be_merged?) }
   end
 
   describe 'modules' do
-    it { should include_module(Issuable) }
+    it { is_expected.to include_module(Issuable) }
   end
 
   describe "#mr_and_commit_notes" do
     let!(:merge_request) { create(:merge_request) }
 
     before do
-      merge_request.stub(:commits) { [merge_request.source_project.repository.commit] }
+      allow(merge_request).to receive(:commits) { [merge_request.source_project.repository.commit] }
       create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit', project: merge_request.project)
       create(:note, noteable: merge_request, project: merge_request.project)
     end
 
     it "should include notes for commits" do
-      merge_request.commits.should_not be_empty
-      merge_request.mr_and_commit_notes.count.should == 2
+      expect(merge_request.commits).not_to be_empty
+      expect(merge_request.mr_and_commit_notes.count).to eq(2)
     end
   end
 
@@ -61,10 +62,10 @@ describe MergeRequest do
   describe '#is_being_reassigned?' do
     it 'returns true if the merge_request assignee has changed' do
       subject.assignee = create(:user)
-      subject.is_being_reassigned?.should be_true
+      expect(subject.is_being_reassigned?).to be_truthy
     end
     it 'returns false if the merge request assignee has not changed' do
-      subject.is_being_reassigned?.should be_false
+      expect(subject.is_being_reassigned?).to be_falsey
     end
   end
 
@@ -73,11 +74,11 @@ describe MergeRequest do
       subject.source_project = create(:project, namespace: create(:group))
       subject.target_project = create(:project, namespace: create(:group))
 
-      subject.for_fork?.should be_true
+      expect(subject.for_fork?).to be_truthy
     end
 
     it 'returns false if is not for a fork' do
-      subject.for_fork?.should be_false
+      expect(subject.for_fork?).to be_falsey
     end
   end
 
@@ -95,14 +96,14 @@ describe MergeRequest do
     it 'accesses the set of issues that will be closed on acceptance' do
       subject.project.stub(default_branch: subject.target_branch)
 
-      subject.closes_issues.should == [issue0, issue1].sort_by(&:id)
+      expect(subject.closes_issues).to eq([issue0, issue1].sort_by(&:id))
     end
 
     it 'only lists issues as to be closed if it targets the default branch' do
       subject.project.stub(default_branch: 'master')
       subject.target_branch = 'something-else'
 
-      subject.closes_issues.should be_empty
+      expect(subject.closes_issues).to be_empty
     end
 
     it 'detects issues mentioned in the description' do
@@ -110,7 +111,7 @@ describe MergeRequest do
       subject.description = "Closes ##{issue2.iid}"
       subject.project.stub(default_branch: subject.target_branch)
 
-      subject.closes_issues.should include(issue2)
+      expect(subject.closes_issues).to include(issue2)
     end
   end
 
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index a3071c3251a245d921810b51ca26f593c3187842..45171e1bf6459a35e4b7c0a4e227cdfc2b9d69f4 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -17,8 +17,8 @@ require 'spec_helper'
 
 describe Milestone do
   describe "Associations" do
-    it { should belong_to(:project) }
-    it { should have_many(:issues) }
+    it { is_expected.to belong_to(:project) }
+    it { is_expected.to have_many(:issues) }
   end
 
   describe "Mass assignment" do
@@ -26,8 +26,8 @@ describe Milestone do
 
   describe "Validation" do
     before { subject.stub(set_iid: false) }
-    it { should validate_presence_of(:title) }
-    it { should validate_presence_of(:project) }
+    it { is_expected.to validate_presence_of(:title) }
+    it { is_expected.to validate_presence_of(:project) }
   end
 
   let(:milestone) { create(:milestone) }
@@ -36,30 +36,30 @@ describe Milestone do
   describe "#percent_complete" do
     it "should not count open issues" do
       milestone.issues << issue
-      milestone.percent_complete.should == 0
+      expect(milestone.percent_complete).to eq(0)
     end
 
     it "should count closed issues" do
       issue.close
       milestone.issues << issue
-      milestone.percent_complete.should == 100
+      expect(milestone.percent_complete).to eq(100)
     end
 
     it "should recover from dividing by zero" do
-      milestone.issues.should_receive(:count).and_return(0)
-      milestone.percent_complete.should == 100
+      expect(milestone.issues).to receive(:count).and_return(0)
+      expect(milestone.percent_complete).to eq(100)
     end
   end
 
   describe "#expires_at" do
     it "should be nil when due_date is unset" do
       milestone.update_attributes(due_date: nil)
-      milestone.expires_at.should be_nil
+      expect(milestone.expires_at).to be_nil
     end
 
     it "should not be nil when due_date is set" do
       milestone.update_attributes(due_date: Date.tomorrow)
-      milestone.expires_at.should be_present
+      expect(milestone.expires_at).to be_present
     end
   end
 
@@ -69,7 +69,7 @@ describe Milestone do
         milestone.stub(due_date: Date.today.prev_year)
       end
 
-      it { milestone.expired?.should be_true }
+      it { expect(milestone.expired?).to be_truthy }
     end
 
     context "not expired" do
@@ -77,7 +77,7 @@ describe Milestone do
         milestone.stub(due_date: Date.today.next_year)
       end
 
-      it { milestone.expired?.should be_false }
+      it { expect(milestone.expired?).to be_falsey }
     end
   end
 
@@ -89,7 +89,7 @@ describe Milestone do
       )
     end
 
-    it { milestone.percent_complete.should == 75 }
+    it { expect(milestone.percent_complete).to eq(75) }
   end
 
   describe :items_count do
@@ -99,14 +99,14 @@ describe Milestone do
       milestone.merge_requests << create(:merge_request)
     end
 
-    it { milestone.closed_items_count.should == 1 }
-    it { milestone.open_items_count.should == 2 }
-    it { milestone.total_items_count.should == 3 }
-    it { milestone.is_empty?.should be_false }
+    it { expect(milestone.closed_items_count).to eq(1) }
+    it { expect(milestone.open_items_count).to eq(2) }
+    it { expect(milestone.total_items_count).to eq(3) }
+    it { expect(milestone.is_empty?).to be_falsey }
   end
 
   describe :can_be_closed? do
-    it { milestone.can_be_closed?.should be_true }
+    it { expect(milestone.can_be_closed?).to be_truthy }
   end
 
   describe :is_empty? do
@@ -116,7 +116,7 @@ describe Milestone do
     end
 
     it 'Should return total count of issues and merge requests assigned to milestone' do
-      milestone.total_items_count.should eq 2
+      expect(milestone.total_items_count).to eq 2
     end
   end
 
@@ -129,14 +129,14 @@ describe Milestone do
     end
 
     it 'should be true if milestone active and all nested issues closed' do
-      milestone.can_be_closed?.should be_true
+      expect(milestone.can_be_closed?).to be_truthy
     end
 
     it 'should be false if milestone active and not all nested issues closed' do
       issue.milestone = milestone
       issue.save
 
-      milestone.can_be_closed?.should be_false
+      expect(milestone.can_be_closed?).to be_falsey
     end
   end
 
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 3562ebed1ffe7bbf8f08b1492f0b9582dcbc4590..ed6845c82ccde162afc94e5cfc1d05551bd926d0 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -18,29 +18,29 @@ require 'spec_helper'
 describe Namespace do
   let!(:namespace) { create(:namespace) }
 
-  it { should have_many :projects }
-  it { should validate_presence_of :name }
-  it { should validate_uniqueness_of(:name) }
-  it { should validate_presence_of :path }
-  it { should validate_uniqueness_of(:path) }
-  it { should validate_presence_of :owner }
+  it { is_expected.to have_many :projects }
+  it { is_expected.to validate_presence_of :name }
+  it { is_expected.to validate_uniqueness_of(:name) }
+  it { is_expected.to validate_presence_of :path }
+  it { is_expected.to validate_uniqueness_of(:path) }
+  it { is_expected.to validate_presence_of :owner }
 
   describe "Mass assignment" do
   end
 
   describe "Respond to" do
-    it { should respond_to(:human_name) }
-    it { should respond_to(:to_param) }
+    it { is_expected.to respond_to(:human_name) }
+    it { is_expected.to respond_to(:to_param) }
   end
 
-  it { Namespace.global_id.should == 'GLN' }
+  it { expect(Namespace.global_id).to eq('GLN') }
 
   describe :to_param do
-    it { namespace.to_param.should == namespace.path }
+    it { expect(namespace.to_param).to eq(namespace.path) }
   end
 
   describe :human_name do
-    it { namespace.human_name.should == namespace.owner_name }
+    it { expect(namespace.human_name).to eq(namespace.owner_name) }
   end
 
   describe :search do
@@ -48,8 +48,8 @@ describe Namespace do
       @namespace = create :namespace
     end
 
-    it { Namespace.search(@namespace.path).should == [@namespace] }
-    it { Namespace.search('unknown').should == [] }
+    it { expect(Namespace.search(@namespace.path)).to eq([@namespace]) }
+    it { expect(Namespace.search('unknown')).to eq([]) }
   end
 
   describe :move_dir do
@@ -66,13 +66,23 @@ describe Namespace do
       new_path = @namespace.path + "_new"
       @namespace.stub(path_was: @namespace.path)
       @namespace.stub(path: new_path)
-      @namespace.move_dir.should be_true
+      expect(@namespace.move_dir).to be_truthy
     end
   end
 
   describe :rm_dir do
     it "should remove dir" do
-      namespace.rm_dir.should be_true
+      expect(namespace.rm_dir).to be_truthy
     end
   end
+
+  describe :find_by_path_or_name do
+    before do
+      @namespace = create(:namespace, name: 'WoW', path: 'woW')
+    end
+
+    it { expect(Namespace.find_by_path_or_name('wow')).to eq(@namespace) }
+    it { expect(Namespace.find_by_path_or_name('WOW')).to eq(@namespace) }
+    it { expect(Namespace.find_by_path_or_name('unknown')).to eq(nil) }
+  end
 end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 6ab7162c15c5b470036171f7fe3784a2446206e6..a7bf5081d5b8a9c98176301132c712ab8e5823de 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -21,17 +21,17 @@ require 'spec_helper'
 
 describe Note do
   describe "Associations" do
-    it { should belong_to(:project) }
-    it { should belong_to(:noteable) }
-    it { should belong_to(:author).class_name('User') }
+    it { is_expected.to belong_to(:project) }
+    it { is_expected.to belong_to(:noteable) }
+    it { is_expected.to belong_to(:author).class_name('User') }
   end
 
   describe "Mass assignment" do
   end
 
   describe "Validation" do
-    it { should validate_presence_of(:note) }
-    it { should validate_presence_of(:project) }
+    it { is_expected.to validate_presence_of(:note) }
+    it { is_expected.to validate_presence_of(:project) }
   end
 
   describe "Voting score" do
@@ -39,44 +39,44 @@ describe Note do
 
     it "recognizes a neutral note" do
       note = create(:votable_note, note: "This is not a +1 note")
-      note.should_not be_upvote
-      note.should_not be_downvote
+      expect(note).not_to be_upvote
+      expect(note).not_to be_downvote
     end
 
     it "recognizes a neutral emoji note" do
       note = build(:votable_note, note: "I would :+1: this, but I don't want to")
-      note.should_not be_upvote
-      note.should_not be_downvote
+      expect(note).not_to be_upvote
+      expect(note).not_to be_downvote
     end
 
     it "recognizes a +1 note" do
       note = create(:votable_note, note: "+1 for this")
-      note.should be_upvote
+      expect(note).to be_upvote
     end
 
     it "recognizes a +1 emoji as a vote" do
       note = build(:votable_note, note: ":+1: for this")
-      note.should be_upvote
+      expect(note).to be_upvote
     end
 
     it "recognizes a thumbsup emoji as a vote" do
       note = build(:votable_note, note: ":thumbsup: for this")
-      note.should be_upvote
+      expect(note).to be_upvote
     end
 
     it "recognizes a -1 note" do
       note = create(:votable_note, note: "-1 for this")
-      note.should be_downvote
+      expect(note).to be_downvote
     end
 
     it "recognizes a -1 emoji as a vote" do
       note = build(:votable_note, note: ":-1: for this")
-      note.should be_downvote
+      expect(note).to be_downvote
     end
 
     it "recognizes a thumbsdown emoji as a vote" do
       note = build(:votable_note, note: ":thumbsdown: for this")
-      note.should be_downvote
+      expect(note).to be_downvote
     end
   end
 
@@ -87,22 +87,22 @@ describe Note do
     let!(:commit) { note.noteable }
 
     it "should be accessible through #noteable" do
-      note.commit_id.should == commit.id
-      note.noteable.should be_a(Commit)
-      note.noteable.should == commit
+      expect(note.commit_id).to eq(commit.id)
+      expect(note.noteable).to be_a(Commit)
+      expect(note.noteable).to eq(commit)
     end
 
     it "should save a valid note" do
-      note.commit_id.should == commit.id
+      expect(note.commit_id).to eq(commit.id)
       note.noteable == commit
     end
 
     it "should be recognized by #for_commit?" do
-      note.should be_for_commit
+      expect(note).to be_for_commit
     end
 
     it "should not be votable" do
-      note.should_not be_votable
+      expect(note).not_to be_votable
     end
   end
 
@@ -111,20 +111,20 @@ describe Note do
     let!(:commit) { note.noteable }
 
     it "should save a valid note" do
-      note.commit_id.should == commit.id
-      note.noteable.id.should == commit.id
+      expect(note.commit_id).to eq(commit.id)
+      expect(note.noteable.id).to eq(commit.id)
     end
 
     it "should be recognized by #for_diff_line?" do
-      note.should be_for_diff_line
+      expect(note).to be_for_diff_line
     end
 
     it "should be recognized by #for_commit_diff_line?" do
-      note.should be_for_commit_diff_line
+      expect(note).to be_for_commit_diff_line
     end
 
     it "should not be votable" do
-      note.should_not be_votable
+      expect(note).not_to be_votable
     end
   end
 
@@ -132,7 +132,7 @@ describe Note do
     let!(:note) { create(:note_on_issue, note: "+1 from me") }
 
     it "should not be votable" do
-      note.should be_votable
+      expect(note).to be_votable
     end
   end
 
@@ -140,7 +140,7 @@ describe Note do
     let!(:note) { create(:note_on_merge_request, note: "+1 from me") }
 
     it "should be votable" do
-      note.should be_votable
+      expect(note).to be_votable
     end
   end
 
@@ -148,7 +148,7 @@ describe Note do
     let!(:note) { create(:note_on_merge_request_diff, note: "+1 from me") }
 
     it "should not be votable" do
-      note.should_not be_votable
+      expect(note).not_to be_votable
     end
   end
 
@@ -161,20 +161,35 @@ describe Note do
     subject { Note.create_status_change_note(thing, project, author, status, nil) }
 
     it 'creates and saves a Note' do
-      should be_a Note
-      subject.id.should_not be_nil
+      is_expected.to be_a Note
+      expect(subject.id).not_to be_nil
     end
 
-    its(:noteable) { should == thing }
-    its(:project) { should == thing.project }
-    its(:author) { should == author }
-    its(:note) { should =~ /Status changed to #{status}/ }
+    describe '#noteable' do
+      subject { super().noteable }
+      it { is_expected.to eq(thing) }
+    end
+
+    describe '#project' do
+      subject { super().project }
+      it { is_expected.to eq(thing.project) }
+    end
+
+    describe '#author' do
+      subject { super().author }
+      it { is_expected.to eq(author) }
+    end
+
+    describe '#note' do
+      subject { super().note }
+      it { is_expected.to eq("Status changed to #{status}") }
+    end
 
     it 'appends a back-reference if a closing mentionable is supplied' do
       commit = double('commit', gfm_reference: 'commit 123456')
       n = Note.create_status_change_note(thing, project, author, status, commit)
 
-      n.note.should =~ /Status changed to #{status} by commit 123456/
+      expect(n.note).to eq("Status changed to #{status} by commit 123456")
     end
   end
 
@@ -182,24 +197,130 @@ describe Note do
     let(:project) { create(:project) }
     let(:thing) { create(:issue, project: project) }
     let(:author) { create(:user) }
-    let(:assignee) { create(:user) }
+    let(:assignee) { create(:user, username: "assigned_user") }
 
     subject { Note.create_assignee_change_note(thing, project, author, assignee) }
 
     context 'creates and saves a Note' do
-      it { should be_a Note }
-      its(:id) { should_not be_nil }
+      it { is_expected.to be_a Note }
+
+      describe '#id' do
+        subject { super().id }
+        it { is_expected.not_to be_nil }
+      end
+    end
+
+    describe '#noteable' do
+      subject { super().noteable }
+      it { is_expected.to eq(thing) }
+    end
+
+    describe '#project' do
+      subject { super().project }
+      it { is_expected.to eq(thing.project) }
+    end
+
+    describe '#author' do
+      subject { super().author }
+      it { is_expected.to eq(author) }
     end
 
-    its(:noteable) { should == thing }
-    its(:project) { should == thing.project }
-    its(:author) { should == author }
-    its(:note) { should =~ /Reassigned to @#{assignee.username}/ }
+    describe '#note' do
+      subject { super().note }
+      it { is_expected.to eq('Reassigned to @assigned_user') }
+    end
 
     context 'assignee is removed' do
       let(:assignee) { nil }
 
-      its(:note) { should =~ /Assignee removed/ }
+      describe '#note' do
+        subject { super().note }
+        it { is_expected.to eq('Assignee removed') }
+      end
+    end
+  end
+
+  describe '#create_labels_change_note' do
+    let(:project) { create(:project) }
+    let(:thing) { create(:issue, project: project) }
+    let(:author) { create(:user) }
+    let(:label1) { create(:label) }
+    let(:label2) { create(:label) }
+    let(:added_labels) { [label1, label2] }
+    let(:removed_labels) { [] }
+
+    subject { Note.create_labels_change_note(thing, project, author, added_labels, removed_labels) }
+
+    context 'creates and saves a Note' do
+      it { is_expected.to be_a Note }
+
+      describe '#id' do
+        subject { super().id }
+        it { is_expected.not_to be_nil }
+      end
+    end
+
+    describe '#noteable' do
+      subject { super().noteable }
+      it { is_expected.to eq(thing) }
+    end
+
+    describe '#project' do
+      subject { super().project }
+      it { is_expected.to eq(thing.project) }
+    end
+
+    describe '#author' do
+      subject { super().author }
+      it { is_expected.to eq(author) }
+    end
+
+    describe '#note' do
+      subject { super().note }
+      it { is_expected.to eq("Added ~#{label1.id} ~#{label2.id} labels") }
+    end
+
+    context 'label is removed' do
+      let(:added_labels) { [label1]  }
+      let(:removed_labels) { [label2] }
+
+      describe '#note' do
+        subject { super().note }
+        it { is_expected.to eq("Added ~#{label1.id} and removed ~#{label2.id} labels") }
+      end
+    end
+  end
+
+  describe '#create_milestone_change_note' do
+    let(:project) { create(:project) }
+    let(:thing) { create(:issue, project: project) }
+    let(:milestone) { create(:milestone, project: project, title: "first_milestone") }
+    let(:author) { create(:user) }
+
+    subject { Note.create_milestone_change_note(thing, project, author, milestone) }
+
+    context 'creates and saves a Note' do
+      it { is_expected.to be_a Note }
+
+      describe '#id' do
+        subject { super().id }
+        it { is_expected.not_to be_nil }
+      end
+    end
+
+    describe '#project' do
+      subject { super().project }
+      it { is_expected.to eq(thing.project) }
+    end
+
+    describe '#author' do
+      subject { super().author }
+      it { is_expected.to eq(author) }
+    end
+
+    describe '#note' do
+      subject { super().note }
+      it { is_expected.to eq("Milestone changed to first_milestone") }
     end
   end
 
@@ -216,64 +337,144 @@ describe Note do
     context 'issue from a merge request' do
       subject { Note.create_cross_reference_note(issue, mergereq, author, project) }
 
-      it { should be_valid }
-      its(:noteable) { should == issue }
-      its(:project)  { should == issue.project }
-      its(:author)   { should == author }
-      its(:note) { should == "_mentioned in merge request !#{mergereq.iid}_" }
+      it { is_expected.to be_valid }
+
+      describe '#noteable' do
+        subject { super().noteable }
+        it { is_expected.to eq(issue) }
+      end
+
+      describe '#project' do
+        subject { super().project }
+        it { is_expected.to eq(issue.project) }
+      end
+
+      describe '#author' do
+        subject { super().author }
+        it { is_expected.to eq(author) }
+      end
+
+      describe '#note' do
+        subject { super().note }
+        it { is_expected.to eq("mentioned in merge request !#{mergereq.iid}") }
+      end
     end
 
     context 'issue from a commit' do
       subject { Note.create_cross_reference_note(issue, commit, author, project) }
 
-      it { should be_valid }
-      its(:noteable) { should == issue }
-      its(:note) { should == "_mentioned in commit #{commit.sha}_" }
+      it { is_expected.to be_valid }
+
+      describe '#noteable' do
+        subject { super().noteable }
+        it { is_expected.to eq(issue) }
+      end
+
+      describe '#note' do
+        subject { super().note }
+        it { is_expected.to eq("mentioned in commit #{commit.sha}") }
+      end
     end
 
     context 'merge request from an issue' do
       subject { Note.create_cross_reference_note(mergereq, issue, author, project) }
 
-      it { should be_valid }
-      its(:noteable) { should == mergereq }
-      its(:project) { should == mergereq.project }
-      its(:note) { should == "_mentioned in issue ##{issue.iid}_" }
+      it { is_expected.to be_valid }
+
+      describe '#noteable' do
+        subject { super().noteable }
+        it { is_expected.to eq(mergereq) }
+      end
+
+      describe '#project' do
+        subject { super().project }
+        it { is_expected.to eq(mergereq.project) }
+      end
+
+      describe '#note' do
+        subject { super().note }
+        it { is_expected.to eq("mentioned in issue ##{issue.iid}") }
+      end
     end
 
     context 'commit from a merge request' do
       subject { Note.create_cross_reference_note(commit, mergereq, author, project) }
 
-      it { should be_valid }
-      its(:noteable) { should == commit }
-      its(:project) { should == project }
-      its(:note) { should == "_mentioned in merge request !#{mergereq.iid}_" }
+      it { is_expected.to be_valid }
+
+      describe '#noteable' do
+        subject { super().noteable }
+        it { is_expected.to eq(commit) }
+      end
+
+      describe '#project' do
+        subject { super().project }
+        it { is_expected.to eq(project) }
+      end
+
+      describe '#note' do
+        subject { super().note }
+        it { is_expected.to eq("mentioned in merge request !#{mergereq.iid}") }
+      end
     end
 
     context 'commit contained in a merge request' do
       subject { Note.create_cross_reference_note(mergereq.commits.first, mergereq, author, project) }
 
-      it { should be_nil }
+      it { is_expected.to be_nil }
     end
 
     context 'commit from issue' do
       subject { Note.create_cross_reference_note(commit, issue, author, project) }
 
-      it { should be_valid }
-      its(:noteable_type) { should == "Commit" }
-      its(:noteable_id) { should be_nil }
-      its(:commit_id) { should == commit.id }
-      its(:note) { should == "_mentioned in issue ##{issue.iid}_" }
+      it { is_expected.to be_valid }
+
+      describe '#noteable_type' do
+        subject { super().noteable_type }
+        it { is_expected.to eq("Commit") }
+      end
+
+      describe '#noteable_id' do
+        subject { super().noteable_id }
+        it { is_expected.to be_nil }
+      end
+
+      describe '#commit_id' do
+        subject { super().commit_id }
+        it { is_expected.to eq(commit.id) }
+      end
+
+      describe '#note' do
+        subject { super().note }
+        it { is_expected.to eq("mentioned in issue ##{issue.iid}") }
+      end
     end
 
     context 'commit from commit' do
       let(:parent_commit) { commit.parents.first }
       subject { Note.create_cross_reference_note(commit, parent_commit, author, project) }
 
-      it { should be_valid }
-      its(:noteable_type) { should == "Commit" }
-      its(:noteable_id) { should be_nil }
-      its(:commit_id) { should == commit.id }
-      its(:note) { should == "_mentioned in commit #{parent_commit.id}_" }
+      it { is_expected.to be_valid }
+
+      describe '#noteable_type' do
+        subject { super().noteable_type }
+        it { is_expected.to eq("Commit") }
+      end
+
+      describe '#noteable_id' do
+        subject { super().noteable_id }
+        it { is_expected.to be_nil }
+      end
+
+      describe '#commit_id' do
+        subject { super().commit_id }
+        it { is_expected.to eq(commit.id) }
+      end
+
+      describe '#note' do
+        subject { super().note }
+        it { is_expected.to eq("mentioned in commit #{parent_commit.id}") }
+      end
     end
   end
 
@@ -289,11 +490,11 @@ describe Note do
     end
 
     it 'detects if a mentionable has already been mentioned' do
-      Note.cross_reference_exists?(issue, commit0).should be_true
+      expect(Note.cross_reference_exists?(issue, commit0)).to be_truthy
     end
 
     it 'detects if a mentionable has not already been mentioned' do
-      Note.cross_reference_exists?(issue, commit1).should be_false
+      expect(Note.cross_reference_exists?(issue, commit1)).to be_falsey
     end
 
     context 'commit on commit' do
@@ -301,8 +502,43 @@ describe Note do
         Note.create_cross_reference_note(commit0, commit1, author, project)
       end
 
-      it { Note.cross_reference_exists?(commit0, commit1).should be_true }
-      it { Note.cross_reference_exists?(commit1, commit0).should be_false }
+      it { expect(Note.cross_reference_exists?(commit0, commit1)).to be_truthy }
+      it { expect(Note.cross_reference_exists?(commit1, commit0)).to be_falsey }
+    end
+
+    context 'legacy note with Markdown emphasis' do
+      let(:issue2) { create :issue, project: project }
+      let!(:note) do
+        create :note, system: true, noteable_id: issue2.id,
+                      noteable_type: "Issue", note: "_mentioned in issue " \
+                      "#{issue.project.path_with_namespace}##{issue.iid}_"
+      end
+
+      it 'detects if a mentionable with emphasis has been mentioned' do
+        expect(Note.cross_reference_exists?(issue2, issue)).to be_truthy
+      end
+    end
+  end
+
+  describe '#cross_references_with_underscores?' do
+    let(:project) { create :project, path: "first_project" }
+    let(:second_project) { create :project, path: "second_project" }
+
+    let(:author) { create :user }
+    let(:issue0) { create :issue, project: project }
+    let(:issue1) { create :issue, project: second_project }
+    let!(:note) { Note.create_cross_reference_note(issue0, issue1, author, project) }
+
+    it 'detects if a mentionable has already been mentioned' do
+      expect(Note.cross_reference_exists?(issue0, issue1)).to be_truthy
+    end
+
+    it 'detects if a mentionable has not already been mentioned' do
+      expect(Note.cross_reference_exists?(issue1, issue0)).to be_falsey
+    end
+
+    it 'detects that text has underscores' do
+      expect(note.note).to eq("mentioned in issue #{second_project.path_with_namespace}##{issue1.iid}")
     end
   end
 
@@ -312,25 +548,37 @@ describe Note do
     let(:other)   { create(:issue, project: project) }
     let(:author)  { create(:user) }
     let(:assignee) { create(:user) }
+    let(:label) { create(:label) }
+    let(:milestone) { create(:milestone) }
 
     it 'should recognize user-supplied notes as non-system' do
       @note = create(:note_on_issue)
-      @note.should_not be_system
+      expect(@note).not_to be_system
     end
 
     it 'should identify status-change notes as system notes' do
       @note = Note.create_status_change_note(issue, project, author, 'closed', nil)
-      @note.should be_system
+      expect(@note).to be_system
     end
 
     it 'should identify cross-reference notes as system notes' do
       @note = Note.create_cross_reference_note(issue, other, author, project)
-      @note.should be_system
+      expect(@note).to be_system
     end
 
     it 'should identify assignee-change notes as system notes' do
       @note = Note.create_assignee_change_note(issue, project, author, assignee)
-      @note.should be_system
+      expect(@note).to be_system
+    end
+
+    it 'should identify label-change notes as system notes' do
+      @note = Note.create_labels_change_note(issue, project, author, [label], [])
+      expect(@note).to be_system
+    end
+
+    it 'should identify milestone-change notes as system notes' do
+      @note = Note.create_milestone_change_note(issue, project, author, milestone)
+      expect(@note).to be_system
     end
   end
 
@@ -351,9 +599,9 @@ describe Note do
         @p2.project_members.create(user: @u3, access_level: ProjectMember::GUEST)
       end
 
-      it { @abilities.allowed?(@u1, :read_note, @p1).should be_false }
-      it { @abilities.allowed?(@u2, :read_note, @p1).should be_true }
-      it { @abilities.allowed?(@u3, :read_note, @p1).should be_false }
+      it { expect(@abilities.allowed?(@u1, :read_note, @p1)).to be_falsey }
+      it { expect(@abilities.allowed?(@u2, :read_note, @p1)).to be_truthy }
+      it { expect(@abilities.allowed?(@u3, :read_note, @p1)).to be_falsey }
     end
 
     describe :write do
@@ -362,9 +610,9 @@ describe Note do
         @p2.project_members.create(user: @u3, access_level: ProjectMember::DEVELOPER)
       end
 
-      it { @abilities.allowed?(@u1, :write_note, @p1).should be_false }
-      it { @abilities.allowed?(@u2, :write_note, @p1).should be_true }
-      it { @abilities.allowed?(@u3, :write_note, @p1).should be_false }
+      it { expect(@abilities.allowed?(@u1, :write_note, @p1)).to be_falsey }
+      it { expect(@abilities.allowed?(@u2, :write_note, @p1)).to be_truthy }
+      it { expect(@abilities.allowed?(@u3, :write_note, @p1)).to be_falsey }
     end
 
     describe :admin do
@@ -374,9 +622,9 @@ describe Note do
         @p2.project_members.create(user: @u3, access_level: ProjectMember::MASTER)
       end
 
-      it { @abilities.allowed?(@u1, :admin_note, @p1).should be_false }
-      it { @abilities.allowed?(@u2, :admin_note, @p1).should be_true }
-      it { @abilities.allowed?(@u3, :admin_note, @p1).should be_false }
+      it { expect(@abilities.allowed?(@u1, :admin_note, @p1)).to be_falsey }
+      it { expect(@abilities.allowed?(@u2, :admin_note, @p1)).to be_truthy }
+      it { expect(@abilities.allowed?(@u3, :admin_note, @p1)).to be_falsey }
     end
   end
 
diff --git a/spec/models/project_security_spec.rb b/spec/models/project_security_spec.rb
index 5c8d1e7438b5fcce0a2ce4fa3a10b9c4f33dcdf7..1ee1900354378f7f4141a257043946ce4e02305a 100644
--- a/spec/models/project_security_spec.rb
+++ b/spec/models/project_security_spec.rb
@@ -23,7 +23,7 @@ describe Project do
     describe "Non member rules" do
       it "should deny for non-project users any actions" do
         admin_actions.each do |action|
-          @abilities.allowed?(@u1, action, @p1).should be_false
+          expect(@abilities.allowed?(@u1, action, @p1)).to be_falsey
         end
       end
     end
@@ -35,7 +35,7 @@ describe Project do
 
       it "should allow for project user any guest actions" do
         guest_actions.each do |action|
-          @abilities.allowed?(@u2, action, @p1).should be_true
+          expect(@abilities.allowed?(@u2, action, @p1)).to be_truthy
         end
       end
     end
@@ -47,7 +47,7 @@ describe Project do
 
       it "should allow for project user any report actions" do
         report_actions.each do |action|
-          @abilities.allowed?(@u2, action, @p1).should be_true
+          expect(@abilities.allowed?(@u2, action, @p1)).to be_truthy
         end
       end
     end
@@ -60,13 +60,13 @@ describe Project do
 
       it "should deny for developer master-specific actions" do
         [dev_actions - report_actions].each do |action|
-          @abilities.allowed?(@u2, action, @p1).should be_false
+          expect(@abilities.allowed?(@u2, action, @p1)).to be_falsey
         end
       end
 
       it "should allow for project user any dev actions" do
         dev_actions.each do |action|
-          @abilities.allowed?(@u3, action, @p1).should be_true
+          expect(@abilities.allowed?(@u3, action, @p1)).to be_truthy
         end
       end
     end
@@ -79,13 +79,13 @@ describe Project do
 
       it "should deny for developer master-specific actions" do
         [master_actions - dev_actions].each do |action|
-          @abilities.allowed?(@u2, action, @p1).should be_false
+          expect(@abilities.allowed?(@u2, action, @p1)).to be_falsey
         end
       end
 
       it "should allow for project user any master actions" do
         master_actions.each do |action|
-          @abilities.allowed?(@u3, action, @p1).should be_true
+          expect(@abilities.allowed?(@u3, action, @p1)).to be_truthy
         end
       end
     end
@@ -98,13 +98,13 @@ describe Project do
 
       it "should deny for masters admin-specific actions" do
         [admin_actions - master_actions].each do |action|
-          @abilities.allowed?(@u2, action, @p1).should be_false
+          expect(@abilities.allowed?(@u2, action, @p1)).to be_falsey
         end
       end
 
       it "should allow for project owner any admin actions" do
         admin_actions.each do |action|
-          @abilities.allowed?(@u4, action, @p1).should be_true
+          expect(@abilities.allowed?(@u4, action, @p1)).to be_truthy
         end
       end
     end
diff --git a/spec/models/project_services/asana_service_spec.rb b/spec/models/project_services/asana_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..13c8d54a2af522664582b7ce487b50a9a84e5235
--- /dev/null
+++ b/spec/models/project_services/asana_service_spec.rb
@@ -0,0 +1,65 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe AsanaService, models: true do
+  describe 'Associations' do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe 'Validations' do
+    context 'active' do
+      before do
+        subject.active = true
+      end
+
+      it { is_expected.to validate_presence_of :api_key }
+    end
+  end
+
+  describe 'Execute' do
+    let(:user) { create(:user) }
+    let(:project) { create(:project) }
+
+    before do
+      @asana = AsanaService.new
+      @asana.stub(
+        project: project,
+        project_id: project.id,
+        service_hook: true,
+        api_key: 'verySecret',
+        restrict_to_branch: 'master'
+      )
+    end
+
+    it 'should call Asana service to created a story' do
+      expect(Asana::Task).to receive(:find).with('123456').once
+
+      @asana.check_commit('related to #123456', 'pushed')
+    end
+
+    it 'should call Asana service to created a story and close a task' do
+      expect(Asana::Task).to receive(:find).with('456789').twice
+
+      @asana.check_commit('fix #456789', 'pushed')
+    end
+  end
+end
diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..91730da1eecdbdf7d6ec85e8dca5d8a14eb649b9
--- /dev/null
+++ b/spec/models/project_services/assembla_service_spec.rb
@@ -0,0 +1,53 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe AssemblaService, models: true do
+  describe "Associations" do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe "Execute" do
+    let(:user)    { create(:user) }
+    let(:project) { create(:project) }
+
+    before do
+      @assembla_service = AssemblaService.new
+      @assembla_service.stub(
+        project_id: project.id,
+        project: project,
+        service_hook: true,
+        token: 'verySecret',
+        subdomain: 'project_name'
+      )
+      @sample_data = Gitlab::PushDataBuilder.build_sample(project, user)
+      @api_url = 'https://atlas.assembla.com/spaces/project_name/github_tool?secret_key=verySecret'
+      WebMock.stub_request(:post, @api_url)
+    end
+
+    it "should call Assembla API" do
+      @assembla_service.execute(@sample_data)
+      expect(WebMock).to have_requested(:post, @api_url).with(
+        body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/
+      ).once
+    end
+  end
+end
diff --git a/spec/models/project_services/buildbox_service_spec.rb b/spec/models/project_services/buildbox_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9f29fbe12b080df9d98b9234ad9706f3cfb219ca
--- /dev/null
+++ b/spec/models/project_services/buildbox_service_spec.rb
@@ -0,0 +1,82 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe BuildboxService do
+  describe 'Associations' do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe 'commits methods' do
+    before do
+      @project = Project.new
+      @project.stub(
+        default_branch: 'default-brancho'
+      )
+
+      @service = BuildboxService.new
+      @service.stub(
+        project: @project,
+        service_hook: true,
+        project_url: 'https://buildkite.com/account-name/example-project',
+        token: 'secret-sauce-webhook-token:secret-sauce-status-token'
+      )
+    end
+
+    describe :webhook_url do
+      it 'returns the webhook url' do
+        expect(@service.webhook_url).to eq(
+          'https://webhook.buildkite.com/deliver/secret-sauce-webhook-token'
+        )
+      end
+    end
+
+    describe :commit_status_path do
+      it 'returns the correct status page' do
+        expect(@service.commit_status_path('2ab7834c')).to eq(
+          'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=2ab7834c'
+        )
+      end
+    end
+
+    describe :build_page do
+      it 'returns the correct build page' do
+        expect(@service.build_page('2ab7834c', nil)).to eq(
+          'https://buildkite.com/account-name/example-project/builds?commit=2ab7834c'
+        )
+      end
+    end
+
+    describe :builds_page do
+      it 'returns the correct path to the builds page' do
+        expect(@service.builds_path).to eq(
+          'https://buildkite.com/account-name/example-project/builds?branch=default-brancho'
+        )
+      end
+    end
+
+    describe :status_img_path do
+      it 'returns the correct path to the status image' do
+        expect(@service.status_img_path).to eq('https://badge.buildkite.com/secret-sauce-status-token.svg')
+      end
+    end
+  end
+end
diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..73f68301a34e309a8ff7b76b587875964c6005bb
--- /dev/null
+++ b/spec/models/project_services/flowdock_service_spec.rb
@@ -0,0 +1,52 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe FlowdockService do
+  describe "Associations" do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe "Execute" do
+    let(:user)    { create(:user) }
+    let(:project) { create(:project) }
+
+    before do
+      @flowdock_service = FlowdockService.new
+      @flowdock_service.stub(
+        project_id: project.id,
+        project: project,
+        service_hook: true,
+        token: 'verySecret'
+      )
+      @sample_data = Gitlab::PushDataBuilder.build_sample(project, user)
+      @api_url = 'https://api.flowdock.com/v1/git/verySecret'
+      WebMock.stub_request(:post, @api_url)
+    end
+
+    it "should call FlowDock API" do
+      @flowdock_service.execute(@sample_data)
+      expect(WebMock).to have_requested(:post, @api_url).with(
+        body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/
+      ).once
+    end
+  end
+end
diff --git a/spec/models/project_services/gemnasium_service_spec.rb b/spec/models/project_services/gemnasium_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d44064bbe6a14f839eb857b9fe9f495b3a3d788c
--- /dev/null
+++ b/spec/models/project_services/gemnasium_service_spec.rb
@@ -0,0 +1,48 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe GemnasiumService do
+  describe "Associations" do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe "Execute" do
+    let(:user)    { create(:user) }
+    let(:project) { create(:project) }
+
+    before do
+      @gemnasium_service = GemnasiumService.new
+      @gemnasium_service.stub(
+        project_id: project.id,
+        project: project,
+        service_hook: true,
+        token: 'verySecret',
+        api_key: 'GemnasiumUserApiKey'
+      )
+      @sample_data = Gitlab::PushDataBuilder.build_sample(project, user)
+    end
+    it "should call Gemnasium service" do
+      expect(Gemnasium::GitlabService).to receive(:execute).with(an_instance_of(Hash)).once
+      @gemnasium_service.execute(@sample_data)
+    end
+  end
+end
diff --git a/spec/models/project_services/gitlab_ci_service_spec.rb b/spec/models/project_services/gitlab_ci_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..610f33c5823c0e93cab8df474f36f0d1aaba4fec
--- /dev/null
+++ b/spec/models/project_services/gitlab_ci_service_spec.rb
@@ -0,0 +1,49 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe GitlabCiService do
+  describe "Associations" do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe "Mass assignment" do
+  end
+
+  describe 'commits methods' do
+    before do
+      @service = GitlabCiService.new
+      @service.stub(
+        service_hook: true,
+        project_url: 'http://ci.gitlab.org/projects/2',
+        token: 'verySecret'
+      )
+    end
+
+    describe :commit_status_path do
+      it { expect(@service.commit_status_path("2ab7834c", 'master')).to eq("http://ci.gitlab.org/projects/2/refs/master/commits/2ab7834c/status.json?token=verySecret")}
+    end
+
+    describe :build_page do
+      it { expect(@service.build_page("2ab7834c", 'master')).to eq("http://ci.gitlab.org/projects/2/refs/master/commits/2ab7834c")}
+    end
+  end
+end
diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..959044dc727561702d68765f1037f6a40604dc39
--- /dev/null
+++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
@@ -0,0 +1,65 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe GitlabIssueTrackerService do
+  describe "Associations" do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+
+  describe 'project and issue urls' do
+    let(:project) { create(:project) }
+
+    context 'with absolute urls' do
+      before do
+        @service = project.create_gitlab_issue_tracker_service(active: true)
+      end
+
+      after do
+        @service.destroy!
+      end
+
+      it 'should give the correct path' do
+        expect(@service.project_url).to eq("/#{project.path_with_namespace}/issues")
+        expect(@service.new_issue_url).to eq("/#{project.path_with_namespace}/issues/new")
+        expect(@service.issue_url(432)).to eq("/#{project.path_with_namespace}/issues/432")
+      end
+    end
+
+    context 'with enabled relative urls' do
+      before do
+        Settings.gitlab.stub(:relative_url_root).and_return("/gitlab/root")
+        @service = project.create_gitlab_issue_tracker_service(active: true)
+      end
+
+      after do
+        @service.destroy!
+      end
+
+      it 'should give the correct path' do
+        expect(@service.project_url).to eq("/gitlab/root/#{project.path_with_namespace}/issues")
+        expect(@service.new_issue_url).to eq("/gitlab/root/#{project.path_with_namespace}/issues/new")
+        expect(@service.issue_url(432)).to eq("/gitlab/root/#{project.path_with_namespace}/issues/432")
+      end
+    end
+  end
+end
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8ab847e64323f06c127ba3ecf8949590d86caff4
--- /dev/null
+++ b/spec/models/project_services/hipchat_service_spec.rb
@@ -0,0 +1,217 @@
+# == 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
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe HipchatService do
+  describe "Associations" do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe "Execute" do
+    let(:hipchat) { HipchatService.new }
+    let(:user)    { create(:user, username: 'username') }
+    let(:project) { create(:project, name: 'project') }
+    let(:api_url) { 'https://hipchat.example.com/v2/room/123456/notification?auth_token=verySecret' }
+    let(:project_name) { project.name_with_namespace.gsub(/\s/, '') }
+
+    before(:each) do
+      hipchat.stub(
+        project_id: project.id,
+        project: project,
+        room: 123456,
+        server: 'https://hipchat.example.com',
+        token: 'verySecret'
+      )
+      WebMock.stub_request(:post, api_url)
+    end
+
+    context 'push events' do
+      let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) }
+
+      it "should call Hipchat API for push events" do
+        hipchat.execute(push_sample_data)
+
+        expect(WebMock).to have_requested(:post, api_url).once
+      end
+
+      it "should create a push message" do
+        message = hipchat.send(:create_push_message, push_sample_data)
+
+        obj_attr = push_sample_data[:object_attributes]
+        branch = push_sample_data[:ref].gsub('refs/heads/', '')
+        expect(message).to include("#{user.name} pushed to branch " \
+            "<a href=\"#{project.web_url}/commits/#{branch}\">#{branch}</a> of " \
+            "<a href=\"#{project.web_url}\">#{project_name}</a>")
+      end
+    end
+
+    context 'tag_push events' do
+      let(:push_sample_data) { Gitlab::PushDataBuilder.build(project, user, Gitlab::Git::BLANK_SHA, '1' * 40, 'refs/tags/test', []) }
+
+      it "should call Hipchat API for tag push events" do
+        hipchat.execute(push_sample_data)
+
+        expect(WebMock).to have_requested(:post, api_url).once
+      end
+
+      it "should create a tag push message" do
+        message = hipchat.send(:create_push_message, push_sample_data)
+
+        obj_attr = push_sample_data[:object_attributes]
+        expect(message).to eq("#{user.name} pushed new tag " \
+            "<a href=\"#{project.web_url}/commits/test\">test</a> to " \
+            "<a href=\"#{project.web_url}\">#{project_name}</a>\n")
+      end
+    end
+
+    context 'issue events' do
+      let(:issue) { create(:issue, title: 'Awesome issue', description: 'please fix') }
+      let(:issue_service) { Issues::CreateService.new(project, user) }
+      let(:issues_sample_data) { issue_service.hook_data(issue, 'open') }
+
+      it "should call Hipchat API for issue events" do
+        hipchat.execute(issues_sample_data)
+
+        expect(WebMock).to have_requested(:post, api_url).once
+      end
+
+      it "should create an issue message" do
+        message = hipchat.send(:create_issue_message, issues_sample_data)
+
+        obj_attr = issues_sample_data[:object_attributes]
+        expect(message).to eq("#{user.name} opened " \
+            "<a href=\"#{obj_attr[:url]}\">issue ##{obj_attr["iid"]}</a> in " \
+            "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
+            "<b>Awesome issue</b>" \
+            "<pre>please fix</pre>")
+      end
+    end
+
+    context 'merge request events' do
+      let(:merge_request) { create(:merge_request, description: 'please fix', title: 'Awesome merge request', target_project: project, source_project: project) }
+      let(:merge_service) { MergeRequests::CreateService.new(project, user) }
+      let(:merge_sample_data) { merge_service.hook_data(merge_request, 'open') }
+
+      it "should call Hipchat API for merge requests events" do
+        hipchat.execute(merge_sample_data)
+
+        expect(WebMock).to have_requested(:post, api_url).once
+      end
+
+      it "should create a merge request message" do
+        message = hipchat.send(:create_merge_request_message,
+                               merge_sample_data)
+
+        obj_attr = merge_sample_data[:object_attributes]
+        expect(message).to eq("#{user.name} opened " \
+            "<a href=\"#{obj_attr[:url]}\">merge request ##{obj_attr["iid"]}</a> in " \
+            "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
+            "<b>Awesome merge request</b>" \
+            "<pre>please fix</pre>")
+      end
+    end
+
+    context "Note events" do
+      let(:user) { create(:user) }
+      let(:project) { create(:project, creator_id: user.id) }
+      let(:issue)         { create(:issue, project: project) }
+      let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+      let(:snippet)       { create(:project_snippet, project: project) }
+      let(:commit_note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') }
+      let(:merge_request_note) { create(:note_on_merge_request, noteable_id: merge_request.id, note: "merge request note") }
+      let(:issue_note) { create(:note_on_issue, noteable_id: issue.id, note: "issue note")}
+      let(:snippet_note) { create(:note_on_project_snippet, noteable_id: snippet.id, note: "snippet note") }
+
+      it "should call Hipchat API for commit comment events" do
+        data = Gitlab::NoteDataBuilder.build(commit_note, user)
+        hipchat.execute(data)
+
+        expect(WebMock).to have_requested(:post, api_url).once
+
+        message = hipchat.send(:create_message, data)
+
+        obj_attr = data[:object_attributes]
+        commit_id = Commit.truncate_sha(data[:commit][:id])
+        title = hipchat.send(:format_title, data[:commit][:message])
+
+        expect(message).to eq("#{user.name} commented on " \
+            "<a href=\"#{obj_attr[:url]}\">commit #{commit_id}</a> in " \
+            "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
+            "#{title}" \
+            "<pre>a comment on a commit</pre>")
+      end
+
+      it "should call Hipchat API for merge request comment events" do
+        data = Gitlab::NoteDataBuilder.build(merge_request_note, user)
+        hipchat.execute(data)
+
+        expect(WebMock).to have_requested(:post, api_url).once
+
+        message = hipchat.send(:create_message, data)
+
+        obj_attr = data[:object_attributes]
+        merge_id = data[:merge_request]['iid']
+        title = data[:merge_request]['title']
+
+        expect(message).to eq("#{user.name} commented on " \
+            "<a href=\"#{obj_attr[:url]}\">merge request ##{merge_id}</a> in " \
+            "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
+            "<b>#{title}</b>" \
+            "<pre>merge request note</pre>")
+      end
+
+      it "should call Hipchat API for issue comment events" do
+        data = Gitlab::NoteDataBuilder.build(issue_note, user)
+        hipchat.execute(data)
+
+        message = hipchat.send(:create_message, data)
+
+        obj_attr = data[:object_attributes]
+        issue_id = data[:issue]['iid']
+        title = data[:issue]['title']
+
+        expect(message).to eq("#{user.name} commented on " \
+            "<a href=\"#{obj_attr[:url]}\">issue ##{issue_id}</a> in " \
+            "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
+            "<b>#{title}</b>" \
+            "<pre>issue note</pre>")
+      end
+
+      it "should call Hipchat API for snippet comment events" do
+        data = Gitlab::NoteDataBuilder.build(snippet_note, user)
+        hipchat.execute(data)
+
+        expect(WebMock).to have_requested(:post, api_url).once
+
+        message = hipchat.send(:create_message, data)
+
+        obj_attr = data[:object_attributes]
+        snippet_id = data[:snippet]['id']
+        title = data[:snippet]['title']
+
+        expect(message).to eq("#{user.name} commented on " \
+            "<a href=\"#{obj_attr[:url]}\">snippet ##{snippet_id}</a> in " \
+            "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
+            "<b>#{title}</b>" \
+            "<pre>snippet note</pre>")
+      end
+    end
+  end
+end
diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d55399bc360102ea6037502ce6adba53013dea4e
--- /dev/null
+++ b/spec/models/project_services/irker_service_spec.rb
@@ -0,0 +1,108 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+require 'socket'
+require 'json'
+
+describe IrkerService do
+  describe 'Associations' do
+    it { should belong_to :project }
+    it { should have_one :service_hook }
+  end
+
+  describe 'Validations' do
+    before do
+      subject.active = true
+      subject.properties['recipients'] = _recipients
+    end
+
+    context 'active' do
+      let(:_recipients) { nil }
+      it { should validate_presence_of :recipients }
+    end
+
+    context 'too many recipients' do
+      let(:_recipients) { 'a b c d' }
+      it 'should add an error if there is too many recipients' do
+        subject.send :check_recipients_count
+        subject.errors.should_not be_blank
+      end
+    end
+
+    context '3 recipients' do
+      let(:_recipients) { 'a b c' }
+      it 'should not add an error if there is 3 recipients' do
+        subject.send :check_recipients_count
+        subject.errors.should be_blank
+      end
+    end
+  end
+
+  describe 'Execute' do
+    let(:irker) { IrkerService.new }
+    let(:user) { create(:user) }
+    let(:project) { create(:project) }
+    let(:sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) }
+
+    let(:recipients) { '#commits' }
+    let(:colorize_messages) { '1' }
+
+    before do
+      irker.stub(
+        active: true,
+        project: project,
+        project_id: project.id,
+        service_hook: true,
+        properties: {
+          'recipients' => recipients,
+          'colorize_messages' => colorize_messages
+        }
+      )
+      irker.settings = {
+        server_ip: 'localhost',
+        server_port: 6659,
+        max_channels: 3,
+        default_irc_uri: 'irc://chat.freenode.net/'
+      }
+      irker.valid?
+      @irker_server = TCPServer.new 'localhost', 6659
+    end
+
+    after do
+      @irker_server.close
+    end
+
+    it 'should send valid JSON messages to an Irker listener' do
+      irker.execute(sample_data)
+
+      conn = @irker_server.accept
+      conn.readlines.each do |line|
+        msg = JSON.load(line.chomp("\n"))
+        msg.keys.should match_array(['to', 'privmsg'])
+        if msg['to'].is_a?(String)
+          msg['to'].should == 'irc://chat.freenode.net/#commits'
+        else
+          msg['to'].should match_array(['irc://chat.freenode.net/#commits'])
+        end
+      end
+      conn.close
+    end
+  end
+end
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..355911e637771a8227faac071953896ec239e5a5
--- /dev/null
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -0,0 +1,102 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe JiraService do
+  describe "Associations" do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe "Validations" do
+    context "active" do
+      before do
+        subject.active = true
+      end
+
+      it { is_expected.to validate_presence_of :project_url }
+      it { is_expected.to validate_presence_of :issues_url }
+      it { is_expected.to validate_presence_of :new_issue_url }
+    end
+  end
+
+  describe 'description and title' do
+    let(:project) { create(:project) }
+
+    context 'when it is not set' do
+      before do
+        @service = project.create_jira_service(active: true)
+      end
+
+      after do
+        @service.destroy!
+      end
+
+      it 'should be initialized' do
+        expect(@service.title).to eq('JIRA')
+        expect(@service.description).to eq("Jira issue tracker")
+      end
+    end
+
+    context 'when it is set' do
+      before do
+        properties = { 'title' => 'Jira One', 'description' => 'Jira One issue tracker' }
+        @service = project.create_jira_service(active: true, properties: properties)
+      end
+
+      after do
+        @service.destroy!
+      end
+
+      it "should be correct" do
+        expect(@service.title).to eq('Jira One')
+        expect(@service.description).to eq('Jira One issue tracker')
+      end
+    end
+  end
+
+  describe 'project and issue urls' do
+    let(:project) { create(:project) }
+
+    context 'when gitlab.yml was initialized' do
+      before do
+        settings = { "jira" => {
+          "title" => "Jira",
+          "project_url" => "http://jira.sample/projects/project_a",
+          "issues_url" => "http://jira.sample/issues/:id",
+          "new_issue_url" => "http://jira.sample/projects/project_a/issues/new"
+          }
+        }
+        allow(Gitlab.config).to receive(:issues_tracker).and_return(settings)
+        @service = project.create_jira_service(active: true)
+      end
+
+      after do
+        @service.destroy!
+      end
+
+      it 'should be prepopulated with the settings' do
+        expect(@service.properties[:project_url]).to eq('http://jira.sample/projects/project_a')
+        expect(@service.properties[:issues_url]).to eq("http://jira.sample/issues/:id")
+        expect(@service.properties[:new_issue_url]).to eq("http://jira.sample/projects/project_a/issues/new")
+      end
+    end
+  end
+end
diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5a18fd09bfc95caf51c590106bb2ee9effbe647c
--- /dev/null
+++ b/spec/models/project_services/pushover_service_spec.rb
@@ -0,0 +1,74 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe PushoverService do
+  describe 'Associations' do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe 'Validations' do
+    context 'active' do
+      before do
+        subject.active = true
+      end
+
+      it { is_expected.to validate_presence_of :api_key }
+      it { is_expected.to validate_presence_of :user_key }
+      it { is_expected.to validate_presence_of :priority }
+    end
+  end
+
+  describe 'Execute' do
+    let(:pushover) { PushoverService.new }
+    let(:user) { create(:user) }
+    let(:project) { create(:project) }
+    let(:sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) }
+
+    let(:api_key) { 'verySecret' }
+    let(:user_key) { 'verySecret' }
+    let(:device) { 'myDevice' }
+    let(:priority) { 0 }
+    let(:sound) { 'bike' }
+    let(:api_url) { 'https://api.pushover.net/1/messages.json' }
+
+    before do
+      pushover.stub(
+        project: project,
+        project_id: project.id,
+        service_hook: true,
+        api_key: api_key,
+        user_key: user_key,
+        device: device,
+        priority: priority,
+        sound: sound
+      )
+
+      WebMock.stub_request(:post, api_url)
+    end
+
+    it 'should call Pushover API' do
+      pushover.execute(sample_data)
+
+      expect(WebMock).to have_requested(:post, api_url).once
+    end
+  end
+end
diff --git a/spec/models/project_services/slack_service/issue_message_spec.rb b/spec/models/project_services/slack_service/issue_message_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8bca1fef44c50f1c281ad2c405fee18e8db6b2cb
--- /dev/null
+++ b/spec/models/project_services/slack_service/issue_message_spec.rb
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+describe SlackService::IssueMessage do
+  subject { SlackService::IssueMessage.new(args) }
+
+  let(:args) {
+    {
+      user: {
+        name: 'Test User',
+        username: 'Test User'
+      },
+      project_name: 'project_name',
+      project_url: 'somewhere.com',
+
+      object_attributes: {
+        title: 'Issue title',
+        id: 10,
+        iid: 100,
+        assignee_id: 1,
+        url: 'url',
+        action: 'open',
+        state: 'opened',
+        description: 'issue description'
+      }
+    }
+  }
+
+  let(:color) { '#345' }
+
+  context 'open' do
+    it 'returns a message regarding opening of issues' do
+      expect(subject.pretext).to eq(
+        'Test User opened <url|issue #100> in <somewhere.com|project_name>: '\
+        '*Issue title*')
+      expect(subject.attachments).to eq([
+        {
+          text: "issue description",
+          color: color,
+        }
+      ])
+    end
+  end
+
+  context 'close' do
+    before do
+      args[:object_attributes][:action] = 'close'
+      args[:object_attributes][:state] = 'closed'
+    end
+    it 'returns a message regarding closing of issues' do
+      expect(subject.pretext). to eq(
+        'Test User closed <url|issue #100> in <somewhere.com|project_name>: '\
+        '*Issue title*')
+      expect(subject.attachments).to be_empty
+    end
+  end
+end
diff --git a/spec/models/project_services/slack_service/merge_message_spec.rb b/spec/models/project_services/slack_service/merge_message_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..aeb408aa766d4b164f7a6daaad07c83f25f5664e
--- /dev/null
+++ b/spec/models/project_services/slack_service/merge_message_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe SlackService::MergeMessage do
+  subject { SlackService::MergeMessage.new(args) }
+
+  let(:args) {
+    {
+      user: {
+          name: 'Test User',
+          username: 'Test User'
+      },
+      project_name: 'project_name',
+      project_url: 'somewhere.com',
+
+      object_attributes: {
+        title: "Issue title\nSecond line",
+        id: 10,
+        iid: 100,
+        assignee_id: 1,
+        url: 'url',
+        state: 'opened',
+        description: 'issue description',
+        source_branch: 'source_branch',
+        target_branch: 'target_branch',
+      }
+    }
+  }
+
+  let(:color) { '#345' }
+
+  context 'open' do
+    it 'returns a message regarding opening of merge requests' do
+      expect(subject.pretext).to eq(
+        'Test User opened <somewhere.com/merge_requests/100|merge request #100> '\
+        'in <somewhere.com|project_name>: *Issue title*')
+      expect(subject.attachments).to be_empty
+    end
+  end
+
+  context 'close' do
+    before do
+      args[:object_attributes][:state] = 'closed'
+    end
+    it 'returns a message regarding closing of merge requests' do
+      expect(subject.pretext).to eq(
+        'Test User closed <somewhere.com/merge_requests/100|merge request #100> '\
+        'in <somewhere.com|project_name>: *Issue title*')
+      expect(subject.attachments).to be_empty
+    end
+  end
+end
diff --git a/spec/models/project_services/slack_service/note_message_spec.rb b/spec/models/project_services/slack_service/note_message_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..21fb575480b8fd091bf0a55ac97b4cc91895acfd
--- /dev/null
+++ b/spec/models/project_services/slack_service/note_message_spec.rb
@@ -0,0 +1,129 @@
+require 'spec_helper'
+
+describe SlackService::NoteMessage do
+  let(:color) { '#345' }
+
+  before do
+    @args = {
+        user: {
+            name: 'Test User',
+            username: 'username',
+            avatar_url: 'http://fakeavatar'
+        },
+        project_name: 'project_name',
+        project_url: 'somewhere.com',
+        repository: {
+            name: 'project_name',
+            url: 'somewhere.com',
+        },
+        object_attributes: {
+            id: 10,
+            note: 'comment on a commit',
+            url: 'url',
+            noteable_type: 'Commit'
+        }
+    }
+  end
+
+  context 'commit notes' do
+    before do
+      @args[:object_attributes][:note] = 'comment on a commit'
+      @args[:object_attributes][:noteable_type] = 'Commit'
+      @args[:commit] = {
+          id: '5f163b2b95e6f53cbd428f5f0b103702a52b9a23',
+          message: "Added a commit message\ndetails\n123\n"
+      }
+    end
+
+    it 'returns a message regarding notes on commits' do
+      message = SlackService::NoteMessage.new(@args)
+      expect(message.pretext).to eq("Test User commented on " \
+      "<url|commit 5f163b2b> in <somewhere.com|project_name>: " \
+      "*Added a commit message*")
+      expected_attachments = [
+          {
+              text: "comment on a commit",
+              color: color,
+          }
+      ]
+      expect(message.attachments).to eq(expected_attachments)
+    end
+  end
+
+  context 'merge request notes' do
+    before do
+      @args[:object_attributes][:note] = 'comment on a merge request'
+      @args[:object_attributes][:noteable_type] = 'MergeRequest'
+      @args[:merge_request] = {
+          id: 1,
+          iid: 30,
+          title: "merge request title\ndetails\n"
+      }
+    end
+    it 'returns a message regarding notes on a merge request' do
+      message = SlackService::NoteMessage.new(@args)
+      expect(message.pretext).to eq("Test User commented on " \
+      "<url|merge request #30> in <somewhere.com|project_name>: " \
+      "*merge request title*")
+      expected_attachments =  [
+          {
+              text: "comment on a merge request",
+              color: color,
+          }
+      ]
+      expect(message.attachments).to eq(expected_attachments)
+    end
+  end
+
+  context 'issue notes' do
+    before do
+      @args[:object_attributes][:note] = 'comment on an issue'
+      @args[:object_attributes][:noteable_type] = 'Issue'
+      @args[:issue] = {
+          id: 1,
+          iid: 20,
+          title: "issue title\ndetails\n"
+      }
+    end
+
+    it 'returns a message regarding notes on an issue' do
+      message = SlackService::NoteMessage.new(@args)
+      expect(message.pretext).to eq(
+                                     "Test User commented on " \
+      "<url|issue #20> in <somewhere.com|project_name>: " \
+      "*issue title*")
+      expected_attachments =  [
+          {
+              text: "comment on an issue",
+              color: color,
+          }
+      ]
+      expect(message.attachments).to eq(expected_attachments)
+    end
+  end
+
+  context 'project snippet notes' do
+    before do
+      @args[:object_attributes][:note] = 'comment on a snippet'
+      @args[:object_attributes][:noteable_type] = 'Snippet'
+      @args[:snippet] = {
+          id: 5,
+          title: "snippet title\ndetails\n"
+      }
+    end
+
+    it 'returns a message regarding notes on a project snippet' do
+      message = SlackService::NoteMessage.new(@args)
+      expect(message.pretext).to eq("Test User commented on " \
+      "<url|snippet #5> in <somewhere.com|project_name>: " \
+      "*snippet title*")
+      expected_attachments =  [
+          {
+              text: "comment on a snippet",
+              color: color,
+          }
+      ]
+      expect(message.attachments).to eq(expected_attachments)
+    end
+  end
+end
diff --git a/spec/models/slack_message_spec.rb b/spec/models/project_services/slack_service/push_message_spec.rb
similarity index 52%
rename from spec/models/slack_message_spec.rb
rename to spec/models/project_services/slack_service/push_message_spec.rb
index c530fad619b735bef379aa8b0845300caf8b8f17..10963481a1248dfee077ece3c86a6b4edb39f665 100644
--- a/spec/models/slack_message_spec.rb
+++ b/spec/models/project_services/slack_service/push_message_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
-describe SlackMessage do
-  subject { SlackMessage.new(args) }
+describe SlackService::PushMessage do
+  subject { SlackService::PushMessage.new(args) }
 
   let(:args) {
     {
@@ -25,41 +25,64 @@ describe SlackMessage do
     end
 
     it 'returns a message regarding pushes' do
-      subject.pretext.should ==
+      expect(subject.pretext).to eq(
         'user_name pushed to branch <url/commits/master|master> of '\
         '<url|project_name> (<url/compare/before...after|Compare changes>)'
-      subject.attachments.should == [
+      )
+      expect(subject.attachments).to eq([
         {
-          text: "<url1|abcdefghi>: message1 - author1\n"\
-                "<url2|123456789>: message2 - author2",
+          text: "<url1|abcdefgh>: message1 - author1\n"\
+                "<url2|12345678>: message2 - author2",
           color: color,
         }
-      ]
+      ])
+    end
+  end
+
+  context 'tag push' do
+    let(:args) {
+      {
+          after: 'after',
+          before: Gitlab::Git::BLANK_SHA,
+          project_name: 'project_name',
+          ref: 'refs/tags/new_tag',
+          user_name: 'user_name',
+          project_url: 'url'
+      }
+    }
+
+    it 'returns a message regarding pushes' do
+      expect(subject.pretext).to eq('user_name pushed new tag ' \
+       '<url/commits/new_tag|new_tag> to ' \
+       '<url|project_name>')
+      expect(subject.attachments).to be_empty
     end
   end
 
   context 'new branch' do
     before do
-      args[:before] = '000000'
+      args[:before] = Gitlab::Git::BLANK_SHA
     end
 
     it 'returns a message regarding a new branch' do
-      subject.pretext.should ==
+      expect(subject.pretext).to eq(
         'user_name pushed new branch <url/commits/master|master> to '\
         '<url|project_name>'
-      subject.attachments.should be_empty
+      )
+      expect(subject.attachments).to be_empty
     end
   end
 
   context 'removed branch' do
     before do
-      args[:after] = '000000'
+      args[:after] = Gitlab::Git::BLANK_SHA
     end
 
     it 'returns a message regarding a removed branch' do
-      subject.pretext.should ==
+      expect(subject.pretext).to eq(
         'user_name removed branch master from <url|project_name>'
-      subject.attachments.should be_empty
+      )
+      expect(subject.attachments).to be_empty
     end
   end
 end
diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c36506644b30c74508a91abaf5e44357a7d9ad7c
--- /dev/null
+++ b/spec/models/project_services/slack_service_spec.rb
@@ -0,0 +1,170 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
+#
+
+require 'spec_helper'
+
+describe SlackService do
+  describe "Associations" do
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
+  end
+
+  describe "Validations" do
+    context "active" do
+      before do
+        subject.active = true
+      end
+
+      it { is_expected.to validate_presence_of :webhook }
+    end
+  end
+
+  describe "Execute" do
+    let(:slack)   { SlackService.new }
+    let(:user)    { create(:user) }
+    let(:project) { create(:project) }
+    let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) }
+    let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' }
+    let(:username) { 'slack_username' }
+    let(:channel) { 'slack_channel' }
+
+    before do
+      slack.stub(
+        project: project,
+        project_id: project.id,
+        service_hook: true,
+        webhook: webhook_url
+      )
+
+      WebMock.stub_request(:post, webhook_url)
+
+      opts = {
+        title: 'Awesome issue',
+        description: 'please fix'
+      }
+
+      issue_service = Issues::CreateService.new(project, user, opts)
+      @issue = issue_service.execute
+      @issues_sample_data = issue_service.hook_data(@issue, 'open')
+
+      opts = {
+        title: 'Awesome merge_request',
+        description: 'please fix',
+        source_branch: 'stable',
+        target_branch: 'master'
+      }
+      merge_service = MergeRequests::CreateService.new(project,
+                                                       user, opts)
+      @merge_request = merge_service.execute
+      @merge_sample_data = merge_service.hook_data(@merge_request,
+                                                   'open')
+    end
+
+    it "should call Slack API for push events" do
+      slack.execute(push_sample_data)
+
+      expect(WebMock).to have_requested(:post, webhook_url).once
+    end
+
+    it "should call Slack API for issue events" do
+      slack.execute(@issues_sample_data)
+
+      expect(WebMock).to have_requested(:post, webhook_url).once
+    end
+
+    it "should call Slack API for merge requests events" do
+      slack.execute(@merge_sample_data)
+
+      expect(WebMock).to have_requested(:post, webhook_url).once
+    end
+
+    it 'should use the username as an option for slack when configured' do
+      slack.stub(username: username)
+      expect(Slack::Notifier).to receive(:new).
+       with(webhook_url, username: username).
+       and_return(
+         double(:slack_service).as_null_object
+       )
+      slack.execute(push_sample_data)
+    end
+
+    it 'should use the channel as an option when it is configured' do
+      slack.stub(channel: channel)
+      expect(Slack::Notifier).to receive(:new).
+        with(webhook_url, channel: channel).
+        and_return(
+          double(:slack_service).as_null_object
+        )
+      slack.execute(push_sample_data)
+    end
+  end
+
+  describe "Note events" do
+    let(:slack)   { SlackService.new }
+    let(:user) { create(:user) }
+    let(:project) { create(:project, creator_id: user.id) }
+    let(:issue)         { create(:issue, project: project) }
+    let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+    let(:snippet)       { create(:project_snippet, project: project) }
+    let(:commit_note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') }
+    let(:merge_request_note) { create(:note_on_merge_request, noteable_id: merge_request.id, note: "merge request note") }
+    let(:issue_note) { create(:note_on_issue, noteable_id: issue.id, note: "issue note")}
+    let(:snippet_note) { create(:note_on_project_snippet, noteable_id: snippet.id, note: "snippet note") }
+    let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' }
+
+    before do
+      slack.stub(
+          project: project,
+          project_id: project.id,
+          service_hook: true,
+          webhook: webhook_url
+      )
+
+      WebMock.stub_request(:post, webhook_url)
+    end
+
+    it "should call Slack API for commit comment events" do
+      data = Gitlab::NoteDataBuilder.build(commit_note, user)
+      slack.execute(data)
+
+      expect(WebMock).to have_requested(:post, webhook_url).once
+    end
+
+    it "should call Slack API for merge request comment events" do
+      data = Gitlab::NoteDataBuilder.build(merge_request_note, user)
+      slack.execute(data)
+
+      expect(WebMock).to have_requested(:post, webhook_url).once
+    end
+
+    it "should call Slack API for issue comment events" do
+      data = Gitlab::NoteDataBuilder.build(issue_note, user)
+      slack.execute(data)
+
+      expect(WebMock).to have_requested(:post, webhook_url).once
+    end
+
+    it "should call Slack API for snippet comment events" do
+      data = Gitlab::NoteDataBuilder.build(snippet_note, user)
+      slack.execute(data)
+
+      expect(WebMock).to have_requested(:post, webhook_url).once
+    end
+  end
+end
diff --git a/spec/models/project_snippet_spec.rb b/spec/models/project_snippet_spec.rb
index a6e1d9eef501363d7bf5783cf06796f866a5946b..3e8f106d27fd90e5c32fc839cc80db60ce6bf907 100644
--- a/spec/models/project_snippet_spec.rb
+++ b/spec/models/project_snippet_spec.rb
@@ -19,13 +19,13 @@ require 'spec_helper'
 
 describe ProjectSnippet do
   describe "Associations" do
-    it { should belong_to(:project) }
+    it { is_expected.to belong_to(:project) }
   end
 
   describe "Mass assignment" do
   end
 
   describe "Validation" do
-    it { should validate_presence_of(:project) }
+    it { is_expected.to validate_presence_of(:project) }
   end
 end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 70a15cac1a888bd0644ae2a09513e1b2f8d6eab5..879a63dd9f954585e08e46ce4618ce62e6dd84c5 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -24,103 +24,107 @@
 #  import_status          :string(255)
 #  repository_size        :float            default(0.0)
 #  star_count             :integer          default(0), not null
+#  import_type            :string(255)
+#  import_source          :string(255)
+#  avatar                 :string(255)
 #
 
 require 'spec_helper'
 
 describe Project do
-  describe "Associations" do
-    it { should belong_to(:group) }
-    it { should belong_to(:namespace) }
-    it { should belong_to(:creator).class_name('User') }
-    it { should have_many(:users) }
-    it { should have_many(:events).dependent(:destroy) }
-    it { should have_many(:merge_requests).dependent(:destroy) }
-    it { should have_many(:issues).dependent(:destroy) }
-    it { should have_many(:milestones).dependent(:destroy) }
-    it { should have_many(:project_members).dependent(:destroy) }
-    it { should have_many(:notes).dependent(:destroy) }
-    it { should have_many(:snippets).class_name('ProjectSnippet').dependent(:destroy) }
-    it { should have_many(:deploy_keys_projects).dependent(:destroy) }
-    it { should have_many(:deploy_keys) }
-    it { should have_many(:hooks).dependent(:destroy) }
-    it { should have_many(:protected_branches).dependent(:destroy) }
-    it { should have_one(:forked_project_link).dependent(:destroy) }
-    it { should have_one(:slack_service).dependent(:destroy) }
-    it { should have_one(:pushover_service).dependent(:destroy) }
+  describe 'Associations' do
+    it { is_expected.to belong_to(:group) }
+    it { is_expected.to belong_to(:namespace) }
+    it { is_expected.to belong_to(:creator).class_name('User') }
+    it { is_expected.to have_many(:users) }
+    it { is_expected.to have_many(:events).dependent(:destroy) }
+    it { is_expected.to have_many(:merge_requests).dependent(:destroy) }
+    it { is_expected.to have_many(:issues).dependent(:destroy) }
+    it { is_expected.to have_many(:milestones).dependent(:destroy) }
+    it { is_expected.to have_many(:project_members).dependent(:destroy) }
+    it { is_expected.to have_many(:notes).dependent(:destroy) }
+    it { is_expected.to have_many(:snippets).class_name('ProjectSnippet').dependent(:destroy) }
+    it { is_expected.to have_many(:deploy_keys_projects).dependent(:destroy) }
+    it { is_expected.to have_many(:deploy_keys) }
+    it { is_expected.to have_many(:hooks).dependent(:destroy) }
+    it { is_expected.to have_many(:protected_branches).dependent(:destroy) }
+    it { is_expected.to have_one(:forked_project_link).dependent(:destroy) }
+    it { is_expected.to have_one(:slack_service).dependent(:destroy) }
+    it { is_expected.to have_one(:pushover_service).dependent(:destroy) }
+    it { is_expected.to have_one(:asana_service).dependent(:destroy) }
   end
 
-  describe "Mass assignment" do
+  describe 'Mass assignment' do
   end
 
-  describe "Validation" do
+  describe 'Validation' do
     let!(:project) { create(:project) }
 
-    it { should validate_presence_of(:name) }
-    it { should validate_uniqueness_of(:name).scoped_to(:namespace_id) }
-    it { should ensure_length_of(:name).is_within(0..255) }
+    it { is_expected.to validate_presence_of(:name) }
+    it { is_expected.to validate_uniqueness_of(:name).scoped_to(:namespace_id) }
+    it { is_expected.to ensure_length_of(:name).is_within(0..255) }
 
-    it { should validate_presence_of(:path) }
-    it { should validate_uniqueness_of(:path).scoped_to(:namespace_id) }
-    it { should ensure_length_of(:path).is_within(0..255) }
-    it { should ensure_length_of(:description).is_within(0..2000) }
-    it { should validate_presence_of(:creator) }
-    it { should ensure_length_of(:issues_tracker_id).is_within(0..255) }
-    it { should validate_presence_of(:namespace) }
+    it { is_expected.to validate_presence_of(:path) }
+    it { is_expected.to validate_uniqueness_of(:path).scoped_to(:namespace_id) }
+    it { is_expected.to ensure_length_of(:path).is_within(0..255) }
+    it { is_expected.to ensure_length_of(:description).is_within(0..2000) }
+    it { is_expected.to validate_presence_of(:creator) }
+    it { is_expected.to ensure_length_of(:issues_tracker_id).is_within(0..255) }
+    it { is_expected.to validate_presence_of(:namespace) }
 
-    it "should not allow new projects beyond user limits" do
+    it 'should not allow new projects beyond user limits' do
       project2 = build(:project)
-      project2.stub(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object)
-      project2.should_not be_valid
-      project2.errors[:limit_reached].first.should match(/Your project limit is 0/)
+      allow(project2).to receive(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object)
+      expect(project2).not_to be_valid
+      expect(project2.errors[:limit_reached].first).to match(/Your project limit is 0/)
     end
   end
 
-  describe "Respond to" do
-    it { should respond_to(:url_to_repo) }
-    it { should respond_to(:repo_exists?) }
-    it { should respond_to(:satellite) }
-    it { should respond_to(:update_merge_requests) }
-    it { should respond_to(:execute_hooks) }
-    it { should respond_to(:name_with_namespace) }
-    it { should respond_to(:owner) }
-    it { should respond_to(:path_with_namespace) }
+  describe 'Respond to' do
+    it { is_expected.to respond_to(:url_to_repo) }
+    it { is_expected.to respond_to(:repo_exists?) }
+    it { is_expected.to respond_to(:satellite) }
+    it { is_expected.to respond_to(:update_merge_requests) }
+    it { is_expected.to respond_to(:execute_hooks) }
+    it { is_expected.to respond_to(:name_with_namespace) }
+    it { is_expected.to respond_to(:owner) }
+    it { is_expected.to respond_to(:path_with_namespace) }
   end
 
-  it "should return valid url to repo" do
-    project = Project.new(path: "somewhere")
-    project.url_to_repo.should == Gitlab.config.gitlab_shell.ssh_path_prefix + "somewhere.git"
+  it 'should return valid url to repo' do
+    project = Project.new(path: 'somewhere')
+    expect(project.url_to_repo).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git')
   end
 
-  it "returns the full web URL for this repo" do
-    project = Project.new(path: "somewhere")
-    project.web_url.should == "#{Gitlab.config.gitlab.url}/somewhere"
+  it 'returns the full web URL for this repo' do
+    project = Project.new(path: 'somewhere')
+    expect(project.web_url).to eq("#{Gitlab.config.gitlab.url}/somewhere")
   end
 
-  it "returns the web URL without the protocol for this repo" do
-    project = Project.new(path: "somewhere")
-    project.web_url_without_protocol.should == "#{Gitlab.config.gitlab.url.split("://")[1]}/somewhere"
+  it 'returns the web URL without the protocol for this repo' do
+    project = Project.new(path: 'somewhere')
+    expect(project.web_url_without_protocol).to eq("#{Gitlab.config.gitlab.url.split('://')[1]}/somewhere")
   end
 
-  describe "last_activity methods" do
+  describe 'last_activity methods' do
     let(:project) { create(:project) }
     let(:last_event) { double(created_at: Time.now) }
 
-    describe "last_activity" do
-      it "should alias last_activity to last_event" do
+    describe 'last_activity' do
+      it 'should alias last_activity to last_event' do
         project.stub(last_event: last_event)
-        project.last_activity.should == last_event
+        expect(project.last_activity).to eq(last_event)
       end
     end
 
     describe 'last_activity_date' do
       it 'returns the creation date of the project\'s last event if present' do
         last_activity_event = create(:event, project: project)
-        project.last_activity_at.to_i.should == last_event.created_at.to_i
+        expect(project.last_activity_at.to_i).to eq(last_event.created_at.to_i)
       end
 
       it 'returns the project\'s last update date if it has no events' do
-        project.last_activity_date.should == project.updated_at
+        expect(project.last_activity_date).to eq(project.updated_at)
       end
     end
   end
@@ -132,16 +136,16 @@ describe Project do
     let(:prev_commit_id) { merge_request.commits.last.id }
     let(:commit_id) { merge_request.commits.first.id }
 
-    it "should close merge request if last commit from source branch was pushed to target branch" do
+    it 'should close merge request if last commit from source branch was pushed to target branch' do
       project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.target_branch}", key.user)
       merge_request.reload
-      merge_request.merged?.should be_true
+      expect(merge_request.merged?).to be_truthy
     end
 
-    it "should update merge request commits with new one if pushed to source branch" do
+    it 'should update merge request commits with new one if pushed to source branch' do
       project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.source_branch}", key.user)
       merge_request.reload
-      merge_request.last_commit.id.should == commit_id
+      expect(merge_request.last_commit.id).to eq(commit_id)
     end
   end
 
@@ -152,8 +156,8 @@ describe Project do
         @project = create(:project, name: 'gitlabhq', namespace: @group)
       end
 
-      it { Project.find_with_namespace('gitlab/gitlabhq').should == @project }
-      it { Project.find_with_namespace('gitlab-ci').should be_nil }
+      it { expect(Project.find_with_namespace('gitlab/gitlabhq')).to eq(@project) }
+      it { expect(Project.find_with_namespace('gitlab-ci')).to be_nil }
     end
   end
 
@@ -164,15 +168,15 @@ describe Project do
         @project = create(:project, name: 'gitlabhq', namespace: @group)
       end
 
-      it { @project.to_param.should == "gitlab/gitlabhq" }
+      it { expect(@project.to_param).to eq('gitlabhq') }
     end
   end
 
   describe :repository do
     let(:project) { create(:project) }
 
-    it "should return valid repo" do
-      project.repository.should be_kind_of(Repository)
+    it 'should return valid repo' do
+      expect(project.repository).to be_kind_of(Repository)
     end
   end
 
@@ -182,29 +186,29 @@ describe Project do
     let(:not_existed_issue) { create(:issue) }
     let(:ext_project) { create(:redmine_project) }
 
-    it "should be true or if used internal tracker and issue exists" do
-      project.issue_exists?(existed_issue.iid).should be_true
+    it 'should be true or if used internal tracker and issue exists' do
+      expect(project.issue_exists?(existed_issue.iid)).to be_truthy
     end
 
-    it "should be false or if used internal tracker and issue not exists" do
-      project.issue_exists?(not_existed_issue.iid).should be_false
+    it 'should be false or if used internal tracker and issue not exists' do
+      expect(project.issue_exists?(not_existed_issue.iid)).to be_falsey
     end
 
-    it "should always be true if used other tracker" do
-      ext_project.issue_exists?(rand(100)).should be_true
+    it 'should always be true if used other tracker' do
+      expect(ext_project.issue_exists?(rand(100))).to be_truthy
     end
   end
 
-  describe :used_default_issues_tracker? do
+  describe :default_issues_tracker? do
     let(:project) { create(:project) }
     let(:ext_project) { create(:redmine_project) }
 
     it "should be true if used internal tracker" do
-      project.used_default_issues_tracker?.should be_true
+      expect(project.default_issues_tracker?).to be_truthy
     end
 
     it "should be false if used other tracker" do
-      ext_project.used_default_issues_tracker?.should be_false
+      expect(ext_project.default_issues_tracker?).to be_falsey
     end
   end
 
@@ -212,20 +216,20 @@ describe Project do
     let(:project) { create(:project) }
     let(:ext_project) { create(:redmine_project) }
 
-    it "should be true for projects with external issues tracker if issues enabled" do
-      ext_project.can_have_issues_tracker_id?.should be_true
+    it 'should be true for projects with external issues tracker if issues enabled' do
+      expect(ext_project.can_have_issues_tracker_id?).to be_truthy
     end
 
-    it "should be false for projects with internal issue tracker if issues enabled" do
-      project.can_have_issues_tracker_id?.should be_false
+    it 'should be false for projects with internal issue tracker if issues enabled' do
+      expect(project.can_have_issues_tracker_id?).to be_falsey
     end
 
-    it "should be always false if issues disabled" do
+    it 'should be always false if issues disabled' do
       project.issues_enabled = false
       ext_project.issues_enabled = false
 
-      project.can_have_issues_tracker_id?.should be_false
-      ext_project.can_have_issues_tracker_id?.should be_false
+      expect(project.can_have_issues_tracker_id?).to be_falsey
+      expect(ext_project.can_have_issues_tracker_id?).to be_falsey
     end
   end
 
@@ -236,8 +240,8 @@ describe Project do
       project.protected_branches.create(name: 'master')
     end
 
-    it { project.open_branches.map(&:name).should include('feature') }
-    it { project.open_branches.map(&:name).should_not include('master') }
+    it { expect(project.open_branches.map(&:name)).to include('feature') }
+    it { expect(project.open_branches.map(&:name)).not_to include('master') }
   end
 
   describe '#star_count' do
@@ -308,4 +312,49 @@ describe Project do
       expect(project.star_count).to eq(0)
     end
   end
+
+  describe :avatar_type do
+    let(:project) { create(:project) }
+
+    it 'should be true if avatar is image' do
+      project.update_attribute(:avatar, 'uploads/avatar.png')
+      expect(project.avatar_type).to be_truthy
+    end
+
+    it 'should be false if avatar is html page' do
+      project.update_attribute(:avatar, 'uploads/avatar.html')
+      expect(project.avatar_type).to eq(['only images allowed'])
+    end
+  end
+
+  describe :avatar_url do
+    subject { project.avatar_url }
+
+    let(:project) { create(:project) }
+
+    context 'When avatar file is uploaded' do
+      before do
+        project.update_columns(avatar: 'uploads/avatar.png')
+        allow(project.avatar).to receive(:present?) { true }
+      end
+
+      let(:avatar_path) do
+        "/uploads/project/avatar/#{project.id}/uploads/avatar.png"
+      end
+
+      it { should eq "http://localhost#{avatar_path}" }
+    end
+
+    context 'When avatar file in git' do
+      before do
+        allow(project).to receive(:avatar_in_git) { true }
+      end
+
+      let(:avatar_path) do
+        "/#{project.namespace.name}/#{project.path}/avatar"
+      end
+
+      it { should eq "http://localhost#{avatar_path}" }
+    end
+  end
 end
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index bbf50b654f4379d80904f949c1c985efea8081ce..19201cc15a7f474ef27e6f3c0d0db6f885b73f92 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -16,19 +16,19 @@ describe ProjectTeam do
     end
 
     describe 'members collection' do
-      it { project.team.masters.should include(master) }
-      it { project.team.masters.should_not include(guest) }
-      it { project.team.masters.should_not include(reporter) }
-      it { project.team.masters.should_not include(nonmember) }
+      it { expect(project.team.masters).to include(master) }
+      it { expect(project.team.masters).not_to include(guest) }
+      it { expect(project.team.masters).not_to include(reporter) }
+      it { expect(project.team.masters).not_to include(nonmember) }
     end
 
     describe 'access methods' do
-      it { project.team.master?(master).should be_true }
-      it { project.team.master?(guest).should be_false }
-      it { project.team.master?(reporter).should be_false }
-      it { project.team.master?(nonmember).should be_false }
-      it { project.team.member?(nonmember).should be_false }
-      it { project.team.member?(guest).should be_true }
+      it { expect(project.team.master?(master)).to be_truthy }
+      it { expect(project.team.master?(guest)).to be_falsey }
+      it { expect(project.team.master?(reporter)).to be_falsey }
+      it { expect(project.team.master?(nonmember)).to be_falsey }
+      it { expect(project.team.member?(nonmember)).to be_falsey }
+      it { expect(project.team.member?(guest)).to be_truthy }
     end
   end
 
@@ -49,21 +49,21 @@ describe ProjectTeam do
     end
 
     describe 'members collection' do
-      it { project.team.reporters.should include(reporter) }
-      it { project.team.masters.should include(master) }
-      it { project.team.masters.should include(guest) }
-      it { project.team.masters.should_not include(reporter) }
-      it { project.team.masters.should_not include(nonmember) }
+      it { expect(project.team.reporters).to include(reporter) }
+      it { expect(project.team.masters).to include(master) }
+      it { expect(project.team.masters).to include(guest) }
+      it { expect(project.team.masters).not_to include(reporter) }
+      it { expect(project.team.masters).not_to include(nonmember) }
     end
 
     describe 'access methods' do
-      it { project.team.reporter?(reporter).should be_true }
-      it { project.team.master?(master).should be_true }
-      it { project.team.master?(guest).should be_true }
-      it { project.team.master?(reporter).should be_false }
-      it { project.team.master?(nonmember).should be_false }
-      it { project.team.member?(nonmember).should be_false }
-      it { project.team.member?(guest).should be_true }
+      it { expect(project.team.reporter?(reporter)).to be_truthy }
+      it { expect(project.team.master?(master)).to be_truthy }
+      it { expect(project.team.master?(guest)).to be_truthy }
+      it { expect(project.team.master?(reporter)).to be_falsey }
+      it { expect(project.team.master?(nonmember)).to be_falsey }
+      it { expect(project.team.member?(nonmember)).to be_falsey }
+      it { expect(project.team.member?(guest)).to be_truthy }
     end
   end
 end
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index e4ee2fc5b1394b13e360f0734d274805f2943f6d..2acdb7dfddcba5af30abeda55bd60ece92488a13 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -12,19 +12,19 @@ describe ProjectWiki do
 
   describe "#path_with_namespace" do
     it "returns the project path with namespace with the .wiki extension" do
-      subject.path_with_namespace.should == project.path_with_namespace + ".wiki"
+      expect(subject.path_with_namespace).to eq(project.path_with_namespace + ".wiki")
     end
   end
 
   describe "#url_to_repo" do
     it "returns the correct ssh url to the repo" do
-      subject.url_to_repo.should == gitlab_shell.url_to_repo(subject.path_with_namespace)
+      expect(subject.url_to_repo).to eq(gitlab_shell.url_to_repo(subject.path_with_namespace))
     end
   end
 
   describe "#ssh_url_to_repo" do
     it "equals #url_to_repo" do
-      subject.ssh_url_to_repo.should == subject.url_to_repo
+      expect(subject.ssh_url_to_repo).to eq(subject.url_to_repo)
     end
   end
 
@@ -32,21 +32,21 @@ describe ProjectWiki do
     it "provides the full http url to the repo" do
       gitlab_url = Gitlab.config.gitlab.url
       repo_http_url = "#{gitlab_url}/#{subject.path_with_namespace}.git"
-      subject.http_url_to_repo.should == repo_http_url
+      expect(subject.http_url_to_repo).to eq(repo_http_url)
     end
   end
 
   describe "#wiki" do
     it "contains a Gollum::Wiki instance" do
-      subject.wiki.should be_a Gollum::Wiki
+      expect(subject.wiki).to be_a Gollum::Wiki
     end
 
     it "creates a new wiki repo if one does not yet exist" do
-      project_wiki.create_page("index", "test content").should be_true
+      expect(project_wiki.create_page("index", "test content")).to be_truthy
     end
 
     it "raises CouldNotCreateWikiError if it can't create the wiki repository" do
-      project_wiki.stub(:init_repo).and_return(false)
+      allow(project_wiki).to receive(:init_repo).and_return(false)
       expect { project_wiki.send(:create_repo!) }.to raise_exception(ProjectWiki::CouldNotCreateWikiError)
     end
   end
@@ -54,21 +54,27 @@ describe ProjectWiki do
   describe "#empty?" do
     context "when the wiki repository is empty" do
       before do
-        Gitlab::Shell.any_instance.stub(:add_repository) do
+        allow_any_instance_of(Gitlab::Shell).to receive(:add_repository) do
           create_temp_repo("#{Rails.root}/tmp/test-git-base-path/non-existant.wiki.git")
         end
-        project.stub(:path_with_namespace).and_return("non-existant")
+        allow(project).to receive(:path_with_namespace).and_return("non-existant")
       end
 
-      its(:empty?) { should be_true }
+      describe '#empty?' do
+        subject { super().empty? }
+        it { is_expected.to be_truthy }
+      end
     end
 
     context "when the wiki has pages" do
       before do
-        create_page("index", "This is an awesome new Gollum Wiki")
+        project_wiki.create_page("index", "This is an awesome new Gollum Wiki")
       end
 
-      its(:empty?) { should be_false }
+      describe '#empty?' do
+        subject { super().empty? }
+        it { is_expected.to be_falsey }
+      end
     end
   end
 
@@ -83,11 +89,11 @@ describe ProjectWiki do
     end
 
     it "returns an array of WikiPage instances" do
-      @pages.first.should be_a WikiPage
+      expect(@pages.first).to be_a WikiPage
     end
 
     it "returns the correct number of pages" do
-      @pages.count.should == 1
+      expect(@pages.count).to eq(1)
     end
   end
 
@@ -102,55 +108,55 @@ describe ProjectWiki do
 
     it "returns the latest version of the page if it exists" do
       page = subject.find_page("index page")
-      page.title.should == "index page"
+      expect(page.title).to eq("index page")
     end
 
     it "returns nil if the page does not exist" do
-      subject.find_page("non-existant").should == nil
+      expect(subject.find_page("non-existant")).to eq(nil)
     end
 
     it "can find a page by slug" do
       page = subject.find_page("index-page")
-      page.title.should == "index page"
+      expect(page.title).to eq("index page")
     end
 
     it "returns a WikiPage instance" do
       page = subject.find_page("index page")
-      page.should be_a WikiPage
+      expect(page).to be_a WikiPage
     end
   end
 
   describe '#find_file' do
     before do
       file = Gollum::File.new(subject.wiki)
-      Gollum::Wiki.any_instance.
-                   stub(:file).with('image.jpg', 'master', true).
+      allow_any_instance_of(Gollum::Wiki).
+                   to receive(:file).with('image.jpg', 'master', true).
                    and_return(file)
-      Gollum::File.any_instance.
-                   stub(:mime_type).
+      allow_any_instance_of(Gollum::File).
+                   to receive(:mime_type).
                    and_return('image/jpeg')
-      Gollum::Wiki.any_instance.
-                   stub(:file).with('non-existant', 'master', true).
+      allow_any_instance_of(Gollum::Wiki).
+                   to receive(:file).with('non-existant', 'master', true).
                    and_return(nil)
     end
 
     after do
-      Gollum::Wiki.any_instance.unstub(:file)
-      Gollum::File.any_instance.unstub(:mime_type)
+      allow_any_instance_of(Gollum::Wiki).to receive(:file).and_call_original
+      allow_any_instance_of(Gollum::File).to receive(:mime_type).and_call_original
     end
 
     it 'returns the latest version of the file if it exists' do
       file = subject.find_file('image.jpg')
-      file.mime_type.should == 'image/jpeg'
+      expect(file.mime_type).to eq('image/jpeg')
     end
 
     it 'returns nil if the page does not exist' do
-      subject.find_file('non-existant').should == nil
+      expect(subject.find_file('non-existant')).to eq(nil)
     end
 
     it 'returns a Gollum::File instance' do
       file = subject.find_file('image.jpg')
-      file.should be_a Gollum::File
+      expect(file).to be_a Gollum::File
     end
   end
 
@@ -160,23 +166,23 @@ describe ProjectWiki do
     end
 
     it "creates a new wiki page" do
-      subject.create_page("test page", "this is content").should_not == false
-      subject.pages.count.should == 1
+      expect(subject.create_page("test page", "this is content")).not_to eq(false)
+      expect(subject.pages.count).to eq(1)
     end
 
     it "returns false when a duplicate page exists" do
       subject.create_page("test page", "content")
-      subject.create_page("test page", "content").should == false
+      expect(subject.create_page("test page", "content")).to eq(false)
     end
 
     it "stores an error message when a duplicate page exists" do
       2.times { subject.create_page("test page", "content") }
-      subject.error_message.should =~ /Duplicate page:/
+      expect(subject.error_message).to match(/Duplicate page:/)
     end
 
     it "sets the correct commit message" do
       subject.create_page("test page", "some content", :markdown, "commit message")
-      subject.pages.first.page.version.message.should == "commit message"
+      expect(subject.pages.first.page.version.message).to eq("commit message")
     end
   end
 
@@ -193,11 +199,11 @@ describe ProjectWiki do
     end
 
     it "updates the content of the page" do
-      @page.raw_data.should == "some other content"
+      expect(@page.raw_data).to eq("some other content")
     end
 
     it "sets the correct commit message" do
-      @page.version.message.should == "updated page"
+      expect(@page.version.message).to eq("updated page")
     end
   end
 
@@ -209,7 +215,7 @@ describe ProjectWiki do
 
     it "deletes the page" do
       subject.delete_page(@page)
-      subject.pages.count.should == 0
+      expect(subject.pages.count).to eq(0)
     end
   end
 
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
index af48c2c6d9e8439b2b2616caa401aeee76835664..1e6937b536c418581c8800c7ab348c6116cc46c1 100644
--- a/spec/models/protected_branch_spec.rb
+++ b/spec/models/protected_branch_spec.rb
@@ -2,25 +2,26 @@
 #
 # Table name: protected_branches
 #
-#  id         :integer          not null, primary key
-#  project_id :integer          not null
-#  name       :string(255)      not null
-#  created_at :datetime
-#  updated_at :datetime
+#  id                  :integer          not null, primary key
+#  project_id          :integer          not null
+#  name                :string(255)      not null
+#  created_at          :datetime
+#  updated_at          :datetime
+#  developers_can_push :boolean          default(FALSE), not null
 #
 
 require 'spec_helper'
 
 describe ProtectedBranch do
   describe 'Associations' do
-    it { should belong_to(:project) }
+    it { is_expected.to belong_to(:project) }
   end
 
   describe "Mass assignment" do
   end
 
   describe 'Validation' do
-    it { should validate_presence_of(:project) }
-    it { should validate_presence_of(:name) }
+    it { is_expected.to validate_presence_of(:project) }
+    it { is_expected.to validate_presence_of(:name) }
   end
 end
diff --git a/spec/models/pushover_service_spec.rb b/spec/models/pushover_service_spec.rb
deleted file mode 100644
index 59db69d7572f567cec17b850bcb8c0f6684c9926..0000000000000000000000000000000000000000
--- a/spec/models/pushover_service_spec.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# == Schema Information
-#
-# Table name: services
-#
-#  id         :integer          not null, primary key
-#  type       :string(255)
-#  title      :string(255)
-#  project_id :integer          not null
-#  created_at :datetime
-#  updated_at :datetime
-#  active     :boolean          default(FALSE), not null
-#  properties :text
-#
-
-require 'spec_helper'
-
-describe PushoverService do
-  describe 'Associations' do
-    it { should belong_to :project }
-    it { should have_one :service_hook }
-  end
-
-  describe 'Validations' do
-    context 'active' do
-      before do
-        subject.active = true
-      end
-
-      it { should validate_presence_of :api_key }
-      it { should validate_presence_of :user_key }
-      it { should validate_presence_of :priority }
-    end
-  end
-
-  describe 'Execute' do
-    let(:pushover) { PushoverService.new }
-    let(:user) { create(:user) }
-    let(:project) { create(:project) }
-    let(:sample_data) { GitPushService.new.sample_data(project, user) }
-
-    let(:api_key) { 'verySecret' }
-    let(:user_key) { 'verySecret' }
-    let(:device) { 'myDevice' }
-    let(:priority) { 0 }
-    let(:sound) { 'bike' }
-    let(:api_url) { 'https://api.pushover.net/1/messages.json' }
-
-    before do
-      pushover.stub(
-        project: project,
-        project_id: project.id,
-        service_hook: true,
-        api_key: api_key,
-        user_key: user_key,
-        device: device,
-        priority: priority,
-        sound: sound
-      )
-
-      WebMock.stub_request(:post, api_url)
-    end
-
-    it 'should call Pushover API' do
-      pushover.execute(sample_data)
-
-      WebMock.should have_requested(:post, api_url).once
-    end
-  end
-end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 6c3e221f34372200cf8af9171d8b38578f61be10..f41e5a97ca34d1b9de26c90ae607b0c884efc567 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -8,14 +8,21 @@ describe Repository do
   describe :branch_names_contains do
     subject { repository.branch_names_contains(sample_commit.id) }
 
-    it { should include('master') }
-    it { should_not include('feature') }
-    it { should_not include('fix') }
+    it { is_expected.to include('master') }
+    it { is_expected.not_to include('feature') }
+    it { is_expected.not_to include('fix') }
+  end
+
+  describe :tag_names_contains do
+    subject { repository.tag_names_contains(sample_commit.id) }
+
+    it { is_expected.to include('v1.1.0') }
+    it { is_expected.not_to include('v1.0.0') }
   end
 
   describe :last_commit_for_path do
     subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id }
 
-    it { should eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') }
+    it { is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') }
   end
 end
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index c96f2b205292150db3e3858abf64f02fd53f1e20..735652aea78e496cedfe441133218de6f66fec96 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -2,14 +2,19 @@
 #
 # 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
+#  id                    :integer          not null, primary key
+#  type                  :string(255)
+#  title                 :string(255)
+#  project_id            :integer
+#  created_at            :datetime
+#  updated_at            :datetime
+#  active                :boolean          default(FALSE), not null
+#  properties            :text
+#  template              :boolean          default(FALSE)
+#  push_events           :boolean          default(TRUE)
+#  issues_events         :boolean          default(TRUE)
+#  merge_requests_events :boolean          default(TRUE)
+#  tag_push_events       :boolean          default(TRUE)
 #
 
 require 'spec_helper'
@@ -17,8 +22,8 @@ require 'spec_helper'
 describe Service do
 
   describe "Associations" do
-    it { should belong_to :project }
-    it { should have_one :service_hook }
+    it { is_expected.to belong_to :project }
+    it { is_expected.to have_one :service_hook }
   end
 
   describe "Mass assignment" do
@@ -40,7 +45,7 @@ describe Service do
       end
 
       describe :can_test do
-        it { @testable.should == true }
+        it { expect(@testable).to eq(true) }
       end
     end
 
@@ -55,7 +60,32 @@ describe Service do
       end
 
       describe :can_test do
-        it { @testable.should == true }
+        it { expect(@testable).to eq(true) }
+      end
+    end
+  end
+
+  describe "Template" do
+    describe "for pushover service" do
+      let(:service_template) {
+        PushoverService.create(template: true, properties: {device: 'MyDevice', sound: 'mic', priority: 4, api_key: '123456789'})
+      }
+      let(:project) { create(:project) }
+
+      describe 'should be prefilled for projects pushover service' do
+        before do
+          service_template
+          project.build_missing_services
+        end
+
+        it "should have all fields prefilled" do
+          service = project.pushover_service
+          expect(service.template).to eq(false)
+          expect(service.device).to eq('MyDevice')
+          expect(service.sound).to eq('mic')
+          expect(service.priority).to eq(4)
+          expect(service.api_key).to eq('123456789')
+        end
       end
     end
   end
diff --git a/spec/models/slack_service_spec.rb b/spec/models/slack_service_spec.rb
deleted file mode 100644
index d48403919676414a3e0ea855ee3abf9608ca401f..0000000000000000000000000000000000000000
--- a/spec/models/slack_service_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# == Schema Information
-#
-# Table name: services
-#
-#  id         :integer          not null, primary key
-#  type       :string(255)
-#  title      :string(255)
-#  project_id :integer          not null
-#  created_at :datetime
-#  updated_at :datetime
-#  active     :boolean          default(FALSE), not null
-#  properties :text
-#
-
-require 'spec_helper'
-
-describe SlackService do
-  describe "Associations" do
-    it { should belong_to :project }
-    it { should have_one :service_hook }
-  end
-
-  describe "Validations" do
-    context "active" do
-      before do
-        subject.active = true
-      end
-
-      it { should validate_presence_of :webhook }
-    end
-  end
-
-  describe "Execute" do
-    let(:slack)   { SlackService.new }
-    let(:user)    { create(:user) }
-    let(:project) { create(:project) }
-    let(:sample_data) { GitPushService.new.sample_data(project, user) }
-    let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' }
-
-    before do
-      slack.stub(
-        project: project,
-        project_id: project.id,
-        service_hook: true,
-        webhook: webhook_url
-      )
-
-      WebMock.stub_request(:post, webhook_url)
-    end
-
-    it "should call Slack API" do
-      slack.execute(sample_data)
-
-      WebMock.should have_requested(:post, webhook_url).once
-    end
-  end
-end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 1ef2c512c1ff9c4e9f766fb76ab0fdef32e7f07e..e37dcc752306869e34bff90528367d313069e600 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -19,22 +19,22 @@ require 'spec_helper'
 
 describe Snippet do
   describe "Associations" do
-    it { should belong_to(:author).class_name('User') }
-    it { should have_many(:notes).dependent(:destroy) }
+    it { is_expected.to belong_to(:author).class_name('User') }
+    it { is_expected.to have_many(:notes).dependent(:destroy) }
   end
 
   describe "Mass assignment" do
   end
 
   describe "Validation" do
-    it { should validate_presence_of(:author) }
+    it { is_expected.to validate_presence_of(:author) }
 
-    it { should validate_presence_of(:title) }
-    it { should ensure_length_of(:title).is_within(0..255) }
+    it { is_expected.to validate_presence_of(:title) }
+    it { is_expected.to ensure_length_of(:title).is_within(0..255) }
 
-    it { should validate_presence_of(:file_name) }
-    it { should ensure_length_of(:title).is_within(0..255) }
+    it { is_expected.to validate_presence_of(:file_name) }
+    it { is_expected.to ensure_length_of(:title).is_within(0..255) }
 
-    it { should validate_presence_of(:content) }
+    it { is_expected.to validate_presence_of(:content) }
   end
 end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 6d865cfc691ce144caa8cd14c0c3f01d714c4f1f..10e90cae1430971becda8f98f2a1f11027753895 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2,79 +2,85 @@
 #
 # Table name: users
 #
-#  id                       :integer          not null, primary key
-#  email                    :string(255)      default(""), not null
-#  encrypted_password       :string(255)      default(""), not null
-#  reset_password_token     :string(255)
-#  reset_password_sent_at   :datetime
-#  remember_created_at      :datetime
-#  sign_in_count            :integer          default(0)
-#  current_sign_in_at       :datetime
-#  last_sign_in_at          :datetime
-#  current_sign_in_ip       :string(255)
-#  last_sign_in_ip          :string(255)
-#  created_at               :datetime
-#  updated_at               :datetime
-#  name                     :string(255)
-#  admin                    :boolean          default(FALSE), not null
-#  projects_limit           :integer          default(10)
-#  skype                    :string(255)      default(""), not null
-#  linkedin                 :string(255)      default(""), not null
-#  twitter                  :string(255)      default(""), not null
-#  authentication_token     :string(255)
-#  theme_id                 :integer          default(1), not null
-#  bio                      :string(255)
-#  failed_attempts          :integer          default(0)
-#  locked_at                :datetime
-#  extern_uid               :string(255)
-#  provider                 :string(255)
-#  username                 :string(255)
-#  can_create_group         :boolean          default(TRUE), not null
-#  can_create_team          :boolean          default(TRUE), not null
-#  state                    :string(255)
-#  color_scheme_id          :integer          default(1), not null
-#  notification_level       :integer          default(1), not null
-#  password_expires_at      :datetime
-#  created_by_id            :integer
-#  last_credential_check_at :datetime
-#  avatar                   :string(255)
-#  confirmation_token       :string(255)
-#  confirmed_at             :datetime
-#  confirmation_sent_at     :datetime
-#  unconfirmed_email        :string(255)
-#  hide_no_ssh_key          :boolean          default(FALSE)
-#  website_url              :string(255)      default(""), not null
+#  id                            :integer          not null, primary key
+#  email                         :string(255)      default(""), not null
+#  encrypted_password            :string(255)      default(""), not null
+#  reset_password_token          :string(255)
+#  reset_password_sent_at        :datetime
+#  remember_created_at           :datetime
+#  sign_in_count                 :integer          default(0)
+#  current_sign_in_at            :datetime
+#  last_sign_in_at               :datetime
+#  current_sign_in_ip            :string(255)
+#  last_sign_in_ip               :string(255)
+#  created_at                    :datetime
+#  updated_at                    :datetime
+#  name                          :string(255)
+#  admin                         :boolean          default(FALSE), not null
+#  projects_limit                :integer          default(10)
+#  skype                         :string(255)      default(""), not null
+#  linkedin                      :string(255)      default(""), not null
+#  twitter                       :string(255)      default(""), not null
+#  authentication_token          :string(255)
+#  theme_id                      :integer          default(1), not null
+#  bio                           :string(255)
+#  failed_attempts               :integer          default(0)
+#  locked_at                     :datetime
+#  username                      :string(255)
+#  can_create_group              :boolean          default(TRUE), not null
+#  can_create_team               :boolean          default(TRUE), not null
+#  state                         :string(255)
+#  color_scheme_id               :integer          default(1), not null
+#  notification_level            :integer          default(1), not null
+#  password_expires_at           :datetime
+#  created_by_id                 :integer
+#  last_credential_check_at      :datetime
+#  avatar                        :string(255)
+#  confirmation_token            :string(255)
+#  confirmed_at                  :datetime
+#  confirmation_sent_at          :datetime
+#  unconfirmed_email             :string(255)
+#  hide_no_ssh_key               :boolean          default(FALSE)
+#  website_url                   :string(255)      default(""), not null
+#  github_access_token           :string(255)
+#  gitlab_access_token           :string(255)
+#  notification_email            :string(255)
+#  hide_no_password              :boolean          default(FALSE)
+#  password_automatically_set    :boolean          default(FALSE)
+#  bitbucket_access_token        :string(255)
+#  bitbucket_access_token_secret :string(255)
 #
 
 require 'spec_helper'
 
 describe User do
   describe "Associations" do
-    it { should have_one(:namespace) }
-    it { should have_many(:snippets).class_name('Snippet').dependent(:destroy) }
-    it { should have_many(:project_members).dependent(:destroy) }
-    it { should have_many(:groups) }
-    it { should have_many(:keys).dependent(:destroy) }
-    it { should have_many(:events).class_name('Event').dependent(:destroy) }
-    it { should have_many(:recent_events).class_name('Event') }
-    it { should have_many(:issues).dependent(:destroy) }
-    it { should have_many(:notes).dependent(:destroy) }
-    it { should have_many(:assigned_issues).dependent(:destroy) }
-    it { should have_many(:merge_requests).dependent(:destroy) }
-    it { should have_many(:assigned_merge_requests).dependent(:destroy) }
+    it { is_expected.to have_one(:namespace) }
+    it { is_expected.to have_many(:snippets).class_name('Snippet').dependent(:destroy) }
+    it { is_expected.to have_many(:project_members).dependent(:destroy) }
+    it { is_expected.to have_many(:groups) }
+    it { is_expected.to have_many(:keys).dependent(:destroy) }
+    it { is_expected.to have_many(:events).class_name('Event').dependent(:destroy) }
+    it { is_expected.to have_many(:recent_events).class_name('Event') }
+    it { is_expected.to have_many(:issues).dependent(:destroy) }
+    it { is_expected.to have_many(:notes).dependent(:destroy) }
+    it { is_expected.to have_many(:assigned_issues).dependent(:destroy) }
+    it { is_expected.to have_many(:merge_requests).dependent(:destroy) }
+    it { is_expected.to have_many(:assigned_merge_requests).dependent(:destroy) }
+    it { is_expected.to have_many(:identities).dependent(:destroy) }
   end
 
   describe "Mass assignment" do
   end
 
   describe 'validations' do
-    it { should validate_presence_of(:username) }
-    it { should validate_presence_of(:projects_limit) }
-    it { should validate_numericality_of(:projects_limit) }
-    it { should allow_value(0).for(:projects_limit) }
-    it { should_not allow_value(-1).for(:projects_limit) }
+    it { is_expected.to validate_presence_of(:username) }
+    it { is_expected.to validate_presence_of(:projects_limit) }
+    it { is_expected.to validate_numericality_of(:projects_limit) }
+    it { is_expected.to allow_value(0).for(:projects_limit) }
+    it { is_expected.not_to allow_value(-1).for(:projects_limit) }
 
-    it { should ensure_length_of(:bio).is_within(0..255) }
+    it { is_expected.to ensure_length_of(:bio).is_within(0..255) }
 
     describe 'email' do
       it 'accepts info@example.com' do
@@ -110,34 +116,34 @@ describe User do
   end
 
   describe "Respond to" do
-    it { should respond_to(:is_admin?) }
-    it { should respond_to(:name) }
-    it { should respond_to(:private_token) }
+    it { is_expected.to respond_to(:is_admin?) }
+    it { is_expected.to respond_to(:name) }
+    it { is_expected.to respond_to(:private_token) }
   end
 
   describe '#generate_password' do
     it "should execute callback when force_random_password specified" do
       user = build(:user, force_random_password: true)
-      user.should_receive(:generate_password)
+      expect(user).to receive(:generate_password)
       user.save
     end
 
     it "should not generate password by default" do
       user = create(:user, password: 'abcdefghe')
-      user.password.should == 'abcdefghe'
+      expect(user.password).to eq('abcdefghe')
     end
 
     it "should generate password when forcing random password" do
-      Devise.stub(:friendly_token).and_return('123456789')
+      allow(Devise).to receive(:friendly_token).and_return('123456789')
       user = create(:user, password: 'abcdefg', force_random_password: true)
-      user.password.should == '12345678'
+      expect(user.password).to eq('12345678')
     end
   end
 
   describe 'authentication token' do
     it "should have authentication token" do
       user = create(:user)
-      user.authentication_token.should_not be_blank
+      expect(user.authentication_token).not_to be_blank
     end
   end
 
@@ -152,15 +158,15 @@ describe User do
       @project_3.team << [@user, :developer]
     end
 
-    it { @user.authorized_projects.should include(@project) }
-    it { @user.authorized_projects.should include(@project_2) }
-    it { @user.authorized_projects.should include(@project_3) }
-    it { @user.owned_projects.should include(@project) }
-    it { @user.owned_projects.should_not include(@project_2) }
-    it { @user.owned_projects.should_not include(@project_3) }
-    it { @user.personal_projects.should include(@project) }
-    it { @user.personal_projects.should_not include(@project_2) }
-    it { @user.personal_projects.should_not include(@project_3) }
+    it { expect(@user.authorized_projects).to include(@project) }
+    it { expect(@user.authorized_projects).to include(@project_2) }
+    it { expect(@user.authorized_projects).to include(@project_3) }
+    it { expect(@user.owned_projects).to include(@project) }
+    it { expect(@user.owned_projects).not_to include(@project_2) }
+    it { expect(@user.owned_projects).not_to include(@project_3) }
+    it { expect(@user.personal_projects).to include(@project) }
+    it { expect(@user.personal_projects).not_to include(@project_2) }
+    it { expect(@user.personal_projects).not_to include(@project_3) }
   end
 
   describe 'groups' do
@@ -170,9 +176,9 @@ describe User do
       @group.add_owner(@user)
     end
 
-    it { @user.several_namespaces?.should be_true }
-    it { @user.authorized_groups.should == [@group] }
-    it { @user.owned_groups.should == [@group] }
+    it { expect(@user.several_namespaces?).to be_truthy }
+    it { expect(@user.authorized_groups).to eq([@group]) }
+    it { expect(@user.owned_groups).to eq([@group]) }
   end
 
   describe 'group multiple owners' do
@@ -185,7 +191,7 @@ describe User do
       @group.add_user(@user2, GroupMember::OWNER)
     end
 
-    it { @user2.several_namespaces?.should be_true }
+    it { expect(@user2.several_namespaces?).to be_truthy }
   end
 
   describe 'namespaced' do
@@ -194,7 +200,7 @@ describe User do
       @project = create :project, namespace: @user.namespace
     end
 
-    it { @user.several_namespaces?.should be_false }
+    it { expect(@user.several_namespaces?).to be_falsey }
   end
 
   describe 'blocking user' do
@@ -202,7 +208,7 @@ describe User do
 
     it "should block user" do
       user.block
-      user.blocked?.should be_true
+      expect(user.blocked?).to be_truthy
     end
   end
 
@@ -214,10 +220,10 @@ describe User do
       @blocked = create :user, state: :blocked
     end
 
-    it { User.filter("admins").should == [@admin] }
-    it { User.filter("blocked").should == [@blocked] }
-    it { User.filter("wop").should include(@user, @admin, @blocked) }
-    it { User.filter(nil).should include(@user, @admin) }
+    it { expect(User.filter("admins")).to eq([@admin]) }
+    it { expect(User.filter("blocked")).to eq([@blocked]) }
+    it { expect(User.filter("wop")).to include(@user, @admin, @blocked) }
+    it { expect(User.filter(nil)).to include(@user, @admin) }
   end
 
   describe :not_in_project do
@@ -227,27 +233,27 @@ describe User do
       @project = create :project
     end
 
-    it { User.not_in_project(@project).should include(@user, @project.owner) }
+    it { expect(User.not_in_project(@project)).to include(@user, @project.owner) }
   end
 
   describe 'user creation' do
     describe 'normal user' do
       let(:user) { create(:user, name: 'John Smith') }
 
-      it { user.is_admin?.should be_false }
-      it { user.require_ssh_key?.should be_true }
-      it { user.can_create_group?.should be_true }
-      it { user.can_create_project?.should be_true }
-      it { user.first_name.should == 'John' }
+      it { expect(user.is_admin?).to be_falsey }
+      it { expect(user.require_ssh_key?).to be_truthy }
+      it { expect(user.can_create_group?).to be_truthy }
+      it { expect(user.can_create_project?).to be_truthy }
+      it { expect(user.first_name).to eq('John') }
     end
 
     describe 'with defaults' do
       let(:user) { User.new }
 
       it "should apply defaults to user" do
-        user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
-        user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
-        user.theme_id.should == Gitlab.config.gitlab.default_theme
+        expect(user.projects_limit).to eq(Gitlab.config.gitlab.default_projects_limit)
+        expect(user.can_create_group).to eq(Gitlab.config.gitlab.default_can_create_group)
+        expect(user.theme_id).to eq(Gitlab.config.gitlab.default_theme)
       end
     end
 
@@ -255,9 +261,9 @@ describe User do
       let(:user) { User.new(projects_limit: 123, can_create_group: false, can_create_team: true, theme_id: Gitlab::Theme::BASIC) }
 
       it "should apply defaults to user" do
-        user.projects_limit.should == 123
-        user.can_create_group.should be_false
-        user.theme_id.should == Gitlab::Theme::BASIC
+        expect(user.projects_limit).to eq(123)
+        expect(user.can_create_group).to be_falsey
+        expect(user.theme_id).to eq(Gitlab::Theme::BASIC)
       end
     end
   end
@@ -267,12 +273,12 @@ describe User do
     let(:user2) { create(:user, username: 'jameson', email: 'jameson@example.com') }
 
     it "should be case insensitive" do
-      User.search(user1.username.upcase).to_a.should == [user1]
-      User.search(user1.username.downcase).to_a.should == [user1]
-      User.search(user2.username.upcase).to_a.should == [user2]
-      User.search(user2.username.downcase).to_a.should == [user2]
-      User.search(user1.username.downcase).to_a.count.should == 2
-      User.search(user2.username.downcase).to_a.count.should == 1
+      expect(User.search(user1.username.upcase).to_a).to eq([user1])
+      expect(User.search(user1.username.downcase).to_a).to eq([user1])
+      expect(User.search(user2.username.upcase).to_a).to eq([user2])
+      expect(User.search(user2.username.downcase).to_a).to eq([user2])
+      expect(User.search(user1.username.downcase).to_a.count).to eq(2)
+      expect(User.search(user2.username.downcase).to_a.count).to eq(1)
     end
   end
 
@@ -280,10 +286,10 @@ describe User do
     let(:user1) { create(:user, username: 'foo') }
 
     it "should get the correct user" do
-      User.by_username_or_id(user1.id).should == user1
-      User.by_username_or_id('foo').should == user1
-      User.by_username_or_id(-1).should be_nil
-      User.by_username_or_id('bar').should be_nil
+      expect(User.by_username_or_id(user1.id)).to eq(user1)
+      expect(User.by_username_or_id('foo')).to eq(user1)
+      expect(User.by_username_or_id(-1)).to be_nil
+      expect(User.by_username_or_id('bar')).to be_nil
     end
   end
 
@@ -301,14 +307,24 @@ describe User do
     end
   end
 
+  describe ".clean_username" do
+
+    let!(:user) { create(:user, username: "johngitlab-etc") }
+    let!(:namespace) { create(:namespace, path: "JohnGitLab-etc1") }
+
+    it "cleans a username and makes sure it's available" do
+      expect(User.clean_username("-john+gitlab-ETC%.git@gmail.com")).to eq("johngitlab-ETC2")
+    end
+  end
+
   describe 'all_ssh_keys' do
-    it { should have_many(:keys).dependent(:destroy) }
+    it { is_expected.to have_many(:keys).dependent(:destroy) }
 
     it "should have all ssh keys" do
       user = create :user
       key = create :key, key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD33bWLBxu48Sev9Fert1yzEO4WGcWglWF7K/AwblIUFselOt/QdOL9DSjpQGxLagO1s9wl53STIO8qGS4Ms0EJZyIXOEFMjFJ5xmjSy+S37By4sG7SsltQEHMxtbtFOaW5LV2wCrX+rUsRNqLMamZjgjcPO0/EgGCXIGMAYW4O7cwGZdXWYIhQ1Vwy+CsVMDdPkPgBXqK7nR/ey8KMs8ho5fMNgB5hBw/AL9fNGhRw3QTD6Q12Nkhl4VZES2EsZqlpNnJttnPdp847DUsT6yuLRlfiQfz5Cn9ysHFdXObMN5VYIiPFwHeYCZp1X2S4fDZooRE8uOLTfxWHPXwrhqSH", user_id: user.id
 
-      user.all_ssh_keys.should include(key.key)
+      expect(user.all_ssh_keys).to include(key.key)
     end
   end
 
@@ -317,12 +333,12 @@ describe User do
 
     it "should be true if avatar is image" do
       user.update_attribute(:avatar, 'uploads/avatar.png')
-      user.avatar_type.should be_true
+      expect(user.avatar_type).to be_truthy
     end
 
     it "should be false if avatar is html page" do
       user.update_attribute(:avatar, 'uploads/avatar.html')
-      user.avatar_type.should == ["only images allowed"]
+      expect(user.avatar_type).to eq(["only images allowed"])
     end
   end
 
@@ -333,7 +349,7 @@ describe User do
       # Create a condition which would otherwise cause 'true' to be returned
       user.stub(ldap_user?: true)
       user.last_credential_check_at = nil
-      expect(user.requires_ldap_check?).to be_false
+      expect(user.requires_ldap_check?).to be_falsey
     end
 
     context 'when LDAP is enabled' do
@@ -341,7 +357,7 @@ describe User do
 
       it 'is false for non-LDAP users' do
         user.stub(ldap_user?: false)
-        expect(user.requires_ldap_check?).to be_false
+        expect(user.requires_ldap_check?).to be_falsey
       end
 
       context 'and when the user is an LDAP user' do
@@ -349,33 +365,38 @@ describe User do
 
         it 'is true when the user has never had an LDAP check before' do
           user.last_credential_check_at = nil
-          expect(user.requires_ldap_check?).to be_true
+          expect(user.requires_ldap_check?).to be_truthy
         end
 
         it 'is true when the last LDAP check happened over 1 hour ago' do
           user.last_credential_check_at = 2.hours.ago
-          expect(user.requires_ldap_check?).to be_true
+          expect(user.requires_ldap_check?).to be_truthy
         end
       end
     end
   end
 
   describe :ldap_user? do
-    let(:user) { build(:user, :ldap) }
-
     it "is true if provider name starts with ldap" do
-      user.provider = 'ldapmain'
-      expect( user.ldap_user? ).to be_true
+      user = create(:omniauth_user, provider: 'ldapmain')
+      expect( user.ldap_user? ).to be_truthy
     end
 
     it "is false for other providers" do
-      user.provider = 'other-provider'
-      expect( user.ldap_user? ).to be_false
+      user = create(:omniauth_user, provider: 'other-provider')
+      expect( user.ldap_user? ).to be_falsey
     end
 
     it "is false if no extern_uid is provided" do
-      user.extern_uid = nil
-      expect( user.ldap_user? ).to be_false
+      user = create(:omniauth_user, extern_uid: nil)
+      expect( user.ldap_user? ).to be_falsey
+    end
+  end
+
+  describe :ldap_identity do
+    it "returns ldap identity" do
+      user = create :omniauth_user
+      expect(user.ldap_identity.provider).not_to be_empty
     end
   end
 
@@ -429,24 +450,24 @@ describe User do
       project1 = create :project, :public
       project2 = create :project, :public
 
-      expect(user.starred?(project1)).to be_false
-      expect(user.starred?(project2)).to be_false
+      expect(user.starred?(project1)).to be_falsey
+      expect(user.starred?(project2)).to be_falsey
 
       star1 = UsersStarProject.create!(project: project1, user: user)
-      expect(user.starred?(project1)).to be_true
-      expect(user.starred?(project2)).to be_false
+      expect(user.starred?(project1)).to be_truthy
+      expect(user.starred?(project2)).to be_falsey
 
       star2 = UsersStarProject.create!(project: project2, user: user)
-      expect(user.starred?(project1)).to be_true
-      expect(user.starred?(project2)).to be_true
+      expect(user.starred?(project1)).to be_truthy
+      expect(user.starred?(project2)).to be_truthy
 
       star1.destroy
-      expect(user.starred?(project1)).to be_false
-      expect(user.starred?(project2)).to be_true
+      expect(user.starred?(project1)).to be_falsey
+      expect(user.starred?(project2)).to be_truthy
 
       star2.destroy
-      expect(user.starred?(project1)).to be_false
-      expect(user.starred?(project2)).to be_false
+      expect(user.starred?(project1)).to be_falsey
+      expect(user.starred?(project2)).to be_falsey
     end
   end
 
@@ -455,11 +476,11 @@ describe User do
       user = create :user
       project = create :project, :public
 
-      expect(user.starred?(project)).to be_false
+      expect(user.starred?(project)).to be_falsey
       user.toggle_star(project)
-      expect(user.starred?(project)).to be_true
+      expect(user.starred?(project)).to be_truthy
       user.toggle_star(project)
-      expect(user.starred?(project)).to be_false
+      expect(user.starred?(project)).to be_falsey
     end
   end
 
@@ -469,25 +490,53 @@ describe User do
       @user = create :user, created_at: Date.today, last_sign_in_at: Date.today, name: 'Alpha'
       @user1 = create :user, created_at: Date.today - 1, last_sign_in_at: Date.today - 1, name: 'Omega'
     end
-    
+
     it "sorts users as recently_signed_in" do
-      User.sort('recent_sign_in').first.should == @user
+      expect(User.sort('recent_sign_in').first).to eq(@user)
     end
 
     it "sorts users as late_signed_in" do
-      User.sort('oldest_sign_in').first.should == @user1
+      expect(User.sort('oldest_sign_in').first).to eq(@user1)
     end
 
     it "sorts users as recently_created" do
-      User.sort('recently_created').first.should == @user
+      expect(User.sort('created_desc').first).to eq(@user)
     end
 
     it "sorts users as late_created" do
-      User.sort('late_created').first.should == @user1
+      expect(User.sort('created_asc').first).to eq(@user1)
     end
 
     it "sorts users by name when nil is passed" do
-      User.sort(nil).first.should == @user
+      expect(User.sort(nil).first).to eq(@user)
+    end
+  end
+
+  describe "#contributed_projects_ids" do
+
+    subject { create(:user) }
+    let!(:project1) { create(:project) }
+    let!(:project2) { create(:project, forked_from_project: project3) }
+    let!(:project3) { create(:project) }
+    let!(:merge_request) { create(:merge_request, source_project: project2, target_project: project3, author: subject) }
+    let!(:push_event) { create(:event, action: Event::PUSHED, project: project1, target: project1, author: subject) }
+    let!(:merge_event) { create(:event, action: Event::CREATED, project: project3, target: merge_request, author: subject) }
+
+    before do
+      project1.team << [subject, :master]
+      project2.team << [subject, :master]
+    end
+
+    it "includes IDs for projects the user has pushed to" do
+      expect(subject.contributed_projects_ids).to include(project1.id)
+    end
+
+    it "includes IDs for projects the user has had merge requests merged into" do
+      expect(subject.contributed_projects_ids).to include(project3.id)
+    end
+
+    it "doesn't include IDs for unrelated projects" do
+      expect(subject.contributed_projects_ids).not_to include(project2.id)
     end
   end
 end
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index d065431ee3a1e6700af196389dea0e0922ace5ae..fceb7668cac4cf22dcb1b73d97b021ba2137057c 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -16,27 +16,27 @@ describe WikiPage do
       end
 
       it "sets the slug attribute" do
-        @wiki_page.slug.should == "test-page"
+        expect(@wiki_page.slug).to eq("test-page")
       end
 
       it "sets the title attribute" do
-        @wiki_page.title.should == "test page"
+        expect(@wiki_page.title).to eq("test page")
       end
 
       it "sets the formatted content attribute" do
-        @wiki_page.content.should == "test content"
+        expect(@wiki_page.content).to eq("test content")
       end
 
       it "sets the format attribute" do
-        @wiki_page.format.should == :markdown
+        expect(@wiki_page.format).to eq(:markdown)
       end
 
       it "sets the message attribute" do
-        @wiki_page.message.should == "test commit"
+        expect(@wiki_page.message).to eq("test commit")
       end
 
       it "sets the version attribute" do
-        @wiki_page.version.should be_a Grit::Commit
+        expect(@wiki_page.version).to be_a Gollum::Git::Commit
       end
     end
   end
@@ -48,12 +48,12 @@ describe WikiPage do
 
     it "validates presence of title" do
       subject.attributes.delete(:title)
-      subject.valid?.should be_false
+      expect(subject.valid?).to be_falsey
     end
 
     it "validates presence of content" do
       subject.attributes.delete(:content)
-      subject.valid?.should be_false
+      expect(subject.valid?).to be_falsey
     end
   end
 
@@ -69,11 +69,52 @@ describe WikiPage do
     context "with valid attributes" do
       it "saves the wiki page" do
         subject.create(@wiki_attr)
-        wiki.find_page("Index").should_not be_nil
+        expect(wiki.find_page("Index")).not_to be_nil
       end
 
       it "returns true" do
-        subject.create(@wiki_attr).should == true
+        expect(subject.create(@wiki_attr)).to eq(true)
+      end
+    end
+  end
+
+  describe "dot in the title" do
+    let(:title) { 'Index v1.2.3' }
+
+    before do
+      @wiki_attr = {title: title, content: "Home Page", format: "markdown"}
+    end
+
+    describe "#create" do
+      after do
+        destroy_page(title)
+      end
+
+      context "with valid attributes" do
+        it "saves the wiki page" do
+          subject.create(@wiki_attr)
+          expect(wiki.find_page(title)).not_to be_nil
+        end
+
+        it "returns true" do
+          expect(subject.create(@wiki_attr)).to eq(true)
+        end
+      end
+    end
+
+    describe "#update" do
+      before do
+        create_page(title, "content")
+        @page = wiki.find_page(title)
+      end
+
+      it "updates the content of the page" do
+        @page.update("new content")
+        @page = wiki.find_page(title)
+      end
+
+      it "returns true" do
+        expect(@page.update("more content")).to be_truthy
       end
     end
   end
@@ -95,7 +136,7 @@ describe WikiPage do
       end
 
       it "returns true" do
-        @page.update("more content").should be_true
+        expect(@page.update("more content")).to be_truthy
       end
     end
   end
@@ -108,11 +149,11 @@ describe WikiPage do
 
     it "should delete the page" do
       @page.delete
-      wiki.pages.should be_empty
+      expect(wiki.pages).to be_empty
     end
 
     it "should return true" do
-      @page.delete.should == true
+      expect(@page.delete).to eq(true)
     end
   end
 
@@ -128,7 +169,7 @@ describe WikiPage do
 
     it "returns an array of all commits for the page" do
       3.times { |i| @page.update("content #{i}") }
-      @page.versions.count.should == 4
+      expect(@page.versions.count).to eq(4)
     end
   end
 
@@ -144,7 +185,7 @@ describe WikiPage do
 
     it "should be replace a hyphen to a space" do
       @page.title = "Import-existing-repositories-into-GitLab"
-      @page.title.should == "Import existing repositories into GitLab"
+      expect(@page.title).to eq("Import existing repositories into GitLab")
     end
   end
 
diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb
index e2f222c0d341266ae63391ecc0a68277cce4d7ab..20cb30a39bb208cc11d05795b21fd57f6c687a48 100644
--- a/spec/requests/api/api_helpers_spec.rb
+++ b/spec/requests/api/api_helpers_spec.rb
@@ -41,32 +41,33 @@ describe API, api: true do
   describe ".current_user" do
     it "should return nil for an invalid token" do
       env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = 'invalid token'
-      current_user.should be_nil
+      allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false }
+      expect(current_user).to be_nil
     end
 
     it "should return nil for a user without access" do
       env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token
       Gitlab::UserAccess.stub(allowed?: false)
-      current_user.should be_nil
+      expect(current_user).to be_nil
     end
 
     it "should leave user as is when sudo not specified" do
       env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token
-      current_user.should == user
+      expect(current_user).to eq(user)
       clear_env
       params[API::APIHelpers::PRIVATE_TOKEN_PARAM] = user.private_token
-      current_user.should == user
+      expect(current_user).to eq(user)
     end
 
     it "should change current user to sudo when admin" do
       set_env(admin, user.id)
-      current_user.should == user
+      expect(current_user).to eq(user)
       set_param(admin, user.id)
-      current_user.should == user
+      expect(current_user).to eq(user)
       set_env(admin, user.username)
-      current_user.should == user
+      expect(current_user).to eq(user)
       set_param(admin, user.username)
-      current_user.should == user
+      expect(current_user).to eq(user)
     end
 
     it "should throw an error when the current user is not an admin and attempting to sudo" do
@@ -82,8 +83,8 @@ describe API, api: true do
 
     it "should throw an error when the user cannot be found for a given id" do
       id = user.id + admin.id
-      user.id.should_not == id
-      admin.id.should_not == id
+      expect(user.id).not_to eq(id)
+      expect(admin.id).not_to eq(id)
       set_env(admin, id)
       expect { current_user }.to raise_error
 
@@ -93,8 +94,8 @@ describe API, api: true do
 
     it "should throw an error when the user cannot be found for a given username" do
       username = "#{user.username}#{admin.username}"
-      user.username.should_not == username
-      admin.username.should_not == username
+      expect(user.username).not_to eq(username)
+      expect(admin.username).not_to eq(username)
       set_env(admin, username)
       expect { current_user }.to raise_error
 
@@ -104,69 +105,69 @@ describe API, api: true do
 
     it "should handle sudo's to oneself" do
       set_env(admin, admin.id)
-      current_user.should == admin
+      expect(current_user).to eq(admin)
       set_param(admin, admin.id)
-      current_user.should == admin
+      expect(current_user).to eq(admin)
       set_env(admin, admin.username)
-      current_user.should == admin
+      expect(current_user).to eq(admin)
       set_param(admin, admin.username)
-      current_user.should == admin
+      expect(current_user).to eq(admin)
     end
 
     it "should handle multiple sudo's to oneself" do
       set_env(admin, user.id)
-      current_user.should == user
-      current_user.should == user
+      expect(current_user).to eq(user)
+      expect(current_user).to eq(user)
       set_env(admin, user.username)
-      current_user.should == user
-      current_user.should == user
+      expect(current_user).to eq(user)
+      expect(current_user).to eq(user)
 
       set_param(admin, user.id)
-      current_user.should == user
-      current_user.should == user
+      expect(current_user).to eq(user)
+      expect(current_user).to eq(user)
       set_param(admin, user.username)
-      current_user.should == user
-      current_user.should == user
+      expect(current_user).to eq(user)
+      expect(current_user).to eq(user)
     end
 
     it "should handle multiple sudo's to oneself using string ids" do
       set_env(admin, user.id.to_s)
-      current_user.should == user
-      current_user.should == user
+      expect(current_user).to eq(user)
+      expect(current_user).to eq(user)
 
       set_param(admin, user.id.to_s)
-      current_user.should == user
-      current_user.should == user
+      expect(current_user).to eq(user)
+      expect(current_user).to eq(user)
     end
   end
 
   describe '.sudo_identifier' do
     it "should return integers when input is an int" do
       set_env(admin, '123')
-      sudo_identifier.should == 123
+      expect(sudo_identifier).to eq(123)
       set_env(admin, '0001234567890')
-      sudo_identifier.should == 1234567890
+      expect(sudo_identifier).to eq(1234567890)
 
       set_param(admin, '123')
-      sudo_identifier.should == 123
+      expect(sudo_identifier).to eq(123)
       set_param(admin, '0001234567890')
-      sudo_identifier.should == 1234567890
+      expect(sudo_identifier).to eq(1234567890)
     end
 
     it "should return string when input is an is not an int" do
       set_env(admin, '12.30')
-      sudo_identifier.should == "12.30"
+      expect(sudo_identifier).to eq("12.30")
       set_env(admin, 'hello')
-      sudo_identifier.should == 'hello'
+      expect(sudo_identifier).to eq('hello')
       set_env(admin, ' 123')
-      sudo_identifier.should == ' 123'
+      expect(sudo_identifier).to eq(' 123')
 
       set_param(admin, '12.30')
-      sudo_identifier.should == "12.30"
+      expect(sudo_identifier).to eq("12.30")
       set_param(admin, 'hello')
-      sudo_identifier.should == 'hello'
+      expect(sudo_identifier).to eq('hello')
       set_param(admin, ' 123')
-      sudo_identifier.should == ' 123'
+      expect(sudo_identifier).to eq(' 123')
     end
   end
 end
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index b45572c39fd18995b37322c2e69cea37e107cc5e..f40d68b75a4ea2399760d6714e57f55b618d2e11 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -15,79 +15,79 @@ describe API::API, api: true  do
   describe "GET /projects/:id/repository/branches" do
     it "should return an array of project branches" do
       get api("/projects/#{project.id}/repository/branches", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.first['name'].should == project.repository.branch_names.first
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.first['name']).to eq(project.repository.branch_names.first)
     end
   end
 
   describe "GET /projects/:id/repository/branches/:branch" do
     it "should return the branch information for a single branch" do
       get api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
 
-      json_response['name'].should == branch_name
-      json_response['commit']['id'].should == branch_sha
-      json_response['protected'].should == false
+      expect(json_response['name']).to eq(branch_name)
+      expect(json_response['commit']['id']).to eq(branch_sha)
+      expect(json_response['protected']).to eq(false)
     end
 
     it "should return a 403 error if guest" do
       get api("/projects/#{project.id}/repository/branches", user2)
-      response.status.should == 403
+      expect(response.status).to eq(403)
     end
 
     it "should return a 404 error if branch is not available" do
       get api("/projects/#{project.id}/repository/branches/unknown", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
   describe "PUT /projects/:id/repository/branches/:branch/protect" do
     it "should protect a single branch" do
       put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
 
-      json_response['name'].should == branch_name
-      json_response['commit']['id'].should == branch_sha
-      json_response['protected'].should == true
+      expect(json_response['name']).to eq(branch_name)
+      expect(json_response['commit']['id']).to eq(branch_sha)
+      expect(json_response['protected']).to eq(true)
     end
 
     it "should return a 404 error if branch not found" do
       put api("/projects/#{project.id}/repository/branches/unknown/protect", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
 
     it "should return a 403 error if guest" do
       put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user2)
-      response.status.should == 403
+      expect(response.status).to eq(403)
     end
 
     it "should return success when protect branch again" do
       put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user)
       put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
   end
 
   describe "PUT /projects/:id/repository/branches/:branch/unprotect" do
     it "should unprotect a single branch" do
       put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
 
-      json_response['name'].should == branch_name
-      json_response['commit']['id'].should == branch_sha
-      json_response['protected'].should == false
+      expect(json_response['name']).to eq(branch_name)
+      expect(json_response['commit']['id']).to eq(branch_sha)
+      expect(json_response['protected']).to eq(false)
     end
 
     it "should return success when unprotect branch" do
       put api("/projects/#{project.id}/repository/branches/unknown/unprotect", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
 
     it "should return success when unprotect branch again" do
       put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user)
       put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
   end
 
@@ -97,46 +97,46 @@ describe API::API, api: true  do
            branch_name: 'feature1',
            ref: branch_sha
 
-      response.status.should == 201
+      expect(response.status).to eq(201)
 
-      json_response['name'].should == 'feature1'
-      json_response['commit']['id'].should == branch_sha
+      expect(json_response['name']).to eq('feature1')
+      expect(json_response['commit']['id']).to eq(branch_sha)
     end
 
     it "should deny for user without push access" do
       post api("/projects/#{project.id}/repository/branches", user2),
            branch_name: branch_name,
            ref: branch_sha
-      response.status.should == 403
+      expect(response.status).to eq(403)
     end
 
     it 'should return 400 if branch name is invalid' do
       post api("/projects/#{project.id}/repository/branches", user),
            branch_name: 'new design',
            ref: branch_sha
-      response.status.should == 400
-      json_response['message'].should == 'Branch name invalid'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('Branch name invalid')
     end
 
     it 'should return 400 if branch already exists' do
       post api("/projects/#{project.id}/repository/branches", user),
            branch_name: 'new_design1',
            ref: branch_sha
-      response.status.should == 201
+      expect(response.status).to eq(201)
 
       post api("/projects/#{project.id}/repository/branches", user),
            branch_name: 'new_design1',
            ref: branch_sha
-      response.status.should == 400
-      json_response['message'].should == 'Branch already exists'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('Branch already exists')
     end
 
     it 'should return 400 if ref name is invalid' do
       post api("/projects/#{project.id}/repository/branches", user),
            branch_name: 'new_design3',
            ref: 'foo'
-      response.status.should == 400
-      json_response['message'].should == 'Invalid reference name'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('Invalid reference name')
     end
   end
 
@@ -145,26 +145,26 @@ describe API::API, api: true  do
 
     it "should remove branch" do
       delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
-      response.status.should == 200
-      json_response['branch_name'].should == branch_name
+      expect(response.status).to eq(200)
+      expect(json_response['branch_name']).to eq(branch_name)
     end
 
     it 'should return 404 if branch not exists' do
       delete api("/projects/#{project.id}/repository/branches/foobar", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
 
     it "should remove protected branch" do
       project.protected_branches.create(name: branch_name)
       delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user)
-      response.status.should == 405
-      json_response['message'].should == 'Protected branch cant be removed'
+      expect(response.status).to eq(405)
+      expect(json_response['message']).to eq('Protected branch cant be removed')
     end
 
     it "should not remove HEAD branch" do
       delete api("/projects/#{project.id}/repository/branches/master", user)
-      response.status.should == 405
-      json_response['message'].should == 'Cannot remove HEAD branch'
+      expect(response.status).to eq(405)
+      expect(json_response['message']).to eq('Cannot remove HEAD branch')
     end
   end
 end
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index a3f58f509132c9dd90b046fc5f55b5628faca54a..9ea60e1a4adb597c230dd5148df8a02dc93737a0 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -18,17 +18,17 @@ describe API::API, api: true  do
 
       it "should return project commits" do
         get api("/projects/#{project.id}/repository/commits", user)
-        response.status.should == 200
+        expect(response.status).to eq(200)
 
-        json_response.should be_an Array
-        json_response.first['id'].should == project.repository.commit.id
+        expect(json_response).to be_an Array
+        expect(json_response.first['id']).to eq(project.repository.commit.id)
       end
     end
 
     context "unauthorized user" do
       it "should not return project commits" do
         get api("/projects/#{project.id}/repository/commits")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
   end
@@ -37,21 +37,21 @@ describe API::API, api: true  do
     context "authorized user" do
       it "should return a commit by sha" do
         get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user)
-        response.status.should == 200
-        json_response['id'].should == project.repository.commit.id
-        json_response['title'].should == project.repository.commit.title
+        expect(response.status).to eq(200)
+        expect(json_response['id']).to eq(project.repository.commit.id)
+        expect(json_response['title']).to eq(project.repository.commit.title)
       end
 
       it "should return a 404 error if not found" do
         get api("/projects/#{project.id}/repository/commits/invalid_sha", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
 
     context "unauthorized user" do
       it "should not return the selected commit" do
         get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
   end
@@ -62,23 +62,23 @@ describe API::API, api: true  do
 
       it "should return the diff of the selected commit" do
         get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff", user)
-        response.status.should == 200
+        expect(response.status).to eq(200)
 
-        json_response.should be_an Array
-        json_response.length.should >= 1
-        json_response.first.keys.should include "diff"
+        expect(json_response).to be_an Array
+        expect(json_response.length).to be >= 1
+        expect(json_response.first.keys).to include "diff"
       end
 
       it "should return a 404 error if invalid commit" do
         get api("/projects/#{project.id}/repository/commits/invalid_sha/diff", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
 
     context "unauthorized user" do
       it "should not return the diff of the selected commit" do
         get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
   end
@@ -87,23 +87,23 @@ describe API::API, api: true  do
     context 'authorized user' do
       it 'should return merge_request comments' do
         get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 1
-        json_response.first['note'].should == 'a comment on a commit'
-        json_response.first['author']['id'].should == user.id
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['note']).to eq('a comment on a commit')
+        expect(json_response.first['author']['id']).to eq(user.id)
       end
 
       it 'should return a 404 error if merge_request_id not found' do
         get api("/projects/#{project.id}/repository/commits/1234ab/comments", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
 
     context 'unauthorized user' do
       it 'should not return the diff of the selected commit' do
         get api("/projects/#{project.id}/repository/commits/1234ab/comments")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
   end
@@ -112,37 +112,37 @@ describe API::API, api: true  do
     context 'authorized user' do
       it 'should return comment' do
         post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment'
-        response.status.should == 201
-        json_response['note'].should == 'My comment'
-        json_response['path'].should be_nil
-        json_response['line'].should be_nil
-        json_response['line_type'].should be_nil
+        expect(response.status).to eq(201)
+        expect(json_response['note']).to eq('My comment')
+        expect(json_response['path']).to be_nil
+        expect(json_response['line']).to be_nil
+        expect(json_response['line_type']).to be_nil
       end
 
       it 'should return the inline comment' do
         post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment', path: project.repository.commit.diffs.first.new_path, line: 7, line_type: 'new'
-        response.status.should == 201
-        json_response['note'].should == 'My comment'
-        json_response['path'].should == project.repository.commit.diffs.first.new_path
-        json_response['line'].should == 7
-        json_response['line_type'].should == 'new'
+        expect(response.status).to eq(201)
+        expect(json_response['note']).to eq('My comment')
+        expect(json_response['path']).to eq(project.repository.commit.diffs.first.new_path)
+        expect(json_response['line']).to eq(7)
+        expect(json_response['line_type']).to eq('new')
       end
 
       it 'should return 400 if note is missing' do
         post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user)
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it 'should return 404 if note is attached to non existent commit' do
         post api("/projects/#{project.id}/repository/commits/1234ab/comments", user), note: 'My comment'
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
 
     context 'unauthorized user' do
       it 'should not return the diff of the selected commit' do
         post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
   end
diff --git a/spec/requests/api/doorkeeper_access_spec.rb b/spec/requests/api/doorkeeper_access_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..39949a9042286cafc791a6554d79b5dadbf9223f
--- /dev/null
+++ b/spec/requests/api/doorkeeper_access_spec.rb
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe API::API, api: true  do
+  include ApiHelpers
+
+  let!(:user) { create(:user) }
+  let!(:application) { Doorkeeper::Application.create!(:name => "MyApp", :redirect_uri => "https://app.com", :owner => user) }
+  let!(:token) { Doorkeeper::AccessToken.create! :application_id => application.id, :resource_owner_id => user.id }
+
+  
+  describe "when unauthenticated" do
+    it "returns authentication success" do
+      get api("/user"), :access_token => token.token
+      expect(response.status).to eq(200)
+    end
+  end
+
+  describe "when token invalid" do
+    it "returns authentication error" do
+      get api("/user"), :access_token => "123a"
+      expect(response.status).to eq(401)
+    end
+  end
+
+  describe "authorization by private token" do
+    it "returns authentication success" do
+      get api("/user", user)
+      expect(response.status).to eq(200)
+    end
+  end
+end
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index b43a202aec03241caf75f1ef52190769d06b8818..bab8888a631277b9c79360405c3fa5bdf6c50ac2 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -16,15 +16,15 @@ describe API::API, api: true  do
       }
 
       get api("/projects/#{project.id}/repository/files", user), params
-      response.status.should == 200
-      json_response['file_path'].should == file_path
-      json_response['file_name'].should == 'popen.rb'
-      Base64.decode64(json_response['content']).lines.first.should == "require 'fileutils'\n"
+      expect(response.status).to eq(200)
+      expect(json_response['file_path']).to eq(file_path)
+      expect(json_response['file_name']).to eq('popen.rb')
+      expect(Base64.decode64(json_response['content']).lines.first).to eq("require 'fileutils'\n")
     end
 
     it "should return a 400 bad request if no params given" do
       get api("/projects/#{project.id}/repository/files", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should return a 404 if such file does not exist" do
@@ -34,7 +34,7 @@ describe API::API, api: true  do
       }
 
       get api("/projects/#{project.id}/repository/files", user), params
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
@@ -54,13 +54,13 @@ describe API::API, api: true  do
       )
 
       post api("/projects/#{project.id}/repository/files", user), valid_params
-      response.status.should == 201
-      json_response['file_path'].should == 'newfile.rb'
+      expect(response.status).to eq(201)
+      expect(json_response['file_path']).to eq('newfile.rb')
     end
 
     it "should return a 400 bad request if no params given" do
       post api("/projects/#{project.id}/repository/files", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should return a 400 if satellite fails to create file" do
@@ -69,7 +69,7 @@ describe API::API, api: true  do
       )
 
       post api("/projects/#{project.id}/repository/files", user), valid_params
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
   end
 
@@ -89,22 +89,42 @@ describe API::API, api: true  do
       )
 
       put api("/projects/#{project.id}/repository/files", user), valid_params
-      response.status.should == 200
-      json_response['file_path'].should == file_path
+      expect(response.status).to eq(200)
+      expect(json_response['file_path']).to eq(file_path)
     end
 
     it "should return a 400 bad request if no params given" do
       put api("/projects/#{project.id}/repository/files", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
-    it "should return a 400 if satellite fails to create file" do
-      Gitlab::Satellite::EditFileAction.any_instance.stub(
-        commit!: false,
-      )
+    it 'should return a 400 if the checkout fails' do
+      Gitlab::Satellite::EditFileAction.any_instance.stub(:commit!)
+        .and_raise(Gitlab::Satellite::CheckoutFailed)
+
+      put api("/projects/#{project.id}/repository/files", user), valid_params
+      expect(response.status).to eq(400)
+
+      ref = valid_params[:branch_name]
+      expect(response.body).to match("ref '#{ref}' could not be checked out")
+    end
+
+    it 'should return a 409 if the file was not modified' do
+      Gitlab::Satellite::EditFileAction.any_instance.stub(:commit!)
+        .and_raise(Gitlab::Satellite::CommitFailed)
+
+      put api("/projects/#{project.id}/repository/files", user), valid_params
+      expect(response.status).to eq(409)
+      expect(response.body).to match("Maybe there was nothing to commit?")
+    end
+
+    it 'should return a 409 if the push fails' do
+      Gitlab::Satellite::EditFileAction.any_instance.stub(:commit!)
+        .and_raise(Gitlab::Satellite::PushFailed)
 
       put api("/projects/#{project.id}/repository/files", user), valid_params
-      response.status.should == 400
+      expect(response.status).to eq(409)
+      expect(response.body).to match("Maybe the file was changed by another process?")
     end
   end
 
@@ -123,13 +143,13 @@ describe API::API, api: true  do
       )
 
       delete api("/projects/#{project.id}/repository/files", user), valid_params
-      response.status.should == 200
-      json_response['file_path'].should == file_path
+      expect(response.status).to eq(200)
+      expect(json_response['file_path']).to eq(file_path)
     end
 
     it "should return a 400 bad request if no params given" do
       delete api("/projects/#{project.id}/repository/files", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should return a 400 if satellite fails to create file" do
@@ -138,7 +158,7 @@ describe API::API, api: true  do
       )
 
       delete api("/projects/#{project.id}/repository/files", user), valid_params
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
   end
 end
diff --git a/spec/requests/api/fork_spec.rb b/spec/requests/api/fork_spec.rb
index cbbd1e7de5a77beacd365cf6af77f83c16b2eae9..fb3ff552c8d412440c4b4b6263d748cecb08ec77 100644
--- a/spec/requests/api/fork_spec.rb
+++ b/spec/requests/api/fork_spec.rb
@@ -23,50 +23,50 @@ describe API::API, api: true  do
     context 'when authenticated' do
       it 'should fork if user has sufficient access to project' do
         post api("/projects/fork/#{project.id}", user2)
-        response.status.should == 201
-        json_response['name'].should == project.name
-        json_response['path'].should == project.path
-        json_response['owner']['id'].should == user2.id
-        json_response['namespace']['id'].should == user2.namespace.id
-        json_response['forked_from_project']['id'].should == project.id
+        expect(response.status).to eq(201)
+        expect(json_response['name']).to eq(project.name)
+        expect(json_response['path']).to eq(project.path)
+        expect(json_response['owner']['id']).to eq(user2.id)
+        expect(json_response['namespace']['id']).to eq(user2.namespace.id)
+        expect(json_response['forked_from_project']['id']).to eq(project.id)
       end
 
       it 'should fork if user is admin' do
         post api("/projects/fork/#{project.id}", admin)
-        response.status.should == 201
-        json_response['name'].should == project.name
-        json_response['path'].should == project.path
-        json_response['owner']['id'].should == admin.id
-        json_response['namespace']['id'].should == admin.namespace.id
-        json_response['forked_from_project']['id'].should == project.id
+        expect(response.status).to eq(201)
+        expect(json_response['name']).to eq(project.name)
+        expect(json_response['path']).to eq(project.path)
+        expect(json_response['owner']['id']).to eq(admin.id)
+        expect(json_response['namespace']['id']).to eq(admin.namespace.id)
+        expect(json_response['forked_from_project']['id']).to eq(project.id)
       end
 
       it 'should fail on missing project access for the project to fork' do
         post api("/projects/fork/#{project.id}", user3)
-        response.status.should == 404
-        json_response['message'].should == '404 Not Found'
+        expect(response.status).to eq(404)
+        expect(json_response['message']).to eq('404 Project Not Found')
       end
 
       it 'should fail if forked project exists in the user namespace' do
         post api("/projects/fork/#{project.id}", user)
-        response.status.should == 409
-        json_response['message']['base'].should == ['Invalid fork destination']
-        json_response['message']['name'].should == ['has already been taken']
-        json_response['message']['path'].should == ['has already been taken']
+        expect(response.status).to eq(409)
+        expect(json_response['message']['base']).to eq(['Invalid fork destination'])
+        expect(json_response['message']['name']).to eq(['has already been taken'])
+        expect(json_response['message']['path']).to eq(['has already been taken'])
       end
 
       it 'should fail if project to fork from does not exist' do
         post api('/projects/fork/424242', user)
-        response.status.should == 404
-        json_response['message'].should == '404 Not Found'
+        expect(response.status).to eq(404)
+        expect(json_response['message']).to eq('404 Project Not Found')
       end
     end
 
     context 'when unauthenticated' do
       it 'should return authentication error' do
         post api("/projects/fork/#{project.id}")
-        response.status.should == 401
-        json_response['message'].should == '401 Unauthorized'
+        expect(response.status).to eq(401)
+        expect(json_response['message']).to eq('401 Unauthorized')
       end
     end
   end
diff --git a/spec/requests/api/group_members_spec.rb b/spec/requests/api/group_members_spec.rb
index 4957186f6056d0b4e5269082a8ac537debbeb06c..8ba6876a95b112b5f66c28467699edca39f223bd 100644
--- a/spec/requests/api/group_members_spec.rb
+++ b/spec/requests/api/group_members_spec.rb
@@ -31,20 +31,20 @@ describe API::API, api: true  do
       it "each user: should return an array of members groups of group3" do
         [owner, master, developer, reporter, guest].each do |user|
           get api("/groups/#{group_with_members.id}/members", user)
-          response.status.should == 200
-          json_response.should be_an Array
-          json_response.size.should == 5
-          json_response.find { |e| e['id']==owner.id }['access_level'].should == GroupMember::OWNER
-          json_response.find { |e| e['id']==reporter.id }['access_level'].should == GroupMember::REPORTER
-          json_response.find { |e| e['id']==developer.id }['access_level'].should == GroupMember::DEVELOPER
-          json_response.find { |e| e['id']==master.id }['access_level'].should == GroupMember::MASTER
-          json_response.find { |e| e['id']==guest.id }['access_level'].should == GroupMember::GUEST
+          expect(response.status).to eq(200)
+          expect(json_response).to be_an Array
+          expect(json_response.size).to eq(5)
+          expect(json_response.find { |e| e['id']==owner.id }['access_level']).to eq(GroupMember::OWNER)
+          expect(json_response.find { |e| e['id']==reporter.id }['access_level']).to eq(GroupMember::REPORTER)
+          expect(json_response.find { |e| e['id']==developer.id }['access_level']).to eq(GroupMember::DEVELOPER)
+          expect(json_response.find { |e| e['id']==master.id }['access_level']).to eq(GroupMember::MASTER)
+          expect(json_response.find { |e| e['id']==guest.id }['access_level']).to eq(GroupMember::GUEST)
         end
       end
 
       it "users not part of the group should get access error" do
         get api("/groups/#{group_with_members.id}/members", stranger)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
   end
@@ -53,7 +53,7 @@ describe API::API, api: true  do
     context "when not a member of the group" do
       it "should not add guest as member of group_no_members when adding being done by person outside the group" do
         post api("/groups/#{group_no_members.id}/members", reporter), user_id: guest.id, access_level: GroupMember::MASTER
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
 
@@ -66,9 +66,9 @@ describe API::API, api: true  do
           user_id: new_user.id, access_level: GroupMember::MASTER
         }.to change { group_no_members.members.count }.by(1)
 
-        response.status.should == 201
-        json_response['name'].should == new_user.name
-        json_response['access_level'].should == GroupMember::MASTER
+        expect(response.status).to eq(201)
+        expect(json_response['name']).to eq(new_user.name)
+        expect(json_response['access_level']).to eq(GroupMember::MASTER)
       end
 
       it "should not allow guest to modify group members" do
@@ -79,27 +79,90 @@ describe API::API, api: true  do
           user_id: new_user.id, access_level: GroupMember::MASTER
         }.not_to change { group_with_members.members.count }
 
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
 
       it "should return error if member already exists" do
         post api("/groups/#{group_with_members.id}/members", owner), user_id: master.id, access_level: GroupMember::MASTER
-        response.status.should == 409
+        expect(response.status).to eq(409)
       end
 
       it "should return a 400 error when user id is not given" do
         post api("/groups/#{group_no_members.id}/members", owner), access_level: GroupMember::MASTER
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it "should return a 400 error when access level is not given" do
         post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it "should return a 422 error when access level is not known" do
         post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id, access_level: 1234
-        response.status.should == 422
+        expect(response.status).to eq(422)
+      end
+    end
+  end
+
+  describe 'PUT /groups/:id/members/:user_id' do
+    context 'when not a member of the group' do
+      it 'should return a 409 error if the user is not a group member' do
+        put(
+          api("/groups/#{group_no_members.id}/members/#{developer.id}",
+              owner), access_level: GroupMember::MASTER
+        )
+        expect(response.status).to eq(404)
+      end
+    end
+
+    context 'when a member of the group' do
+      it 'should return ok and update member access level' do
+        put(
+          api("/groups/#{group_with_members.id}/members/#{reporter.id}",
+              owner),
+          access_level: GroupMember::MASTER
+        )
+
+        expect(response.status).to eq(200)
+
+        get api("/groups/#{group_with_members.id}/members", owner)
+        json_reporter = json_response.find do |e|
+          e['id'] == reporter.id
+        end
+
+        expect(json_reporter['access_level']).to eq(GroupMember::MASTER)
+      end
+
+      it 'should not allow guest to modify group members' do
+        put(
+          api("/groups/#{group_with_members.id}/members/#{developer.id}",
+              guest),
+          access_level: GroupMember::MASTER
+        )
+
+        expect(response.status).to eq(403)
+
+        get api("/groups/#{group_with_members.id}/members", owner)
+        json_developer = json_response.find do |e|
+          e['id'] == developer.id
+        end
+
+        expect(json_developer['access_level']).to eq(GroupMember::DEVELOPER)
+      end
+
+      it 'should return a 400 error when access level is not given' do
+        put(
+          api("/groups/#{group_with_members.id}/members/#{master.id}", owner)
+        )
+        expect(response.status).to eq(400)
+      end
+
+      it 'should return a 422 error when access level is not known' do
+        put(
+          api("/groups/#{group_with_members.id}/members/#{master.id}", owner),
+          access_level: 1234
+        )
+        expect(response.status).to eq(422)
       end
     end
   end
@@ -109,7 +172,7 @@ describe API::API, api: true  do
       it "should not delete guest's membership of group_with_members" do
         random_user = create(:user)
         delete api("/groups/#{group_with_members.id}/members/#{owner.id}", random_user)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
 
@@ -119,17 +182,17 @@ describe API::API, api: true  do
           delete api("/groups/#{group_with_members.id}/members/#{guest.id}", owner)
         }.to change { group_with_members.members.count }.by(-1)
 
-        response.status.should == 200
+        expect(response.status).to eq(200)
       end
 
       it "should return a 404 error when user id is not known" do
         delete api("/groups/#{group_with_members.id}/members/1328", owner)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
 
       it "should not allow guest to modify group members" do
         delete api("/groups/#{group_with_members.id}/members/#{master.id}", guest)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
   end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 8dfd2cd650e79965f2ebf24c388aada08553d8da..d963dbac9f1196b285bfd57d3cd3539f89749fe3 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -18,26 +18,26 @@ describe API::API, api: true  do
     context "when unauthenticated" do
       it "should return authentication error" do
         get api("/groups")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
     context "when authenticated as user" do
       it "normal user: should return an array of groups of user1" do
         get api("/groups", user1)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 1
-        json_response.first['name'].should == group1.name
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['name']).to eq(group1.name)
       end
     end
 
     context "when authenticated as  admin" do
       it "admin: should return an array of all groups" do
         get api("/groups", admin)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 2
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(2)
       end
     end
   end
@@ -46,31 +46,49 @@ describe API::API, api: true  do
     context "when authenticated as user" do
       it "should return one of user1's groups" do
         get api("/groups/#{group1.id}", user1)
-        response.status.should == 200
+        expect(response.status).to eq(200)
         json_response['name'] == group1.name
       end
 
       it "should not return a non existing group" do
         get api("/groups/1328", user1)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
 
       it "should not return a group not attached to user1" do
         get api("/groups/#{group2.id}", user1)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
 
     context "when authenticated as admin" do
       it "should return any existing group" do
         get api("/groups/#{group2.id}", admin)
-        response.status.should == 200
+        expect(response.status).to eq(200)
         json_response['name'] == group2.name
       end
 
       it "should not return a non existing group" do
         get api("/groups/1328", admin)
-        response.status.should == 404
+        expect(response.status).to eq(404)
+      end
+    end
+
+    context 'when using group path in URL' do
+      it 'should return any existing group' do
+        get api("/groups/#{group1.path}", admin)
+        expect(response.status).to eq(200)
+        json_response['name'] == group2.name
+      end
+
+      it 'should not return a non existing group' do
+        get api('/groups/unknown', admin)
+        expect(response.status).to eq(404)
+      end
+
+      it 'should not return a group not attached to user1' do
+        get api("/groups/#{group2.path}", user1)
+        expect(response.status).to eq(403)
       end
     end
   end
@@ -79,29 +97,30 @@ describe API::API, api: true  do
     context "when authenticated as user" do
       it "should not create group" do
         post api("/groups", user1), attributes_for(:group)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
 
     context "when authenticated as admin" do
       it "should create group" do
         post api("/groups", admin), attributes_for(:group)
-        response.status.should == 201
+        expect(response.status).to eq(201)
       end
 
       it "should not create group, duplicate" do
         post api("/groups", admin), {name: "Duplicate Test", path: group2.path}
-        response.status.should == 404
+        expect(response.status).to eq(400)
+        expect(response.message).to eq("Bad Request")
       end
 
       it "should return 400 bad request error if name not given" do
         post api("/groups", admin), {path: group2.path}
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it "should return 400 bad request error if path not given" do
         post api("/groups", admin), { name: 'test' }
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
     end
   end
@@ -110,36 +129,36 @@ describe API::API, api: true  do
     context "when authenticated as user" do
       it "should remove group" do
         delete api("/groups/#{group1.id}", user1)
-        response.status.should == 200
+        expect(response.status).to eq(200)
       end
 
       it "should not remove a group if not an owner" do
         user3 = create(:user)
         group1.add_user(user3, Gitlab::Access::MASTER)
         delete api("/groups/#{group1.id}", user3)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
 
       it "should not remove a non existing group" do
         delete api("/groups/1328", user1)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
 
       it "should not remove a group not attached to user1" do
         delete api("/groups/#{group2.id}", user1)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
 
     context "when authenticated as admin" do
       it "should remove any existing group" do
         delete api("/groups/#{group2.id}", admin)
-        response.status.should == 200
+        expect(response.status).to eq(200)
       end
 
       it "should not remove a non existing group" do
         delete api("/groups/1328", admin)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
   end
@@ -148,20 +167,20 @@ describe API::API, api: true  do
     let(:project) { create(:project) }
     before(:each) do
       Projects::TransferService.any_instance.stub(execute: true)
-      Project.stub(:find).and_return(project)
+      allow(Project).to receive(:find).and_return(project)
     end
 
     context "when authenticated as user" do
       it "should not transfer project to group" do
         post api("/groups/#{group1.id}/projects/#{project.id}", user2)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
 
     context "when authenticated as admin" do
       it "should transfer project to group" do
         post api("/groups/#{group1.id}/projects/#{project.id}", admin)
-        response.status.should == 201
+        expect(response.status).to eq(201)
       end
     end
   end
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index 677b14940414b75d501b6e24b81ebf2b9fe5d618..4c7d15d6594e8766b7dbb701b4d39a808190ec35 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -11,8 +11,30 @@ describe API::API, api: true  do
     it do
       get api("/internal/check"), secret_token: secret_token
 
-      response.status.should == 200
-      json_response['api_version'].should == API::API.version
+      expect(response.status).to eq(200)
+      expect(json_response['api_version']).to eq(API::API.version)
+    end
+  end
+
+  describe "GET /internal/broadcast_message" do
+    context "broadcast message exists" do
+      let!(:broadcast_message) { create(:broadcast_message, starts_at: Time.now.yesterday, ends_at: Time.now.tomorrow ) }
+
+      it do
+        get api("/internal/broadcast_message"), secret_token: secret_token
+
+        expect(response.status).to eq(200)
+        expect(json_response["message"]).to eq(broadcast_message.message)
+      end
+    end
+
+    context "broadcast message doesn't exist" do
+      it do
+        get api("/internal/broadcast_message"), secret_token: secret_token
+
+        expect(response.status).to eq(200)
+        expect(json_response).to be_empty
+      end
     end
   end
 
@@ -20,13 +42,13 @@ describe API::API, api: true  do
     it do
       get(api("/internal/discover"), key_id: key.id, secret_token: secret_token)
 
-      response.status.should == 200
+      expect(response.status).to eq(200)
 
-      json_response['name'].should == user.name
+      expect(json_response['name']).to eq(user.name)
     end
   end
 
-  describe "GET /internal/allowed" do
+  describe "POST /internal/allowed" do
     context "access granted" do
       before do
         project.team << [user, :developer]
@@ -36,8 +58,8 @@ describe API::API, api: true  do
         it do
           pull(key, project)
 
-          response.status.should == 200
-          response.body.should == 'true'
+          expect(response.status).to eq(200)
+          expect(json_response["status"]).to be_truthy
         end
       end
 
@@ -45,8 +67,8 @@ describe API::API, api: true  do
         it do
           push(key, project)
 
-          response.status.should == 200
-          response.body.should == 'true'
+          expect(response.status).to eq(200)
+          expect(json_response["status"]).to be_truthy
         end
       end
     end
@@ -60,8 +82,8 @@ describe API::API, api: true  do
         it do
           pull(key, project)
 
-          response.status.should == 200
-          response.body.should == 'false'
+          expect(response.status).to eq(200)
+          expect(json_response["status"]).to be_falsey
         end
       end
 
@@ -69,8 +91,8 @@ describe API::API, api: true  do
         it do
           push(key, project)
 
-          response.status.should == 200
-          response.body.should == 'false'
+          expect(response.status).to eq(200)
+          expect(json_response["status"]).to be_falsey
         end
       end
     end
@@ -86,8 +108,8 @@ describe API::API, api: true  do
         it do
           pull(key, personal_project)
 
-          response.status.should == 200
-          response.body.should == 'false'
+          expect(response.status).to eq(200)
+          expect(json_response["status"]).to be_falsey
         end
       end
 
@@ -95,8 +117,8 @@ describe API::API, api: true  do
         it do
           push(key, personal_project)
 
-          response.status.should == 200
-          response.body.should == 'false'
+          expect(response.status).to eq(200)
+          expect(json_response["status"]).to be_falsey
         end
       end
     end
@@ -113,8 +135,8 @@ describe API::API, api: true  do
         it do
           pull(key, project)
 
-          response.status.should == 200
-          response.body.should == 'true'
+          expect(response.status).to eq(200)
+          expect(json_response["status"]).to be_truthy
         end
       end
 
@@ -122,8 +144,8 @@ describe API::API, api: true  do
         it do
           push(key, project)
 
-          response.status.should == 200
-          response.body.should == 'false'
+          expect(response.status).to eq(200)
+          expect(json_response["status"]).to be_falsey
         end
       end
     end
@@ -139,8 +161,8 @@ describe API::API, api: true  do
         it do
           archive(key, project)
 
-          response.status.should == 200
-          response.body.should == 'true'
+          expect(response.status).to eq(200)
+          expect(json_response["status"]).to be_truthy
         end
       end
 
@@ -148,11 +170,29 @@ describe API::API, api: true  do
         it do
           archive(key, project)
 
-          response.status.should == 200
-          response.body.should == 'false'
+          expect(response.status).to eq(200)
+          expect(json_response["status"]).to be_falsey
         end
       end
     end
+
+    context 'project does not exist' do
+      it do
+        pull(key, OpenStruct.new(path_with_namespace: 'gitlab/notexists'))
+
+        expect(response.status).to eq(200)
+        expect(json_response["status"]).to be_falsey
+      end
+    end
+
+    context 'user does not exist' do
+      it do
+        pull(OpenStruct.new(id: 0), project)
+
+        expect(response.status).to eq(200)
+        expect(json_response["status"]).to be_falsey
+      end
+    end
   end
 
   def pull(key, project)
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 775d7b4e18d032cdd3f09d3a3b5b5ca7f1f0d3d3..b6b0427debf93666406cf5180af659bf6af273be 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -34,86 +34,87 @@ describe API::API, api: true  do
     context "when unauthenticated" do
       it "should return authentication error" do
         get api("/issues")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
     context "when authenticated" do
       it "should return an array of issues" do
         get api("/issues", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first['title'].should == issue.title
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['title']).to eq(issue.title)
       end
 
       it "should add pagination headers" do
         get api("/issues?per_page=3", user)
-        response.headers['Link'].should ==
+        expect(response.headers['Link']).to eq(
           '<http://www.example.com/api/v3/issues?page=1&per_page=3>; rel="first", <http://www.example.com/api/v3/issues?page=1&per_page=3>; rel="last"'
+        )
       end
 
       it 'should return an array of closed issues' do
         get api('/issues?state=closed', user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 1
-        json_response.first['id'].should == closed_issue.id
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['id']).to eq(closed_issue.id)
       end
 
       it 'should return an array of opened issues' do
         get api('/issues?state=opened', user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 1
-        json_response.first['id'].should == issue.id
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['id']).to eq(issue.id)
       end
 
       it 'should return an array of all issues' do
         get api('/issues?state=all', user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 2
-        json_response.first['id'].should == issue.id
-        json_response.second['id'].should == closed_issue.id
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(2)
+        expect(json_response.first['id']).to eq(issue.id)
+        expect(json_response.second['id']).to eq(closed_issue.id)
       end
 
       it 'should return an array of labeled issues' do
         get api("/issues?labels=#{label.title}", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 1
-        json_response.first['labels'].should == [label.title]
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['labels']).to eq([label.title])
       end
 
       it 'should return an array of labeled issues when at least one label matches' do
         get api("/issues?labels=#{label.title},foo,bar", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 1
-        json_response.first['labels'].should == [label.title]
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['labels']).to eq([label.title])
       end
 
       it 'should return an empty array if no issue matches labels' do
         get api('/issues?labels=foo,bar', user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 0
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(0)
       end
 
       it 'should return an array of labeled issues matching given state' do
         get api("/issues?labels=#{label.title}&state=opened", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 1
-        json_response.first['labels'].should == [label.title]
-        json_response.first['state'].should == 'opened'
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['labels']).to eq([label.title])
+        expect(json_response.first['state']).to eq('opened')
       end
 
       it 'should return an empty array if no issue matches labels and state filters' do
         get api("/issues?labels=#{label.title}&state=closed", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 0
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(0)
       end
     end
   end
@@ -124,78 +125,78 @@ describe API::API, api: true  do
 
     it "should return project issues" do
       get api("#{base_url}/issues", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.first['title'].should == issue.title
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.first['title']).to eq(issue.title)
     end
 
     it 'should return an array of labeled project issues' do
       get api("#{base_url}/issues?labels=#{label.title}", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.length.should == 1
-      json_response.first['labels'].should == [label.title]
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.length).to eq(1)
+      expect(json_response.first['labels']).to eq([label.title])
     end
 
     it 'should return an array of labeled project issues when at least one label matches' do
       get api("#{base_url}/issues?labels=#{label.title},foo,bar", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.length.should == 1
-      json_response.first['labels'].should == [label.title]
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.length).to eq(1)
+      expect(json_response.first['labels']).to eq([label.title])
     end
 
     it 'should return an empty array if no project issue matches labels' do
       get api("#{base_url}/issues?labels=foo,bar", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.length.should == 0
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.length).to eq(0)
     end
 
     it 'should return an empty array if no issue matches milestone' do
       get api("#{base_url}/issues?milestone=#{empty_milestone.title}", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.length.should == 0
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.length).to eq(0)
     end
 
     it 'should return an empty array if milestone does not exist' do
       get api("#{base_url}/issues?milestone=foo", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.length.should == 0
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.length).to eq(0)
     end
 
     it 'should return an array of issues in given milestone' do
       get api("#{base_url}/issues?milestone=#{title}", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.length.should == 2
-      json_response.first['id'].should == issue.id
-      json_response.second['id'].should == closed_issue.id
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.length).to eq(2)
+      expect(json_response.first['id']).to eq(issue.id)
+      expect(json_response.second['id']).to eq(closed_issue.id)
     end
 
     it 'should return an array of issues matching state in milestone' do
       get api("#{base_url}/issues?milestone=#{milestone.title}"\
               '&state=closed', user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.length.should == 1
-      json_response.first['id'].should == closed_issue.id
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.length).to eq(1)
+      expect(json_response.first['id']).to eq(closed_issue.id)
     end
   end
 
   describe "GET /projects/:id/issues/:issue_id" do
     it "should return a project issue by id" do
       get api("/projects/#{project.id}/issues/#{issue.id}", user)
-      response.status.should == 200
-      json_response['title'].should == issue.title
-      json_response['iid'].should == issue.iid
+      expect(response.status).to eq(200)
+      expect(json_response['title']).to eq(issue.title)
+      expect(json_response['iid']).to eq(issue.iid)
     end
 
     it "should return 404 if issue id not found" do
       get api("/projects/#{project.id}/issues/54321", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
@@ -203,32 +204,32 @@ describe API::API, api: true  do
     it "should create a new project issue" do
       post api("/projects/#{project.id}/issues", user),
         title: 'new issue', labels: 'label, label2'
-      response.status.should == 201
-      json_response['title'].should == 'new issue'
-      json_response['description'].should be_nil
-      json_response['labels'].should == ['label', 'label2']
+      expect(response.status).to eq(201)
+      expect(json_response['title']).to eq('new issue')
+      expect(json_response['description']).to be_nil
+      expect(json_response['labels']).to eq(['label', 'label2'])
     end
 
     it "should return a 400 bad request if title not given" do
       post api("/projects/#{project.id}/issues", user), labels: 'label, label2'
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it 'should return 400 on invalid label names' do
       post api("/projects/#{project.id}/issues", user),
            title: 'new issue',
            labels: 'label, ?'
-      response.status.should == 400
-      json_response['message']['labels']['?']['title'].should == ['is invalid']
+      expect(response.status).to eq(400)
+      expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
     end
 
     it 'should return 400 if title is too long' do
       post api("/projects/#{project.id}/issues", user),
            title: 'g' * 256
-      response.status.should == 400
-      json_response['message']['title'].should == [
+      expect(response.status).to eq(400)
+      expect(json_response['message']['title']).to eq([
         'is too long (maximum is 255 characters)'
-      ]
+      ])
     end
   end
 
@@ -236,23 +237,23 @@ describe API::API, api: true  do
     it "should update a project issue" do
       put api("/projects/#{project.id}/issues/#{issue.id}", user),
         title: 'updated title'
-      response.status.should == 200
+      expect(response.status).to eq(200)
 
-      json_response['title'].should == 'updated title'
+      expect(json_response['title']).to eq('updated title')
     end
 
     it "should return 404 error if issue id not found" do
       put api("/projects/#{project.id}/issues/44444", user),
         title: 'updated title'
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
 
     it 'should return 400 on invalid label names' do
       put api("/projects/#{project.id}/issues/#{issue.id}", user),
           title: 'updated title',
           labels: 'label, ?'
-      response.status.should == 400
-      json_response['message']['labels']['?']['title'].should == ['is invalid']
+      expect(response.status).to eq(400)
+      expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
     end
   end
 
@@ -263,49 +264,49 @@ describe API::API, api: true  do
     it 'should not update labels if not present' do
       put api("/projects/#{project.id}/issues/#{issue.id}", user),
           title: 'updated title'
-      response.status.should == 200
-      json_response['labels'].should == [label.title]
+      expect(response.status).to eq(200)
+      expect(json_response['labels']).to eq([label.title])
     end
 
     it 'should remove all labels' do
       put api("/projects/#{project.id}/issues/#{issue.id}", user),
           labels: ''
-      response.status.should == 200
-      json_response['labels'].should == []
+      expect(response.status).to eq(200)
+      expect(json_response['labels']).to eq([])
     end
 
     it 'should update labels' do
       put api("/projects/#{project.id}/issues/#{issue.id}", user),
           labels: 'foo,bar'
-      response.status.should == 200
-      json_response['labels'].should include 'foo'
-      json_response['labels'].should include 'bar'
+      expect(response.status).to eq(200)
+      expect(json_response['labels']).to include 'foo'
+      expect(json_response['labels']).to include 'bar'
     end
 
     it 'should return 400 on invalid label names' do
       put api("/projects/#{project.id}/issues/#{issue.id}", user),
           labels: 'label, ?'
-      response.status.should == 400
-      json_response['message']['labels']['?']['title'].should == ['is invalid']
+      expect(response.status).to eq(400)
+      expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
     end
 
     it 'should allow special label names' do
       put api("/projects/#{project.id}/issues/#{issue.id}", user),
           labels: 'label:foo, label-bar,label_bar,label/bar'
-      response.status.should == 200
-      json_response['labels'].should include 'label:foo'
-      json_response['labels'].should include 'label-bar'
-      json_response['labels'].should include 'label_bar'
-      json_response['labels'].should include 'label/bar'
+      expect(response.status).to eq(200)
+      expect(json_response['labels']).to include 'label:foo'
+      expect(json_response['labels']).to include 'label-bar'
+      expect(json_response['labels']).to include 'label_bar'
+      expect(json_response['labels']).to include 'label/bar'
     end
 
     it 'should return 400 if title is too long' do
       put api("/projects/#{project.id}/issues/#{issue.id}", user),
           title: 'g' * 256
-      response.status.should == 400
-      json_response['message']['title'].should == [
+      expect(response.status).to eq(400)
+      expect(json_response['message']['title']).to eq([
         'is too long (maximum is 255 characters)'
-      ]
+      ])
     end
   end
 
@@ -313,17 +314,17 @@ describe API::API, api: true  do
     it "should update a project issue" do
       put api("/projects/#{project.id}/issues/#{issue.id}", user),
         labels: 'label2', state_event: "close"
-      response.status.should == 200
+      expect(response.status).to eq(200)
 
-      json_response['labels'].should include 'label2'
-      json_response['state'].should eq "closed"
+      expect(json_response['labels']).to include 'label2'
+      expect(json_response['state']).to eq "closed"
     end
   end
 
   describe "DELETE /projects/:id/issues/:issue_id" do
     it "should delete a project issue" do
       delete api("/projects/#{project.id}/issues/#{issue.id}", user)
-      response.status.should == 405
+      expect(response.status).to eq(405)
     end
   end
 end
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index dbddc8a7da40438390a29ebd1f1a958c60aca1e9..aff109a942469fe8d37b61ec2ed8a5a2ed0034b9 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -15,10 +15,10 @@ describe API::API, api: true  do
   describe 'GET /projects/:id/labels' do
     it 'should return project labels' do
       get api("/projects/#{project.id}/labels", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.size.should == 1
-      json_response.first['name'].should == label1.name
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.size).to eq(1)
+      expect(json_response.first['name']).to eq(label1.name)
     end
   end
 
@@ -27,69 +27,69 @@ describe API::API, api: true  do
       post api("/projects/#{project.id}/labels", user),
            name: 'Foo',
            color: '#FFAABB'
-      response.status.should == 201
-      json_response['name'].should == 'Foo'
-      json_response['color'].should == '#FFAABB'
+      expect(response.status).to eq(201)
+      expect(json_response['name']).to eq('Foo')
+      expect(json_response['color']).to eq('#FFAABB')
     end
 
     it 'should return a 400 bad request if name not given' do
       post api("/projects/#{project.id}/labels", user), color: '#FFAABB'
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it 'should return a 400 bad request if color not given' do
       post api("/projects/#{project.id}/labels", user), name: 'Foobar'
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it 'should return 400 for invalid color' do
       post api("/projects/#{project.id}/labels", user),
            name: 'Foo',
            color: '#FFAA'
-      response.status.should == 400
-      json_response['message']['color'].should == ['is invalid']
+      expect(response.status).to eq(400)
+      expect(json_response['message']['color']).to eq(['is invalid'])
     end
 
     it 'should return 400 for too long color code' do
       post api("/projects/#{project.id}/labels", user),
            name: 'Foo',
            color: '#FFAAFFFF'
-      response.status.should == 400
-      json_response['message']['color'].should == ['is invalid']
+      expect(response.status).to eq(400)
+      expect(json_response['message']['color']).to eq(['is invalid'])
     end
 
     it 'should return 400 for invalid name' do
       post api("/projects/#{project.id}/labels", user),
            name: '?',
            color: '#FFAABB'
-      response.status.should == 400
-      json_response['message']['title'].should == ['is invalid']
+      expect(response.status).to eq(400)
+      expect(json_response['message']['title']).to eq(['is invalid'])
     end
 
     it 'should return 409 if label already exists' do
       post api("/projects/#{project.id}/labels", user),
            name: 'label1',
            color: '#FFAABB'
-      response.status.should == 409
-      json_response['message'].should == 'Label already exists'
+      expect(response.status).to eq(409)
+      expect(json_response['message']).to eq('Label already exists')
     end
   end
 
   describe 'DELETE /projects/:id/labels' do
     it 'should return 200 for existing label' do
       delete api("/projects/#{project.id}/labels", user), name: 'label1'
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it 'should return 404 for non existing label' do
       delete api("/projects/#{project.id}/labels", user), name: 'label2'
-      response.status.should == 404
-      json_response['message'].should == '404 Label Not Found'
+      expect(response.status).to eq(404)
+      expect(json_response['message']).to eq('404 Label Not Found')
     end
 
     it 'should return 400 for wrong parameters' do
       delete api("/projects/#{project.id}/labels", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
   end
 
@@ -99,47 +99,47 @@ describe API::API, api: true  do
           name: 'label1',
           new_name: 'New Label',
           color: '#FFFFFF'
-      response.status.should == 200
-      json_response['name'].should == 'New Label'
-      json_response['color'].should == '#FFFFFF'
+      expect(response.status).to eq(200)
+      expect(json_response['name']).to eq('New Label')
+      expect(json_response['color']).to eq('#FFFFFF')
     end
 
     it 'should return 200 if name is changed' do
       put api("/projects/#{project.id}/labels", user),
           name: 'label1',
           new_name: 'New Label'
-      response.status.should == 200
-      json_response['name'].should == 'New Label'
-      json_response['color'].should == label1.color
+      expect(response.status).to eq(200)
+      expect(json_response['name']).to eq('New Label')
+      expect(json_response['color']).to eq(label1.color)
     end
 
     it 'should return 200 if colors is changed' do
       put api("/projects/#{project.id}/labels", user),
           name: 'label1',
           color: '#FFFFFF'
-      response.status.should == 200
-      json_response['name'].should == label1.name
-      json_response['color'].should == '#FFFFFF'
+      expect(response.status).to eq(200)
+      expect(json_response['name']).to eq(label1.name)
+      expect(json_response['color']).to eq('#FFFFFF')
     end
 
     it 'should return 404 if label does not exist' do
       put api("/projects/#{project.id}/labels", user),
           name: 'label2',
           new_name: 'label3'
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
 
     it 'should return 400 if no label name given' do
       put api("/projects/#{project.id}/labels", user), new_name: 'label2'
-      response.status.should == 400
-      json_response['message'].should == '400 (Bad request) "name" not given'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('400 (Bad request) "name" not given')
     end
 
     it 'should return 400 if no new parameters given' do
       put api("/projects/#{project.id}/labels", user), name: 'label1'
-      response.status.should == 400
-      json_response['message'].should == 'Required parameters '\
-                                         '"new_name" or "color" missing'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('Required parameters '\
+                                         '"new_name" or "color" missing')
     end
 
     it 'should return 400 for invalid name' do
@@ -147,24 +147,24 @@ describe API::API, api: true  do
           name: 'label1',
           new_name: '?',
           color: '#FFFFFF'
-      response.status.should == 400
-      json_response['message']['title'].should == ['is invalid']
+      expect(response.status).to eq(400)
+      expect(json_response['message']['title']).to eq(['is invalid'])
     end
 
     it 'should return 400 for invalid name' do
       put api("/projects/#{project.id}/labels", user),
           name: 'label1',
           color: '#FF'
-      response.status.should == 400
-      json_response['message']['color'].should == ['is invalid']
+      expect(response.status).to eq(400)
+      expect(json_response['message']['color']).to eq(['is invalid'])
     end
 
     it 'should return 400 for too long color code' do
       post api("/projects/#{project.id}/labels", user),
            name: 'Foo',
            color: '#FFAAFFFF'
-      response.status.should == 400
-      json_response['message']['color'].should == ['is invalid']
+      expect(response.status).to eq(400)
+      expect(json_response['message']['color']).to eq(['is invalid'])
     end
   end
 end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 5ba3a33099154e4d6c917489103b9f96d9c91e54..9e252441a4f417d4aeeeb280161fac89f2cf0e08 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -16,46 +16,50 @@ describe API::API, api: true  do
     context "when unauthenticated" do
       it "should return authentication error" do
         get api("/projects/#{project.id}/merge_requests")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
     context "when authenticated" do
       it "should return an array of all merge_requests" do
         get api("/projects/#{project.id}/merge_requests", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 3
-        json_response.first['title'].should == merge_request.title
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(3)
+        expect(json_response.last['title']).to eq(merge_request.title)
       end
+
       it "should return an array of all merge_requests" do
         get api("/projects/#{project.id}/merge_requests?state", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 3
-        json_response.first['title'].should == merge_request.title
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(3)
+        expect(json_response.last['title']).to eq(merge_request.title)
       end
+
       it "should return an array of open merge_requests" do
         get api("/projects/#{project.id}/merge_requests?state=opened", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 1
-        json_response.first['title'].should == merge_request.title
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(1)
+        expect(json_response.last['title']).to eq(merge_request.title)
       end
+
       it "should return an array of closed merge_requests" do
         get api("/projects/#{project.id}/merge_requests?state=closed", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 2
-        json_response.first['title'].should == merge_request_closed.title
-        json_response.second['title'].should == merge_request_merged.title
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(2)
+        expect(json_response.second['title']).to eq(merge_request_closed.title)
+        expect(json_response.first['title']).to eq(merge_request_merged.title)
       end
+
       it "should return an array of merged merge_requests" do
         get api("/projects/#{project.id}/merge_requests?state=merged", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.length.should == 1
-        json_response.first['title'].should == merge_request_merged.title
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['title']).to eq(merge_request_merged.title)
       end
 
       context "with ordering" do
@@ -66,35 +70,38 @@ describe API::API, api: true  do
 
         it "should return an array of merge_requests in ascending order" do
           get api("/projects/#{project.id}/merge_requests?sort=asc", user)
-          response.status.should == 200
-          json_response.should be_an Array
-          json_response.length.should == 3
-          json_response.first['id'].should == @mr_earlier.id
-          json_response.last['id'].should == @mr_later.id
+          expect(response.status).to eq(200)
+          expect(json_response).to be_an Array
+          expect(json_response.length).to eq(3)
+          expect(json_response.last['id']).to eq(@mr_earlier.id)
+          expect(json_response.first['id']).to eq(@mr_later.id)
         end
+
         it "should return an array of merge_requests in descending order" do
           get api("/projects/#{project.id}/merge_requests?sort=desc", user)
-          response.status.should == 200
-          json_response.should be_an Array
-          json_response.length.should == 3
-          json_response.first['id'].should == @mr_later.id
-          json_response.last['id'].should == @mr_earlier.id
+          expect(response.status).to eq(200)
+          expect(json_response).to be_an Array
+          expect(json_response.length).to eq(3)
+          expect(json_response.first['id']).to eq(@mr_later.id)
+          expect(json_response.last['id']).to eq(@mr_earlier.id)
         end
+
         it "should return an array of merge_requests ordered by updated_at" do
           get api("/projects/#{project.id}/merge_requests?order_by=updated_at", user)
-          response.status.should == 200
-          json_response.should be_an Array
-          json_response.length.should == 3
-          json_response.first['id'].should == @mr_earlier.id
-          json_response.last['id'].should == @mr_later.id
+          expect(response.status).to eq(200)
+          expect(json_response).to be_an Array
+          expect(json_response.length).to eq(3)
+          expect(json_response.last['id']).to eq(@mr_earlier.id)
+          expect(json_response.first['id']).to eq(@mr_later.id)
         end
+
         it "should return an array of merge_requests ordered by created_at" do
           get api("/projects/#{project.id}/merge_requests?sort=created_at", user)
-          response.status.should == 200
-          json_response.should be_an Array
-          json_response.length.should == 3
-          json_response.first['id'].should == @mr_earlier.id
-          json_response.last['id'].should == @mr_later.id
+          expect(response.status).to eq(200)
+          expect(json_response).to be_an Array
+          expect(json_response.length).to eq(3)
+          expect(json_response.last['id']).to eq(@mr_earlier.id)
+          expect(json_response.first['id']).to eq(@mr_later.id)
         end
       end
     end
@@ -103,14 +110,27 @@ describe API::API, api: true  do
   describe "GET /projects/:id/merge_request/:merge_request_id" do
     it "should return merge_request" do
       get api("/projects/#{project.id}/merge_request/#{merge_request.id}", user)
-      response.status.should == 200
-      json_response['title'].should == merge_request.title
-      json_response['iid'].should == merge_request.iid
+      expect(response.status).to eq(200)
+      expect(json_response['title']).to eq(merge_request.title)
+      expect(json_response['iid']).to eq(merge_request.iid)
     end
 
     it "should return a 404 error if merge_request_id not found" do
       get api("/projects/#{project.id}/merge_request/999", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
+    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
 
@@ -123,33 +143,33 @@ describe API::API, api: true  do
              target_branch: 'master',
              author: user,
              labels: 'label, label2'
-        response.status.should == 201
-        json_response['title'].should == 'Test merge_request'
-        json_response['labels'].should == ['label', 'label2']
+        expect(response.status).to eq(201)
+        expect(json_response['title']).to eq('Test merge_request')
+        expect(json_response['labels']).to eq(['label', 'label2'])
       end
 
       it "should return 422 when source_branch equals target_branch" do
         post api("/projects/#{project.id}/merge_requests", user),
         title: "Test merge_request", source_branch: "master", target_branch: "master", author: user
-        response.status.should == 422
+        expect(response.status).to eq(422)
       end
 
       it "should return 400 when source_branch is missing" do
         post api("/projects/#{project.id}/merge_requests", user),
         title: "Test merge_request", target_branch: "master", author: user
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it "should return 400 when target_branch is missing" do
         post api("/projects/#{project.id}/merge_requests", user),
         title: "Test merge_request", source_branch: "stable", author: user
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it "should return 400 when title is missing" do
         post api("/projects/#{project.id}/merge_requests", user),
         target_branch: 'master', source_branch: 'stable'
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it 'should return 400 on invalid label names' do
@@ -159,9 +179,10 @@ describe API::API, api: true  do
              target_branch: 'master',
              author: user,
              labels: 'label, ?'
-        response.status.should == 400
-        json_response['message']['labels']['?']['title'].should ==
+        expect(response.status).to eq(400)
+        expect(json_response['message']['labels']['?']['title']).to eq(
           ['is invalid']
+        )
       end
 
       context 'with existing MR' do
@@ -182,7 +203,7 @@ describe API::API, api: true  do
                  target_branch: 'master',
                  author: user
           end.to change { MergeRequest.count }.by(0)
-          response.status.should == 409
+          expect(response.status).to eq(409)
         end
       end
     end
@@ -199,37 +220,37 @@ describe API::API, api: true  do
       it "should return merge_request" do
         post api("/projects/#{fork_project.id}/merge_requests", user2),
         title: 'Test merge_request', source_branch: "stable", target_branch: "master", author: user2, target_project_id: project.id, description: 'Test description for Test merge_request'
-        response.status.should == 201
-        json_response['title'].should == 'Test merge_request'
-        json_response['description'].should == 'Test description for Test merge_request'
+        expect(response.status).to eq(201)
+        expect(json_response['title']).to eq('Test merge_request')
+        expect(json_response['description']).to eq('Test description for Test merge_request')
       end
 
       it "should not return 422 when source_branch equals target_branch" do
-        project.id.should_not == fork_project.id
-        fork_project.forked?.should be_true
-        fork_project.forked_from_project.should == project
+        expect(project.id).not_to eq(fork_project.id)
+        expect(fork_project.forked?).to be_truthy
+        expect(fork_project.forked_from_project).to eq(project)
         post api("/projects/#{fork_project.id}/merge_requests", user2),
         title: 'Test merge_request', source_branch: "master", target_branch: "master", author: user2, target_project_id: project.id
-        response.status.should == 201
-        json_response['title'].should == 'Test merge_request'
+        expect(response.status).to eq(201)
+        expect(json_response['title']).to eq('Test merge_request')
       end
 
       it "should return 400 when source_branch is missing" do
         post api("/projects/#{fork_project.id}/merge_requests", user2),
         title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it "should return 400 when target_branch is missing" do
         post api("/projects/#{fork_project.id}/merge_requests", user2),
         title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it "should return 400 when title is missing" do
         post api("/projects/#{fork_project.id}/merge_requests", user2),
         target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: project.id
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       context 'when target_branch is specified' do
@@ -240,7 +261,7 @@ describe API::API, api: true  do
                source_branch: 'stable',
                author: user,
                target_project_id: fork_project.id
-          response.status.should == 422
+          expect(response.status).to eq(422)
         end
 
         it 'should return 422 if targeting a different fork' do
@@ -250,14 +271,14 @@ describe API::API, api: true  do
                source_branch: 'stable',
                author: user2,
                target_project_id: unrelated_project.id
-          response.status.should == 422
+          expect(response.status).to eq(422)
         end
       end
 
       it "should return 201 when target_branch is specified and for the same project" do
         post api("/projects/#{fork_project.id}/merge_requests", user2),
         title: 'Test merge_request', target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: fork_project.id
-        response.status.should == 201
+        expect(response.status).to eq(201)
       end
     end
   end
@@ -265,8 +286,8 @@ describe API::API, api: true  do
   describe "PUT /projects/:id/merge_request/:merge_request_id to close MR" do
     it "should return merge_request" do
       put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "close"
-      response.status.should == 200
-      json_response['state'].should == 'closed'
+      expect(response.status).to eq(200)
+      expect(json_response['state']).to eq('closed')
     end
   end
 
@@ -274,55 +295,55 @@ describe API::API, api: true  do
     it "should return merge_request in case of success" do
       MergeRequest.any_instance.stub(can_be_merged?: true, automerge!: true)
       put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it "should return 405 if branch can't be merged" do
       MergeRequest.any_instance.stub(can_be_merged?: false)
       put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user)
-      response.status.should == 405
-      json_response['message'].should == 'Branch cannot be merged'
+      expect(response.status).to eq(405)
+      expect(json_response['message']).to eq('Branch cannot be merged')
     end
 
     it "should return 405 if merge_request is not open" do
       merge_request.close
       put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user)
-      response.status.should == 405
-      json_response['message'].should == '405 Method Not Allowed'
+      expect(response.status).to eq(405)
+      expect(json_response['message']).to eq('405 Method Not Allowed')
     end
 
     it "should return 401 if user has no permissions to merge" do
       user2 = create(:user)
       project.team << [user2, :reporter]
       put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user2)
-      response.status.should == 401
-      json_response['message'].should == '401 Unauthorized'
+      expect(response.status).to eq(401)
+      expect(json_response['message']).to eq('401 Unauthorized')
     end
   end
 
   describe "PUT /projects/:id/merge_request/:merge_request_id" do
     it "should return merge_request" do
       put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), title: "New title"
-      response.status.should == 200
-      json_response['title'].should == 'New title'
+      expect(response.status).to eq(200)
+      expect(json_response['title']).to eq('New title')
     end
 
     it "should return merge_request" do
       put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), description: "New description"
-      response.status.should == 200
-      json_response['description'].should == 'New description'
+      expect(response.status).to eq(200)
+      expect(json_response['description']).to eq('New description')
     end
 
     it "should return 422 when source_branch and target_branch are renamed the same" do
       put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user),
       source_branch: "master", target_branch: "master"
-      response.status.should == 422
+      expect(response.status).to eq(422)
     end
 
     it "should return merge_request with renamed target_branch" do
       put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), target_branch: "wiki"
-      response.status.should == 200
-      json_response['target_branch'].should == 'wiki'
+      expect(response.status).to eq(200)
+      expect(json_response['target_branch']).to eq('wiki')
     end
 
     it 'should return 400 on invalid label names' do
@@ -330,43 +351,43 @@ describe API::API, api: true  do
               user),
           title: 'new issue',
           labels: 'label, ?'
-      response.status.should == 400
-      json_response['message']['labels']['?']['title'].should == ['is invalid']
+      expect(response.status).to eq(400)
+      expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
     end
   end
 
   describe "POST /projects/:id/merge_request/:merge_request_id/comments" do
     it "should return comment" do
       post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user), note: "My comment"
-      response.status.should == 201
-      json_response['note'].should == 'My comment'
+      expect(response.status).to eq(201)
+      expect(json_response['note']).to eq('My comment')
     end
 
     it "should return 400 if note is missing" do
       post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should return 404 if note is attached to non existent merge request" do
       post api("/projects/#{project.id}/merge_request/404/comments", user),
            note: 'My comment'
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
   describe "GET :id/merge_request/:merge_request_id/comments" do
     it "should return merge_request comments" do
       get api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.length.should == 1
-      json_response.first['note'].should == "a comment on a MR"
-      json_response.first['author']['id'].should == user.id
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.length).to eq(1)
+      expect(json_response.first['note']).to eq("a comment on a MR")
+      expect(json_response.first['author']['id']).to eq(user.id)
     end
 
     it "should return a 404 error if merge_request_id not found" do
       get api("/projects/#{project.id}/merge_request/999/comments", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb
index f0619a1c80100aa9f390ec9a3a93d7712aee903c..effb0723476e843bc0e66101baf7e78480bf5b2e 100644
--- a/spec/requests/api/milestones_spec.rb
+++ b/spec/requests/api/milestones_spec.rb
@@ -8,92 +8,109 @@ describe API::API, api: true  do
 
   before { project.team << [user, :developer] }
 
-  describe "GET /projects/:id/milestones" do
-    it "should return project milestones" do
+  describe 'GET /projects/:id/milestones' do
+    it 'should return project milestones' do
       get api("/projects/#{project.id}/milestones", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.first['title'].should == milestone.title
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.first['title']).to eq(milestone.title)
     end
 
-    it "should return a 401 error if user not authenticated" do
+    it 'should return a 401 error if user not authenticated' do
       get api("/projects/#{project.id}/milestones")
-      response.status.should == 401
+      expect(response.status).to eq(401)
     end
   end
 
-  describe "GET /projects/:id/milestones/:milestone_id" do
-    it "should return a project milestone by id" do
+  describe 'GET /projects/:id/milestones/:milestone_id' do
+    it 'should return a project milestone by id' do
       get api("/projects/#{project.id}/milestones/#{milestone.id}", user)
-      response.status.should == 200
-      json_response['title'].should == milestone.title
-      json_response['iid'].should == milestone.iid
+      expect(response.status).to eq(200)
+      expect(json_response['title']).to eq(milestone.title)
+      expect(json_response['iid']).to eq(milestone.iid)
     end
 
-    it "should return 401 error if user not authenticated" do
+    it 'should return 401 error if user not authenticated' do
       get api("/projects/#{project.id}/milestones/#{milestone.id}")
-      response.status.should == 401
+      expect(response.status).to eq(401)
     end
 
-    it "should return a 404 error if milestone id not found" do
+    it 'should return a 404 error if milestone id not found' do
       get api("/projects/#{project.id}/milestones/1234", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
-  describe "POST /projects/:id/milestones" do
-    it "should create a new project milestone" do
+  describe 'POST /projects/:id/milestones' do
+    it 'should create a new project milestone' do
       post api("/projects/#{project.id}/milestones", user), title: 'new milestone'
-      response.status.should == 201
-      json_response['title'].should == 'new milestone'
-      json_response['description'].should be_nil
+      expect(response.status).to eq(201)
+      expect(json_response['title']).to eq('new milestone')
+      expect(json_response['description']).to be_nil
     end
 
-    it "should create a new project milestone with description and due date" do
+    it 'should create a new project milestone with description and due date' do
       post api("/projects/#{project.id}/milestones", user),
         title: 'new milestone', description: 'release', due_date: '2013-03-02'
-      response.status.should == 201
-      json_response['description'].should == 'release'
-      json_response['due_date'].should == '2013-03-02'
+      expect(response.status).to eq(201)
+      expect(json_response['description']).to eq('release')
+      expect(json_response['due_date']).to eq('2013-03-02')
     end
 
-    it "should return a 400 error if title is missing" do
+    it 'should return a 400 error if title is missing' do
       post api("/projects/#{project.id}/milestones", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
   end
 
-  describe "PUT /projects/:id/milestones/:milestone_id" do
-    it "should update a project milestone" do
+  describe 'PUT /projects/:id/milestones/:milestone_id' do
+    it 'should update a project milestone' do
       put api("/projects/#{project.id}/milestones/#{milestone.id}", user),
         title: 'updated title'
-      response.status.should == 200
-      json_response['title'].should == 'updated title'
+      expect(response.status).to eq(200)
+      expect(json_response['title']).to eq('updated title')
     end
 
-    it "should return a 404 error if milestone id not found" do
+    it 'should return a 404 error if milestone id not found' do
       put api("/projects/#{project.id}/milestones/1234", user),
         title: 'updated title'
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
-  describe "PUT /projects/:id/milestones/:milestone_id to close milestone" do
-    it "should update a project milestone" do
+  describe 'PUT /projects/:id/milestones/:milestone_id to close milestone' do
+    it 'should update a project milestone' do
       put api("/projects/#{project.id}/milestones/#{milestone.id}", user),
         state_event: 'close'
-      response.status.should == 200
+      expect(response.status).to eq(200)
 
-      json_response['state'].should == 'closed'
+      expect(json_response['state']).to eq('closed')
     end
   end
 
-  describe "PUT /projects/:id/milestones/:milestone_id to test observer on close" do
-    it "should create an activity event when an milestone is closed" do
-      Event.should_receive(:create)
+  describe 'PUT /projects/:id/milestones/:milestone_id to test observer on close' do
+    it 'should create an activity event when an milestone is closed' do
+      expect(Event).to receive(:create)
 
       put api("/projects/#{project.id}/milestones/#{milestone.id}", user),
           state_event: 'close'
     end
   end
+
+  describe 'GET /projects/:id/milestones/:milestone_id/issues' do
+    before do
+      milestone.issues << create(:issue)
+    end
+    it 'should return project issues for a particular milestone' do
+      get api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user)
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.first['milestone']['title']).to eq(milestone.title)
+    end
+
+    it 'should return a 401 error if user not authenticated' do
+      get api("/projects/#{project.id}/milestones/#{milestone.id}/issues")
+      expect(response.status).to eq(401)
+    end
+  end
 end
diff --git a/spec/requests/api/namespaces_spec.rb b/spec/requests/api/namespaces_spec.rb
index b8943ea0762fabcf8dee6eb9e22547d6edd20c9b..6ddaaa0a6dde9603476184e91a9b5814ccd0b34f 100644
--- a/spec/requests/api/namespaces_spec.rb
+++ b/spec/requests/api/namespaces_spec.rb
@@ -10,17 +10,17 @@ describe API::API, api: true  do
     context "when unauthenticated" do
       it "should return authentication error" do
         get api("/namespaces")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
     context "when authenticated as  admin" do
       it "admin: should return an array of all namespaces" do
         get api("/namespaces", admin)
-        response.status.should == 200
-        json_response.should be_an Array
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
 
-        json_response.length.should == Namespace.count
+        expect(json_response.length).to eq(Namespace.count)
       end
     end
   end
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index 7aa53787aedb666c0d1311b8f140e451d2452c42..8b177af4689b09b63ff434c891d7d4feebdfa358 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -16,42 +16,42 @@ describe API::API, api: true  do
     context "when noteable is an Issue" do
       it "should return an array of issue notes" do
         get api("/projects/#{project.id}/issues/#{issue.id}/notes", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first['body'].should == issue_note.note
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['body']).to eq(issue_note.note)
       end
 
       it "should return a 404 error when issue id not found" do
         get api("/projects/#{project.id}/issues/123/notes", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
 
     context "when noteable is a Snippet" do
       it "should return an array of snippet notes" do
         get api("/projects/#{project.id}/snippets/#{snippet.id}/notes", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first['body'].should == snippet_note.note
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['body']).to eq(snippet_note.note)
       end
 
       it "should return a 404 error when snippet id not found" do
         get api("/projects/#{project.id}/snippets/42/notes", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
 
     context "when noteable is a Merge Request" do
       it "should return an array of merge_requests notes" do
         get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/notes", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first['body'].should == merge_request_note.note
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['body']).to eq(merge_request_note.note)
       end
 
       it "should return a 404 error if merge request id not found" do
         get api("/projects/#{project.id}/merge_requests/4444/notes", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
   end
@@ -60,26 +60,26 @@ describe API::API, api: true  do
     context "when noteable is an Issue" do
       it "should return an issue note by id" do
         get api("/projects/#{project.id}/issues/#{issue.id}/notes/#{issue_note.id}", user)
-        response.status.should == 200
-        json_response['body'].should == issue_note.note
+        expect(response.status).to eq(200)
+        expect(json_response['body']).to eq(issue_note.note)
       end
 
       it "should return a 404 error if issue note not found" do
         get api("/projects/#{project.id}/issues/#{issue.id}/notes/123", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
 
     context "when noteable is a Snippet" do
       it "should return a snippet note by id" do
         get api("/projects/#{project.id}/snippets/#{snippet.id}/notes/#{snippet_note.id}", user)
-        response.status.should == 200
-        json_response['body'].should == snippet_note.note
+        expect(response.status).to eq(200)
+        expect(json_response['body']).to eq(snippet_note.note)
       end
 
       it "should return a 404 error if snippet note not found" do
         get api("/projects/#{project.id}/snippets/#{snippet.id}/notes/123", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
   end
@@ -88,47 +88,101 @@ describe API::API, api: true  do
     context "when noteable is an Issue" do
       it "should create a new issue note" do
         post api("/projects/#{project.id}/issues/#{issue.id}/notes", user), body: 'hi!'
-        response.status.should == 201
-        json_response['body'].should == 'hi!'
-        json_response['author']['username'].should == user.username
+        expect(response.status).to eq(201)
+        expect(json_response['body']).to eq('hi!')
+        expect(json_response['author']['username']).to eq(user.username)
       end
 
       it "should return a 400 bad request error if body not given" do
         post api("/projects/#{project.id}/issues/#{issue.id}/notes", user)
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it "should return a 401 unauthorized error if user not authenticated" do
         post api("/projects/#{project.id}/issues/#{issue.id}/notes"), body: 'hi!'
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
     context "when noteable is a Snippet" do
       it "should create a new snippet note" do
         post api("/projects/#{project.id}/snippets/#{snippet.id}/notes", user), body: 'hi!'
-        response.status.should == 201
-        json_response['body'].should == 'hi!'
-        json_response['author']['username'].should == user.username
+        expect(response.status).to eq(201)
+        expect(json_response['body']).to eq('hi!')
+        expect(json_response['author']['username']).to eq(user.username)
       end
 
       it "should return a 400 bad request error if body not given" do
         post api("/projects/#{project.id}/snippets/#{snippet.id}/notes", user)
-        response.status.should == 400
+        expect(response.status).to eq(400)
       end
 
       it "should return a 401 unauthorized error if user not authenticated" do
         post api("/projects/#{project.id}/snippets/#{snippet.id}/notes"), body: 'hi!'
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
   end
 
   describe "POST /projects/:id/noteable/:noteable_id/notes to test observer on create" do
     it "should create an activity event when an issue note is created" do
-      Event.should_receive(:create)
+      expect(Event).to receive(:create)
 
       post api("/projects/#{project.id}/issues/#{issue.id}/notes", user), body: 'hi!'
     end
   end
+
+  describe 'PUT /projects/:id/noteable/:noteable_id/notes/:note_id' do
+    context 'when noteable is an Issue' do
+      it 'should return modified note' do
+        put api("/projects/#{project.id}/issues/#{issue.id}/"\
+                  "notes/#{issue_note.id}", user), body: 'Hello!'
+        expect(response.status).to eq(200)
+        expect(json_response['body']).to eq('Hello!')
+      end
+
+      it 'should return a 404 error when note id not found' do
+        put api("/projects/#{project.id}/issues/#{issue.id}/notes/123", user),
+                body: 'Hello!'
+        expect(response.status).to eq(404)
+      end
+
+      it 'should return a 400 bad request error if body not given' do
+        put api("/projects/#{project.id}/issues/#{issue.id}/"\
+                  "notes/#{issue_note.id}", user)
+        expect(response.status).to eq(400)
+      end
+    end
+
+    context 'when noteable is a Snippet' do
+      it 'should return modified note' do
+        put api("/projects/#{project.id}/snippets/#{snippet.id}/"\
+                  "notes/#{snippet_note.id}", user), body: 'Hello!'
+        expect(response.status).to eq(200)
+        expect(json_response['body']).to eq('Hello!')
+      end
+
+      it 'should return a 404 error when note id not found' do
+        put api("/projects/#{project.id}/snippets/#{snippet.id}/"\
+                  "notes/123", user), body: "Hello!"
+        expect(response.status).to eq(404)
+      end
+    end
+
+    context 'when noteable is a Merge Request' do
+      it 'should return modified note' do
+        put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/"\
+                  "notes/#{merge_request_note.id}", user), body: 'Hello!'
+        expect(response.status).to eq(200)
+        expect(json_response['body']).to eq('Hello!')
+      end
+
+      it 'should return a 404 error when note id not found' do
+        put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/"\
+                  "notes/123", user), body: "Hello!"
+        expect(response.status).to eq(404)
+      end
+    end
+  end
+
 end
diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb
index cdb5e3d061278e36dba652fd7c5028f74474db24..81fe68de662c94a01a4d8090da89a50268262178 100644
--- a/spec/requests/api/project_hooks_spec.rb
+++ b/spec/requests/api/project_hooks_spec.rb
@@ -16,18 +16,18 @@ describe API::API, 'ProjectHooks', api: true  do
     context "authorized user" do
       it "should return project hooks" do
         get api("/projects/#{project.id}/hooks", user)
-        response.status.should == 200
+        expect(response.status).to eq(200)
 
-        json_response.should be_an Array
-        json_response.count.should == 1
-        json_response.first['url'].should == "http://example.com"
+        expect(json_response).to be_an Array
+        expect(json_response.count).to eq(1)
+        expect(json_response.first['url']).to eq("http://example.com")
       end
     end
 
     context "unauthorized user" do
       it "should not access project hooks" do
         get api("/projects/#{project.id}/hooks", user3)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
   end
@@ -36,26 +36,26 @@ describe API::API, 'ProjectHooks', api: true  do
     context "authorized user" do
       it "should return a project hook" do
         get api("/projects/#{project.id}/hooks/#{hook.id}", user)
-        response.status.should == 200
-        json_response['url'].should == hook.url
+        expect(response.status).to eq(200)
+        expect(json_response['url']).to eq(hook.url)
       end
 
       it "should return a 404 error if hook id is not available" do
         get api("/projects/#{project.id}/hooks/1234", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
 
     context "unauthorized user" do
       it "should not access an existing hook" do
         get api("/projects/#{project.id}/hooks/#{hook.id}", user3)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
 
     it "should return a 404 error if hook id is not available" do
       get api("/projects/#{project.id}/hooks/1234", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
@@ -65,17 +65,17 @@ describe API::API, 'ProjectHooks', api: true  do
         post api("/projects/#{project.id}/hooks", user),
           url: "http://example.com", issues_events: true
       }.to change {project.hooks.count}.by(1)
-      response.status.should == 201
+      expect(response.status).to eq(201)
     end
 
     it "should return a 400 error if url not given" do
       post api("/projects/#{project.id}/hooks", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should return a 422 error if url not valid" do
       post api("/projects/#{project.id}/hooks", user), "url" => "ftp://example.com"
-      response.status.should == 422
+      expect(response.status).to eq(422)
     end
   end
 
@@ -83,23 +83,23 @@ describe API::API, 'ProjectHooks', api: true  do
     it "should update an existing project hook" do
       put api("/projects/#{project.id}/hooks/#{hook.id}", user),
         url: 'http://example.org', push_events: false
-      response.status.should == 200
-      json_response['url'].should == 'http://example.org'
+      expect(response.status).to eq(200)
+      expect(json_response['url']).to eq('http://example.org')
     end
 
     it "should return 404 error if hook id not found" do
       put api("/projects/#{project.id}/hooks/1234", user), url: 'http://example.org'
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
 
     it "should return 400 error if url is not given" do
       put api("/projects/#{project.id}/hooks/#{hook.id}", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should return a 422 error if url is not valid" do
       put api("/projects/#{project.id}/hooks/#{hook.id}", user), url: 'ftp://example.com'
-      response.status.should == 422
+      expect(response.status).to eq(422)
     end
   end
 
@@ -108,22 +108,22 @@ describe API::API, 'ProjectHooks', api: true  do
       expect {
         delete api("/projects/#{project.id}/hooks/#{hook.id}", user)
       }.to change {project.hooks.count}.by(-1)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it "should return success when deleting hook" do
       delete api("/projects/#{project.id}/hooks/#{hook.id}", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it "should return success when deleting non existent hook" do
       delete api("/projects/#{project.id}/hooks/42", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it "should return a 405 error if hook id not given" do
       delete api("/projects/#{project.id}/hooks", user)
-      response.status.should == 405
+      expect(response.status).to eq(405)
     end
   end
 end
diff --git a/spec/requests/api/project_members_spec.rb b/spec/requests/api/project_members_spec.rb
index 836f21f3e0bae6b1fc0ed2a2edf8a64c941f209c..8419a364ed115501b4d512cd73878c5766f0bc40 100644
--- a/spec/requests/api/project_members_spec.rb
+++ b/spec/requests/api/project_members_spec.rb
@@ -15,23 +15,23 @@ describe API::API, api: true  do
 
     it "should return project team members" do
       get api("/projects/#{project.id}/members", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.count.should == 2
-      json_response.map { |u| u['username'] }.should include user.username
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.count).to eq(2)
+      expect(json_response.map { |u| u['username'] }).to include user.username
     end
 
     it "finds team members with query string" do
       get api("/projects/#{project.id}/members", user), query: user.username
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.count.should == 1
-      json_response.first['username'].should == user.username
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.count).to eq(1)
+      expect(json_response.first['username']).to eq(user.username)
     end
 
     it "should return a 404 error if id not found" do
       get api("/projects/9999/members", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
@@ -40,14 +40,14 @@ describe API::API, api: true  do
 
     it "should return project team member" do
       get api("/projects/#{project.id}/members/#{user.id}", user)
-      response.status.should == 200
-      json_response['username'].should == user.username
-      json_response['access_level'].should == ProjectMember::MASTER
+      expect(response.status).to eq(200)
+      expect(json_response['username']).to eq(user.username)
+      expect(json_response['access_level']).to eq(ProjectMember::MASTER)
     end
 
     it "should return a 404 error if user id not found" do
       get api("/projects/#{project.id}/members/1234", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
@@ -58,9 +58,9 @@ describe API::API, api: true  do
           access_level: ProjectMember::DEVELOPER
       }.to change { ProjectMember.count }.by(1)
 
-      response.status.should == 201
-      json_response['username'].should == user2.username
-      json_response['access_level'].should == ProjectMember::DEVELOPER
+      expect(response.status).to eq(201)
+      expect(json_response['username']).to eq(user2.username)
+      expect(json_response['access_level']).to eq(ProjectMember::DEVELOPER)
     end
 
     it "should return a 201 status if user is already project member" do
@@ -69,26 +69,26 @@ describe API::API, api: true  do
       expect {
         post api("/projects/#{project.id}/members", user), user_id: user2.id,
           access_level: ProjectMember::DEVELOPER
-      }.not_to change { ProjectMember.count }.by(1)
+      }.not_to change { ProjectMember.count }
 
-      response.status.should == 201
-      json_response['username'].should == user2.username
-      json_response['access_level'].should == ProjectMember::DEVELOPER
+      expect(response.status).to eq(201)
+      expect(json_response['username']).to eq(user2.username)
+      expect(json_response['access_level']).to eq(ProjectMember::DEVELOPER)
     end
 
     it "should return a 400 error when user id is not given" do
       post api("/projects/#{project.id}/members", user), access_level: ProjectMember::MASTER
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should return a 400 error when access level is not given" do
       post api("/projects/#{project.id}/members", user), user_id: user2.id
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should return a 422 error when access level is not known" do
       post api("/projects/#{project.id}/members", user), user_id: user2.id, access_level: 1234
-      response.status.should == 422
+      expect(response.status).to eq(422)
     end
   end
 
@@ -97,24 +97,24 @@ describe API::API, api: true  do
 
     it "should update project team member" do
       put api("/projects/#{project.id}/members/#{user3.id}", user), access_level: ProjectMember::MASTER
-      response.status.should == 200
-      json_response['username'].should == user3.username
-      json_response['access_level'].should == ProjectMember::MASTER
+      expect(response.status).to eq(200)
+      expect(json_response['username']).to eq(user3.username)
+      expect(json_response['access_level']).to eq(ProjectMember::MASTER)
     end
 
     it "should return a 404 error if user_id is not found" do
       put api("/projects/#{project.id}/members/1234", user), access_level: ProjectMember::MASTER
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
 
     it "should return a 400 error when access level is not given" do
       put api("/projects/#{project.id}/members/#{user3.id}", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should return a 422 error when access level is not known" do
       put api("/projects/#{project.id}/members/#{user3.id}", user), access_level: 123
-      response.status.should == 422
+      expect(response.status).to eq(422)
     end
   end
 
@@ -132,22 +132,22 @@ describe API::API, api: true  do
       delete api("/projects/#{project.id}/members/#{user3.id}", user)
       expect {
         delete api("/projects/#{project.id}/members/#{user3.id}", user)
-      }.to_not change { ProjectMember.count }.by(1)
+      }.to_not change { ProjectMember.count }
     end
 
     it "should return 200 if team member already removed" do
       delete api("/projects/#{project.id}/members/#{user3.id}", user)
       delete api("/projects/#{project.id}/members/#{user3.id}", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it "should return 200 OK when the user was not member" do
       expect {
         delete api("/projects/#{project.id}/members/1000000", user)
       }.to change { ProjectMember.count }.by(0)
-      response.status.should == 200
-      json_response['message'].should == "Access revoked"
-      json_response['id'].should == 1000000
+      expect(response.status).to eq(200)
+      expect(json_response['message']).to eq("Access revoked")
+      expect(json_response['id']).to eq(1000000)
     end
   end
 end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 2c4b68c10b688402ec76dc2e63ff43c1ca827c62..f28dfea3ccf62e1e84085772d77bfa13e1a8f4b9 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1,122 +1,149 @@
+# -*- coding: utf-8 -*-
 require 'spec_helper'
 
 describe API::API, api: true  do
   include ApiHelpers
+  include Gitlab::CurrentSettings
   let(:user) { create(:user) }
   let(:user2) { create(:user) }
   let(:user3) { create(:user) }
   let(:admin) { create(:admin) }
   let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
+  let(:project2) { create(:project, path: 'project2', creator_id: user.id, namespace: user.namespace) }
+  let(:project3) { create(:project, path: 'project3', creator_id: user.id, namespace: user.namespace) }
   let(:snippet) { create(:project_snippet, author: user, project: project, title: 'example') }
   let(:project_member) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) }
   let(:project_member2) { create(:project_member, user: user3, project: project, access_level: ProjectMember::DEVELOPER) }
+  let(:user4) { create(:user) }
+  let(:project3) do
+    create(:project,
+    name: 'second_project',
+    path: 'second_project',
+    creator_id: user.id,
+    namespace: user.namespace,
+    merge_requests_enabled: false,
+    issues_enabled: false, wiki_enabled: false,
+    snippets_enabled: false, visibility_level: 0)
+  end
+  let(:project_member3) do
+    create(:project_member,
+    user: user4,
+    project: project3,
+    access_level: ProjectMember::MASTER)
+  end
+  let(:project4) do
+    create(:project,
+    name: 'third_project',
+    path: 'third_project',
+    creator_id: user4.id,
+    namespace: user4.namespace)
+  end
 
-  describe "GET /projects" do
+  describe 'GET /projects' do
     before { project }
 
-    context "when unauthenticated" do
-      it "should return authentication error" do
-        get api("/projects")
-        response.status.should == 401
+    context 'when unauthenticated' do
+      it 'should return authentication error' do
+        get api('/projects')
+        expect(response.status).to eq(401)
       end
     end
 
-    context "when authenticated" do
-      it "should return an array of projects" do
-        get api("/projects", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first['name'].should == project.name
-        json_response.first['owner']['username'].should == user.username
+    context 'when authenticated' do
+      it 'should return an array of projects' do
+        get api('/projects', user)
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['name']).to eq(project.name)
+        expect(json_response.first['owner']['username']).to eq(user.username)
+      end
+
+      context 'and using search' do
+        it 'should return searched project' do
+          get api('/projects', user), { search: project.name }
+          expect(response.status).to eq(200)
+          expect(json_response).to be_an Array
+          expect(json_response.length).to eq(1)
+        end
+      end
+
+      context 'and using sorting' do
+        before do
+          project2
+          project3
+        end
+
+        it 'should return the correct order when sorted by id' do
+          get api('/projects', user), { order_by: 'id', sort: 'desc'}
+          expect(response.status).to eq(200)
+          expect(json_response).to be_an Array
+          expect(json_response.first['id']).to eq(project3.id)
+        end
       end
     end
   end
 
-  describe "GET /projects/all" do
+  describe 'GET /projects/all' do
     before { project }
 
-    context "when unauthenticated" do
-      it "should return authentication error" do
-        get api("/projects/all")
-        response.status.should == 401
+    context 'when unauthenticated' do
+      it 'should return authentication error' do
+        get api('/projects/all')
+        expect(response.status).to eq(401)
       end
     end
 
-    context "when authenticated as regular user" do
-      it "should return authentication error" do
-        get api("/projects/all", user)
-        response.status.should == 403
+    context 'when authenticated as regular user' do
+      it 'should return authentication error' do
+        get api('/projects/all', user)
+        expect(response.status).to eq(403)
       end
     end
 
-    context "when authenticated as admin" do
-      it "should return an array of all projects" do
-        get api("/projects/all", admin)
-        response.status.should == 200
-        json_response.should be_an Array
+    context 'when authenticated as admin' do
+      it 'should return an array of all projects' do
+        get api('/projects/all', admin)
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
         project_name = project.name
 
-        json_response.detect {
+        expect(json_response.detect {
           |project| project['name'] == project_name
-        }['name'].should == project_name
+        }['name']).to eq(project_name)
 
-        json_response.detect {
+        expect(json_response.detect {
           |project| project['owner']['username'] == user.username
-        }['owner']['username'].should == user.username
+        }['owner']['username']).to eq(user.username)
       end
     end
   end
 
-  describe "POST /projects" do
-    context "maximum number of projects reached" do
-      before do
-        (1..user2.projects_limit).each do |project|
-          post api("/projects", user2), name: "foo#{project}"
-        end
-      end
-
-      it "should not create new project" do
+  describe 'POST /projects' do
+    context 'maximum number of projects reached' do
+      it 'should not create new project and respond with 403' do
+        allow_any_instance_of(User).to receive(:projects_limit_left).and_return(0)
         expect {
-          post api("/projects", user2), name: 'foo'
+          post api('/projects', user2), name: 'foo'
         }.to change {Project.count}.by(0)
+        expect(response.status).to eq(403)
       end
     end
 
-    it "should create new project without path" do
-      expect { post api("/projects", user), name: 'foo' }.to change {Project.count}.by(1)
+    it 'should create new project without path and return 201' do
+      expect { post api('/projects', user), name: 'foo' }.
+        to change { Project.count }.by(1)
+      expect(response.status).to eq(201)
     end
 
-    it "should not create new project without name" do
-      expect { post api("/projects", user) }.to_not change {Project.count}
+    it 'should create last project before reaching project limit' do
+      allow_any_instance_of(User).to receive(:projects_limit_left).and_return(1)
+      post api('/projects', user2), name: 'foo'
+      expect(response.status).to eq(201)
     end
 
-    it "should return a 400 error if name not given" do
-      post api("/projects", user)
-      response.status.should == 400
-    end
-
-    it "should create last project before reaching project limit" do
-      (1..user2.projects_limit-1).each { |p| post api("/projects", user2), name: "foo#{p}" }
-      post api("/projects", user2), name: "foo"
-      response.status.should == 201
-    end
-
-    it "should respond with 201 on success" do
-      post api("/projects", user), name: 'foo'
-      response.status.should == 201
-    end
-
-    it "should respond with 400 if name is not given" do
-      post api("/projects", user)
-      response.status.should == 400
-    end
-
-    it "should return a 403 error if project limit reached" do
-      (1..user.projects_limit).each do |p|
-        post api("/projects", user), name: "foo#{p}"
-      end
-      post api("/projects", user), name: 'bar'
-      response.status.should == 403
+    it 'should not create new project without name and return 400' do
+      expect { post api('/projects', user) }.to_not change { Project.count }
+      expect(response.status).to eq(400)
     end
 
     it "should assign attributes to project" do
@@ -128,91 +155,108 @@ describe API::API, api: true  do
         wiki_enabled: false
       })
 
-      post api("/projects", user), project
+      post api('/projects', user), project
 
       project.each_pair do |k,v|
-        json_response[k.to_s].should == v
+        expect(json_response[k.to_s]).to eq(v)
       end
     end
 
-    it "should set a project as public" do
+    it 'should set a project as public' do
       project = attributes_for(:project, :public)
-      post api("/projects", user), project
-      json_response['public'].should be_true
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::PUBLIC
+      post api('/projects', user), project
+      expect(json_response['public']).to be_truthy
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
     end
 
-    it "should set a project as public using :public" do
+    it 'should set a project as public using :public' do
       project = attributes_for(:project, { public: true })
-      post api("/projects", user), project
-      json_response['public'].should be_true
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::PUBLIC
+      post api('/projects', user), project
+      expect(json_response['public']).to be_truthy
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
     end
 
-    it "should set a project as internal" do
+    it 'should set a project as internal' do
       project = attributes_for(:project, :internal)
-      post api("/projects", user), project
-      json_response['public'].should be_false
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL
+      post api('/projects', user), project
+      expect(json_response['public']).to be_falsey
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
     end
 
-    it "should set a project as internal overriding :public" do
+    it 'should set a project as internal overriding :public' do
       project = attributes_for(:project, :internal, { public: true })
-      post api("/projects", user), project
-      json_response['public'].should be_false
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL
+      post api('/projects', user), project
+      expect(json_response['public']).to be_falsey
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
     end
 
-    it "should set a project as private" do
+    it 'should set a project as private' do
       project = attributes_for(:project, :private)
-      post api("/projects", user), project
-      json_response['public'].should be_false
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::PRIVATE
+      post api('/projects', user), project
+      expect(json_response['public']).to be_falsey
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
     end
 
-    it "should set a project as private using :public" do
+    it 'should set a project as private using :public' do
       project = attributes_for(:project, { public: false })
-      post api("/projects", user), project
-      json_response['public'].should be_false
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::PRIVATE
+      post api('/projects', user), project
+      expect(json_response['public']).to be_falsey
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
+    end
+
+    context 'when a visibility level is restricted' do
+      before do
+        @project = attributes_for(:project, { public: true })
+        allow_any_instance_of(ApplicationSetting).to(
+          receive(:restricted_visibility_levels).and_return([20])
+        )
+      end
+
+      it 'should not allow a non-admin to use a restricted visibility level' do
+        post api('/projects', user), @project
+        expect(response.status).to eq(400)
+        expect(json_response['message']['visibility_level'].first).to(
+          match('restricted by your GitLab administrator')
+        )
+      end
+
+      it 'should allow an admin to override restricted visibility settings' do
+        post api('/projects', admin), @project
+        expect(json_response['public']).to be_truthy
+        expect(json_response['visibility_level']).to(
+          eq(Gitlab::VisibilityLevel::PUBLIC)
+        )
+      end
     end
   end
 
-  describe "POST /projects/user/:id" do
+  describe 'POST /projects/user/:id' do
     before { project }
     before { admin }
 
-    it "should create new project without path" do
+    it 'should create new project without path and return 201' do
       expect { post api("/projects/user/#{user.id}", admin), name: 'foo' }.to change {Project.count}.by(1)
+      expect(response.status).to eq(201)
     end
 
-    it "should not create new project without name" do
-      expect { post api("/projects/user/#{user.id}", admin) }.to_not change {Project.count}
-    end
-
-    it "should respond with 201 on success" do
-      post api("/projects/user/#{user.id}", admin), name: 'foo'
-      response.status.should == 201
-    end
+    it 'should respond with 400 on failure and not project' do
+      expect { post api("/projects/user/#{user.id}", admin) }.
+        to_not change { Project.count }
 
-    it 'should respond with 400 on failure' do
-      post api("/projects/user/#{user.id}", admin)
-      response.status.should == 400
-      json_response['message']['creator'].should == ['can\'t be blank']
-      json_response['message']['namespace'].should == ['can\'t be blank']
-      json_response['message']['name'].should == [
+      expect(response.status).to eq(400)
+      expect(json_response['message']['name']).to eq([
         'can\'t be blank',
         'is too short (minimum is 0 characters)',
         Gitlab::Regex.project_regex_message
-      ]
-      json_response['message']['path'].should == [
+      ])
+      expect(json_response['message']['path']).to eq([
         'can\'t be blank',
         'is too short (minimum is 0 characters)',
         Gitlab::Regex.send(:default_regex_message)
-      ]
+      ])
     end
 
-    it "should assign attributes to project" do
+    it 'should assign attributes to project' do
       project = attributes_for(:project, {
         description: Faker::Lorem.sentence,
         issues_enabled: false,
@@ -224,227 +268,217 @@ describe API::API, api: true  do
 
       project.each_pair do |k,v|
         next if k == :path
-        json_response[k.to_s].should == v
+        expect(json_response[k.to_s]).to eq(v)
       end
     end
 
-    it "should set a project as public" do
+    it 'should set a project as public' do
       project = attributes_for(:project, :public)
       post api("/projects/user/#{user.id}", admin), project
-      json_response['public'].should be_true
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::PUBLIC
+      expect(json_response['public']).to be_truthy
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
     end
 
-    it "should set a project as public using :public" do
+    it 'should set a project as public using :public' do
       project = attributes_for(:project, { public: true })
       post api("/projects/user/#{user.id}", admin), project
-      json_response['public'].should be_true
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::PUBLIC
+      expect(json_response['public']).to be_truthy
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC)
     end
 
-    it "should set a project as internal" do
+    it 'should set a project as internal' do
       project = attributes_for(:project, :internal)
       post api("/projects/user/#{user.id}", admin), project
-      json_response['public'].should be_false
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL
+      expect(json_response['public']).to be_falsey
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
     end
 
-    it "should set a project as internal overriding :public" do
+    it 'should set a project as internal overriding :public' do
       project = attributes_for(:project, :internal, { public: true })
       post api("/projects/user/#{user.id}", admin), project
-      json_response['public'].should be_false
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL
+      expect(json_response['public']).to be_falsey
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL)
     end
 
-    it "should set a project as private" do
+    it 'should set a project as private' do
       project = attributes_for(:project, :private)
       post api("/projects/user/#{user.id}", admin), project
-      json_response['public'].should be_false
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::PRIVATE
+      expect(json_response['public']).to be_falsey
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
     end
 
-    it "should set a project as private using :public" do
+    it 'should set a project as private using :public' do
       project = attributes_for(:project, { public: false })
       post api("/projects/user/#{user.id}", admin), project
-      json_response['public'].should be_false
-      json_response['visibility_level'].should == Gitlab::VisibilityLevel::PRIVATE
+      expect(json_response['public']).to be_falsey
+      expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE)
     end
   end
 
-  describe "GET /projects/:id" do
+  describe 'GET /projects/:id' do
     before { project }
     before { project_member }
 
-    it "should return a project by id" do
+    it 'should return a project by id' do
       get api("/projects/#{project.id}", user)
-      response.status.should == 200
-      json_response['name'].should == project.name
-      json_response['owner']['username'].should == user.username
+      expect(response.status).to eq(200)
+      expect(json_response['name']).to eq(project.name)
+      expect(json_response['owner']['username']).to eq(user.username)
     end
 
-    it "should return a project by path name" do
+    it 'should return a project by path name' do
       get api("/projects/#{project.id}", user)
-      response.status.should == 200
-      json_response['name'].should == project.name
+      expect(response.status).to eq(200)
+      expect(json_response['name']).to eq(project.name)
     end
 
-    it "should return a 404 error if not found" do
-      get api("/projects/42", user)
-      response.status.should == 404
-      json_response['message'].should == '404 Not Found'
+    it 'should return a 404 error if not found' do
+      get api('/projects/42', user)
+      expect(response.status).to eq(404)
+      expect(json_response['message']).to eq('404 Project Not Found')
     end
 
-    it "should return a 404 error if user is not a member" do
+    it 'should return a 404 error if user is not a member' do
       other_user = create(:user)
       get api("/projects/#{project.id}", other_user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
 
     describe 'permissions' do
       context 'personal project' do
-        before do
+        it 'Sets project access and returns 200' do
           project.team << [user, :master]
           get api("/projects/#{project.id}", user)
-        end
 
-        it { response.status.should == 200 }
-        it { json_response['permissions']["project_access"]["access_level"].should == Gitlab::Access::MASTER }
-        it { json_response['permissions']["group_access"].should be_nil }
+          expect(response.status).to eq(200)
+          expect(json_response['permissions']['project_access']['access_level']).
+            to eq(Gitlab::Access::MASTER)
+          expect(json_response['permissions']['group_access']).to be_nil
+        end
       end
 
       context 'group project' do
-        before do
+        it 'should set the owner and return 200' do
           project2 = create(:project, group: create(:group))
           project2.group.add_owner(user)
           get api("/projects/#{project2.id}", user)
-        end
 
-        it { response.status.should == 200 }
-        it { json_response['permissions']["project_access"].should be_nil }
-        it { json_response['permissions']["group_access"]["access_level"].should == Gitlab::Access::OWNER }
+          expect(response.status).to eq(200)
+          expect(json_response['permissions']['project_access']).to be_nil
+          expect(json_response['permissions']['group_access']['access_level']).
+            to eq(Gitlab::Access::OWNER)
+        end
       end
     end
   end
 
-  describe "GET /projects/:id/events" do
-    before { project_member }
+  describe 'GET /projects/:id/events' do
+    before { project_member2 }
 
-    it "should return a project events" do
+    it 'should return a project events' do
       get api("/projects/#{project.id}/events", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
       json_event = json_response.first
 
-      json_event['action_name'].should == 'joined'
-      json_event['project_id'].to_i.should == project.id
-      json_event['author_username'].should == user.username
+      expect(json_event['action_name']).to eq('joined')
+      expect(json_event['project_id'].to_i).to eq(project.id)
+      expect(json_event['author_username']).to eq(user3.username)
     end
 
-    it "should return a 404 error if not found" do
-      get api("/projects/42/events", user)
-      response.status.should == 404
-      json_response['message'].should == '404 Not Found'
+    it 'should return a 404 error if not found' do
+      get api('/projects/42/events', user)
+      expect(response.status).to eq(404)
+      expect(json_response['message']).to eq('404 Project Not Found')
     end
 
-    it "should return a 404 error if user is not a member" do
+    it 'should return a 404 error if user is not a member' do
       other_user = create(:user)
       get api("/projects/#{project.id}/events", other_user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
-  describe "GET /projects/:id/snippets" do
+  describe 'GET /projects/:id/snippets' do
     before { snippet }
 
-    it "should return an array of project snippets" do
+    it 'should return an array of project snippets' do
       get api("/projects/#{project.id}/snippets", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.first['title'].should == snippet.title
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.first['title']).to eq(snippet.title)
     end
   end
 
-  describe "GET /projects/:id/snippets/:snippet_id" do
-    it "should return a project snippet" do
+  describe 'GET /projects/:id/snippets/:snippet_id' do
+    it 'should return a project snippet' do
       get api("/projects/#{project.id}/snippets/#{snippet.id}", user)
-      response.status.should == 200
-      json_response['title'].should == snippet.title
+      expect(response.status).to eq(200)
+      expect(json_response['title']).to eq(snippet.title)
     end
 
-    it "should return a 404 error if snippet id not found" do
+    it 'should return a 404 error if snippet id not found' do
       get api("/projects/#{project.id}/snippets/1234", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
-  describe "POST /projects/:id/snippets" do
-    it "should create a new project snippet" do
+  describe 'POST /projects/:id/snippets' do
+    it 'should create a new project snippet' do
       post api("/projects/#{project.id}/snippets", user),
-        title: 'api test', file_name: 'sample.rb', code: 'test'
-      response.status.should == 201
-      json_response['title'].should == 'api test'
+        title: 'api test', file_name: 'sample.rb', code: 'test',
+        visibility_level: '0'
+      expect(response.status).to eq(201)
+      expect(json_response['title']).to eq('api test')
     end
 
-    it "should return a 400 error if title is not given" do
-      post api("/projects/#{project.id}/snippets", user),
-        file_name: 'sample.rb', code: 'test'
-      response.status.should == 400
-    end
-
-    it "should return a 400 error if file_name not given" do
-      post api("/projects/#{project.id}/snippets", user),
-        title: 'api test', code: 'test'
-      response.status.should == 400
-    end
-
-    it "should return a 400 error if code not given" do
-      post api("/projects/#{project.id}/snippets", user),
-        title: 'api test', file_name: 'sample.rb'
-      response.status.should == 400
+    it 'should return a 400 error if invalid snippet is given' do
+      post api("/projects/#{project.id}/snippets", user)
+      expect(status).to eq(400)
     end
   end
 
-  describe "PUT /projects/:id/snippets/:shippet_id" do
-    it "should update an existing project snippet" do
+  describe 'PUT /projects/:id/snippets/:shippet_id' do
+    it 'should update an existing project snippet' do
       put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
         code: 'updated code'
-      response.status.should == 200
-      json_response['title'].should == 'example'
-      snippet.reload.content.should == 'updated code'
+      expect(response.status).to eq(200)
+      expect(json_response['title']).to eq('example')
+      expect(snippet.reload.content).to eq('updated code')
     end
 
-    it "should update an existing project snippet with new title" do
+    it 'should update an existing project snippet with new title' do
       put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
         title: 'other api test'
-      response.status.should == 200
-      json_response['title'].should == 'other api test'
+      expect(response.status).to eq(200)
+      expect(json_response['title']).to eq('other api test')
     end
   end
 
-  describe "DELETE /projects/:id/snippets/:snippet_id" do
+  describe 'DELETE /projects/:id/snippets/:snippet_id' do
     before { snippet }
 
-    it "should delete existing project snippet" do
+    it 'should delete existing project snippet' do
       expect {
         delete api("/projects/#{project.id}/snippets/#{snippet.id}", user)
       }.to change { Snippet.count }.by(-1)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it 'should return 404 when deleting unknown snippet id' do
       delete api("/projects/#{project.id}/snippets/1234", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
-  describe "GET /projects/:id/snippets/:snippet_id/raw" do
-    it "should get a raw project snippet" do
+  describe 'GET /projects/:id/snippets/:snippet_id/raw' do
+    it 'should get a raw project snippet' do
       get api("/projects/#{project.id}/snippets/#{snippet.id}/raw", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
-    it "should return a 404 error if raw project snippet not found" do
+    it 'should return a 404 error if raw project snippet not found' do
       get api("/projects/#{project.id}/snippets/5555/raw", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
@@ -452,51 +486,51 @@ describe API::API, api: true  do
     let(:deploy_keys_project) { create(:deploy_keys_project, project: project) }
     let(:deploy_key) { deploy_keys_project.deploy_key }
 
-    describe "GET /projects/:id/keys" do
+    describe 'GET /projects/:id/keys' do
       before { deploy_key }
 
-      it "should return array of ssh keys" do
+      it 'should return array of ssh keys' do
         get api("/projects/#{project.id}/keys", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first['title'].should == deploy_key.title
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['title']).to eq(deploy_key.title)
       end
     end
 
-    describe "GET /projects/:id/keys/:key_id" do
-      it "should return a single key" do
+    describe 'GET /projects/:id/keys/:key_id' do
+      it 'should return a single key' do
         get api("/projects/#{project.id}/keys/#{deploy_key.id}", user)
-        response.status.should == 200
-        json_response['title'].should == deploy_key.title
+        expect(response.status).to eq(200)
+        expect(json_response['title']).to eq(deploy_key.title)
       end
 
-      it "should return 404 Not Found with invalid ID" do
+      it 'should return 404 Not Found with invalid ID' do
         get api("/projects/#{project.id}/keys/404", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
 
-    describe "POST /projects/:id/keys" do
-      it "should not create an invalid ssh key" do
-        post api("/projects/#{project.id}/keys", user), { title: "invalid key" }
-        response.status.should == 400
-        json_response['message']['key'].should == [
+    describe 'POST /projects/:id/keys' do
+      it 'should not create an invalid ssh key' do
+        post api("/projects/#{project.id}/keys", user), { title: 'invalid key' }
+        expect(response.status).to eq(400)
+        expect(json_response['message']['key']).to eq([
           'can\'t be blank',
           'is too short (minimum is 0 characters)',
           'is invalid'
-        ]
+        ])
       end
 
       it 'should not create a key without title' do
         post api("/projects/#{project.id}/keys", user), key: 'some key'
-        response.status.should == 400
-        json_response['message']['title'].should == [
+        expect(response.status).to eq(400)
+        expect(json_response['message']['title']).to eq([
           'can\'t be blank',
           'is too short (minimum is 0 characters)'
-        ]
+        ])
       end
 
-      it "should create new ssh key" do
+      it 'should create new ssh key' do
         key_attrs = attributes_for :key
         expect {
           post api("/projects/#{project.id}/keys", user), key_attrs
@@ -504,18 +538,18 @@ describe API::API, api: true  do
       end
     end
 
-    describe "DELETE /projects/:id/keys/:key_id" do
+    describe 'DELETE /projects/:id/keys/:key_id' do
       before { deploy_key }
 
-      it "should delete existing key" do
+      it 'should delete existing key' do
         expect {
           delete api("/projects/#{project.id}/keys/#{deploy_key.id}", user)
         }.to change{ project.deploy_keys.count }.by(-1)
       end
 
-      it "should return 404 Not Found with invalid ID" do
+      it 'should return 404 Not Found with invalid ID' do
         delete api("/projects/#{project.id}/keys/404", user)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
   end
@@ -524,70 +558,70 @@ describe API::API, api: true  do
     let(:project_fork_target) { create(:project) }
     let(:project_fork_source) { create(:project, :public) }
 
-    describe "POST /projects/:id/fork/:forked_from_id" do
+    describe 'POST /projects/:id/fork/:forked_from_id' do
       let(:new_project_fork_source) { create(:project, :public) }
 
       it "shouldn't available for non admin users" do
         post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
 
-      it "should allow project to be forked from an existing project" do
-        project_fork_target.forked?.should_not be_true
+      it 'should allow project to be forked from an existing project' do
+        expect(project_fork_target.forked?).not_to be_truthy
         post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
-        response.status.should == 201
+        expect(response.status).to eq(201)
         project_fork_target.reload
-        project_fork_target.forked_from_project.id.should == project_fork_source.id
-        project_fork_target.forked_project_link.should_not be_nil
-        project_fork_target.forked?.should be_true
+        expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
+        expect(project_fork_target.forked_project_link).not_to be_nil
+        expect(project_fork_target.forked?).to be_truthy
       end
 
-      it "should fail if forked_from project which does not exist" do
+      it 'should fail if forked_from project which does not exist' do
         post api("/projects/#{project_fork_target.id}/fork/9999", admin)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
 
-      it "should fail with 409 if already forked" do
+      it 'should fail with 409 if already forked' do
         post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
         project_fork_target.reload
-        project_fork_target.forked_from_project.id.should == project_fork_source.id
+        expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
         post api("/projects/#{project_fork_target.id}/fork/#{new_project_fork_source.id}", admin)
-        response.status.should == 409
+        expect(response.status).to eq(409)
         project_fork_target.reload
-        project_fork_target.forked_from_project.id.should == project_fork_source.id
-        project_fork_target.forked?.should be_true
+        expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
+        expect(project_fork_target.forked?).to be_truthy
       end
     end
 
-    describe "DELETE /projects/:id/fork" do
+    describe 'DELETE /projects/:id/fork' do
 
       it "shouldn't available for non admin users" do
         delete api("/projects/#{project_fork_target.id}/fork", user)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
 
-      it "should make forked project unforked" do
+      it 'should make forked project unforked' do
         post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
         project_fork_target.reload
-        project_fork_target.forked_from_project.should_not be_nil
-        project_fork_target.forked?.should be_true
+        expect(project_fork_target.forked_from_project).not_to be_nil
+        expect(project_fork_target.forked?).to be_truthy
         delete api("/projects/#{project_fork_target.id}/fork", admin)
-        response.status.should == 200
+        expect(response.status).to eq(200)
         project_fork_target.reload
-        project_fork_target.forked_from_project.should be_nil
-        project_fork_target.forked?.should_not be_true
+        expect(project_fork_target.forked_from_project).to be_nil
+        expect(project_fork_target.forked?).not_to be_truthy
       end
 
-      it "should be idempotent if not forked" do
-        project_fork_target.forked_from_project.should be_nil
+      it 'should be idempotent if not forked' do
+        expect(project_fork_target.forked_from_project).to be_nil
         delete api("/projects/#{project_fork_target.id}/fork", admin)
-        response.status.should == 200
-        project_fork_target.reload.forked_from_project.should be_nil
+        expect(response.status).to eq(200)
+        expect(project_fork_target.reload.forked_from_project).to be_nil
       end
     end
   end
 
-  describe "GET /projects/search/:query" do
+  describe 'GET /projects/search/:query' do
     let!(:query) { 'query'}
     let!(:search)           { create(:empty_project, name: query, creator_id: user.id, namespace: user.namespace) }
     let!(:pre)              { create(:empty_project, name: "pre_#{query}", creator_id: user.id, namespace: user.namespace) }
@@ -599,73 +633,185 @@ describe API::API, api: true  do
     let!(:public)           { create(:empty_project, :public, name: "public #{query}") }
     let!(:unfound_public)   { create(:empty_project, :public, name: 'unfound public') }
 
-    context "when unauthenticated" do
-      it "should return authentication error" do
+    context 'when unauthenticated' do
+      it 'should return authentication error' do
         get api("/projects/search/#{query}")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
-    context "when authenticated" do
-      it "should return an array of projects" do
+    context 'when authenticated' do
+      it 'should return an array of projects' do
         get api("/projects/search/#{query}",user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.size.should == 6
-        json_response.each {|project| project['name'].should =~ /.*query.*/}
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.size).to eq(6)
+        json_response.each {|project| expect(project['name']).to match(/.*query.*/)}
       end
     end
 
-    context "when authenticated as a different user" do
-      it "should return matching public projects" do
+    context 'when authenticated as a different user' do
+      it 'should return matching public projects' do
         get api("/projects/search/#{query}", user2)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.size.should == 2
-        json_response.each {|project| project['name'].should =~ /(internal|public) query/}
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.size).to eq(2)
+        json_response.each {|project| expect(project['name']).to match(/(internal|public) query/)}
+      end
+    end
+  end
+
+  describe 'PUT /projects/:id̈́' do
+    before { project }
+    before { user }
+    before { user3 }
+    before { user4 }
+    before { project3 }
+    before { project4 }
+    before { project_member3 }
+    before { project_member2 }
+
+    context 'when unauthenticated' do
+      it 'should return authentication error' do
+        project_param = { name: 'bar' }
+        put api("/projects/#{project.id}"), project_param
+        expect(response.status).to eq(401)
+      end
+    end
+
+    context 'when authenticated as project owner' do
+      it 'should update name' do
+        project_param = { name: 'bar' }
+        put api("/projects/#{project.id}", user), project_param
+        expect(response.status).to eq(200)
+        project_param.each_pair do |k, v|
+          expect(json_response[k.to_s]).to eq(v)
+        end
+      end
+
+      it 'should update visibility_level' do
+        project_param = { visibility_level: 20 }
+        put api("/projects/#{project3.id}", user), project_param
+        expect(response.status).to eq(200)
+        project_param.each_pair do |k, v|
+          expect(json_response[k.to_s]).to eq(v)
+        end
+      end
+
+      it 'should not update name to existing name' do
+        project_param = { name: project3.name }
+        put api("/projects/#{project.id}", user), project_param
+        expect(response.status).to eq(400)
+        expect(json_response['message']['name']).to eq(['has already been taken'])
+      end
+
+      it 'should update path & name to existing path & name in different namespace' do
+        project_param = { path: project4.path, name: project4.name }
+        put api("/projects/#{project3.id}", user), project_param
+        expect(response.status).to eq(200)
+        project_param.each_pair do |k, v|
+          expect(json_response[k.to_s]).to eq(v)
+        end
+      end
+    end
+
+    context 'when authenticated as project master' do
+      it 'should update path' do
+        project_param = { path: 'bar' }
+        put api("/projects/#{project3.id}", user4), project_param
+        expect(response.status).to eq(200)
+        project_param.each_pair do |k, v|
+          expect(json_response[k.to_s]).to eq(v)
+        end
+      end
+
+      it 'should update other attributes' do
+        project_param = { issues_enabled: true,
+                          wiki_enabled: true,
+                          snippets_enabled: true,
+                          merge_requests_enabled: true,
+                          description: 'new description' }
+
+        put api("/projects/#{project3.id}", user4), project_param
+        expect(response.status).to eq(200)
+        project_param.each_pair do |k, v|
+          expect(json_response[k.to_s]).to eq(v)
+        end
+      end
+
+      it 'should not update path to existing path' do
+        project_param = { path: project.path }
+        put api("/projects/#{project3.id}", user4), project_param
+        expect(response.status).to eq(400)
+        expect(json_response['message']['path']).to eq(['has already been taken'])
+      end
+
+      it 'should not update name' do
+        project_param = { name: 'bar' }
+        put api("/projects/#{project3.id}", user4), project_param
+        expect(response.status).to eq(403)
+      end
+
+      it 'should not update visibility_level' do
+        project_param = { visibility_level: 20 }
+        put api("/projects/#{project3.id}", user4), project_param
+        expect(response.status).to eq(403)
+      end
+    end
+
+    context 'when authenticated as project developer' do
+      it 'should not update other attributes' do
+        project_param = { path: 'bar',
+                          issues_enabled: true,
+                          wiki_enabled: true,
+                          snippets_enabled: true,
+                          merge_requests_enabled: true,
+                          description: 'new description' }
+        put api("/projects/#{project.id}", user3), project_param
+        expect(response.status).to eq(403)
       end
     end
   end
 
-  describe "DELETE /projects/:id" do
-    context "when authenticated as user" do
-      it "should remove project" do
+  describe 'DELETE /projects/:id' do
+    context 'when authenticated as user' do
+      it 'should remove project' do
         expect(GitlabShellWorker).to(
           receive(:perform_async).with(:remove_repository,
                                        /#{project.path_with_namespace}/)
         ).twice
 
         delete api("/projects/#{project.id}", user)
-        response.status.should == 200
+        expect(response.status).to eq(200)
       end
 
-      it "should not remove a project if not an owner" do
+      it 'should not remove a project if not an owner' do
         user3 = create(:user)
         project.team << [user3, :developer]
         delete api("/projects/#{project.id}", user3)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
 
-      it "should not remove a non existing project" do
-        delete api("/projects/1328", user)
-        response.status.should == 404
+      it 'should not remove a non existing project' do
+        delete api('/projects/1328', user)
+        expect(response.status).to eq(404)
       end
 
-      it "should not remove a project not attached to user" do
+      it 'should not remove a project not attached to user' do
         delete api("/projects/#{project.id}", user2)
-        response.status.should == 404
+        expect(response.status).to eq(404)
       end
     end
 
-    context "when authenticated as admin" do
-      it "should remove any existing project" do
+    context 'when authenticated as admin' do
+      it 'should remove any existing project' do
         delete api("/projects/#{project.id}", admin)
-        response.status.should == 200
+        expect(response.status).to eq(200)
       end
 
-      it "should not remove a non existing project" do
-        delete api("/projects/1328", admin)
-        response.status.should == 404
+      it 'should not remove a non existing project' do
+        delete api('/projects/1328', admin)
+        expect(response.status).to eq(404)
       end
     end
   end
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index beae71c02d9343b5c73939f32205a62fc97c2ec5..729970153d1f196da09b54543095603f2b2dce71 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -16,9 +16,9 @@ describe API::API, api: true  do
   describe "GET /projects/:id/repository/tags" do
     it "should return an array of project tags" do
       get api("/projects/#{project.id}/repository/tags", user)
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.first['name'].should == project.repo.tags.sort_by(&:name).reverse.first.name
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+      expect(json_response.first['name']).to eq(project.repo.tags.sort_by(&:name).reverse.first.name)
     end
   end
 
@@ -29,8 +29,8 @@ describe API::API, api: true  do
              tag_name: 'v7.0.1',
              ref: 'master'
 
-        response.status.should == 201
-        json_response['name'].should == 'v7.0.1'
+        expect(response.status).to eq(201)
+        expect(json_response['name']).to eq('v7.0.1')
       end
     end
 
@@ -46,9 +46,9 @@ describe API::API, api: true  do
              ref: 'master',
              message: 'Release 7.1.0'
 
-        response.status.should == 201
-        json_response['name'].should == 'v7.1.0'
-        json_response['message'].should == 'Release 7.1.0'
+        expect(response.status).to eq(201)
+        expect(json_response['name']).to eq('v7.1.0')
+        expect(json_response['message']).to eq('Release 7.1.0')
       end
     end
 
@@ -56,35 +56,35 @@ describe API::API, api: true  do
       post api("/projects/#{project.id}/repository/tags", user2),
            tag_name: 'v1.9.0',
            ref: '621491c677087aa243f165eab467bfdfbee00be1'
-      response.status.should == 403
+      expect(response.status).to eq(403)
     end
 
     it 'should return 400 if tag name is invalid' do
       post api("/projects/#{project.id}/repository/tags", user),
            tag_name: 'v 1.0.0',
            ref: 'master'
-      response.status.should == 400
-      json_response['message'].should == 'Tag name invalid'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('Tag name invalid')
     end
 
     it 'should return 400 if tag already exists' do
       post api("/projects/#{project.id}/repository/tags", user),
            tag_name: 'v8.0.0',
            ref: 'master'
-      response.status.should == 201
+      expect(response.status).to eq(201)
       post api("/projects/#{project.id}/repository/tags", user),
            tag_name: 'v8.0.0',
            ref: 'master'
-      response.status.should == 400
-      json_response['message'].should == 'Tag already exists'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('Tag already exists')
     end
 
     it 'should return 400 if ref name is invalid' do
       post api("/projects/#{project.id}/repository/tags", user),
            tag_name: 'mytag',
            ref: 'foo'
-      response.status.should == 400
-      json_response['message'].should == 'Invalid reference name'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('Invalid reference name')
     end
   end
 
@@ -94,19 +94,27 @@ describe API::API, api: true  do
 
       it "should return project commits" do
         get api("/projects/#{project.id}/repository/tree", user)
-        response.status.should == 200
+        expect(response.status).to eq(200)
 
-        json_response.should be_an Array
-        json_response.first['name'].should == 'encoding'
-        json_response.first['type'].should == 'tree'
-        json_response.first['mode'].should == '040000'
+        expect(json_response).to be_an Array
+        expect(json_response.first['name']).to eq('encoding')
+        expect(json_response.first['type']).to eq('tree')
+        expect(json_response.first['mode']).to eq('040000')
+      end
+
+      it 'should return a 404 for unknown ref' do
+        get api("/projects/#{project.id}/repository/tree?ref_name=foo", user)
+        expect(response.status).to eq(404)
+
+        expect(json_response).to be_an Object
+        json_response['message'] == '404 Tree Not Found'
       end
     end
 
     context "unauthorized user" do
       it "should not return project commits" do
         get api("/projects/#{project.id}/repository/tree")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
   end
@@ -114,36 +122,44 @@ describe API::API, api: true  do
   describe "GET /projects/:id/repository/blobs/:sha" do
     it "should get the raw file contents" do
       get api("/projects/#{project.id}/repository/blobs/master?filepath=README.md", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it "should return 404 for invalid branch_name" do
       get api("/projects/#{project.id}/repository/blobs/invalid_branch_name?filepath=README.md", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
 
     it "should return 404 for invalid file" do
       get api("/projects/#{project.id}/repository/blobs/master?filepath=README.invalid", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
 
     it "should return a 400 error if filepath is missing" do
       get api("/projects/#{project.id}/repository/blobs/master", user)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
   end
 
   describe "GET /projects/:id/repository/commits/:sha/blob" do
     it "should get the raw file contents" do
       get api("/projects/#{project.id}/repository/commits/master/blob?filepath=README.md", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
   end
 
   describe "GET /projects/:id/repository/raw_blobs/:sha" do
     it "should get the raw file contents" do
       get api("/projects/#{project.id}/repository/raw_blobs/#{sample_blob.oid}", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
+    end
+
+    it 'should return a 404 for unknown blob' do
+      get api("/projects/#{project.id}/repository/raw_blobs/123456", user)
+      expect(response.status).to eq(404)
+
+      expect(json_response).to be_an Object
+      json_response['message'] == '404 Blob Not Found'
     end
   end
 
@@ -151,83 +167,83 @@ describe API::API, api: true  do
     it "should get the archive" do
       get api("/projects/#{project.id}/repository/archive", user)
       repo_name = project.repository.name.gsub("\.git", "")
-      response.status.should == 200
-      response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.tar.gz\"/
-      response.content_type.should == MIME::Types.type_for('file.tar.gz').first.content_type
+      expect(response.status).to eq(200)
+      expect(response.headers['Content-Disposition']).to match(/filename\=\"#{repo_name}\-[^\.]+\.tar.gz\"/)
+      expect(response.content_type).to eq(MIME::Types.type_for('file.tar.gz').first.content_type)
     end
 
     it "should get the archive.zip" do
       get api("/projects/#{project.id}/repository/archive.zip", user)
       repo_name = project.repository.name.gsub("\.git", "")
-      response.status.should == 200
-      response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.zip\"/
-      response.content_type.should == MIME::Types.type_for('file.zip').first.content_type
+      expect(response.status).to eq(200)
+      expect(response.headers['Content-Disposition']).to match(/filename\=\"#{repo_name}\-[^\.]+\.zip\"/)
+      expect(response.content_type).to eq(MIME::Types.type_for('file.zip').first.content_type)
     end
 
     it "should get the archive.tar.bz2" do
       get api("/projects/#{project.id}/repository/archive.tar.bz2", user)
       repo_name = project.repository.name.gsub("\.git", "")
-      response.status.should == 200
-      response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.tar.bz2\"/
-      response.content_type.should == MIME::Types.type_for('file.tar.bz2').first.content_type
+      expect(response.status).to eq(200)
+      expect(response.headers['Content-Disposition']).to match(/filename\=\"#{repo_name}\-[^\.]+\.tar.bz2\"/)
+      expect(response.content_type).to eq(MIME::Types.type_for('file.tar.bz2').first.content_type)
     end
 
     it "should return 404 for invalid sha" do
       get api("/projects/#{project.id}/repository/archive/?sha=xxx", user)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
   describe 'GET /projects/:id/repository/compare' do
     it "should compare branches" do
       get api("/projects/#{project.id}/repository/compare", user), from: 'master', to: 'feature'
-      response.status.should == 200
-      json_response['commits'].should be_present
-      json_response['diffs'].should be_present
+      expect(response.status).to eq(200)
+      expect(json_response['commits']).to be_present
+      expect(json_response['diffs']).to be_present
     end
 
     it "should compare tags" do
       get api("/projects/#{project.id}/repository/compare", user), from: 'v1.0.0', to: 'v1.1.0'
-      response.status.should == 200
-      json_response['commits'].should be_present
-      json_response['diffs'].should be_present
+      expect(response.status).to eq(200)
+      expect(json_response['commits']).to be_present
+      expect(json_response['diffs']).to be_present
     end
 
     it "should compare commits" do
       get api("/projects/#{project.id}/repository/compare", user), from: sample_commit.id, to: sample_commit.parent_id
-      response.status.should == 200
-      json_response['commits'].should be_empty
-      json_response['diffs'].should be_empty
-      json_response['compare_same_ref'].should be_false
+      expect(response.status).to eq(200)
+      expect(json_response['commits']).to be_empty
+      expect(json_response['diffs']).to be_empty
+      expect(json_response['compare_same_ref']).to be_falsey
     end
 
     it "should compare commits in reverse order" do
       get api("/projects/#{project.id}/repository/compare", user), from: sample_commit.parent_id, to: sample_commit.id
-      response.status.should == 200
-      json_response['commits'].should be_present
-      json_response['diffs'].should be_present
+      expect(response.status).to eq(200)
+      expect(json_response['commits']).to be_present
+      expect(json_response['diffs']).to be_present
     end
 
     it "should compare same refs" do
       get api("/projects/#{project.id}/repository/compare", user), from: 'master', to: 'master'
-      response.status.should == 200
-      json_response['commits'].should be_empty
-      json_response['diffs'].should be_empty
-      json_response['compare_same_ref'].should be_true
+      expect(response.status).to eq(200)
+      expect(json_response['commits']).to be_empty
+      expect(json_response['diffs']).to be_empty
+      expect(json_response['compare_same_ref']).to be_truthy
     end
   end
 
   describe 'GET /projects/:id/repository/contributors' do
     it 'should return valid data' do
       get api("/projects/#{project.id}/repository/contributors", user)
-      response.status.should == 200
-      json_response.should be_an Array
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
       contributor = json_response.first
-      contributor['email'].should == 'dmitriy.zaporozhets@gmail.com'
-      contributor['name'].should == 'Dmitriy Zaporozhets'
-      contributor['commits'].should == 13
-      contributor['additions'].should == 0
-      contributor['deletions'].should == 0
+      expect(contributor['email']).to eq('dmitriy.zaporozhets@gmail.com')
+      expect(contributor['name']).to eq('Dmitriy Zaporozhets')
+      expect(contributor['commits']).to eq(13)
+      expect(contributor['additions']).to eq(0)
+      expect(contributor['deletions']).to eq(0)
     end
   end
 end
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index d8282d0696bd92fda584150692deaf2bfd938747..51c543578df747fec3bb0a5e5d3a7103248137a5 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -9,13 +9,13 @@ describe API::API, api: true  do
     it "should update gitlab-ci settings" do
       put api("/projects/#{project.id}/services/gitlab-ci", user), token: 'secret-token', project_url: "http://ci.example.com/projects/1"
 
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it "should return if required fields missing" do
       put api("/projects/#{project.id}/services/gitlab-ci", user), project_url: "http://ci.example.com/projects/1", active: true
 
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
   end
 
@@ -23,8 +23,8 @@ describe API::API, api: true  do
     it "should update gitlab-ci settings" do
       delete api("/projects/#{project.id}/services/gitlab-ci", user)
 
-      response.status.should == 200
-      project.gitlab_ci_service.should be_nil
+      expect(response.status).to eq(200)
+      expect(project.gitlab_ci_service).to be_nil
     end
   end
 
@@ -33,15 +33,15 @@ describe API::API, api: true  do
       put api("/projects/#{project.id}/services/hipchat", user),
           token: 'secret-token', room: 'test'
 
-      response.status.should == 200
-      project.hipchat_service.should_not be_nil
+      expect(response.status).to eq(200)
+      expect(project.hipchat_service).not_to be_nil
     end
 
     it 'should return if required fields missing' do
       put api("/projects/#{project.id}/services/gitlab-ci", user),
           token: 'secret-token', active: true
 
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
   end
 
@@ -49,8 +49,8 @@ describe API::API, api: true  do
     it 'should delete hipchat settings' do
       delete api("/projects/#{project.id}/services/hipchat", user)
 
-      response.status.should == 200
-      project.hipchat_service.should be_nil
+      expect(response.status).to eq(200)
+      expect(project.hipchat_service).to be_nil
     end
   end
 end
diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb
index 57b2e6cbd6abcd12b815c260481acb4ef1dd15b1..fbd57b34a58d32308e969cdddf4b7b681011b645 100644
--- a/spec/requests/api/session_spec.rb
+++ b/spec/requests/api/session_spec.rb
@@ -9,13 +9,13 @@ describe API::API, api: true  do
     context "when valid password" do
       it "should return private token" do
         post api("/session"), email: user.email, password: '12345678'
-        response.status.should == 201
+        expect(response.status).to eq(201)
 
-        json_response['email'].should == user.email
-        json_response['private_token'].should == user.private_token
-        json_response['is_admin'].should == user.is_admin?
-        json_response['can_create_project'].should == user.can_create_project?
-        json_response['can_create_group'].should == user.can_create_group?
+        expect(json_response['email']).to eq(user.email)
+        expect(json_response['private_token']).to eq(user.private_token)
+        expect(json_response['is_admin']).to eq(user.is_admin?)
+        expect(json_response['can_create_project']).to eq(user.can_create_project?)
+        expect(json_response['can_create_group']).to eq(user.can_create_group?)
       end
     end
 
@@ -48,30 +48,30 @@ describe API::API, api: true  do
     context "when invalid password" do
       it "should return authentication error" do
         post api("/session"), email: user.email, password: '123'
-        response.status.should == 401
+        expect(response.status).to eq(401)
 
-        json_response['email'].should be_nil
-        json_response['private_token'].should be_nil
+        expect(json_response['email']).to be_nil
+        expect(json_response['private_token']).to be_nil
       end
     end
 
     context "when empty password" do
       it "should return authentication error" do
         post api("/session"), email: user.email
-        response.status.should == 401
+        expect(response.status).to eq(401)
 
-        json_response['email'].should be_nil
-        json_response['private_token'].should be_nil
+        expect(json_response['email']).to be_nil
+        expect(json_response['private_token']).to be_nil
       end
     end
 
     context "when empty name" do
       it "should return authentication error" do
         post api("/session"), password: user.password
-        response.status.should == 401
+        expect(response.status).to eq(401)
 
-        json_response['email'].should be_nil
-        json_response['private_token'].should be_nil
+        expect(json_response['email']).to be_nil
+        expect(json_response['private_token']).to be_nil
       end
     end
   end
diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb
index 5784ae8c23a65f55cacaeef0bb30066e8b4fe4eb..a9d86bbce6c9165d715cecd235be557d27f5519a 100644
--- a/spec/requests/api/system_hooks_spec.rb
+++ b/spec/requests/api/system_hooks_spec.rb
@@ -13,23 +13,23 @@ describe API::API, api: true  do
     context "when no user" do
       it "should return authentication error" do
         get api("/hooks")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
     context "when not an admin" do
       it "should return forbidden error" do
         get api("/hooks", user)
-        response.status.should == 403
+        expect(response.status).to eq(403)
       end
     end
 
     context "when authenticated as admin" do
       it "should return an array of hooks" do
         get api("/hooks", admin)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first['url'].should == hook.url
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['url']).to eq(hook.url)
       end
     end
   end
@@ -43,7 +43,7 @@ describe API::API, api: true  do
 
     it "should respond with 400 if url not given" do
       post api("/hooks", admin)
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should not create new hook without url" do
@@ -56,13 +56,13 @@ describe API::API, api: true  do
   describe "GET /hooks/:id" do
     it "should return hook by id" do
       get api("/hooks/#{hook.id}", admin)
-      response.status.should == 200
-      json_response['event_name'].should == 'project_create'
+      expect(response.status).to eq(200)
+      expect(json_response['event_name']).to eq('project_create')
     end
 
     it "should return 404 on failure" do
       get api("/hooks/404", admin)
-      response.status.should == 404
+      expect(response.status).to eq(404)
     end
   end
 
@@ -75,7 +75,7 @@ describe API::API, api: true  do
 
     it "should return success if hook id not found" do
       delete api("/hooks/12345", admin)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
   end
 end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 113a39b870ed9e5e85d293a51458ef1426650a5f..081400cdedda826ca3c1d1b69c6a861493a3a992 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -11,30 +11,30 @@ describe API::API, api: true  do
     context "when unauthenticated" do
       it "should return authentication error" do
         get api("/users")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
     context "when authenticated" do
       it "should return an array of users" do
         get api("/users", user)
-        response.status.should == 200
-        json_response.should be_an Array
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
         username = user.username
-        json_response.detect {
+        expect(json_response.detect {
           |user| user['username'] == username
-          }['username'].should == username
+          }['username']).to eq(username)
       end
     end
 
     context "when admin" do
       it "should return an array of users" do
         get api("/users", admin)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first.keys.should include 'email'
-        json_response.first.keys.should include 'extern_uid'
-        json_response.first.keys.should include 'can_create_project'
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first.keys).to include 'email'
+        expect(json_response.first.keys).to include 'identities'
+        expect(json_response.first.keys).to include 'can_create_project'
       end
     end
   end
@@ -42,19 +42,19 @@ describe API::API, api: true  do
   describe "GET /users/:id" do
     it "should return a user by id" do
       get api("/users/#{user.id}", user)
-      response.status.should == 200
-      json_response['username'].should == user.username
+      expect(response.status).to eq(200)
+      expect(json_response['username']).to eq(user.username)
     end
 
     it "should return a 401 if unauthenticated" do
       get api("/users/9998")
-      response.status.should == 401
+      expect(response.status).to eq(401)
     end
 
     it "should return a 404 error if user id not found" do
       get api("/users/9999", user)
-      response.status.should == 404
-      json_response['message'].should == '404 Not found'
+      expect(response.status).to eq(404)
+      expect(json_response['message']).to eq('404 Not found')
     end
   end
 
@@ -69,36 +69,36 @@ describe API::API, api: true  do
 
     it "should create user with correct attributes" do
       post api('/users', admin), attributes_for(:user, admin: true, can_create_group: true)
-      response.status.should == 201
+      expect(response.status).to eq(201)
       user_id = json_response['id']
       new_user = User.find(user_id)
-      new_user.should_not == nil
-      new_user.admin.should == true
-      new_user.can_create_group.should == true
+      expect(new_user).not_to eq(nil)
+      expect(new_user.admin).to eq(true)
+      expect(new_user.can_create_group).to eq(true)
     end
 
     it "should create non-admin user" do
       post api('/users', admin), attributes_for(:user, admin: false, can_create_group: false)
-      response.status.should == 201
+      expect(response.status).to eq(201)
       user_id = json_response['id']
       new_user = User.find(user_id)
-      new_user.should_not == nil
-      new_user.admin.should == false
-      new_user.can_create_group.should == false
+      expect(new_user).not_to eq(nil)
+      expect(new_user.admin).to eq(false)
+      expect(new_user.can_create_group).to eq(false)
     end
 
     it "should create non-admin users by default" do
       post api('/users', admin), attributes_for(:user)
-      response.status.should == 201
+      expect(response.status).to eq(201)
       user_id = json_response['id']
       new_user = User.find(user_id)
-      new_user.should_not == nil
-      new_user.admin.should == false
+      expect(new_user).not_to eq(nil)
+      expect(new_user.admin).to eq(false)
     end
 
     it "should return 201 Created on success" do
       post api("/users", admin), attributes_for(:user, projects_limit: 3)
-      response.status.should == 201
+      expect(response.status).to eq(201)
     end
 
     it "should not create user with invalid email" do
@@ -106,22 +106,22 @@ describe API::API, api: true  do
            email: 'invalid email',
            password: 'password',
            name: 'test'
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it 'should return 400 error if name not given' do
       post api('/users', admin), email: 'test@example.com', password: 'pass1234'
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it 'should return 400 error if password not given' do
       post api('/users', admin), email: 'test@example.com', name: 'test'
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it "should return 400 error if email not given" do
       post api('/users', admin), password: 'pass1234', name: 'test'
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
 
     it 'should return 400 error if user does not validate' do
@@ -132,20 +132,20 @@ describe API::API, api: true  do
            name: 'test',
            bio: 'g' * 256,
            projects_limit: -1
-      response.status.should == 400
-      json_response['message']['password'].
-          should == ['is too short (minimum is 8 characters)']
-      json_response['message']['bio'].
-          should == ['is too long (maximum is 255 characters)']
-      json_response['message']['projects_limit'].
-          should == ['must be greater than or equal to 0']
-      json_response['message']['username'].
-          should == [Gitlab::Regex.send(:default_regex_message)]
+      expect(response.status).to eq(400)
+      expect(json_response['message']['password']).
+          to eq(['is too short (minimum is 8 characters)'])
+      expect(json_response['message']['bio']).
+          to eq(['is too long (maximum is 255 characters)'])
+      expect(json_response['message']['projects_limit']).
+          to eq(['must be greater than or equal to 0'])
+      expect(json_response['message']['username']).
+          to eq([Gitlab::Regex.send(:default_regex_message)])
     end
 
     it "shouldn't available for non admin users" do
       post api("/users", user), attributes_for(:user)
-      response.status.should == 403
+      expect(response.status).to eq(403)
     end
 
     context 'with existing user' do
@@ -165,8 +165,8 @@ describe API::API, api: true  do
                password: 'password',
                username: 'foo'
         }.to change { User.count }.by(0)
-        response.status.should == 409
-        json_response['message'].should == 'Email has already been taken'
+        expect(response.status).to eq(409)
+        expect(json_response['message']).to eq('Email has already been taken')
       end
 
       it 'should return 409 conflict error if same username exists' do
@@ -177,34 +177,18 @@ describe API::API, api: true  do
                password: 'password',
                username: 'test'
         end.to change { User.count }.by(0)
-        response.status.should == 409
-        json_response['message'].should == 'Username has already been taken'
+        expect(response.status).to eq(409)
+        expect(json_response['message']).to eq('Username has already been taken')
       end
     end
   end
 
   describe "GET /users/sign_up" do
-    context 'enabled' do
-      before do
-        Gitlab.config.gitlab.stub(:signup_enabled).and_return(true)
-      end
-
-      it "should return sign up page if signup is enabled" do
-        get "/users/sign_up"
-        response.status.should == 200
-      end
-    end
 
-    context 'disabled' do
-      before do
-        Gitlab.config.gitlab.stub(:signup_enabled).and_return(false)
-      end
-
-      it "should redirect to sign in page if signup is disabled" do
-        get "/users/sign_up"
-        response.status.should == 302
-        response.should redirect_to(new_user_session_path)
-      end
+    it "should redirect to sign in page" do
+      get "/users/sign_up"
+      expect(response.status).to eq(302)
+      expect(response).to redirect_to(new_user_session_path)
     end
   end
 
@@ -215,55 +199,55 @@ describe API::API, api: true  do
 
     it "should update user with new bio" do
       put api("/users/#{user.id}", admin), {bio: 'new test bio'}
-      response.status.should == 200
-      json_response['bio'].should == 'new test bio'
-      user.reload.bio.should == 'new test bio'
+      expect(response.status).to eq(200)
+      expect(json_response['bio']).to eq('new test bio')
+      expect(user.reload.bio).to eq('new test bio')
     end
 
     it 'should update user with his own email' do
       put api("/users/#{user.id}", admin), email: user.email
-      response.status.should == 200
-      json_response['email'].should == user.email
-      user.reload.email.should == user.email
+      expect(response.status).to eq(200)
+      expect(json_response['email']).to eq(user.email)
+      expect(user.reload.email).to eq(user.email)
     end
 
     it 'should update user with his own username' do
       put api("/users/#{user.id}", admin), username: user.username
-      response.status.should == 200
-      json_response['username'].should == user.username
-      user.reload.username.should == user.username
+      expect(response.status).to eq(200)
+      expect(json_response['username']).to eq(user.username)
+      expect(user.reload.username).to eq(user.username)
     end
 
     it "should update admin status" do
       put api("/users/#{user.id}", admin), {admin: true}
-      response.status.should == 200
-      json_response['is_admin'].should == true
-      user.reload.admin.should == true
+      expect(response.status).to eq(200)
+      expect(json_response['is_admin']).to eq(true)
+      expect(user.reload.admin).to eq(true)
     end
 
     it "should not update admin status" do
       put api("/users/#{admin_user.id}", admin), {can_create_group: false}
-      response.status.should == 200
-      json_response['is_admin'].should == true
-      admin_user.reload.admin.should == true
-      admin_user.can_create_group.should == false
+      expect(response.status).to eq(200)
+      expect(json_response['is_admin']).to eq(true)
+      expect(admin_user.reload.admin).to eq(true)
+      expect(admin_user.can_create_group).to eq(false)
     end
 
     it "should not allow invalid update" do
       put api("/users/#{user.id}", admin), {email: 'invalid email'}
-      response.status.should == 400
-      user.reload.email.should_not == 'invalid email'
+      expect(response.status).to eq(400)
+      expect(user.reload.email).not_to eq('invalid email')
     end
 
     it "shouldn't available for non admin users" do
       put api("/users/#{user.id}", user), attributes_for(:user)
-      response.status.should == 403
+      expect(response.status).to eq(403)
     end
 
     it "should return 404 for non-existing user" do
       put api("/users/999999", admin), {bio: 'update should fail'}
-      response.status.should == 404
-      json_response['message'].should == '404 Not found'
+      expect(response.status).to eq(404)
+      expect(json_response['message']).to eq('404 Not found')
     end
 
     it 'should return 400 error if user does not validate' do
@@ -274,15 +258,15 @@ describe API::API, api: true  do
           name: 'test',
           bio: 'g' * 256,
           projects_limit: -1
-      response.status.should == 400
-      json_response['message']['password'].
-          should == ['is too short (minimum is 8 characters)']
-      json_response['message']['bio'].
-          should == ['is too long (maximum is 255 characters)']
-      json_response['message']['projects_limit'].
-          should == ['must be greater than or equal to 0']
-      json_response['message']['username'].
-          should == [Gitlab::Regex.send(:default_regex_message)]
+      expect(response.status).to eq(400)
+      expect(json_response['message']['password']).
+          to eq(['is too short (minimum is 8 characters)'])
+      expect(json_response['message']['bio']).
+          to eq(['is too long (maximum is 255 characters)'])
+      expect(json_response['message']['projects_limit']).
+          to eq(['must be greater than or equal to 0'])
+      expect(json_response['message']['username']).
+          to eq([Gitlab::Regex.send(:default_regex_message)])
     end
 
     context "with existing user" do
@@ -294,15 +278,15 @@ describe API::API, api: true  do
 
       it 'should return 409 conflict error if email address exists' do
         put api("/users/#{@user.id}", admin), email: 'test@example.com'
-        response.status.should == 409
-        @user.reload.email.should == @user.email
+        expect(response.status).to eq(409)
+        expect(@user.reload.email).to eq(@user.email)
       end
 
       it 'should return 409 conflict error if username taken' do
         @user_id = User.all.last.id
         put api("/users/#{@user.id}", admin), username: 'test'
-        response.status.should == 409
-        @user.reload.username.should == @user.username
+        expect(response.status).to eq(409)
+        expect(@user.reload.username).to eq(@user.username)
       end
     end
   end
@@ -312,14 +296,14 @@ describe API::API, api: true  do
 
     it "should not create invalid ssh key" do
       post api("/users/#{user.id}/keys", admin), { title: "invalid key" }
-      response.status.should == 400
-      json_response['message'].should == '400 (Bad request) "key" not given'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('400 (Bad request) "key" not given')
     end
 
     it 'should not create key without title' do
       post api("/users/#{user.id}/keys", admin), key: 'some key'
-      response.status.should == 400
-      json_response['message'].should == '400 (Bad request) "title" not given'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('400 (Bad request) "title" not given')
     end
 
     it "should create ssh key" do
@@ -336,24 +320,24 @@ describe API::API, api: true  do
     context 'when unauthenticated' do
       it 'should return authentication error' do
         get api("/users/#{user.id}/keys")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
     context 'when authenticated' do
       it 'should return 404 for non-existing user' do
         get api('/users/999999/keys', admin)
-        response.status.should == 404
-        json_response['message'].should == '404 User Not Found'
+        expect(response.status).to eq(404)
+        expect(json_response['message']).to eq('404 User Not Found')
       end
 
       it 'should return array of ssh keys' do
         user.keys << key
         user.save
         get api("/users/#{user.id}/keys", admin)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first['title'].should == key.title
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['title']).to eq(key.title)
       end
     end
   end
@@ -364,7 +348,7 @@ describe API::API, api: true  do
     context 'when unauthenticated' do
       it 'should return authentication error' do
         delete api("/users/#{user.id}/keys/42")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
@@ -375,21 +359,21 @@ describe API::API, api: true  do
         expect {
           delete api("/users/#{user.id}/keys/#{key.id}", admin)
         }.to change { user.keys.count }.by(-1)
-        response.status.should == 200
+        expect(response.status).to eq(200)
       end
 
       it 'should return 404 error if user not found' do
         user.keys << key
         user.save
         delete api("/users/999999/keys/#{key.id}", admin)
-        response.status.should == 404
-        json_response['message'].should == '404 User Not Found'
+        expect(response.status).to eq(404)
+        expect(json_response['message']).to eq('404 User Not Found')
       end
 
       it 'should return 404 error if key not foud' do
         delete api("/users/#{user.id}/keys/42", admin)
-        response.status.should == 404
-        json_response['message'].should == '404 Key Not Found'
+        expect(response.status).to eq(404)
+        expect(json_response['message']).to eq('404 Key Not Found')
       end
     end
   end
@@ -399,42 +383,42 @@ describe API::API, api: true  do
 
     it "should delete user" do
       delete api("/users/#{user.id}", admin)
-      response.status.should == 200
+      expect(response.status).to eq(200)
       expect { User.find(user.id) }.to raise_error ActiveRecord::RecordNotFound
-      json_response['email'].should == user.email
+      expect(json_response['email']).to eq(user.email)
     end
 
     it "should not delete for unauthenticated user" do
       delete api("/users/#{user.id}")
-      response.status.should == 401
+      expect(response.status).to eq(401)
     end
 
     it "shouldn't available for non admin users" do
       delete api("/users/#{user.id}", user)
-      response.status.should == 403
+      expect(response.status).to eq(403)
     end
 
     it "should return 404 for non-existing user" do
       delete api("/users/999999", admin)
-      response.status.should == 404
-      json_response['message'].should == '404 User Not Found'
+      expect(response.status).to eq(404)
+      expect(json_response['message']).to eq('404 User Not Found')
     end
   end
 
   describe "GET /user" do
     it "should return current user" do
       get api("/user", user)
-      response.status.should == 200
-      json_response['email'].should == user.email
-      json_response['is_admin'].should == user.is_admin?
-      json_response['can_create_project'].should == user.can_create_project?
-      json_response['can_create_group'].should == user.can_create_group?
-      json_response['projects_limit'].should == user.projects_limit
+      expect(response.status).to eq(200)
+      expect(json_response['email']).to eq(user.email)
+      expect(json_response['is_admin']).to eq(user.is_admin?)
+      expect(json_response['can_create_project']).to eq(user.can_create_project?)
+      expect(json_response['can_create_group']).to eq(user.can_create_group?)
+      expect(json_response['projects_limit']).to eq(user.projects_limit)
     end
 
     it "should return 401 error if user is unauthenticated" do
       get api("/user")
-      response.status.should == 401
+      expect(response.status).to eq(401)
     end
   end
 
@@ -442,7 +426,7 @@ describe API::API, api: true  do
     context "when unauthenticated" do
       it "should return authentication error" do
         get api("/user/keys")
-        response.status.should == 401
+        expect(response.status).to eq(401)
       end
     end
 
@@ -451,9 +435,9 @@ describe API::API, api: true  do
         user.keys << key
         user.save
         get api("/user/keys", user)
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first["title"].should == key.title
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first["title"]).to eq(key.title)
       end
     end
   end
@@ -463,14 +447,14 @@ describe API::API, api: true  do
       user.keys << key
       user.save
       get api("/user/keys/#{key.id}", user)
-      response.status.should == 200
-      json_response["title"].should == key.title
+      expect(response.status).to eq(200)
+      expect(json_response["title"]).to eq(key.title)
     end
 
     it "should return 404 Not Found within invalid ID" do
       get api("/user/keys/42", user)
-      response.status.should == 404
-      json_response['message'].should == '404 Not found'
+      expect(response.status).to eq(404)
+      expect(json_response['message']).to eq('404 Not found')
     end
 
     it "should return 404 error if admin accesses user's ssh key" do
@@ -478,8 +462,8 @@ describe API::API, api: true  do
       user.save
       admin
       get api("/user/keys/#{key.id}", admin)
-      response.status.should == 404
-      json_response['message'].should == '404 Not found'
+      expect(response.status).to eq(404)
+      expect(json_response['message']).to eq('404 Not found')
     end
   end
 
@@ -489,29 +473,29 @@ describe API::API, api: true  do
       expect {
         post api("/user/keys", user), key_attrs
       }.to change{ user.keys.count }.by(1)
-      response.status.should == 201
+      expect(response.status).to eq(201)
     end
 
     it "should return a 401 error if unauthorized" do
       post api("/user/keys"), title: 'some title', key: 'some key'
-      response.status.should == 401
+      expect(response.status).to eq(401)
     end
 
     it "should not create ssh key without key" do
       post api("/user/keys", user), title: 'title'
-      response.status.should == 400
-      json_response['message'].should == '400 (Bad request) "key" not given'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('400 (Bad request) "key" not given')
     end
 
     it 'should not create ssh key without title' do
       post api('/user/keys', user), key: 'some key'
-      response.status.should == 400
-      json_response['message'].should == '400 (Bad request) "title" not given'
+      expect(response.status).to eq(400)
+      expect(json_response['message']).to eq('400 (Bad request) "title" not given')
     end
 
     it "should not create ssh key without title" do
       post api("/user/keys", user), key: "somekey"
-      response.status.should == 400
+      expect(response.status).to eq(400)
     end
   end
 
@@ -522,19 +506,19 @@ describe API::API, api: true  do
       expect {
         delete api("/user/keys/#{key.id}", user)
       }.to change{user.keys.count}.by(-1)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it "should return success if key ID not found" do
       delete api("/user/keys/42", user)
-      response.status.should == 200
+      expect(response.status).to eq(200)
     end
 
     it "should return 401 error if unauthorized" do
       user.keys << key
       user.save
       delete api("/user/keys/#{key.id}")
-      response.status.should == 401
+      expect(response.status).to eq(401)
     end
   end
 end
diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb
index 7fe18ff47c3d1d93b59128821e360aa6c5f206a1..bf8abcfb00f86ba4293748f0a5e232c82357ff6e 100644
--- a/spec/routing/admin_routing_spec.rb
+++ b/spec/routing/admin_routing_spec.rb
@@ -12,47 +12,47 @@ require 'spec_helper'
 #                        DELETE /admin/users/:id(.:format)             admin/users#destroy
 describe Admin::UsersController, "routing" do
   it "to #team_update" do
-    put("/admin/users/1/team_update").should route_to('admin/users#team_update', id: '1')
+    expect(put("/admin/users/1/team_update")).to route_to('admin/users#team_update', id: '1')
   end
 
   it "to #block" do
-    put("/admin/users/1/block").should route_to('admin/users#block', id: '1')
+    expect(put("/admin/users/1/block")).to route_to('admin/users#block', id: '1')
   end
 
   it "to #unblock" do
-    put("/admin/users/1/unblock").should route_to('admin/users#unblock', id: '1')
+    expect(put("/admin/users/1/unblock")).to route_to('admin/users#unblock', id: '1')
   end
 
   it "to #index" do
-    get("/admin/users").should route_to('admin/users#index')
+    expect(get("/admin/users")).to route_to('admin/users#index')
   end
 
   it "to #show" do
-    get("/admin/users/1").should route_to('admin/users#show', id: '1')
+    expect(get("/admin/users/1")).to route_to('admin/users#show', id: '1')
   end
 
   it "to #create" do
-    post("/admin/users").should route_to('admin/users#create')
+    expect(post("/admin/users")).to route_to('admin/users#create')
   end
 
   it "to #new" do
-    get("/admin/users/new").should route_to('admin/users#new')
+    expect(get("/admin/users/new")).to route_to('admin/users#new')
   end
 
   it "to #edit" do
-    get("/admin/users/1/edit").should route_to('admin/users#edit', id: '1')
+    expect(get("/admin/users/1/edit")).to route_to('admin/users#edit', id: '1')
   end
 
   it "to #show" do
-    get("/admin/users/1").should route_to('admin/users#show', id: '1')
+    expect(get("/admin/users/1")).to route_to('admin/users#show', id: '1')
   end
 
   it "to #update" do
-    put("/admin/users/1").should route_to('admin/users#update', id: '1')
+    expect(put("/admin/users/1")).to route_to('admin/users#update', id: '1')
   end
 
   it "to #destroy" do
-    delete("/admin/users/1").should route_to('admin/users#destroy', id: '1')
+    expect(delete("/admin/users/1")).to route_to('admin/users#destroy', id: '1')
   end
 end
 
@@ -67,11 +67,11 @@ end
 #                           DELETE /admin/projects/:id(.:format)             admin/projects#destroy {id: /[^\/]+/}
 describe Admin::ProjectsController, "routing" do
   it "to #index" do
-    get("/admin/projects").should route_to('admin/projects#index')
+    expect(get("/admin/projects")).to route_to('admin/projects#index')
   end
 
   it "to #show" do
-    get("/admin/projects/gitlab").should route_to('admin/projects#show', id: 'gitlab')
+    expect(get("/admin/projects/gitlab")).to route_to('admin/projects#show', namespace_id: 'gitlab')
   end
 end
 
@@ -81,19 +81,19 @@ end
 #      admin_hook DELETE /admin/hooks/:id(.:format)           admin/hooks#destroy
 describe Admin::HooksController, "routing" do
   it "to #test" do
-    get("/admin/hooks/1/test").should route_to('admin/hooks#test', hook_id: '1')
+    expect(get("/admin/hooks/1/test")).to route_to('admin/hooks#test', hook_id: '1')
   end
 
   it "to #index" do
-    get("/admin/hooks").should route_to('admin/hooks#index')
+    expect(get("/admin/hooks")).to route_to('admin/hooks#index')
   end
 
   it "to #create" do
-    post("/admin/hooks").should route_to('admin/hooks#create')
+    expect(post("/admin/hooks")).to route_to('admin/hooks#create')
   end
 
   it "to #destroy" do
-    delete("/admin/hooks/1").should route_to('admin/hooks#destroy', id: '1')
+    expect(delete("/admin/hooks/1")).to route_to('admin/hooks#destroy', id: '1')
   end
 
 end
@@ -101,21 +101,21 @@ end
 # admin_logs GET    /admin/logs(.:format) admin/logs#show
 describe Admin::LogsController, "routing" do
   it "to #show" do
-    get("/admin/logs").should route_to('admin/logs#show')
+    expect(get("/admin/logs")).to route_to('admin/logs#show')
   end
 end
 
 # admin_background_jobs GET    /admin/background_jobs(.:format) admin/background_jobs#show
 describe Admin::BackgroundJobsController, "routing" do
   it "to #show" do
-    get("/admin/background_jobs").should route_to('admin/background_jobs#show')
+    expect(get("/admin/background_jobs")).to route_to('admin/background_jobs#show')
   end
 end
 
 # admin_root        /admin(.:format) admin/dashboard#index
 describe Admin::DashboardController, "routing" do
   it "to #index" do
-    get("/admin").should route_to('admin/dashboard#index')
+    expect(get("/admin")).to route_to('admin/dashboard#index')
   end
 end
 
diff --git a/spec/routing/notifications_routing_spec.rb b/spec/routing/notifications_routing_spec.rb
index 112b825e0230cd8a1c04d269b6890e01bd9358d8..24592942a967e77b20d38dc6391550af2890239d 100644
--- a/spec/routing/notifications_routing_spec.rb
+++ b/spec/routing/notifications_routing_spec.rb
@@ -3,11 +3,11 @@ require "spec_helper"
 describe Profiles::NotificationsController do
   describe "routing" do
     it "routes to #show" do
-      get("/profile/notifications").should route_to("profiles/notifications#show")
+      expect(get("/profile/notifications")).to route_to("profiles/notifications#show")
     end
 
     it "routes to #update" do
-      put("/profile/notifications").should route_to("profiles/notifications#update")
+      expect(put("/profile/notifications")).to route_to("profiles/notifications#update")
     end
   end
 end
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 4b2eb42c709b1b870f4f05115af1655913e032cb..d9bd91f59901352348f0bb50f7109667d8994af8 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -12,86 +12,88 @@ require 'spec_helper'
 # Examples
 #
 #   # Default behavior
-#   it_behaves_like "RESTful project resources" do
+#   it_behaves_like 'RESTful project resources' do
 #     let(:controller) { 'issues' }
 #   end
 #
 #   # Customizing actions
-#   it_behaves_like "RESTful project resources" do
+#   it_behaves_like 'RESTful project resources' do
 #     let(:actions)    { [:index] }
 #     let(:controller) { 'issues' }
 #   end
-shared_examples "RESTful project resources" do
+shared_examples 'RESTful project resources' do
   let(:actions) { [:index, :create, :new, :edit, :show, :update, :destroy] }
 
-  it "to #index" do
-    get("/gitlab/gitlabhq/#{controller}").should route_to("projects/#{controller}#index", project_id: 'gitlab/gitlabhq') if actions.include?(:index)
+  it 'to #index' do
+    expect(get("/gitlab/gitlabhq/#{controller}")).to route_to("projects/#{controller}#index", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:index)
   end
 
-  it "to #create" do
-    post("/gitlab/gitlabhq/#{controller}").should route_to("projects/#{controller}#create", project_id: 'gitlab/gitlabhq') if actions.include?(:create)
+  it 'to #create' do
+    expect(post("/gitlab/gitlabhq/#{controller}")).to route_to("projects/#{controller}#create", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:create)
   end
 
-  it "to #new" do
-    get("/gitlab/gitlabhq/#{controller}/new").should route_to("projects/#{controller}#new", project_id: 'gitlab/gitlabhq') if actions.include?(:new)
+  it 'to #new' do
+    expect(get("/gitlab/gitlabhq/#{controller}/new")).to route_to("projects/#{controller}#new", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:new)
   end
 
-  it "to #edit" do
-    get("/gitlab/gitlabhq/#{controller}/1/edit").should route_to("projects/#{controller}#edit", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:edit)
+  it 'to #edit' do
+    expect(get("/gitlab/gitlabhq/#{controller}/1/edit")).to route_to("projects/#{controller}#edit", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:edit)
   end
 
-  it "to #show" do
-    get("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#show", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:show)
+  it 'to #show' do
+    expect(get("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#show", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:show)
   end
 
-  it "to #update" do
-    put("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#update", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:update)
+  it 'to #update' do
+    expect(put("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#update", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:update)
   end
 
-  it "to #destroy" do
-    delete("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#destroy", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:destroy)
+  it 'to #destroy' do
+    expect(delete("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#destroy", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:destroy)
   end
 end
 
-#      projects POST   /projects(.:format)     projects#create
-#   new_project GET    /projects/new(.:format) projects#new
-#  fork_project POST   /:id/fork(.:format)     projects#fork
-# files_project GET    /:id/files(.:format)    projects#files
-#  edit_project GET    /:id/edit(.:format)     projects#edit
-#       project GET    /:id(.:format)          projects#show
-#               PUT    /:id(.:format)          projects#update
-#               DELETE /:id(.:format)          projects#destroy
-describe ProjectsController, "routing" do
-  it "to #create" do
-    post("/projects").should route_to('projects#create')
+#                 projects POST   /projects(.:format)     projects#create
+#              new_project GET    /projects/new(.:format) projects#new
+#            files_project GET    /:id/files(.:format)    projects#files
+#             edit_project GET    /:id/edit(.:format)     projects#edit
+#                  project GET    /:id(.:format)          projects#show
+#                          PUT    /:id(.:format)          projects#update
+#                          DELETE /:id(.:format)          projects#destroy
+# markdown_preview_project POST   /:id/markdown_preview(.:format) projects#markdown_preview
+describe ProjectsController, 'routing' do
+  it 'to #create' do
+    expect(post('/projects')).to route_to('projects#create')
   end
 
-  it "to #new" do
-    get("/projects/new").should route_to('projects#new')
+  it 'to #new' do
+    expect(get('/projects/new')).to route_to('projects#new')
   end
 
-  it "to #fork" do
-    post("/gitlab/gitlabhq/fork").should route_to('projects#fork', id: 'gitlab/gitlabhq')
+  it 'to #edit' do
+    expect(get('/gitlab/gitlabhq/edit')).to route_to('projects#edit', namespace_id: 'gitlab', id: 'gitlabhq')
   end
 
-  it "to #edit" do
-    get("/gitlab/gitlabhq/edit").should route_to('projects#edit', id: 'gitlab/gitlabhq')
+  it 'to #autocomplete_sources' do
+    expect(get('/gitlab/gitlabhq/autocomplete_sources')).to route_to('projects#autocomplete_sources', namespace_id: 'gitlab', id: 'gitlabhq')
   end
 
-  it "to #autocomplete_sources" do
-    get('/gitlab/gitlabhq/autocomplete_sources').should route_to('projects#autocomplete_sources', id: "gitlab/gitlabhq")
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq')).to route_to('projects#show', namespace_id: 'gitlab', id: 'gitlabhq')
   end
 
-  it "to #show" do
-    get("/gitlab/gitlabhq").should route_to('projects#show', id: 'gitlab/gitlabhq')
+  it 'to #update' do
+    expect(put('/gitlab/gitlabhq')).to route_to('projects#update', namespace_id: 'gitlab', id: 'gitlabhq')
   end
 
-  it "to #update" do
-    put("/gitlab/gitlabhq").should route_to('projects#update', id: 'gitlab/gitlabhq')
+  it 'to #destroy' do
+    expect(delete('/gitlab/gitlabhq')).to route_to('projects#destroy', namespace_id: 'gitlab', id: 'gitlabhq')
   end
 
-  it "to #destroy" do
-    delete("/gitlab/gitlabhq").should route_to('projects#destroy', id: 'gitlab/gitlabhq')
+  it 'to #markdown_preview' do
+    expect(post('/gitlab/gitlabhq/markdown_preview')).to(
+      route_to('projects#markdown_preview', namespace_id: 'gitlab', id: 'gitlabhq')
+    )
   end
 end
 
@@ -101,16 +103,16 @@ end
 #    edit_project_wiki GET    /:project_id/wikis/:id/edit(.:format)    projects/wikis#edit
 #         project_wiki GET    /:project_id/wikis/:id(.:format)         projects/wikis#show
 #                      DELETE /:project_id/wikis/:id(.:format)         projects/wikis#destroy
-describe Projects::WikisController, "routing" do
-  it "to #pages" do
-    get("/gitlab/gitlabhq/wikis/pages").should route_to('projects/wikis#pages', project_id: 'gitlab/gitlabhq')
+describe Projects::WikisController, 'routing' do
+  it 'to #pages' do
+    expect(get('/gitlab/gitlabhq/wikis/pages')).to route_to('projects/wikis#pages', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 
-  it "to #history" do
-    get("/gitlab/gitlabhq/wikis/1/history").should route_to('projects/wikis#history', project_id: 'gitlab/gitlabhq', id: '1')
+  it 'to #history' do
+    expect(get('/gitlab/gitlabhq/wikis/1/history')).to route_to('projects/wikis#history', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
   end
 
-  it_behaves_like "RESTful project resources" do
+  it_behaves_like 'RESTful project resources' do
     let(:actions)    { [:create, :edit, :show, :destroy] }
     let(:controller) { 'wikis' }
   end
@@ -120,45 +122,45 @@ end
 #     tags_project_repository GET    /:project_id/repository/tags(.:format)     projects/repositories#tags
 #  archive_project_repository GET    /:project_id/repository/archive(.:format)  projects/repositories#archive
 #     edit_project_repository GET    /:project_id/repository/edit(.:format)     projects/repositories#edit
-describe Projects::RepositoriesController, "routing" do
-  it "to #archive" do
-    get("/gitlab/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq')
+describe Projects::RepositoriesController, 'routing' do
+  it 'to #archive' do
+    expect(get('/gitlab/gitlabhq/repository/archive')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 
-  it "to #archive format:zip" do
-    get("/gitlab/gitlabhq/repository/archive.zip").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'zip')
+  it 'to #archive format:zip' do
+    expect(get('/gitlab/gitlabhq/repository/archive.zip')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'zip')
   end
 
-  it "to #archive format:tar.bz2" do
-    get("/gitlab/gitlabhq/repository/archive.tar.bz2").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'tar.bz2')
+  it 'to #archive format:tar.bz2' do
+    expect(get('/gitlab/gitlabhq/repository/archive.tar.bz2')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'tar.bz2')
   end
 
-  it "to #show" do
-    get("/gitlab/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlab/gitlabhq')
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/repository')).to route_to('projects/repositories#show', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 end
 
-describe Projects::BranchesController, "routing" do
-  it "to #branches" do
-    get("/gitlab/gitlabhq/branches").should route_to('projects/branches#index', project_id: 'gitlab/gitlabhq')
-    delete("/gitlab/gitlabhq/branches/feature%2345").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45')
-    delete("/gitlab/gitlabhq/branches/feature%2B45").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45')
-    delete("/gitlab/gitlabhq/branches/feature@45").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45')
-    delete("/gitlab/gitlabhq/branches/feature%2345/foo/bar/baz").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45/foo/bar/baz')
-    delete("/gitlab/gitlabhq/branches/feature%2B45/foo/bar/baz").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45/foo/bar/baz')
-    delete("/gitlab/gitlabhq/branches/feature@45/foo/bar/baz").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45/foo/bar/baz')
+describe Projects::BranchesController, 'routing' do
+  it 'to #branches' do
+    expect(get('/gitlab/gitlabhq/branches')).to route_to('projects/branches#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
+    expect(delete('/gitlab/gitlabhq/branches/feature%2345')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
+    expect(delete('/gitlab/gitlabhq/branches/feature%2B45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
+    expect(delete('/gitlab/gitlabhq/branches/feature@45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
+    expect(delete('/gitlab/gitlabhq/branches/feature%2345/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz')
+    expect(delete('/gitlab/gitlabhq/branches/feature%2B45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz')
+    expect(delete('/gitlab/gitlabhq/branches/feature@45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz')
   end
 end
 
-describe Projects::TagsController, "routing" do
-  it "to #tags" do
-    get("/gitlab/gitlabhq/tags").should route_to('projects/tags#index', project_id: 'gitlab/gitlabhq')
-    delete("/gitlab/gitlabhq/tags/feature%2345").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45')
-    delete("/gitlab/gitlabhq/tags/feature%2B45").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45')
-    delete("/gitlab/gitlabhq/tags/feature@45").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45')
-    delete("/gitlab/gitlabhq/tags/feature%2345/foo/bar/baz").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45/foo/bar/baz')
-    delete("/gitlab/gitlabhq/tags/feature%2B45/foo/bar/baz").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45/foo/bar/baz')
-    delete("/gitlab/gitlabhq/tags/feature@45/foo/bar/baz").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45/foo/bar/baz')
+describe Projects::TagsController, 'routing' do
+  it 'to #tags' do
+    expect(get('/gitlab/gitlabhq/tags')).to route_to('projects/tags#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
+    expect(delete('/gitlab/gitlabhq/tags/feature%2345')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
+    expect(delete('/gitlab/gitlabhq/tags/feature%2B45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
+    expect(delete('/gitlab/gitlabhq/tags/feature@45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
+    expect(delete('/gitlab/gitlabhq/tags/feature%2345/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz')
+    expect(delete('/gitlab/gitlabhq/tags/feature%2B45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz')
+    expect(delete('/gitlab/gitlabhq/tags/feature@45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz')
   end
 end
 
@@ -170,8 +172,8 @@ end
 #      project_deploy_key GET    /:project_id/deploy_keys/:id(.:format)      deploy_keys#show
 #                         PUT    /:project_id/deploy_keys/:id(.:format)      deploy_keys#update
 #                         DELETE /:project_id/deploy_keys/:id(.:format)      deploy_keys#destroy
-describe Projects::DeployKeysController, "routing" do
-  it_behaves_like "RESTful project resources" do
+describe Projects::DeployKeysController, 'routing' do
+  it_behaves_like 'RESTful project resources' do
     let(:controller) { 'deploy_keys' }
   end
 end
@@ -179,8 +181,8 @@ end
 # project_protected_branches GET    /:project_id/protected_branches(.:format)     protected_branches#index
 #                            POST   /:project_id/protected_branches(.:format)     protected_branches#create
 #   project_protected_branch DELETE /:project_id/protected_branches/:id(.:format) protected_branches#destroy
-describe Projects::ProtectedBranchesController, "routing" do
-  it_behaves_like "RESTful project resources" do
+describe Projects::ProtectedBranchesController, 'routing' do
+  it_behaves_like 'RESTful project resources' do
     let(:actions)    { [:index, :create, :destroy] }
     let(:controller) { 'protected_branches' }
   end
@@ -189,21 +191,21 @@ end
 #    switch_project_refs GET    /:project_id/refs/switch(.:format)              refs#switch
 #  logs_tree_project_ref GET    /:project_id/refs/:id/logs_tree(.:format)       refs#logs_tree
 #  logs_file_project_ref GET    /:project_id/refs/:id/logs_tree/:path(.:format) refs#logs_tree
-describe Projects::RefsController, "routing" do
-  it "to #switch" do
-    get("/gitlab/gitlabhq/refs/switch").should route_to('projects/refs#switch', project_id: 'gitlab/gitlabhq')
-  end
-
-  it "to #logs_tree" do
-    get("/gitlab/gitlabhq/refs/stable/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable')
-    get("/gitlab/gitlabhq/refs/feature%2345/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45')
-    get("/gitlab/gitlabhq/refs/feature%2B45/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45')
-    get("/gitlab/gitlabhq/refs/feature@45/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature@45')
-    get("/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'foo/bar/baz')
-    get("/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45', path: 'foo/bar/baz')
-    get("/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45', path: 'foo/bar/baz')
-    get("/gitlab/gitlabhq/refs/feature@45/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature@45', path: 'foo/bar/baz')
-    get("/gitlab/gitlabhq/refs/stable/logs_tree/files.scss").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'files.scss')
+describe Projects::RefsController, 'routing' do
+  it 'to #switch' do
+    expect(get('/gitlab/gitlabhq/refs/switch')).to route_to('projects/refs#switch', namespace_id: 'gitlab', project_id: 'gitlabhq')
+  end
+
+  it 'to #logs_tree' do
+    expect(get('/gitlab/gitlabhq/refs/stable/logs_tree')).to             route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable')
+    expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree')).to             route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
+    expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree')).to             route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
+    expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree')).to             route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
+    expect(get('/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
+    expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45', path: 'foo/bar/baz')
+    expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45', path: 'foo/bar/baz')
+    expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45', path: 'foo/bar/baz')
+    expect(get('/gitlab/gitlabhq/refs/stable/logs_tree/files.scss')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable', path: 'files.scss')
   end
 end
 
@@ -219,36 +221,36 @@ end
 #                 project_merge_request GET    /:project_id/merge_requests/:id(.:format)                 projects/merge_requests#show
 #                                       PUT    /:project_id/merge_requests/:id(.:format)                 projects/merge_requests#update
 #                                       DELETE /:project_id/merge_requests/:id(.:format)                 projects/merge_requests#destroy
-describe Projects::MergeRequestsController, "routing" do
-  it "to #diffs" do
-    get("/gitlab/gitlabhq/merge_requests/1/diffs").should route_to('projects/merge_requests#diffs', project_id: 'gitlab/gitlabhq', id: '1')
+describe Projects::MergeRequestsController, 'routing' do
+  it 'to #diffs' do
+    expect(get('/gitlab/gitlabhq/merge_requests/1/diffs')).to route_to('projects/merge_requests#diffs', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
   end
 
-  it "to #automerge" do
-    post('/gitlab/gitlabhq/merge_requests/1/automerge').should route_to(
+  it 'to #automerge' do
+    expect(post('/gitlab/gitlabhq/merge_requests/1/automerge')).to route_to(
       'projects/merge_requests#automerge',
-      project_id: 'gitlab/gitlabhq', id: '1'
+      namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1'
     )
   end
 
-  it "to #automerge_check" do
-    get("/gitlab/gitlabhq/merge_requests/1/automerge_check").should route_to('projects/merge_requests#automerge_check', project_id: 'gitlab/gitlabhq', id: '1')
+  it 'to #automerge_check' do
+    expect(get('/gitlab/gitlabhq/merge_requests/1/automerge_check')).to route_to('projects/merge_requests#automerge_check', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
   end
 
-  it "to #branch_from" do
-    get("/gitlab/gitlabhq/merge_requests/branch_from").should route_to('projects/merge_requests#branch_from', project_id: 'gitlab/gitlabhq')
+  it 'to #branch_from' do
+    expect(get('/gitlab/gitlabhq/merge_requests/branch_from')).to route_to('projects/merge_requests#branch_from', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 
-  it "to #branch_to" do
-    get("/gitlab/gitlabhq/merge_requests/branch_to").should route_to('projects/merge_requests#branch_to', project_id: 'gitlab/gitlabhq')
+  it 'to #branch_to' do
+    expect(get('/gitlab/gitlabhq/merge_requests/branch_to')).to route_to('projects/merge_requests#branch_to', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 
-  it "to #show" do
-    get("/gitlab/gitlabhq/merge_requests/1.diff").should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'diff')
-    get("/gitlab/gitlabhq/merge_requests/1.patch").should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'patch')
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/merge_requests/1.diff')).to route_to('projects/merge_requests#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1', format: 'diff')
+    expect(get('/gitlab/gitlabhq/merge_requests/1.patch')).to route_to('projects/merge_requests#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1', format: 'patch')
   end
 
-  it_behaves_like "RESTful project resources" do
+  it_behaves_like 'RESTful project resources' do
     let(:controller) { 'merge_requests' }
     let(:actions) { [:index, :create, :new, :edit, :show, :update] }
   end
@@ -262,37 +264,37 @@ end
 #      project_snippet GET    /:project_id/snippets/:id(.:format)      snippets#show
 #                      PUT    /:project_id/snippets/:id(.:format)      snippets#update
 #                      DELETE /:project_id/snippets/:id(.:format)      snippets#destroy
-describe SnippetsController, "routing" do
-  it "to #raw" do
-    get("/gitlab/gitlabhq/snippets/1/raw").should route_to('projects/snippets#raw', project_id: 'gitlab/gitlabhq', id: '1')
+describe SnippetsController, 'routing' do
+  it 'to #raw' do
+    expect(get('/gitlab/gitlabhq/snippets/1/raw')).to route_to('projects/snippets#raw', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
   end
 
-  it "to #index" do
-    get("/gitlab/gitlabhq/snippets").should route_to("projects/snippets#index", project_id: 'gitlab/gitlabhq')
+  it 'to #index' do
+    expect(get('/gitlab/gitlabhq/snippets')).to route_to('projects/snippets#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 
-  it "to #create" do
-    post("/gitlab/gitlabhq/snippets").should route_to("projects/snippets#create", project_id: 'gitlab/gitlabhq')
+  it 'to #create' do
+    expect(post('/gitlab/gitlabhq/snippets')).to route_to('projects/snippets#create', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 
-  it "to #new" do
-    get("/gitlab/gitlabhq/snippets/new").should route_to("projects/snippets#new", project_id: 'gitlab/gitlabhq')
+  it 'to #new' do
+    expect(get('/gitlab/gitlabhq/snippets/new')).to route_to('projects/snippets#new', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 
-  it "to #edit" do
-    get("/gitlab/gitlabhq/snippets/1/edit").should route_to("projects/snippets#edit", project_id: 'gitlab/gitlabhq', id: '1')
+  it 'to #edit' do
+    expect(get('/gitlab/gitlabhq/snippets/1/edit')).to route_to('projects/snippets#edit', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
   end
 
-  it "to #show" do
-    get("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#show", project_id: 'gitlab/gitlabhq', id: '1')
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
   end
 
-  it "to #update" do
-    put("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#update", project_id: 'gitlab/gitlabhq', id: '1')
+  it 'to #update' do
+    expect(put('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#update', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
   end
 
-  it "to #destroy" do
-    delete("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#destroy", project_id: 'gitlab/gitlabhq', id: '1')
+  it 'to #destroy' do
+    expect(delete('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
   end
 end
 
@@ -300,24 +302,24 @@ end
 #     project_hooks GET    /:project_id/hooks(.:format)          hooks#index
 #                   POST   /:project_id/hooks(.:format)          hooks#create
 #      project_hook DELETE /:project_id/hooks/:id(.:format)      hooks#destroy
-describe Projects::HooksController, "routing" do
-  it "to #test" do
-    get("/gitlab/gitlabhq/hooks/1/test").should route_to('projects/hooks#test', project_id: 'gitlab/gitlabhq', id: '1')
+describe Projects::HooksController, 'routing' do
+  it 'to #test' do
+    expect(get('/gitlab/gitlabhq/hooks/1/test')).to route_to('projects/hooks#test', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
   end
 
-  it_behaves_like "RESTful project resources" do
+  it_behaves_like 'RESTful project resources' do
     let(:actions)    { [:index, :create, :destroy] }
     let(:controller) { 'hooks' }
   end
 end
 
 # project_commit GET    /:project_id/commit/:id(.:format) commit#show {id: /[[:alnum:]]{6,40}/, project_id: /[^\/]+/}
-describe Projects::CommitController, "routing" do
-  it "to #show" do
-    get("/gitlab/gitlabhq/commit/4246fb").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb')
-    get("/gitlab/gitlabhq/commit/4246fb.diff").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'diff')
-    get("/gitlab/gitlabhq/commit/4246fb.patch").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'patch')
-    get("/gitlab/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5')
+describe Projects::CommitController, 'routing' do
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/commit/4246fb')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fb')
+    expect(get('/gitlab/gitlabhq/commit/4246fb.diff')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fb', format: 'diff')
+    expect(get('/gitlab/gitlabhq/commit/4246fb.patch')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fb', format: 'patch')
+    expect(get('/gitlab/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5')
   end
 end
 
@@ -325,28 +327,25 @@ end
 #         project_commits GET    /:project_id/commits(.:format)           commits#index
 #                         POST   /:project_id/commits(.:format)           commits#create
 #          project_commit GET    /:project_id/commits/:id(.:format)       commits#show
-describe Projects::CommitsController, "routing" do
-  it_behaves_like "RESTful project resources" do
+describe Projects::CommitsController, 'routing' do
+  it_behaves_like 'RESTful project resources' do
     let(:actions)    { [:show] }
     let(:controller) { 'commits' }
   end
 
-  it "to #show" do
-    get("/gitlab/gitlabhq/commits/master.atom").should route_to('projects/commits#show', project_id: 'gitlab/gitlabhq', id: "master", format: "atom")
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/commits/master.atom')).to route_to('projects/commits#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'atom')
   end
 end
 
-#     project_team_members GET    /:project_id/team_members(.:format)          team_members#index
-#                          POST   /:project_id/team_members(.:format)          team_members#create
-#  new_project_team_member GET    /:project_id/team_members/new(.:format)      team_members#new
-# edit_project_team_member GET    /:project_id/team_members/:id/edit(.:format) team_members#edit
-#      project_team_member GET    /:project_id/team_members/:id(.:format)      team_members#show
-#                          PUT    /:project_id/team_members/:id(.:format)      team_members#update
-#                          DELETE /:project_id/team_members/:id(.:format)      team_members#destroy
-describe Projects::TeamMembersController, "routing" do
-  it_behaves_like "RESTful project resources" do
-    let(:actions)    { [:new, :create, :update, :destroy] }
-    let(:controller) { 'team_members' }
+#     project_project_members GET    /:project_id/project_members(.:format)          project_members#index
+#                          POST   /:project_id/project_members(.:format)          project_members#create
+#                          PUT    /:project_id/project_members/:id(.:format)      project_members#update
+#                          DELETE /:project_id/project_members/:id(.:format)      project_members#destroy
+describe Projects::ProjectMembersController, 'routing' do
+  it_behaves_like 'RESTful project resources' do
+    let(:actions)    { [:index, :create, :update, :destroy] }
+    let(:controller) { 'project_members' }
   end
 end
 
@@ -357,17 +356,17 @@ end
 #      project_milestone GET    /:project_id/milestones/:id(.:format)      milestones#show
 #                        PUT    /:project_id/milestones/:id(.:format)      milestones#update
 #                        DELETE /:project_id/milestones/:id(.:format)      milestones#destroy
-describe Projects::MilestonesController, "routing" do
-  it_behaves_like "RESTful project resources" do
+describe Projects::MilestonesController, 'routing' do
+  it_behaves_like 'RESTful project resources' do
     let(:controller) { 'milestones' }
     let(:actions) { [:index, :create, :new, :edit, :show, :update] }
   end
 end
 
 # project_labels GET    /:project_id/labels(.:format) labels#index
-describe Projects::LabelsController, "routing" do
-  it "to #index" do
-    get("/gitlab/gitlabhq/labels").should route_to('projects/labels#index', project_id: 'gitlab/gitlabhq')
+describe Projects::LabelsController, 'routing' do
+  it 'to #index' do
+    expect(get('/gitlab/gitlabhq/labels')).to route_to('projects/labels#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 end
 
@@ -381,84 +380,114 @@ end
 #              project_issue GET    /:project_id/issues/:id(.:format)         issues#show
 #                            PUT    /:project_id/issues/:id(.:format)         issues#update
 #                            DELETE /:project_id/issues/:id(.:format)         issues#destroy
-describe Projects::IssuesController, "routing" do
-  it "to #bulk_update" do
-    post("/gitlab/gitlabhq/issues/bulk_update").should route_to('projects/issues#bulk_update', project_id: 'gitlab/gitlabhq')
+describe Projects::IssuesController, 'routing' do
+  it 'to #bulk_update' do
+    expect(post('/gitlab/gitlabhq/issues/bulk_update')).to route_to('projects/issues#bulk_update', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 
-  it_behaves_like "RESTful project resources" do
+  it_behaves_like 'RESTful project resources' do
     let(:controller) { 'issues' }
     let(:actions) { [:index, :create, :new, :edit, :show, :update] }
   end
 end
 
-# preview_project_notes POST   /:project_id/notes/preview(.:format) notes#preview
 #         project_notes GET    /:project_id/notes(.:format)         notes#index
 #                       POST   /:project_id/notes(.:format)         notes#create
 #          project_note DELETE /:project_id/notes/:id(.:format)     notes#destroy
-describe Projects::NotesController, "routing" do
-  it "to #preview" do
-    post("/gitlab/gitlabhq/notes/preview").should route_to('projects/notes#preview', project_id: 'gitlab/gitlabhq')
-  end
-
-  it_behaves_like "RESTful project resources" do
+describe Projects::NotesController, 'routing' do
+  it_behaves_like 'RESTful project resources' do
     let(:actions)    { [:index, :create, :destroy] }
     let(:controller) { 'notes' }
   end
 end
 
 # project_blame GET    /:project_id/blame/:id(.:format) blame#show {id: /.+/, project_id: /[^\/]+/}
-describe Projects::BlameController, "routing" do
-  it "to #show" do
-    get("/gitlab/gitlabhq/blame/master/app/models/project.rb").should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
-    get("/gitlab/gitlabhq/blame/master/files.scss").should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
+describe Projects::BlameController, 'routing' do
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/blame/master/app/models/project.rb')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+    expect(get('/gitlab/gitlabhq/blame/master/files.scss')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss')
   end
 end
 
 # project_blob GET    /:project_id/blob/:id(.:format) blob#show {id: /.+/, project_id: /[^\/]+/}
-describe Projects::BlobController, "routing" do
-  it "to #show" do
-    get("/gitlab/gitlabhq/blob/master/app/models/project.rb").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
-    get("/gitlab/gitlabhq/blob/master/app/models/compare.rb").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/compare.rb')
-    get("/gitlab/gitlabhq/blob/master/files.scss").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
+describe Projects::BlobController, 'routing' do
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/blob/master/app/models/project.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+    expect(get('/gitlab/gitlabhq/blob/master/app/models/compare.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/compare.rb')
+    expect(get('/gitlab/gitlabhq/blob/master/app/models/diff.js')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/diff.js')
+    expect(get('/gitlab/gitlabhq/blob/master/files.scss')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss')
   end
 end
 
 # project_tree GET    /:project_id/tree/:id(.:format) tree#show {id: /.+/, project_id: /[^\/]+/}
-describe Projects::TreeController, "routing" do
-  it "to #show" do
-    get("/gitlab/gitlabhq/tree/master/app/models/project.rb").should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
-    get("/gitlab/gitlabhq/tree/master/files.scss").should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
+describe Projects::TreeController, 'routing' do
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/tree/master/app/models/project.rb')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+    expect(get('/gitlab/gitlabhq/tree/master/files.scss')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss')
+  end
+end
+
+describe Projects::BlobController, 'routing' do
+  it 'to #edit' do
+    expect(get('/gitlab/gitlabhq/edit/master/app/models/project.rb')).to(
+      route_to('projects/blob#edit',
+               namespace_id: 'gitlab', project_id: 'gitlabhq',
+               id: 'master/app/models/project.rb'))
+  end
+
+  it 'to #preview' do
+    expect(post('/gitlab/gitlabhq/preview/master/app/models/project.rb')).to(
+      route_to('projects/blob#preview',
+               namespace_id: 'gitlab', project_id: 'gitlabhq',
+               id: 'master/app/models/project.rb'))
   end
 end
 
 # project_compare_index GET    /:project_id/compare(.:format)             compare#index {id: /[^\/]+/, project_id: /[^\/]+/}
 #                       POST   /:project_id/compare(.:format)             compare#create {id: /[^\/]+/, project_id: /[^\/]+/}
 #       project_compare        /:project_id/compare/:from...:to(.:format) compare#show {from: /.+/, to: /.+/, id: /[^\/]+/, project_id: /[^\/]+/}
-describe Projects::CompareController, "routing" do
-  it "to #index" do
-    get("/gitlab/gitlabhq/compare").should route_to('projects/compare#index', project_id: 'gitlab/gitlabhq')
+describe Projects::CompareController, 'routing' do
+  it 'to #index' do
+    expect(get('/gitlab/gitlabhq/compare')).to route_to('projects/compare#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 
-  it "to #compare" do
-    post("/gitlab/gitlabhq/compare").should route_to('projects/compare#create', project_id: 'gitlab/gitlabhq')
+  it 'to #compare' do
+    expect(post('/gitlab/gitlabhq/compare')).to route_to('projects/compare#create', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 
-  it "to #show" do
-    get("/gitlab/gitlabhq/compare/master...stable").should     route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'master', to: 'stable')
-    get("/gitlab/gitlabhq/compare/issue/1234...stable").should route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'issue/1234', to: 'stable')
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/compare/master...stable')).to     route_to('projects/compare#show', namespace_id: 'gitlab', project_id: 'gitlabhq', from: 'master', to: 'stable')
+    expect(get('/gitlab/gitlabhq/compare/issue/1234...stable')).to route_to('projects/compare#show', namespace_id: 'gitlab', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable')
   end
 end
 
-describe Projects::NetworkController, "routing" do
-  it "to #show" do
-    get("/gitlab/gitlabhq/network/master").should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master')
-    get("/gitlab/gitlabhq/network/master.json").should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master', format: "json")
+describe Projects::NetworkController, 'routing' do
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/network/master')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
+    expect(get('/gitlab/gitlabhq/network/master.json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json')
+  end
+end
+
+describe Projects::GraphsController, 'routing' do
+  it 'to #show' do
+    expect(get('/gitlab/gitlabhq/graphs/master')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
+  end
+end
+
+describe Projects::ForksController, 'routing' do
+  it 'to #new' do
+    expect(get('/gitlab/gitlabhq/fork/new')).to route_to('projects/forks#new', namespace_id: 'gitlab', project_id: 'gitlabhq')
+  end
+
+  it 'to #create' do
+    expect(post('/gitlab/gitlabhq/fork')).to route_to('projects/forks#create', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 end
 
-describe Projects::GraphsController, "routing" do
-  it "to #show" do
-    get("/gitlab/gitlabhq/graphs/master").should route_to('projects/graphs#show', project_id: 'gitlab/gitlabhq', id: 'master')
+# project_avatar DELETE /project/avatar(.:format) projects/avatars#destroy
+describe Projects::AvatarsController, 'routing' do
+  it 'to #destroy' do
+    expect(delete('/gitlab/gitlabhq/avatar')).to route_to(
+      'projects/avatars#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq')
   end
 end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 1e92cf62dd5183e593fa9e092fe9adf5db8b8bd8..d4915b519520e240510600df21d529cdb9c911b6 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
 # search GET    /search(.:format) search#show
 describe SearchController, "routing" do
   it "to #show" do
-    get("/search").should route_to('search#show')
+    expect(get("/search")).to route_to('search#show')
   end
 end
 
@@ -11,11 +11,11 @@ end
 #            /:path       Grack
 describe "Mounted Apps", "routing" do
   it "to API" do
-    get("/api/issues").should be_routable
+    expect(get("/api/issues")).to be_routable
   end
 
   it "to Grack" do
-    get("/gitlab/gitlabhq.git").should be_routable
+    expect(get("/gitlab/gitlabhq.git")).to be_routable
   end
 end
 
@@ -28,39 +28,39 @@ end
 #          DELETE /snippets/:id(.:format)      snippets#destroy
 describe SnippetsController, "routing" do
   it "to #user_index" do
-    get("/s/User").should route_to('snippets#user_index', username: 'User')
+    expect(get("/s/User")).to route_to('snippets#user_index', username: 'User')
   end
 
   it "to #raw" do
-    get("/snippets/1/raw").should route_to('snippets#raw', id: '1')
+    expect(get("/snippets/1/raw")).to route_to('snippets#raw', id: '1')
   end
 
   it "to #index" do
-    get("/snippets").should route_to('snippets#index')
+    expect(get("/snippets")).to route_to('snippets#index')
   end
 
   it "to #create" do
-    post("/snippets").should route_to('snippets#create')
+    expect(post("/snippets")).to route_to('snippets#create')
   end
 
   it "to #new" do
-    get("/snippets/new").should route_to('snippets#new')
+    expect(get("/snippets/new")).to route_to('snippets#new')
   end
 
   it "to #edit" do
-    get("/snippets/1/edit").should route_to('snippets#edit', id: '1')
+    expect(get("/snippets/1/edit")).to route_to('snippets#edit', id: '1')
   end
 
   it "to #show" do
-    get("/snippets/1").should route_to('snippets#show', id: '1')
+    expect(get("/snippets/1")).to route_to('snippets#show', id: '1')
   end
 
   it "to #update" do
-    put("/snippets/1").should route_to('snippets#update', id: '1')
+    expect(put("/snippets/1")).to route_to('snippets#update', id: '1')
   end
 
   it "to #destroy" do
-    delete("/snippets/1").should route_to('snippets#destroy', id: '1')
+    expect(delete("/snippets/1")).to route_to('snippets#destroy', id: '1')
   end
 end
 
@@ -75,39 +75,39 @@ end
 #    help_raketasks GET    /help/raketasks(.:format)    help#raketasks
 describe HelpController, "routing" do
   it "to #index" do
-    get("/help").should route_to('help#index')
+    expect(get("/help")).to route_to('help#index')
   end
 
   it "to #permissions" do
-    get("/help/permissions/permissions").should route_to('help#show', category: "permissions", file: "permissions")
+    expect(get("/help/permissions/permissions")).to route_to('help#show', category: "permissions", file: "permissions")
   end
 
   it "to #workflow" do
-    get("/help/workflow/README").should route_to('help#show', category: "workflow", file: "README")
+    expect(get("/help/workflow/README")).to route_to('help#show', category: "workflow", file: "README")
   end
 
   it "to #api" do
-    get("/help/api/README").should route_to('help#show', category: "api", file: "README")
+    expect(get("/help/api/README")).to route_to('help#show', category: "api", file: "README")
   end
 
   it "to #web_hooks" do
-    get("/help/web_hooks/web_hooks").should route_to('help#show', category: "web_hooks", file: "web_hooks")
+    expect(get("/help/web_hooks/web_hooks")).to route_to('help#show', category: "web_hooks", file: "web_hooks")
   end
 
   it "to #system_hooks" do
-    get("/help/system_hooks/system_hooks").should route_to('help#show', category: "system_hooks", file: "system_hooks")
+    expect(get("/help/system_hooks/system_hooks")).to route_to('help#show', category: "system_hooks", file: "system_hooks")
   end
 
   it "to #markdown" do
-    get("/help/markdown/markdown").should route_to('help#show',category: "markdown", file: "markdown")
+    expect(get("/help/markdown/markdown")).to route_to('help#show',category: "markdown", file: "markdown")
   end
 
   it "to #ssh" do
-    get("/help/ssh/README").should route_to('help#show', category: "ssh", file: "README")
+    expect(get("/help/ssh/README")).to route_to('help#show', category: "ssh", file: "README")
   end
 
   it "to #raketasks" do
-    get("/help/raketasks/README").should route_to('help#show', category: "raketasks", file: "README")
+    expect(get("/help/raketasks/README")).to route_to('help#show', category: "raketasks", file: "README")
   end
 end
 
@@ -121,23 +121,23 @@ end
 #              profile_update PUT    /profile/update(.:format)              profile#update
 describe ProfilesController, "routing" do
   it "to #account" do
-    get("/profile/account").should route_to('profiles/accounts#show')
+    expect(get("/profile/account")).to route_to('profiles/accounts#show')
   end
 
   it "to #history" do
-    get("/profile/history").should route_to('profiles#history')
+    expect(get("/profile/history")).to route_to('profiles#history')
   end
 
   it "to #reset_private_token" do
-    put("/profile/reset_private_token").should route_to('profiles#reset_private_token')
+    expect(put("/profile/reset_private_token")).to route_to('profiles#reset_private_token')
   end
 
   it "to #show" do
-    get("/profile").should route_to('profiles#show')
+    expect(get("/profile")).to route_to('profiles#show')
   end
 
   it "to #design" do
-    get("/profile/design").should route_to('profiles#design')
+    expect(get("/profile/design")).to route_to('profiles#design')
   end
 end
 
@@ -150,36 +150,36 @@ end
 #          DELETE /keys/:id(.:format)      keys#destroy
 describe Profiles::KeysController, "routing" do
   it "to #index" do
-    get("/profile/keys").should route_to('profiles/keys#index')
+    expect(get("/profile/keys")).to route_to('profiles/keys#index')
   end
 
   it "to #create" do
-    post("/profile/keys").should route_to('profiles/keys#create')
+    expect(post("/profile/keys")).to route_to('profiles/keys#create')
   end
 
   it "to #new" do
-    get("/profile/keys/new").should route_to('profiles/keys#new')
+    expect(get("/profile/keys/new")).to route_to('profiles/keys#new')
   end
 
   it "to #edit" do
-    get("/profile/keys/1/edit").should route_to('profiles/keys#edit', id: '1')
+    expect(get("/profile/keys/1/edit")).to route_to('profiles/keys#edit', id: '1')
   end
 
   it "to #show" do
-    get("/profile/keys/1").should route_to('profiles/keys#show', id: '1')
+    expect(get("/profile/keys/1")).to route_to('profiles/keys#show', id: '1')
   end
 
   it "to #update" do
-    put("/profile/keys/1").should route_to('profiles/keys#update', id: '1')
+    expect(put("/profile/keys/1")).to route_to('profiles/keys#update', id: '1')
   end
 
   it "to #destroy" do
-    delete("/profile/keys/1").should route_to('profiles/keys#destroy', id: '1')
+    expect(delete("/profile/keys/1")).to route_to('profiles/keys#destroy', id: '1')
   end
 
   # get all the ssh-keys of a user
   it "to #get_keys" do
-    get("/foo.keys").should route_to('profiles/keys#get_keys', username: 'foo')
+    expect(get("/foo.keys")).to route_to('profiles/keys#get_keys', username: 'foo')
   end
 end
 
@@ -188,22 +188,22 @@ end
 #          DELETE /keys/:id(.:format)      keys#destroy
 describe Profiles::EmailsController, "routing" do
   it "to #index" do
-    get("/profile/emails").should route_to('profiles/emails#index')
+    expect(get("/profile/emails")).to route_to('profiles/emails#index')
   end
 
   it "to #create" do
-    post("/profile/emails").should route_to('profiles/emails#create')
+    expect(post("/profile/emails")).to route_to('profiles/emails#create')
   end
 
   it "to #destroy" do
-    delete("/profile/emails/1").should route_to('profiles/emails#destroy', id: '1')
+    expect(delete("/profile/emails/1")).to route_to('profiles/emails#destroy', id: '1')
   end
 end
 
 # profile_avatar DELETE /profile/avatar(.:format) profiles/avatars#destroy
 describe Profiles::AvatarsController, "routing" do
   it "to #destroy" do
-    delete("/profile/avatar").should route_to('profiles/avatars#destroy')
+    expect(delete("/profile/avatar")).to route_to('profiles/avatars#destroy')
   end
 end
 
@@ -213,16 +213,16 @@ end
 #                     root        /                                   dashboard#show
 describe DashboardController, "routing" do
   it "to #index" do
-    get("/dashboard").should route_to('dashboard#show')
-    get("/").should route_to('dashboard#show')
+    expect(get("/dashboard")).to route_to('dashboard#show')
+    expect(get("/")).to route_to('dashboard#show')
   end
 
   it "to #issues" do
-    get("/dashboard/issues").should route_to('dashboard#issues')
+    expect(get("/dashboard/issues")).to route_to('dashboard#issues')
   end
 
   it "to #merge_requests" do
-    get("/dashboard/merge_requests").should route_to('dashboard#merge_requests')
+    expect(get("/dashboard/merge_requests")).to route_to('dashboard#merge_requests')
   end
 end
 
@@ -241,11 +241,11 @@ end
 
 describe "Groups", "routing" do
   it "to #show" do
-    get("/groups/1").should route_to('groups#show', id: '1')
+    expect(get("/groups/1")).to route_to('groups#show', id: '1')
   end
 
   it "also display group#show on the short path" do
-    get('/1').should route_to('namespaces#show', id: '1')
+    expect(get('/1')).to route_to('namespaces#show', id: '1')
   end
 end
 
diff --git a/spec/services/create_snippet_service_spec.rb b/spec/services/create_snippet_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..08689c15ca8ac937677691c73bd00bf21834ba80
--- /dev/null
+++ b/spec/services/create_snippet_service_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe CreateSnippetService do
+  before do
+    @user = create :user
+    @admin = create :user, admin: true
+    @opts = {
+      title: 'Test snippet',
+      file_name: 'snippet.rb',
+      content: 'puts "hello world"',
+      visibility_level: Gitlab::VisibilityLevel::PRIVATE
+    }
+  end
+
+  context 'When public visibility is restricted' do
+    before do
+      allow_any_instance_of(ApplicationSetting).to(
+        receive(:restricted_visibility_levels).and_return(
+          [Gitlab::VisibilityLevel::PUBLIC]
+        )
+      )
+
+      @opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+    end
+
+    it 'non-admins should not be able to create a public snippet' do
+      snippet = create_snippet(nil, @user, @opts)
+      expect(snippet.errors.messages).to have_key(:visibility_level)
+      expect(snippet.errors.messages[:visibility_level].first).to(
+        match('Public visibility has been restricted')
+      )
+    end
+
+    it 'admins should be able to create a public snippet' do
+      snippet = create_snippet(nil, @admin, @opts)
+      expect(snippet.errors.any?).to be_falsey
+      expect(snippet.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
+    end
+  end
+
+  def create_snippet(project, user, opts)
+    CreateSnippetService.new(project, user, opts).execute
+  end
+end
diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb
index 713aa3e7e747714b25dc9bb5c8c852c28103fa30..007a9eed192e2ea4c11f89a9c83caca139fe966d 100644
--- a/spec/services/event_create_service_spec.rb
+++ b/spec/services/event_create_service_spec.rb
@@ -7,7 +7,7 @@ describe EventCreateService do
     describe :open_issue do
       let(:issue) { create(:issue) }
 
-      it { service.open_issue(issue, issue.author).should be_true }
+      it { expect(service.open_issue(issue, issue.author)).to be_truthy }
 
       it "should create new event" do
         expect { service.open_issue(issue, issue.author) }.to change { Event.count }
@@ -17,7 +17,7 @@ describe EventCreateService do
     describe :close_issue do
       let(:issue) { create(:issue) }
 
-      it { service.close_issue(issue, issue.author).should be_true }
+      it { expect(service.close_issue(issue, issue.author)).to be_truthy }
 
       it "should create new event" do
         expect { service.close_issue(issue, issue.author) }.to change { Event.count }
@@ -27,7 +27,7 @@ describe EventCreateService do
     describe :reopen_issue do
       let(:issue) { create(:issue) }
 
-      it { service.reopen_issue(issue, issue.author).should be_true }
+      it { expect(service.reopen_issue(issue, issue.author)).to be_truthy }
 
       it "should create new event" do
         expect { service.reopen_issue(issue, issue.author) }.to change { Event.count }
@@ -39,7 +39,7 @@ describe EventCreateService do
     describe :open_mr do
       let(:merge_request) { create(:merge_request) }
 
-      it { service.open_mr(merge_request, merge_request.author).should be_true }
+      it { expect(service.open_mr(merge_request, merge_request.author)).to be_truthy }
 
       it "should create new event" do
         expect { service.open_mr(merge_request, merge_request.author) }.to change { Event.count }
@@ -49,7 +49,7 @@ describe EventCreateService do
     describe :close_mr do
       let(:merge_request) { create(:merge_request) }
 
-      it { service.close_mr(merge_request, merge_request.author).should be_true }
+      it { expect(service.close_mr(merge_request, merge_request.author)).to be_truthy }
 
       it "should create new event" do
         expect { service.close_mr(merge_request, merge_request.author) }.to change { Event.count }
@@ -59,7 +59,7 @@ describe EventCreateService do
     describe :merge_mr do
       let(:merge_request) { create(:merge_request) }
 
-      it { service.merge_mr(merge_request, merge_request.author).should be_true }
+      it { expect(service.merge_mr(merge_request, merge_request.author)).to be_truthy }
 
       it "should create new event" do
         expect { service.merge_mr(merge_request, merge_request.author) }.to change { Event.count }
@@ -69,7 +69,7 @@ describe EventCreateService do
     describe :reopen_mr do
       let(:merge_request) { create(:merge_request) }
 
-      it { service.reopen_mr(merge_request, merge_request.author).should be_true }
+      it { expect(service.reopen_mr(merge_request, merge_request.author)).to be_truthy }
 
       it "should create new event" do
         expect { service.reopen_mr(merge_request, merge_request.author) }.to change { Event.count }
@@ -83,7 +83,7 @@ describe EventCreateService do
     describe :open_milestone do
       let(:milestone) { create(:milestone) }
 
-      it { service.open_milestone(milestone, user).should be_true }
+      it { expect(service.open_milestone(milestone, user)).to be_truthy }
 
       it "should create new event" do
         expect { service.open_milestone(milestone, user) }.to change { Event.count }
@@ -93,7 +93,7 @@ describe EventCreateService do
     describe :close_mr do
       let(:milestone) { create(:milestone) }
 
-      it { service.close_milestone(milestone, user).should be_true }
+      it { expect(service.close_milestone(milestone, user)).to be_truthy }
 
       it "should create new event" do
         expect { service.close_milestone(milestone, user) }.to change { Event.count }
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index 19b442573f4febf814d949b200e2eeec9c6d9ba9..aa9b15dd9ecc1855b112ccb4274964b44c0e3837 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -20,7 +20,7 @@ describe GitPushService do
         service.execute(project, user, @blankrev, @newrev, @ref)
       end
 
-      it { should be_true }
+      it { is_expected.to be_truthy }
     end
 
     context 'existing branch' do
@@ -28,7 +28,7 @@ describe GitPushService do
         service.execute(project, user, @oldrev, @newrev, @ref)
       end
 
-      it { should be_true }
+      it { is_expected.to be_truthy }
     end
 
     context 'rm branch' do
@@ -36,7 +36,7 @@ describe GitPushService do
         service.execute(project, user, @oldrev, @blankrev, @ref)
       end
 
-      it { should be_true }
+      it { is_expected.to be_truthy }
     end
   end
 
@@ -49,41 +49,54 @@ describe GitPushService do
 
     subject { @push_data }
 
-    it { should include(before: @oldrev) }
-    it { should include(after: @newrev) }
-    it { should include(ref: @ref) }
-    it { should include(user_id: user.id) }
-    it { should include(user_name: user.name) }
-    it { should include(project_id: project.id) }
+    it { is_expected.to include(object_kind: 'push') }
+    it { is_expected.to include(before: @oldrev) }
+    it { is_expected.to include(after: @newrev) }
+    it { is_expected.to include(ref: @ref) }
+    it { is_expected.to include(user_id: user.id) }
+    it { is_expected.to include(user_name: user.name) }
+    it { is_expected.to include(project_id: project.id) }
 
     context "with repository data" do
       subject { @push_data[:repository] }
 
-      it { should include(name: project.name) }
-      it { should include(url: project.url_to_repo) }
-      it { should include(description: project.description) }
-      it { should include(homepage: project.web_url) }
+      it { is_expected.to include(name: project.name) }
+      it { is_expected.to include(url: project.url_to_repo) }
+      it { is_expected.to include(description: project.description) }
+      it { is_expected.to include(homepage: project.web_url) }
     end
 
     context "with commits" do
       subject { @push_data[:commits] }
 
-      it { should be_an(Array) }
-      it { should have(1).element }
+      it { is_expected.to be_an(Array) }
+      it 'has 1 element' do
+        expect(subject.size).to eq(1)
+      end
 
       context "the commit" do
         subject { @push_data[:commits].first }
 
-        it { should include(id: @commit.id) }
-        it { should include(message: @commit.safe_message) }
-        it { should include(timestamp: @commit.date.xmlschema) }
-        it { should include(url: "#{Gitlab.config.gitlab.url}/#{project.to_param}/commit/#{@commit.id}") }
+        it { is_expected.to include(id: @commit.id) }
+        it { is_expected.to include(message: @commit.safe_message) }
+        it { is_expected.to include(timestamp: @commit.date.xmlschema) }
+        it do
+          is_expected.to include(
+            url: [
+              Gitlab.config.gitlab.url,
+              project.namespace.to_param,
+              project.to_param,
+              'commit',
+              @commit.id
+            ].join('/')
+          )
+        end
 
         context "with a author" do
           subject { @push_data[:commits].first[:author] }
 
-          it { should include(name: @commit.author_name) }
-          it { should include(email: @commit.author_email) }
+          it { is_expected.to include(name: @commit.author_name) }
+          it { is_expected.to include(email: @commit.author_email) }
         end
       end
     end
@@ -95,29 +108,42 @@ describe GitPushService do
       @event = Event.last
     end
 
-    it { @event.should_not be_nil }
-    it { @event.project.should == project }
-    it { @event.action.should == Event::PUSHED }
-    it { @event.data.should == service.push_data }
+    it { expect(@event).not_to be_nil }
+    it { expect(@event.project).to eq(project) }
+    it { expect(@event.action).to eq(Event::PUSHED) }
+    it { expect(@event.data).to eq(service.push_data) }
   end
 
   describe "Web Hooks" do
     context "execute web hooks" do
       it "when pushing a branch for the first time" do
-        project.should_receive(:execute_hooks)
-        project.default_branch.should == "master"
-        project.protected_branches.should_receive(:create).with({ name: "master" })
+        expect(project).to receive(:execute_hooks)
+        expect(project.default_branch).to eq("master")
+        expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: false })
         service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master')
       end
 
-      it "when pushing new commits to existing branch" do
-        project.should_receive(:execute_hooks)
-        service.execute(project, user, 'oldrev', 'newrev', 'refs/heads/master')
+      it "when pushing a branch for the first time with default branch protection disabled" do
+        ApplicationSetting.any_instance.stub(default_branch_protection: 0)
+
+        expect(project).to receive(:execute_hooks)
+        expect(project.default_branch).to eq("master")
+        expect(project.protected_branches).not_to 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)
+
+        expect(project).to receive(:execute_hooks)
+        expect(project.default_branch).to eq("master")
+        expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: true })
+        service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master')
       end
 
-      it "when pushing tags" do
-        project.should_not_receive(:execute_hooks)
-        service.execute(project, user, 'newrev', 'newrev', 'refs/tags/v1.0.0')
+      it "when pushing new commits to existing branch" do
+        expect(project).to receive(:execute_hooks)
+        service.execute(project, user, 'oldrev', 'newrev', 'refs/heads/master')
       end
     end
   end
@@ -138,7 +164,7 @@ describe GitPushService do
     end
 
     it "creates a note if a pushed commit mentions an issue" do
-      Note.should_receive(:create_cross_reference_note).with(issue, commit, commit_author, project)
+      expect(Note).to receive(:create_cross_reference_note).with(issue, commit, commit_author, project)
 
       service.execute(project, user, @oldrev, @newrev, @ref)
     end
@@ -146,35 +172,26 @@ describe GitPushService do
     it "only creates a cross-reference note if one doesn't already exist" do
       Note.create_cross_reference_note(issue, commit, user, project)
 
-      Note.should_not_receive(:create_cross_reference_note).with(issue, commit, commit_author, project)
+      expect(Note).not_to receive(:create_cross_reference_note).with(issue, commit, commit_author, project)
 
       service.execute(project, user, @oldrev, @newrev, @ref)
     end
 
     it "defaults to the pushing user if the commit's author is not known" do
       commit.stub(author_name: 'unknown name', author_email: 'unknown@email.com')
-      Note.should_receive(:create_cross_reference_note).with(issue, commit, user, project)
+      expect(Note).to receive(:create_cross_reference_note).with(issue, commit, user, project)
 
       service.execute(project, user, @oldrev, @newrev, @ref)
     end
 
     it "finds references in the first push to a non-default branch" do
-      project.repository.stub(:commits_between).with(@blankrev, @newrev).and_return([])
-      project.repository.stub(:commits_between).with("master", @newrev).and_return([commit])
+      allow(project.repository).to receive(:commits_between).with(@blankrev, @newrev).and_return([])
+      allow(project.repository).to receive(:commits_between).with("master", @newrev).and_return([commit])
 
-      Note.should_receive(:create_cross_reference_note).with(issue, commit, commit_author, project)
+      expect(Note).to receive(:create_cross_reference_note).with(issue, commit, commit_author, project)
 
       service.execute(project, user, @blankrev, @newrev, 'refs/heads/other')
     end
-
-    it "finds references in the first push to a default branch" do
-      project.repository.stub(:commits_between).with(@blankrev, @newrev).and_return([])
-      project.repository.stub(:commits).with(@newrev).and_return([commit])
-
-      Note.should_receive(:create_cross_reference_note).with(issue, commit, commit_author, project)
-
-      service.execute(project, user, @blankrev, @newrev, 'refs/heads/master')
-    end
   end
 
   describe "closing issues from pushed commits" do
@@ -197,7 +214,7 @@ describe GitPushService do
     it "closes issues with commit messages" do
       service.execute(project, user, @oldrev, @newrev, @ref)
 
-      Issue.find(issue.id).should be_closed
+      expect(Issue.find(issue.id)).to be_closed
     end
 
     it "doesn't create cross-reference notes for a closing reference" do
@@ -214,7 +231,7 @@ describe GitPushService do
         service.execute(project, user, @oldrev, @newrev, 'refs/heads/hurf')
       }.not_to change { Note.where(project_id: project.id, system: true).count }
 
-      Issue.find(issue.id).should be_opened
+      expect(Issue.find(issue.id)).to be_opened
     end
   end
 end
diff --git a/spec/services/git_tag_push_service_spec.rb b/spec/services/git_tag_push_service_spec.rb
index e65a8204c54ac71d309fcf967844181a12ec619d..a050fdf6c0eb1ac58e08a7243c49d2c76c45db22 100644
--- a/spec/services/git_tag_push_service_spec.rb
+++ b/spec/services/git_tag_push_service_spec.rb
@@ -1,45 +1,87 @@
 require 'spec_helper'
 
 describe GitTagPushService do
+  include RepoHelpers
+
   let (:user) { create :user }
   let (:project) { create :project }
   let (:service) { GitTagPushService.new }
 
   before do
-    @ref = 'refs/tags/super-tag'
-    @oldrev = 'b98a310def241a6fd9c9a9a3e7934c48e498fe81'
-    @newrev = 'b19a04f53caeebf4fe5ec2327cb83e9253dc91bb'
+    @oldrev = Gitlab::Git::BLANK_SHA
+    @newrev = "8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b" # gitlab-test: git rev-parse refs/tags/v1.1.0
+    @ref = 'refs/tags/v1.1.0'
   end
 
-  describe 'Git Tag Push Data' do
+  describe "Git Tag Push Data" do
     before do
       service.execute(project, user, @oldrev, @newrev, @ref)
       @push_data = service.push_data
+      @tag_name = Gitlab::Git.ref_name(@ref)
+      @tag = project.repository.find_tag(@tag_name)
+      @commit = project.repository.commit(@tag.target)
     end
 
     subject { @push_data }
 
-    it { should include(ref: @ref) }
-    it { should include(before: @oldrev) }
-    it { should include(after: @newrev) }
-    it { should include(user_id: user.id) }
-    it { should include(user_name: user.name) }
-    it { should include(project_id: project.id) }
+    it { is_expected.to include(object_kind: 'tag_push') }
+    it { is_expected.to include(ref: @ref) }
+    it { is_expected.to include(before: @oldrev) }
+    it { is_expected.to include(after: @newrev) }
+    it { is_expected.to include(message: @tag.message) }
+    it { is_expected.to include(user_id: user.id) }
+    it { is_expected.to include(user_name: user.name) }
+    it { is_expected.to include(project_id: project.id) }
 
-    context 'With repository data' do
+    context "with repository data" do
       subject { @push_data[:repository] }
 
-      it { should include(name: project.name) }
-      it { should include(url: project.url_to_repo) }
-      it { should include(description: project.description) }
-      it { should include(homepage: project.web_url) }
+      it { is_expected.to include(name: project.name) }
+      it { is_expected.to include(url: project.url_to_repo) }
+      it { is_expected.to include(description: project.description) }
+      it { is_expected.to include(homepage: project.web_url) }
+    end
+
+    context "with commits" do
+      subject { @push_data[:commits] }
+
+      it { is_expected.to be_an(Array) }
+      it 'has 1 element' do
+        expect(subject.size).to eq(1)
+      end
+
+      context "the commit" do
+        subject { @push_data[:commits].first }
+
+        it { is_expected.to include(id: @commit.id) }
+        it { is_expected.to include(message: @commit.safe_message) }
+        it { is_expected.to include(timestamp: @commit.date.xmlschema) }
+        it do
+          is_expected.to include(
+                           url: [
+                             Gitlab.config.gitlab.url,
+                             project.namespace.to_param,
+                             project.to_param,
+                             'commit',
+                             @commit.id
+                           ].join('/')
+                         )
+        end
+
+        context "with a author" do
+          subject { @push_data[:commits].first[:author] }
+
+          it { is_expected.to include(name: @commit.author_name) }
+          it { is_expected.to include(email: @commit.author_email) }
+        end
+      end
     end
   end
 
   describe "Web Hooks" do
     context "execute web hooks" do
       it "when pushing tags" do
-        project.should_receive(:execute_hooks)
+        expect(project).to receive(:execute_hooks)
         service.execute(project, user, 'oldrev', 'newrev', 'refs/tags/v1.0.0')
       end
     end
diff --git a/spec/services/issues/bulk_update_context_spec.rb b/spec/services/issues/bulk_update_context_spec.rb
deleted file mode 100644
index f4c9148f1a37bcc4e0e74beb51eedd97c50ff07a..0000000000000000000000000000000000000000
--- a/spec/services/issues/bulk_update_context_spec.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-require 'spec_helper'
-
-describe Issues::BulkUpdateService do
-  let(:issue) {
-    create(:issue, project: @project)
-  }
-
-  before do
-    @user = create :user
-    opts = {
-      name: "GitLab",
-      namespace: @user.namespace
-    }
-    @project = Projects::CreateService.new(@user, opts).execute
-  end
-
-  describe :close_issue do
-
-    before do
-      @issues = 5.times.collect do
-        create(:issue, project: @project)
-      end
-      @params = {
-        update: {
-          status: 'closed',
-          issues_ids: @issues.map(&:id)
-        }
-      }
-    end
-
-    it {
-      result = Issues::BulkUpdateService.new(@project, @user, @params).execute
-      result[:success].should be_true
-      result[:count].should == @issues.count
-
-      @project.issues.opened.should be_empty
-      @project.issues.closed.should_not be_empty
-    }
-
-  end
-
-  describe :reopen_issues do
-
-    before do
-      @issues = 5.times.collect do
-        create(:closed_issue, project: @project)
-      end
-      @params = {
-        update: {
-          status: 'reopen',
-          issues_ids: @issues.map(&:id)
-        }
-      }
-    end
-
-    it {
-      result = Issues::BulkUpdateService.new(@project, @user, @params).execute
-      result[:success].should be_true
-      result[:count].should == @issues.count
-
-      @project.issues.closed.should be_empty
-      @project.issues.opened.should_not be_empty
-    }
-
-  end
-
-  describe :update_assignee do
-
-    before do
-      @new_assignee = create :user
-      @params = {
-        update: {
-          issues_ids: [issue.id],
-          assignee_id: @new_assignee.id
-        }
-      }
-    end
-
-    it {
-      result = Issues::BulkUpdateService.new(@project, @user, @params).execute
-      result[:success].should be_true
-      result[:count].should == 1
-
-      @project.issues.first.assignee.should == @new_assignee
-    }
-
-  end
-
-  describe :update_milestone do
-
-    before do
-      @milestone = create :milestone
-      @params = {
-        update: {
-          issues_ids: [issue.id],
-          milestone_id: @milestone.id
-        }
-      }
-    end
-
-    it {
-      result = Issues::BulkUpdateService.new(@project, @user, @params).execute
-      result[:success].should be_true
-      result[:count].should == 1
-
-      @project.issues.first.milestone.should == @milestone
-    }
-  end
-
-end
diff --git a/spec/services/issues/bulk_update_service_spec.rb b/spec/services/issues/bulk_update_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a97c55011c91e8a4db4839a925f618eb6143af0f
--- /dev/null
+++ b/spec/services/issues/bulk_update_service_spec.rb
@@ -0,0 +1,121 @@
+require 'spec_helper'
+
+describe Issues::BulkUpdateService do
+  let(:issue) {
+    create(:issue, project: @project)
+  }
+
+  before do
+    @user = create :user
+    opts = {
+      name: "GitLab",
+      namespace: @user.namespace
+    }
+    @project = Projects::CreateService.new(@user, opts).execute
+  end
+
+  describe :close_issue do
+
+    before do
+      @issues = 5.times.collect do
+        create(:issue, project: @project)
+      end
+      @params = {
+        state_event: 'close',
+        issues_ids: @issues.map(&:id)
+      }
+    end
+
+    it {
+      result = Issues::BulkUpdateService.new(@project, @user, @params).execute
+      expect(result[:success]).to be_truthy
+      expect(result[:count]).to eq(@issues.count)
+
+      expect(@project.issues.opened).to be_empty
+      expect(@project.issues.closed).not_to be_empty
+    }
+
+  end
+
+  describe :reopen_issues do
+
+    before do
+      @issues = 5.times.collect do
+        create(:closed_issue, project: @project)
+      end
+      @params = {
+        state_event: 'reopen',
+        issues_ids: @issues.map(&:id)
+      }
+    end
+
+    it {
+      result = Issues::BulkUpdateService.new(@project, @user, @params).execute
+      expect(result[:success]).to be_truthy
+      expect(result[:count]).to eq(@issues.count)
+
+      expect(@project.issues.closed).to be_empty
+      expect(@project.issues.opened).not_to be_empty
+    }
+
+  end
+
+  describe :update_assignee do
+
+    before do
+      @new_assignee = create :user
+      @params = {
+        issues_ids: [issue.id],
+        assignee_id: @new_assignee.id
+      }
+    end
+
+    it {
+      result = Issues::BulkUpdateService.new(@project, @user, @params).execute
+      expect(result[:success]).to be_truthy
+      expect(result[:count]).to eq(1)
+
+      expect(@project.issues.first.assignee).to eq(@new_assignee)
+    }
+
+    it 'allows mass-unassigning' do
+      @project.issues.first.update_attribute(:assignee, @new_assignee)
+      expect(@project.issues.first.assignee).not_to be_nil
+
+      @params[:assignee_id] = -1
+
+      Issues::BulkUpdateService.new(@project, @user, @params).execute
+      expect(@project.issues.first.assignee).to be_nil
+    end
+
+    it 'does not unassign when assignee_id is not present' do
+      @project.issues.first.update_attribute(:assignee, @new_assignee)
+      expect(@project.issues.first.assignee).not_to be_nil
+
+      @params[:assignee_id] = ''
+
+      Issues::BulkUpdateService.new(@project, @user, @params).execute
+      expect(@project.issues.first.assignee).not_to be_nil
+    end
+  end
+
+  describe :update_milestone do
+
+    before do
+      @milestone = create :milestone
+      @params = {
+        issues_ids: [issue.id],
+        milestone_id: @milestone.id
+      }
+    end
+
+    it {
+      result = Issues::BulkUpdateService.new(@project, @user, @params).execute
+      expect(result[:success]).to be_truthy
+      expect(result[:count]).to eq(1)
+
+      expect(@project.issues.first.milestone).to eq(@milestone)
+    }
+  end
+
+end
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index d4f2cc1339bef8a917e1dacfc8cd325edd3e4f6c..d15dff1b52b24e1f17f8084d238b8151316eaacc 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -17,18 +17,18 @@ describe Issues::CloseService do
         @issue = Issues::CloseService.new(project, user, {}).execute(issue)
       end
 
-      it { @issue.should be_valid }
-      it { @issue.should be_closed }
+      it { expect(@issue).to be_valid }
+      it { expect(@issue).to be_closed }
 
       it 'should send email to user2 about assign of new issue' do
         email = ActionMailer::Base.deliveries.last
-        email.to.first.should == user2.email
-        email.subject.should include(issue.title)
+        expect(email.to.first).to eq(user2.email)
+        expect(email.subject).to include(issue.title)
       end
 
       it 'should create system note about issue reassign' do
         note = @issue.notes.last
-        note.note.should include "Status changed to closed"
+        expect(note.note).to include "Status changed to closed"
       end
     end
   end
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 90720be5ded3618eca088277014a943151a84ee4..7f1ebcb319897ce69b965524670ddadbc385666d 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -16,8 +16,8 @@ describe Issues::CreateService do
         @issue = Issues::CreateService.new(project, user, opts).execute
       end
 
-      it { @issue.should be_valid }
-      it { @issue.title.should == 'Awesome issue' }
+      it { expect(@issue).to be_valid }
+      it { expect(@issue.title).to eq('Awesome issue') }
     end
   end
 end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 347560414e78bbfb937aa3ada177153c05a84039..22b89bec96d0e032ecf6bdc6e0a404186fe7c008 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -5,6 +5,7 @@ describe Issues::UpdateService do
   let(:user) { create(:user) }
   let(:user2) { create(:user) }
   let(:issue) { create(:issue) }
+  let(:label) { create(:label) }
 
   before do
     project.team << [user, :master]
@@ -18,26 +19,35 @@ describe Issues::UpdateService do
           title: 'New title',
           description: 'Also please fix',
           assignee_id: user2.id,
-          state_event: 'close'
+          state_event: 'close',
+          label_ids: [label.id]
         }
 
         @issue = Issues::UpdateService.new(project, user, opts).execute(issue)
+        @issue.reload
       end
 
-      it { @issue.should be_valid }
-      it { @issue.title.should == 'New title' }
-      it { @issue.assignee.should == user2 }
-      it { @issue.should be_closed }
+      it { expect(@issue).to be_valid }
+      it { expect(@issue.title).to eq('New title') }
+      it { expect(@issue.assignee).to eq(user2) }
+      it { expect(@issue).to be_closed }
+      it { expect(@issue.labels.count).to eq(1) }
+      it { expect(@issue.labels.first.title).to eq('Bug') }
 
       it 'should send email to user2 about assign of new issue' do
         email = ActionMailer::Base.deliveries.last
-        email.to.first.should == user2.email
-        email.subject.should include(issue.title)
+        expect(email.to.first).to eq(user2.email)
+        expect(email.subject).to include(issue.title)
       end
 
       it 'should create system note about issue reassign' do
         note = @issue.notes.last
-        note.note.should include "Reassigned to \@#{user2.username}"
+        expect(note.note).to include "Reassigned to \@#{user2.username}"
+      end
+
+      it 'should create system note about issue label edit' do
+        note = @issue.notes[1]
+        expect(note.note).to include "Added ~#{label.id} label"
       end
     end
   end
diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb
index a504f916b08c6eaf17a21636b16ebb4c7318a507..b3cbfd4b5b8d8e9074b186300d10f41191a1a2cd 100644
--- a/spec/services/merge_requests/close_service_spec.rb
+++ b/spec/services/merge_requests/close_service_spec.rb
@@ -12,23 +12,32 @@ describe MergeRequests::CloseService do
   end
 
   describe :execute do
-    context "valid params" do
+    context 'valid params' do
+      let(:service) { MergeRequests::CloseService.new(project, user, {}) }
+
       before do
-        @merge_request = MergeRequests::CloseService.new(project, user, {}).execute(merge_request)
+        allow(service).to receive(:execute_hooks)
+
+        @merge_request = service.execute(merge_request)
       end
 
-      it { @merge_request.should be_valid }
-      it { @merge_request.should be_closed }
+      it { expect(@merge_request).to be_valid }
+      it { expect(@merge_request).to be_closed }
+
+      it 'should execute hooks with close action' do
+        expect(service).to have_received(:execute_hooks).
+                               with(@merge_request, 'close')
+      end
 
       it 'should send email to user2 about assign of new merge_request' do
         email = ActionMailer::Base.deliveries.last
-        email.to.first.should == user2.email
-        email.subject.should include(merge_request.title)
+        expect(email.to.first).to eq(user2.email)
+        expect(email.subject).to include(merge_request.title)
       end
 
       it 'should create system note about merge_request reassign' do
         note = @merge_request.notes.last
-        note.note.should include "Status changed to closed"
+        expect(note.note).to include 'Status changed to closed'
       end
     end
   end
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index cebeb0644d0b527aece51263bce35c44149ae3d9..d9bfdf643080752f3ede55ae554b7f590ba8d3c3 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -5,21 +5,30 @@ describe MergeRequests::CreateService do
   let(:user) { create(:user) }
 
   describe :execute do
-    context "valid params" do
-      before do
-        project.team << [user, :master]
-        opts = {
+    context 'valid params' do
+      let(:opts) do
+        {
           title: 'Awesome merge_request',
           description: 'please fix',
           source_branch: 'stable',
           target_branch: 'master'
         }
+      end
+      let(:service) { MergeRequests::CreateService.new(project, user, opts) }
+
+      before do
+        project.team << [user, :master]
+        allow(service).to receive(:execute_hooks)
 
-        @merge_request = MergeRequests::CreateService.new(project, user, opts).execute
+        @merge_request = service.execute
       end
 
-      it { @merge_request.should be_valid }
-      it { @merge_request.title.should == 'Awesome merge_request' }
+      it { expect(@merge_request).to be_valid }
+      it { expect(@merge_request.title).to eq('Awesome merge_request') }
+
+      it 'should execute hooks with default action' do
+        expect(service).to have_received(:execute_hooks).with(@merge_request)
+      end
     end
   end
 end
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0a25fb12f4eaa34e964f97349fa7cb5d9ff197f3
--- /dev/null
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe MergeRequests::MergeService do
+  let(:user) { create(:user) }
+  let(:user2) { create(:user) }
+  let(:merge_request) { create(:merge_request, assignee: user2) }
+  let(:project) { merge_request.project }
+
+  before do
+    project.team << [user, :master]
+    project.team << [user2, :developer]
+  end
+
+  describe :execute do
+    context 'valid params' do
+      let(:service) { MergeRequests::MergeService.new(project, user, {}) }
+
+      before do
+        allow(service).to receive(:execute_hooks)
+
+        service.execute(merge_request, 'Awesome message')
+      end
+
+      it { expect(merge_request).to be_valid }
+      it { expect(merge_request).to be_merged }
+
+      it 'should execute hooks with merge action' do
+        expect(service).to have_received(:execute_hooks).
+                               with(merge_request, 'merge')
+      end
+
+      it 'should send email to user2 about merge of new merge_request' do
+        email = ActionMailer::Base.deliveries.last
+        expect(email.to.first).to eq(user2.email)
+        expect(email.subject).to include(merge_request.title)
+      end
+
+      it 'should create system note about merge_request merge' do
+        note = merge_request.notes.last
+        expect(note.note).to include 'Status changed to merged'
+      end
+    end
+  end
+end
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 9f2941520532aef3e771aa60b742809f7a40066e..879df0c9c67655bfcf7880aab8c7e5cffe8bc0ac 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -35,10 +35,10 @@ describe MergeRequests::RefreshService do
         reload_mrs
       end
 
-      it { @merge_request.notes.should_not be_empty }
-      it { @merge_request.should be_open }
-      it { @fork_merge_request.should be_open }
-      it { @fork_merge_request.notes.should be_empty }
+      it { expect(@merge_request.notes).not_to be_empty }
+      it { expect(@merge_request).to be_open }
+      it { expect(@fork_merge_request).to be_open }
+      it { expect(@fork_merge_request.notes).to be_empty }
     end
 
     context 'push to origin repo target branch' do
@@ -47,10 +47,10 @@ describe MergeRequests::RefreshService do
         reload_mrs
       end
 
-      it { @merge_request.notes.should be_empty }
-      it { @merge_request.should be_merged }
-      it { @fork_merge_request.should be_merged }
-      it { @fork_merge_request.notes.should be_empty }
+      it { expect(@merge_request.notes.last.note).to include('changed to merged') }
+      it { expect(@merge_request).to be_merged }
+      it { expect(@fork_merge_request).to be_merged }
+      it { expect(@fork_merge_request.notes.last.note).to include('changed to merged') }
     end
 
     context 'push to fork repo source branch' do
@@ -59,10 +59,10 @@ describe MergeRequests::RefreshService do
         reload_mrs
       end
 
-      it { @merge_request.notes.should be_empty }
-      it { @merge_request.should be_open }
-      it { @fork_merge_request.notes.should_not be_empty }
-      it { @fork_merge_request.should be_open }
+      it { expect(@merge_request.notes).to be_empty }
+      it { expect(@merge_request).to be_open }
+      it { expect(@fork_merge_request.notes.last.note).to include('Added 4 commits') }
+      it { expect(@fork_merge_request).to be_open }
     end
 
     context 'push to fork repo target branch' do
@@ -71,10 +71,10 @@ describe MergeRequests::RefreshService do
         reload_mrs
       end
 
-      it { @merge_request.notes.should be_empty }
-      it { @merge_request.should be_open }
-      it { @fork_merge_request.notes.should be_empty }
-      it { @fork_merge_request.should be_open }
+      it { expect(@merge_request.notes).to be_empty }
+      it { expect(@merge_request).to be_open }
+      it { expect(@fork_merge_request.notes).to be_empty }
+      it { expect(@fork_merge_request).to be_open }
     end
 
     context 'push to origin repo target branch after fork project was removed' do
@@ -84,10 +84,10 @@ describe MergeRequests::RefreshService do
         reload_mrs
       end
 
-      it { @merge_request.notes.should be_empty }
-      it { @merge_request.should be_merged }
-      it { @fork_merge_request.should be_open }
-      it { @fork_merge_request.notes.should be_empty }
+      it { expect(@merge_request.notes.last.note).to include('changed to merged') }
+      it { expect(@merge_request).to be_merged }
+      it { expect(@fork_merge_request).to be_open }
+      it { expect(@fork_merge_request.notes).to be_empty }
     end
 
     def reload_mrs
diff --git a/spec/services/merge_requests/reopen_service_spec.rb b/spec/services/merge_requests/reopen_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9401bc3b55893ab47e734083b10d2dbd6cead703
--- /dev/null
+++ b/spec/services/merge_requests/reopen_service_spec.rb
@@ -0,0 +1,45 @@
+require 'spec_helper'
+
+describe MergeRequests::ReopenService do
+  let(:user) { create(:user) }
+  let(:user2) { create(:user) }
+  let(:merge_request) { create(:merge_request, assignee: user2) }
+  let(:project) { merge_request.project }
+
+  before do
+    project.team << [user, :master]
+    project.team << [user2, :developer]
+  end
+
+  describe :execute do
+    context 'valid params' do
+      let(:service) { MergeRequests::ReopenService.new(project, user, {}) }
+
+      before do
+        allow(service).to receive(:execute_hooks)
+
+        merge_request.state = :closed
+        service.execute(merge_request)
+      end
+
+      it { expect(merge_request).to be_valid }
+      it { expect(merge_request).to be_reopened }
+
+      it 'should execute hooks with reopen action' do
+        expect(service).to have_received(:execute_hooks).
+                               with(merge_request, 'reopen')
+      end
+
+      it 'should send email to user2 about reopen of merge_request' do
+        email = ActionMailer::Base.deliveries.last
+        expect(email.to.first).to eq(user2.email)
+        expect(email.subject).to include(merge_request.title)
+      end
+
+      it 'should create system note about merge_request reopen' do
+        note = merge_request.notes.last
+        expect(note.note).to include 'Status changed to reopened'
+      end
+    end
+  end
+end
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index af5d3a3dc817e0f9a727c15cc0e08dfd1a73141a..916b01e1c45e4a84403f52626623dd529ab9837e 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -5,6 +5,7 @@ describe MergeRequests::UpdateService do
   let(:user2) { create(:user) }
   let(:merge_request) { create(:merge_request, :simple) }
   let(:project) { merge_request.project }
+  let(:label) { create(:label) }
 
   before do
     project.team << [user, :master]
@@ -12,32 +13,52 @@ describe MergeRequests::UpdateService do
   end
 
   describe :execute do
-    context "valid params" do
-      before do
-        opts = {
+    context 'valid params' do
+      let(:opts) do
+        {
           title: 'New title',
           description: 'Also please fix',
           assignee_id: user2.id,
-          state_event: 'close'
+          state_event: 'close',
+          label_ids: [label.id]
         }
+      end
+
+      let(:service) { MergeRequests::UpdateService.new(project, user, opts) }
+
+      before do
+        allow(service).to receive(:execute_hooks)
 
-        @merge_request = MergeRequests::UpdateService.new(project, user, opts).execute(merge_request)
+        @merge_request = service.execute(merge_request)
+        @merge_request.reload
       end
 
-      it { @merge_request.should be_valid }
-      it { @merge_request.title.should == 'New title' }
-      it { @merge_request.assignee.should == user2 }
-      it { @merge_request.should be_closed }
+      it { expect(@merge_request).to be_valid }
+      it { expect(@merge_request.title).to eq('New title') }
+      it { expect(@merge_request.assignee).to eq(user2) }
+      it { expect(@merge_request).to be_closed }
+      it { expect(@merge_request.labels.count).to eq(1) }
+      it { expect(@merge_request.labels.first.title).to eq('Bug') }
+
+      it 'should execute hooks with update action' do
+        expect(service).to have_received(:execute_hooks).
+                               with(@merge_request, 'update')
+      end
 
       it 'should send email to user2 about assign of new merge_request' do
         email = ActionMailer::Base.deliveries.last
-        email.to.first.should == user2.email
-        email.subject.should include(merge_request.title)
+        expect(email.to.first).to eq(user2.email)
+        expect(email.subject).to include(merge_request.title)
       end
 
       it 'should create system note about merge_request reassign' do
         note = @merge_request.notes.last
-        note.note.should include "Reassigned to \@#{user2.username}"
+        expect(note.note).to include "Reassigned to \@#{user2.username}"
+      end
+
+      it 'should create system note about merge_request label edit' do
+        note = @merge_request.notes[1]
+        expect(note.note).to include "Added ~#{label.id} label"
       end
     end
   end
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index f59786efcf917266ee30b4ec0f934009c3f115a9..1a02299bf19c5f4b247d134b56c589396767ca43 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -18,8 +18,8 @@ describe Notes::CreateService do
         @note = Notes::CreateService.new(project, user, opts).execute
       end
 
-      it { @note.should be_valid }
-      it { @note.note.should == 'Awesome comment' }
+      it { expect(@note).to be_valid }
+      it { expect(@note.note).to eq('Awesome comment') }
     end
   end
 end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index f8377650e0a6193a2200f93868e4850d55bbf248..bfca2c88264354f7aca3f3abd5c06579ec18ccc0 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -7,10 +7,10 @@ describe NotificationService do
     describe :new_key do
       let!(:key) { create(:personal_key) }
 
-      it { notification.new_key(key).should be_true }
+      it { expect(notification.new_key(key)).to be_truthy }
 
       it 'should sent email to key owner' do
-        Notify.should_receive(:new_ssh_key_email).with(key.id)
+        expect(Notify).to receive(:new_ssh_key_email).with(key.id)
         notification.new_key(key)
       end
     end
@@ -20,10 +20,10 @@ describe NotificationService do
     describe :new_email do
       let!(:email) { create(:email) }
 
-      it { notification.new_email(email).should be_true }
+      it { expect(notification.new_email(email)).to be_truthy }
 
       it 'should send email to email owner' do
-        Notify.should_receive(:new_email_email).with(email.id)
+        expect(Notify).to receive(:new_email_email).with(email.id)
         notification.new_email(email)
       end
     end
@@ -41,20 +41,25 @@ describe NotificationService do
 
       describe :new_note do
         it do
+          add_users_with_subscription(note.project, issue)
+
           should_email(@u_watcher.id)
           should_email(note.noteable.author_id)
           should_email(note.noteable.assignee_id)
           should_email(@u_mentioned.id)
+          should_email(@subscriber.id)
           should_not_email(note.author_id)
           should_not_email(@u_participating.id)
           should_not_email(@u_disabled.id)
+          should_not_email(@unsubscriber.id)
+
           notification.new_note(note)
         end
 
         it 'filters out "mentioned in" notes' do
           mentioned_note = Note.create_cross_reference_note(mentioned_issue, issue, issue.author, issue.project)
 
-          Notify.should_not_receive(:note_issue_email)
+          expect(Notify).not_to receive(:note_issue_email)
           notification.new_note(mentioned_note)
         end
       end
@@ -69,9 +74,9 @@ describe NotificationService do
           user_project = note.project.project_members.find_by_user_id(@u_watcher.id)
           user_project.notification_level = Notification::N_PARTICIPATING
           user_project.save
-          user_group = note.project.group.group_members.find_by_user_id(@u_watcher.id)
-          user_group.notification_level = Notification::N_GLOBAL
-          user_group.save
+          group_member = note.project.group.group_members.find_by_user_id(@u_watcher.id)
+          group_member.notification_level = Notification::N_GLOBAL
+          group_member.save
         end
 
         it do
@@ -87,11 +92,11 @@ describe NotificationService do
       end
 
       def should_email(user_id)
-        Notify.should_receive(:note_issue_email).with(user_id, note.id)
+        expect(Notify).to receive(:note_issue_email).with(user_id, note.id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:note_issue_email).with(user_id, note.id)
+        expect(Notify).not_to receive(:note_issue_email).with(user_id, note.id)
       end
     end
 
@@ -116,6 +121,7 @@ describe NotificationService do
           should_email(note.noteable.assignee_id)
 
           should_not_email(note.author_id)
+          should_not_email(@u_mentioned.id)
           should_not_email(@u_disabled.id)
           should_not_email(@u_not_mentioned.id)
           notification.new_note(note)
@@ -124,17 +130,17 @@ describe NotificationService do
         it 'filters out "mentioned in" notes' do
           mentioned_note = Note.create_cross_reference_note(mentioned_issue, issue, issue.author, issue.project)
 
-          Notify.should_not_receive(:note_issue_email)
+          expect(Notify).not_to receive(:note_issue_email)
           notification.new_note(mentioned_note)
         end
       end
 
       def should_email(user_id)
-        Notify.should_receive(:note_issue_email).with(user_id, note.id)
+        expect(Notify).to receive(:note_issue_email).with(user_id, note.id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:note_issue_email).with(user_id, note.id)
+        expect(Notify).not_to receive(:note_issue_email).with(user_id, note.id)
       end
     end
 
@@ -168,39 +174,54 @@ describe NotificationService do
           notification.new_note(note)
         end
 
+        it do
+          @u_committer.update_attributes(notification_level: Notification::N_MENTION)
+          should_not_email(@u_committer.id, note)
+          notification.new_note(note)
+        end
+
         def should_email(user_id, n)
-          Notify.should_receive(:note_commit_email).with(user_id, n.id)
+          expect(Notify).to receive(:note_commit_email).with(user_id, n.id)
         end
 
         def should_not_email(user_id, n)
-          Notify.should_not_receive(:note_commit_email).with(user_id, n.id)
+          expect(Notify).not_to receive(:note_commit_email).with(user_id, n.id)
         end
       end
     end
   end
 
   describe 'Issues' do
-    let(:issue) { create :issue, assignee: create(:user) }
+    let(:issue) { create :issue, assignee: create(:user), description: 'cc @participant' }
 
     before do
       build_team(issue.project)
+      add_users_with_subscription(issue.project, issue)
     end
 
     describe :new_issue do
       it do
         should_email(issue.assignee_id)
         should_email(@u_watcher.id)
+        should_email(@u_participant_mentioned.id)
+        should_not_email(@u_mentioned.id)
         should_not_email(@u_participating.id)
         should_not_email(@u_disabled.id)
         notification.new_issue(issue, @u_disabled)
       end
 
+      it do
+        issue.assignee.update_attributes(notification_level: Notification::N_MENTION)
+        should_not_email(issue.assignee_id)
+        notification.new_issue(issue, @u_disabled)
+      end
+
       def should_email(user_id)
-        Notify.should_receive(:new_issue_email).with(user_id, issue.id)
+        expect(Notify).to receive(:new_issue_email).with(user_id, issue.id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:new_issue_email).with(user_id, issue.id)
+        expect(Notify).not_to receive(:new_issue_email).with(user_id, issue.id)
       end
     end
 
@@ -208,6 +229,9 @@ describe NotificationService do
       it 'should email new assignee' do
         should_email(issue.assignee_id)
         should_email(@u_watcher.id)
+        should_email(@u_participant_mentioned.id)
+        should_email(@subscriber.id)
+        should_not_email(@unsubscriber.id)
         should_not_email(@u_participating.id)
         should_not_email(@u_disabled.id)
 
@@ -215,11 +239,11 @@ describe NotificationService do
       end
 
       def should_email(user_id)
-        Notify.should_receive(:reassigned_issue_email).with(user_id, issue.id, nil, @u_disabled.id)
+        expect(Notify).to receive(:reassigned_issue_email).with(user_id, issue.id, nil, @u_disabled.id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id, @u_disabled.id)
+        expect(Notify).not_to receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id, @u_disabled.id)
       end
     end
 
@@ -228,6 +252,9 @@ describe NotificationService do
         should_email(issue.assignee_id)
         should_email(issue.author_id)
         should_email(@u_watcher.id)
+        should_email(@u_participant_mentioned.id)
+        should_email(@subscriber.id)
+        should_not_email(@unsubscriber.id)
         should_not_email(@u_participating.id)
         should_not_email(@u_disabled.id)
 
@@ -235,11 +262,11 @@ describe NotificationService do
       end
 
       def should_email(user_id)
-        Notify.should_receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id)
+        expect(Notify).to receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id)
+        expect(Notify).not_to receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id)
       end
     end
 
@@ -248,6 +275,9 @@ describe NotificationService do
         should_email(issue.assignee_id)
         should_email(issue.author_id)
         should_email(@u_watcher.id)
+        should_email(@u_participant_mentioned.id)
+        should_email(@subscriber.id)
+        should_not_email(@unsubscriber.id)
         should_not_email(@u_participating.id)
         should_not_email(@u_disabled.id)
 
@@ -255,11 +285,11 @@ describe NotificationService do
       end
 
       def should_email(user_id)
-        Notify.should_receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id)
+        expect(Notify).to receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id)
+        expect(Notify).not_to receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id)
       end
     end
   end
@@ -269,6 +299,7 @@ describe NotificationService do
 
     before do
       build_team(merge_request.target_project)
+      add_users_with_subscription(merge_request.target_project, merge_request)
     end
 
     describe :new_merge_request do
@@ -281,11 +312,11 @@ describe NotificationService do
       end
 
       def should_email(user_id)
-        Notify.should_receive(:new_merge_request_email).with(user_id, merge_request.id)
+        expect(Notify).to receive(:new_merge_request_email).with(user_id, merge_request.id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:new_merge_request_email).with(user_id, merge_request.id)
+        expect(Notify).not_to receive(:new_merge_request_email).with(user_id, merge_request.id)
       end
     end
 
@@ -293,17 +324,19 @@ describe NotificationService do
       it do
         should_email(merge_request.assignee_id)
         should_email(@u_watcher.id)
+        should_email(@subscriber.id)
+        should_not_email(@unsubscriber.id)
         should_not_email(@u_participating.id)
         should_not_email(@u_disabled.id)
         notification.reassigned_merge_request(merge_request, merge_request.author)
       end
 
       def should_email(user_id)
-        Notify.should_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, nil, merge_request.author_id)
+        expect(Notify).to receive(:reassigned_merge_request_email).with(user_id, merge_request.id, nil, merge_request.author_id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id, merge_request.author_id)
+        expect(Notify).not_to receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id, merge_request.author_id)
       end
     end
 
@@ -311,17 +344,19 @@ describe NotificationService do
       it do
         should_email(merge_request.assignee_id)
         should_email(@u_watcher.id)
+        should_email(@subscriber.id)
+        should_not_email(@unsubscriber.id)
         should_not_email(@u_participating.id)
         should_not_email(@u_disabled.id)
         notification.close_mr(merge_request, @u_disabled)
       end
 
       def should_email(user_id)
-        Notify.should_receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
+        expect(Notify).to receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
+        expect(Notify).not_to receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
       end
     end
 
@@ -329,17 +364,19 @@ describe NotificationService do
       it do
         should_email(merge_request.assignee_id)
         should_email(@u_watcher.id)
+        should_email(@subscriber.id)
+        should_not_email(@unsubscriber.id)
         should_not_email(@u_participating.id)
         should_not_email(@u_disabled.id)
         notification.merge_mr(merge_request, @u_disabled)
       end
 
       def should_email(user_id)
-        Notify.should_receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
+        expect(Notify).to receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
+        expect(Notify).not_to receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id)
       end
     end
 
@@ -347,17 +384,19 @@ describe NotificationService do
       it do
         should_email(merge_request.assignee_id)
         should_email(@u_watcher.id)
+        should_email(@subscriber.id)
+        should_not_email(@unsubscriber.id)
         should_not_email(@u_participating.id)
         should_not_email(@u_disabled.id)
         notification.reopen_mr(merge_request, @u_disabled)
       end
 
       def should_email(user_id)
-        Notify.should_receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id)
+        expect(Notify).to receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id)
+        expect(Notify).not_to receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id)
       end
     end
   end
@@ -378,11 +417,11 @@ describe NotificationService do
       end
 
       def should_email(user_id)
-        Notify.should_receive(:project_was_moved_email).with(project.id, user_id)
+        expect(Notify).to receive(:project_was_moved_email).with(project.id, user_id)
       end
 
       def should_not_email(user_id)
-        Notify.should_not_receive(:project_was_moved_email).with(project.id, user_id)
+        expect(Notify).not_to receive(:project_was_moved_email).with(project.id, user_id)
       end
     end
   end
@@ -390,8 +429,9 @@ describe NotificationService do
   def build_team(project)
     @u_watcher = create(:user, notification_level: Notification::N_WATCH)
     @u_participating = create(:user, notification_level: Notification::N_PARTICIPATING)
+    @u_participant_mentioned = create(:user, username: 'participant', notification_level: Notification::N_PARTICIPATING)
     @u_disabled = create(:user, notification_level: Notification::N_DISABLED)
-    @u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_PARTICIPATING)
+    @u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_MENTION)
     @u_committer = create(:user, username: 'committer')
     @u_not_mentioned = create(:user, username: 'regular', notification_level: Notification::N_PARTICIPATING)
 
@@ -401,4 +441,15 @@ describe NotificationService do
     project.team << [@u_mentioned, :master]
     project.team << [@u_committer, :master]
   end
+
+  def add_users_with_subscription(project, issuable)
+    @subscriber = create :user
+    @unsubscriber = create :user
+
+    project.team << [@subscriber, :master]
+    project.team << [@unsubscriber, :master]
+
+    issuable.subscriptions.create(user: @subscriber, subscribed: true)
+    issuable.subscriptions.create(user: @unsubscriber, subscribed: false)
+  end
 end
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index 9c97dad2ff014b2d7499307bf71516a4fc4927ce..337dae592dd488024653093b2c918ec94880c2bc 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -16,9 +16,9 @@ describe Projects::CreateService do
         @project = create_project(@user, @opts)
       end
 
-      it { @project.should be_valid }
-      it { @project.owner.should == @user }
-      it { @project.namespace.should == @user.namespace }
+      it { expect(@project).to be_valid }
+      it { expect(@project.owner).to eq(@user) }
+      it { expect(@project.namespace).to eq(@user.namespace) }
     end
 
     context 'group namespace' do
@@ -30,9 +30,9 @@ describe Projects::CreateService do
         @project = create_project(@user, @opts)
       end
 
-      it { @project.should be_valid }
-      it { @project.owner.should == @group }
-      it { @project.namespace.should == @group }
+      it { expect(@project).to be_valid }
+      it { expect(@project.owner).to eq(@group) }
+      it { expect(@project.namespace).to eq(@group) }
     end
 
     context 'wiki_enabled creates repository directory' do
@@ -42,7 +42,7 @@ describe Projects::CreateService do
           @path = ProjectWiki.new(@project, @user).send(:path_to_repo)
         end
 
-        it { File.exists?(@path).should be_true }
+        it { expect(File.exists?(@path)).to be_truthy }
       end
 
       context 'wiki_enabled false does not create wiki repository directory' do
@@ -52,7 +52,34 @@ describe Projects::CreateService do
           @path = ProjectWiki.new(@project, @user).send(:path_to_repo)
         end
 
-        it { File.exists?(@path).should be_false }
+        it { expect(File.exists?(@path)).to be_falsey }
+      end
+    end
+
+    context 'restricted visibility level' do
+      before do
+        allow_any_instance_of(ApplicationSetting).to(
+          receive(:restricted_visibility_levels).and_return([20])
+        )
+
+        @opts.merge!(
+          visibility_level: Gitlab::VisibilityLevel.options['Public']
+        )
+      end
+
+      it 'should not allow a restricted visibility level for non-admins' do
+        project = create_project(@user, @opts)
+        expect(project).to respond_to(:errors)
+        expect(project.errors.messages).to have_key(:visibility_level)
+        expect(project.errors.messages[:visibility_level].first).to(
+          match('restricted by your GitLab administrator')
+        )
+      end
+
+      it 'should allow a restricted visibility level for admins' do
+        project = create_project(@admin, @opts)
+        expect(project.errors.any?).to be(false)
+        expect(project.saved?).to be(true)
       end
     end
   end
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index 0edc3a8e8076846477ad7938dee5ae9bfb37fc1c..e55a2e3f8a0d8c5f1ac6f1194a014b9a8cc1bcbb 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -16,18 +16,18 @@ describe Projects::ForkService do
       describe "successfully creates project in the user namespace" do
         let(:to_project) { fork_project(@from_project, @to_user) }
 
-        it { to_project.owner.should == @to_user }
-        it { to_project.namespace.should == @to_user.namespace }
-        it { to_project.star_count.should be_zero }
-        it { to_project.description.should == @from_project.description }
+        it { expect(to_project.owner).to eq(@to_user) }
+        it { expect(to_project.namespace).to eq(@to_user.namespace) }
+        it { expect(to_project.star_count).to be_zero }
+        it { expect(to_project.description).to eq(@from_project.description) }
       end
     end
 
     context 'fork project failure' do
       it "fails due to transaction failure" do
         @to_project = fork_project(@from_project, @to_user, false)
-        @to_project.errors.should_not be_empty
-        @to_project.errors[:base].should include("Fork transaction failed.")
+        expect(@to_project.errors).not_to be_empty
+        expect(@to_project.errors[:base]).to include("Fork transaction failed.")
       end
     end
 
@@ -35,17 +35,61 @@ describe Projects::ForkService do
       it "should fail due to validation, not transaction failure" do
         @existing_project = create(:project, creator_id: @to_user.id, name: @from_project.name, namespace: @to_namespace)
         @to_project = fork_project(@from_project, @to_user)
-        @existing_project.persisted?.should be_true
-        @to_project.errors[:base].should include("Invalid fork destination")
-        @to_project.errors[:base].should_not include("Fork transaction failed.")
+        expect(@existing_project.persisted?).to be_truthy
+        expect(@to_project.errors[:base]).to include("Invalid fork destination")
+        expect(@to_project.errors[:base]).not_to include("Fork transaction failed.")
       end
     end
   end
 
-  def fork_project(from_project, user, fork_success = true)
-    context = Projects::ForkService.new(from_project, user)
-    shell = double("gitlab_shell")
-    shell.stub(fork_repository: fork_success)
+  describe :fork_to_namespace do
+    before do
+      @group_owner = create(:user)
+      @developer   = create(:user)
+      @project     = create(:project, creator_id: @group_owner.id,
+                                      star_count: 777,
+                                      description: 'Wow, such a cool project!')
+      @group = create(:group)
+      @group.add_user(@group_owner, GroupMember::OWNER)
+      @group.add_user(@developer,   GroupMember::DEVELOPER)
+      @opts = { namespace: @group }
+    end
+
+    context 'fork project for group' do
+      it 'group owner successfully forks project into the group' do
+        to_project = fork_project(@project, @group_owner, true, @opts)
+        expect(to_project.owner).to       eq(@group)
+        expect(to_project.namespace).to   eq(@group)
+        expect(to_project.name).to        eq(@project.name)
+        expect(to_project.path).to        eq(@project.path)
+        expect(to_project.description).to eq(@project.description)
+        expect(to_project.star_count).to     be_zero
+      end
+    end
+
+    context 'fork project for group when user not owner' do
+      it 'group developer should fail to fork project into the group' do
+        to_project = fork_project(@project, @developer, true, @opts)
+        expect(to_project.errors[:namespace]).to eq(['insufficient access rights'])
+      end
+    end
+
+    context 'project already exists in group' do
+      it 'should fail due to validation, not transaction failure' do
+        existing_project = create(:project, name: @project.name,
+                                            namespace: @group)
+        to_project = fork_project(@project, @group_owner, true, @opts)
+        expect(existing_project.persisted?).to be_truthy
+        expect(to_project.errors[:base]).to eq(['Invalid fork destination'])
+        expect(to_project.errors[:name]).to eq(['has already been taken'])
+        expect(to_project.errors[:path]).to eq(['has already been taken'])
+      end
+    end
+  end
+
+  def fork_project(from_project, user, fork_success = true, params = {})
+    context = Projects::ForkService.new(from_project, user, params)
+    shell = double('gitlab_shell').stub(fork_repository: fork_success)
     context.stub(gitlab_shell: shell)
     context.execute
   end
diff --git a/spec/services/projects/image_service_spec.rb b/spec/services/projects/image_service_spec.rb
deleted file mode 100644
index 23c4e227ae303ed6534eeb591650ba3e1b7cc6f5..0000000000000000000000000000000000000000
--- a/spec/services/projects/image_service_spec.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-require 'spec_helper'
-
-describe Projects::ImageService do
-  describe 'Image service' do
-    before do
-      @user = create :user
-      @project = create :project, creator_id: @user.id, namespace: @user.namespace
-    end
-
-    context 'for valid gif file' do
-      before do
-        gif = fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif')
-        @link_to_image = upload_image(@project.repository, { 'markdown_img' => gif }, "http://test.example/")
-      end
-
-      it { expect(@link_to_image).to have_key("alt") }
-      it { expect(@link_to_image).to have_key("url") }
-      it { expect(@link_to_image).to have_value("banana_sample") }
-      it { expect(@link_to_image["url"]).to match("http://test.example/uploads/#{@project.path_with_namespace}") }
-      it { expect(@link_to_image["url"]).to match("banana_sample.gif") }
-    end
-
-     context 'for valid png file' do
-      before do
-        png = fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/png')
-        @link_to_image = upload_image(@project.repository, { 'markdown_img' => png }, "http://test.example/")
-      end
-
-      it { expect(@link_to_image).to have_key("alt") }
-      it { expect(@link_to_image).to have_key("url") }
-      it { expect(@link_to_image).to have_value("dk") }
-      it { expect(@link_to_image["url"]).to match("http://test.example/uploads/#{@project.path_with_namespace}") }
-      it { expect(@link_to_image["url"]).to match("dk.png") }
-    end
-
-     context 'for valid jpg file' do
-      before do
-        jpg = fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg')
-        @link_to_image = upload_image(@project.repository, { 'markdown_img' => jpg }, "http://test.example/")
-      end
-
-      it { expect(@link_to_image).to have_key("alt") }
-      it { expect(@link_to_image).to have_key("url") }
-      it { expect(@link_to_image).to have_value("rails_sample") }
-      it { expect(@link_to_image["url"]).to match("http://test.example/uploads/#{@project.path_with_namespace}") }
-      it { expect(@link_to_image["url"]).to match("rails_sample.jpg") }
-    end
-
-    context 'for txt file' do
-      before do
-        txt = fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain')
-        @link_to_image = upload_image(@project.repository, { 'markdown_img' => txt }, "http://test.example/")
-      end
-
-      it { expect(@link_to_image).to be_nil }
-    end
-  end
-
-  def upload_image(repository, params, root_url)
-    Projects::ImageService.new(repository, params, root_url).execute
-  end
-end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index 79d0526ff89cb3b1d2a8793a3b456f304b2a426e..5650626fb18428cc082776a9bbb6169da491ebfb 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -8,31 +8,31 @@ describe Projects::TransferService do
   context 'namespace -> namespace' do
     before do
       group.add_owner(user)
-      @result = transfer_project(project, user, namespace_id: group.id)
+      @result = transfer_project(project, user, new_namespace_id: group.id)
     end
 
-    it { @result.should be_true }
-    it { project.namespace.should == group }
+    it { expect(@result).to be_truthy }
+    it { expect(project.namespace).to eq(group) }
   end
 
   context 'namespace -> no namespace' do
     before do
-      @result = transfer_project(project, user, namespace_id: nil)
+      @result = transfer_project(project, user, new_namespace_id: nil)
     end
 
-    it { @result.should_not be_nil } # { result.should be_false } passes on nil
-    it { @result.should be_false }
-    it { project.namespace.should == user.namespace }
+    it { expect(@result).not_to be_nil } # { result.should be_false } passes on nil
+    it { expect(@result).to be_falsey }
+    it { expect(project.namespace).to eq(user.namespace) }
   end
 
   context 'namespace -> not allowed namespace' do
     before do
-      @result = transfer_project(project, user, namespace_id: group.id)
+      @result = transfer_project(project, user, new_namespace_id: group.id)
     end
 
-    it { @result.should_not be_nil } # { result.should be_false } passes on nil
-    it { @result.should be_false }
-    it { project.namespace.should == user.namespace }
+    it { expect(@result).not_to be_nil } # { result.should be_false } passes on nil
+    it { expect(@result).to be_falsey }
+    it { expect(project.namespace).to eq(user.namespace) }
   end
 
   def transfer_project(project, user, params)
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index 5a10174eb36b6ee52b4b9a52c4380ec08c181b24..ea5b8813105ca7f1a7b6f4585e2ebb2c8a341ac3 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -17,8 +17,8 @@ describe Projects::UpdateService do
         update_project(@project, @user, @opts)
       end
 
-      it { @created_private.should be_true }
-      it { @project.private?.should be_true }
+      it { expect(@created_private).to be_truthy }
+      it { expect(@project.private?).to be_truthy }
     end
 
     context 'should be internal when updated to internal' do
@@ -29,8 +29,8 @@ describe Projects::UpdateService do
         update_project(@project, @user, @opts)
       end
 
-      it { @created_private.should be_true }
-      it { @project.internal?.should be_true }
+      it { expect(@created_private).to be_truthy }
+      it { expect(@project.internal?).to be_truthy }
     end
 
     context 'should be public when updated to public' do
@@ -41,15 +41,15 @@ describe Projects::UpdateService do
         update_project(@project, @user, @opts)
       end
 
-      it { @created_private.should be_true }
-      it { @project.public?.should be_true }
+      it { expect(@created_private).to be_truthy }
+      it { expect(@project.public?).to be_truthy }
     end
 
     context 'respect configured visibility restrictions setting' do
       before(:each) do
-        @restrictions = double("restrictions")
-        @restrictions.stub(:restricted_visibility_levels) { [ "public" ] }
-        Settings.stub_chain(:gitlab).and_return(@restrictions)
+        allow_any_instance_of(ApplicationSetting).to(
+          receive(:restricted_visibility_levels).and_return([20])
+        )
       end
 
       context 'should be private when updated to private' do
@@ -60,8 +60,8 @@ describe Projects::UpdateService do
           update_project(@project, @user, @opts)
         end
 
-        it { @created_private.should be_true }
-        it { @project.private?.should be_true }
+        it { expect(@created_private).to be_truthy }
+        it { expect(@project.private?).to be_truthy }
       end
 
       context 'should be internal when updated to internal' do
@@ -72,8 +72,8 @@ describe Projects::UpdateService do
           update_project(@project, @user, @opts)
         end
 
-        it { @created_private.should be_true }
-        it { @project.internal?.should be_true }
+        it { expect(@created_private).to be_truthy }
+        it { expect(@project.internal?).to be_truthy }
       end
 
       context 'should be private when updated to public' do
@@ -84,8 +84,8 @@ describe Projects::UpdateService do
           update_project(@project, @user, @opts)
         end
 
-        it { @created_private.should be_true }
-        it { @project.private?.should be_true }
+        it { expect(@created_private).to be_truthy }
+        it { expect(@project.private?).to be_truthy }
       end
 
       context 'should be public when updated to public by admin' do
@@ -96,8 +96,8 @@ describe Projects::UpdateService do
           update_project(@project, @admin, @opts)
         end
 
-        it { @created_private.should be_true }
-        it { @project.public?.should be_true }
+        it { expect(@created_private).to be_truthy }
+        it { expect(@project.public?).to be_truthy }
       end
     end
   end
diff --git a/spec/services/projects/upload_service_spec.rb b/spec/services/projects/upload_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fc34b45648262fd4345d04aa6e4ba59cc913f24b
--- /dev/null
+++ b/spec/services/projects/upload_service_spec.rb
@@ -0,0 +1,75 @@
+require 'spec_helper'
+
+describe Projects::UploadService do
+  describe 'File service' do
+    before do
+      @user = create :user
+      @project = create :project, creator_id: @user.id, namespace: @user.namespace
+    end
+
+    context 'for valid gif file' do
+      before do
+        gif = fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif')
+        @link_to_file = upload_file(@project.repository, gif)
+      end
+
+      it { expect(@link_to_file).to have_key('alt') }
+      it { expect(@link_to_file).to have_key('url') }
+      it { expect(@link_to_file).to have_key('is_image') }
+      it { expect(@link_to_file).to have_value('banana_sample') }
+      it { expect(@link_to_file['is_image']).to equal(true) }
+      it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") }
+      it { expect(@link_to_file['url']).to match('banana_sample.gif') }
+    end
+
+     context 'for valid png file' do
+      before do
+        png = fixture_file_upload(Rails.root + 'spec/fixtures/dk.png',
+          'image/png')
+        @link_to_file = upload_file(@project.repository, png)
+      end
+
+      it { expect(@link_to_file).to have_key('alt') }
+      it { expect(@link_to_file).to have_key('url') }
+      it { expect(@link_to_file).to have_value('dk') }
+      it { expect(@link_to_file).to have_key('is_image') }
+      it { expect(@link_to_file['is_image']).to equal(true) }
+      it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") }
+      it { expect(@link_to_file['url']).to match('dk.png') }
+    end
+
+     context 'for valid jpg file' do
+      before do
+        jpg = fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg')
+        @link_to_file = upload_file(@project.repository, jpg)
+      end
+
+      it { expect(@link_to_file).to have_key('alt') }
+      it { expect(@link_to_file).to have_key('url') }
+      it { expect(@link_to_file).to have_key('is_image') }
+      it { expect(@link_to_file).to have_value('rails_sample') }
+      it { expect(@link_to_file['is_image']).to equal(true) }
+      it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") }
+      it { expect(@link_to_file['url']).to match('rails_sample.jpg') }
+    end
+
+    context 'for txt file' do
+      before do
+        txt = fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain')
+        @link_to_file = upload_file(@project.repository, txt)
+      end
+
+      it { expect(@link_to_file).to have_key('alt') }
+      it { expect(@link_to_file).to have_key('url') }
+      it { expect(@link_to_file).to have_key('is_image') }
+      it { expect(@link_to_file).to have_value('doc_sample.txt') }
+      it { expect(@link_to_file['is_image']).to equal(false) }
+      it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") }
+      it { expect(@link_to_file['url']).to match('doc_sample.txt') }
+    end
+  end
+
+  def upload_file(repository, file)
+    Projects::UploadService.new(repository, file).execute
+  end
+end
diff --git a/spec/services/search_service_spec.rb b/spec/services/search_service_spec.rb
index 3217c571e67a6072cf0ab97bfd8813cce09b24aa..f57bfaea8798f19d0ca7fe145494324b8fd73c3b 100644
--- a/spec/services/search_service_spec.rb
+++ b/spec/services/search_service_spec.rb
@@ -19,7 +19,7 @@ describe 'Search::GlobalService' do
       it 'should return public projects only' do
         context = Search::GlobalService.new(nil, search: "searchable")
         results = context.execute
-        results.objects('projects').should match_array [public_project]
+        expect(results.objects('projects')).to match_array [public_project]
       end
     end
 
@@ -27,19 +27,19 @@ describe 'Search::GlobalService' do
       it 'should return public, internal and private projects' do
         context = Search::GlobalService.new(user, search: "searchable")
         results = context.execute
-        results.objects('projects').should match_array [public_project, found_project, internal_project]
+        expect(results.objects('projects')).to match_array [public_project, found_project, internal_project]
       end
 
       it 'should return only public & internal projects' do
         context = Search::GlobalService.new(internal_user, search: "searchable")
         results = context.execute
-        results.objects('projects').should match_array [internal_project, public_project]
+        expect(results.objects('projects')).to match_array [internal_project, public_project]
       end
 
       it 'namespace name should be searchable' do
         context = Search::GlobalService.new(user, search: found_project.namespace.path)
         results = context.execute
-        results.objects('projects').should match_array [found_project]
+        expect(results.objects('projects')).to match_array [found_project]
       end
     end
   end
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index 573446d3a190dab2c564ee60ea7a711f2af2fd69..199ac9966087ae5ed2162d856cc194a5e3b96765 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -5,27 +5,58 @@ describe SystemHooksService do
   let (:project)       { create :project }
   let (:project_member) { create :project_member }
   let (:key)           { create(:key, user: user) }
+  let (:group)         { create(:group) }
+  let (:group_member)  { create(:group_member) }
 
   context 'event data' do
-    it { event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id) }
-    it { event_data(user, :destroy).should include(:event_name, :name, :created_at, :email, :user_id) }
-    it { event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
-    it { event_data(project, :destroy).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
-    it { event_data(project_member, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
-    it { event_data(project_member, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
-    it { event_data(key, :create).should include(:username, :key, :id) }
-    it { event_data(key, :destroy).should include(:username, :key, :id) }
+    it { expect(event_data(user, :create)).to include(:event_name, :name, :created_at, :email, :user_id) }
+    it { expect(event_data(user, :destroy)).to include(:event_name, :name, :created_at, :email, :user_id) }
+    it { expect(event_data(project, :create)).to include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
+    it { expect(event_data(project, :destroy)).to include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
+    it { expect(event_data(project_member, :create)).to include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
+    it { expect(event_data(project_member, :destroy)).to include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
+    it { expect(event_data(key, :create)).to include(:username, :key, :id) }
+    it { expect(event_data(key, :destroy)).to include(:username, :key, :id) }
+
+    it do
+      expect(event_data(group, :create)).to include(
+        :event_name, :name, :created_at, :path, :group_id, :owner_name,
+        :owner_email
+      )
+    end
+    it do
+      expect(event_data(group, :destroy)).to include(
+        :event_name, :name, :created_at, :path, :group_id, :owner_name,
+        :owner_email
+      )
+    end
+    it do
+      expect(event_data(group_member, :create)).to include(
+        :event_name, :created_at, :group_name, :group_path, :group_id, :user_id,
+        :user_name, :user_email, :group_access
+      )
+    end
+    it do
+      expect(event_data(group_member, :destroy)).to include(
+        :event_name, :created_at, :group_name, :group_path, :group_id, :user_id,
+        :user_name, :user_email, :group_access
+      )
+    end
   end
 
   context 'event names' do
-    it { event_name(user, :create).should eq "user_create" }
-    it { event_name(user, :destroy).should eq "user_destroy" }
-    it { event_name(project, :create).should eq "project_create" }
-    it { event_name(project, :destroy).should eq "project_destroy" }
-    it { event_name(project_member, :create).should eq "user_add_to_team" }
-    it { event_name(project_member, :destroy).should eq "user_remove_from_team" }
-    it { event_name(key, :create).should eq 'key_create' }
-    it { event_name(key, :destroy).should eq 'key_destroy' }
+    it { expect(event_name(user, :create)).to eq "user_create" }
+    it { expect(event_name(user, :destroy)).to eq "user_destroy" }
+    it { expect(event_name(project, :create)).to eq "project_create" }
+    it { expect(event_name(project, :destroy)).to eq "project_destroy" }
+    it { expect(event_name(project_member, :create)).to eq "user_add_to_team" }
+    it { expect(event_name(project_member, :destroy)).to eq "user_remove_from_team" }
+    it { expect(event_name(key, :create)).to eq 'key_create' }
+    it { expect(event_name(key, :destroy)).to eq 'key_destroy' }
+    it { expect(event_name(group, :create)).to eq 'group_create' }
+    it { expect(event_name(group, :destroy)).to eq 'group_destroy' }
+    it { expect(event_name(group_member, :create)).to eq 'user_add_to_group' }
+    it { expect(event_name(group_member, :destroy)).to eq 'user_remove_from_group' }
   end
 
   def event_data(*args)
diff --git a/spec/services/test_hook_service_spec.rb b/spec/services/test_hook_service_spec.rb
index 76af5bf7b88c9071e38bcad0f49d26b6bcdb40ec..d2b505f55a250bbc4ab2a9440abde3d8f060a8a2 100644
--- a/spec/services/test_hook_service_spec.rb
+++ b/spec/services/test_hook_service_spec.rb
@@ -8,7 +8,7 @@ describe TestHookService do
   describe :execute do
     it "should execute successfully" do
       stub_request(:post, hook.url).to_return(status: 200)
-      TestHookService.new.execute(hook, user).should be_true
+      expect(TestHookService.new.execute(hook, user)).to be_truthy
     end
   end
 end
diff --git a/spec/services/update_snippet_service_spec.rb b/spec/services/update_snippet_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..841ef9bfed11e5e037b686e80a5f0ecfbae2e97a
--- /dev/null
+++ b/spec/services/update_snippet_service_spec.rb
@@ -0,0 +1,52 @@
+require 'spec_helper'
+
+describe UpdateSnippetService do
+  before do
+    @user = create :user
+    @admin = create :user, admin: true
+    @opts = {
+      title: 'Test snippet',
+      file_name: 'snippet.rb',
+      content: 'puts "hello world"',
+      visibility_level: Gitlab::VisibilityLevel::PRIVATE
+    }
+  end
+
+  context 'When public visibility is restricted' do
+    before do
+      allow_any_instance_of(ApplicationSetting).to(
+        receive(:restricted_visibility_levels).and_return(
+          [Gitlab::VisibilityLevel::PUBLIC]
+        )
+      )
+
+      @snippet = create_snippet(@project, @user, @opts)
+      @opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+    end
+
+    it 'non-admins should not be able to update to public visibility' do
+      old_visibility = @snippet.visibility_level
+      update_snippet(@project, @user, @snippet, @opts)
+      expect(@snippet.errors.messages).to have_key(:visibility_level)
+      expect(@snippet.errors.messages[:visibility_level].first).to(
+        match('Public visibility has been restricted')
+      )
+      expect(@snippet.visibility_level).to eq(old_visibility)
+    end
+
+    it 'admins should be able to update to pubic visibility' do
+      old_visibility = @snippet.visibility_level
+      update_snippet(@project, @admin, @snippet, @opts)
+      expect(@snippet.visibility_level).not_to eq(old_visibility)
+      expect(@snippet.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
+    end
+  end
+
+  def create_snippet(project, user, opts)
+    CreateSnippetService.new(project, user, opts).execute
+  end
+
+  def update_snippet(project = nil, user, snippet, opts)
+    UpdateSnippetService.new(project, user, snippet, opts).execute
+  end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 773de6628b17ce666760f08fba86983dceec98a0..53ccaa4fd6791833f2adcbaf028d579031bc2a39 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -37,8 +37,12 @@ RSpec.configure do |config|
   config.include Devise::TestHelpers, type: :controller
 
   config.include TestEnv
+  config.infer_spec_type_from_file_location!
+  config.raise_errors_for_deprecations!
 
   config.before(:suite) do
     TestEnv.init
   end
 end
+
+ActiveRecord::Migration.maintain_test_schema!
diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb
index d2d532d9738ad13def8132d23b0ec37497ad7253..cca7652093a6e17bb5013123c36a81d797231ecd 100644
--- a/spec/support/db_cleaner.rb
+++ b/spec/support/db_cleaner.rb
@@ -36,4 +36,15 @@ RSpec.configure do |config|
   config.after(:each) do
     DatabaseCleaner.clean
   end
+
+  # rspec-rails 3 will no longer automatically infer an example group's spec type
+  # from the file location. You can explicitly opt-in to the feature using this
+  # config option.
+  # To explicitly tag specs without using automatic inference, set the `:type`
+  # metadata manually:
+  #
+  #     describe ThingsController, :type => :controller do
+  #       # Equivalent to being in spec/controllers
+  #     end
+  config.infer_spec_type_from_file_location!
 end
diff --git a/spec/support/mentionable_shared_examples.rb b/spec/support/mentionable_shared_examples.rb
index ebd742066998d6548a9d6e61e160c4b75c7ce611..305592fa5a656fcaa937cea525fee7e4c0fad05d 100644
--- a/spec/support/mentionable_shared_examples.rb
+++ b/spec/support/mentionable_shared_examples.rb
@@ -39,7 +39,7 @@ def common_mentionable_setup
     # unrecognized commits.
     commitmap = { '1234567890a' => mentioned_commit }
     extra_commits.each { |c| commitmap[c.short_id] = c }
-    mproject.repository.stub(:commit) { |sha| commitmap[sha] }
+    allow(mproject.repository).to receive(:commit) { |sha| commitmap[sha] }
     set_mentionable_text.call(ref_string)
   end
 end
@@ -48,19 +48,19 @@ shared_examples 'a mentionable' do
   common_mentionable_setup
 
   it 'generates a descriptive back-reference' do
-    subject.gfm_reference.should == backref_text
+    expect(subject.gfm_reference).to eq(backref_text)
   end
 
   it "extracts references from its reference property" do
     # De-duplicate and omit itself
     refs = subject.references(mproject)
-    refs.should have(6).items
-    refs.should include(mentioned_issue)
-    refs.should include(mentioned_mr)
-    refs.should include(mentioned_commit)
-    refs.should include(ext_issue)
-    refs.should include(ext_mr)
-    refs.should include(ext_commit)
+    expect(refs.size).to eq(6)
+    expect(refs).to include(mentioned_issue)
+    expect(refs).to include(mentioned_mr)
+    expect(refs).to include(mentioned_commit)
+    expect(refs).to include(ext_issue)
+    expect(refs).to include(ext_mr)
+    expect(refs).to include(ext_commit)
   end
 
   it 'creates cross-reference notes' do
@@ -68,7 +68,7 @@ shared_examples 'a mentionable' do
                          ext_issue, ext_mr, ext_commit]
 
     mentioned_objects.each do |referenced|
-      Note.should_receive(:create_cross_reference_note).with(referenced, subject.local_reference, mauthor, mproject)
+      expect(Note).to receive(:create_cross_reference_note).with(referenced, subject.local_reference, mauthor, mproject)
     end
 
     subject.create_cross_references!(mproject, mauthor)
@@ -77,8 +77,8 @@ shared_examples 'a mentionable' do
   it 'detects existing cross-references' do
     Note.create_cross_reference_note(mentioned_issue, subject.local_reference, mauthor, mproject)
 
-    subject.has_mentioned?(mentioned_issue).should be_true
-    subject.has_mentioned?(mentioned_mr).should be_false
+    expect(subject.has_mentioned?(mentioned_issue)).to be_truthy
+    expect(subject.has_mentioned?(mentioned_mr)).to be_falsey
   end
 end
 
@@ -95,12 +95,12 @@ shared_examples 'an editable mentionable' do
       "#{ext_proj.path_with_namespace}##{other_ext_issue.iid}"
 
     [mentioned_issue, mentioned_commit, ext_issue].each do |oldref|
-      Note.should_not_receive(:create_cross_reference_note).with(oldref, subject.local_reference,
+      expect(Note).not_to receive(:create_cross_reference_note).with(oldref, subject.local_reference,
         mauthor, mproject)
     end
 
     [other_issue, other_ext_issue].each do |newref|
-      Note.should_receive(:create_cross_reference_note).with(
+      expect(Note).to receive(:create_cross_reference_note).with(
         newref,
         subject.local_reference,
         mauthor,
diff --git a/spec/support/repo_helpers.rb b/spec/support/repo_helpers.rb
index 4c4775da69237f54e4e689e500199769cb565d50..aadf791bf3ff1ee5c245dc11e31dd1ac1d6f8d25 100644
--- a/spec/support/repo_helpers.rb
+++ b/spec/support/repo_helpers.rb
@@ -43,6 +43,25 @@ eos
     )
   end
 
+  def another_sample_commit
+    OpenStruct.new(
+        id: "e56497bb5f03a90a51293fc6d516788730953899",
+        parent_id: '4cd80ccab63c82b4bad16faa5193fbd2aa06df40',
+        author_full_name: "Sytse Sijbrandij",
+        author_email: "sytse@gitlab.com",
+        files_changed_count: 1,
+        message: <<eos
+Add directory structure for tree_helper spec
+
+This directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module
+
+See [merge request #275](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/275#note_732774)
+
+See merge request !2
+eos
+    )
+  end
+
   def sample_big_commit
     OpenStruct.new(
       id: "913c66a37b4a45b9769037c55c2d238bd0942d2e",
diff --git a/spec/support/select2_helper.rb b/spec/support/select2_helper.rb
index c7cf109a7bb1b5d1b24442fd32d2d56c86d6cfc1..691f84f39d477335d54c845799abc892bf2278e0 100644
--- a/spec/support/select2_helper.rb
+++ b/spec/support/select2_helper.rb
@@ -17,9 +17,9 @@ module Select2Helper
     selector = options[:from]
 
     if options[:multiple]
-      execute_script("$('#{selector}').select2('val', ['#{value}']);")
+      execute_script("$('#{selector}').select2('val', ['#{value}'], true);")
     else
-      execute_script("$('#{selector}').select2('val', '#{value}');")
+      execute_script("$('#{selector}').select2('val', '#{value}', true);")
     end
   end
 end
diff --git a/spec/support/taskable_shared_examples.rb b/spec/support/taskable_shared_examples.rb
index 42252675683db3e18ae6320a19a873c19a5a51db..490f453d4684cb027b0362db842ba5d7b0ff3b76 100644
--- a/spec/support/taskable_shared_examples.rb
+++ b/spec/support/taskable_shared_examples.rb
@@ -34,9 +34,9 @@ EOT
   end
 
   it 'knows if it has tasks' do
-    expect(subject.tasks?).to be_true
+    expect(subject.tasks?).to be_truthy
 
     subject.description = 'Now I have no tasks'
-    expect(subject.tasks?).to be_false
+    expect(subject.tasks?).to be_falsey
   end
 end
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
index e6db410fb1cad0f43978e7cd5c2e08994a2659f4..44d70e741b2500df892b820e5d38f3629227cfeb 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/test_env.rb
@@ -5,6 +5,7 @@ module TestEnv
 
   # When developing the seed repository, comment out the branch you will modify.
   BRANCH_SHA = {
+    'flatten-dir'      => 'e56497b',
     'feature'          => '0b4bc9a',
     'feature_conflict' => 'bb5206f',
     'fix'              => '12d65c8',
@@ -18,21 +19,10 @@ module TestEnv
   # See gitlab.yml.example test section for paths
   #
   def init(opts = {})
-    RSpec::Mocks::setup(self)
-
     # Disable mailer for spinach tests
     disable_mailer if opts[:mailer] == false
 
-    # Clean /tmp/tests
-    tmp_test_path = Rails.root.join('tmp', 'tests')
-
-    if File.directory?(tmp_test_path)
-      Dir.entries(tmp_test_path).each do |entry|
-        unless ['.', '..', 'gitlab-shell', factory_repo_name].include?(entry)
-          FileUtils.rm_r(File.join(tmp_test_path, entry))
-        end
-      end
-    end
+    clean_test_path
 
     FileUtils.mkdir_p(repos_path)
 
@@ -48,18 +38,33 @@ module TestEnv
   end
 
   def enable_mailer
-    NotificationService.any_instance.unstub(:mailer)
+    allow_any_instance_of(NotificationService).to receive(:mailer).and_call_original
+  end
+
+  # Clean /tmp/tests
+  #
+  # Keeps gitlab-shell and gitlab-test
+  def clean_test_path
+    tmp_test_path = Rails.root.join('tmp', 'tests', '**')
+
+    Dir[tmp_test_path].each do |entry|
+      unless File.basename(entry) =~ /\Agitlab-(shell|test)\z/
+        FileUtils.rm_rf(entry)
+      end
+    end
   end
 
   def setup_gitlab_shell
-    `rake gitlab:shell:install`
+    unless File.directory?(Rails.root.join(*%w(tmp tests gitlab-shell)))
+      `rake gitlab:shell:install`
+    end
   end
 
   def setup_factory_repo
     clone_url = "https://gitlab.com/gitlab-org/#{factory_repo_name}.git"
 
     unless File.directory?(factory_repo_path)
-      system(*%W(git clone #{clone_url} #{factory_repo_path}))
+      system(*%W(git clone -q #{clone_url} #{factory_repo_path}))
     end
 
     Dir.chdir(factory_repo_path) do
@@ -80,7 +85,7 @@ module TestEnv
     end
 
     # We must copy bare repositories because we will push to them.
-    system(*%W(git clone --bare #{factory_repo_path} #{factory_repo_path_bare}))
+    system(git_env, *%W(git clone -q --bare #{factory_repo_path} #{factory_repo_path_bare}))
   end
 
   def copy_repo(project)
@@ -102,10 +107,16 @@ module TestEnv
   end
 
   def factory_repo_path_bare
-    factory_repo_path.to_s + '_bare'
+    "#{factory_repo_path}_bare"
   end
 
   def factory_repo_name
     'gitlab-test'
   end
+
+  # Prevent developer git configurations from being persisted to test
+  # repositories
+  def git_env
+    {'GIT_TEMPLATE_DIR' => ''}
+  end
 end
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index 71a45eb2fa6f4e1ea03ea20814a41e71c5ab18da..8a411b7720ac4a2ad3ca7b3db583f1d111c0259e 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -10,21 +10,21 @@ describe 'gitlab:app namespace rake task' do
     Rake::Task.define_task :environment
   end
 
+  def run_rake_task(task_name)
+    Rake::Task[task_name].reenable
+    Rake.application.invoke_task task_name
+  end
+
   describe 'backup_restore' do
     before do
       # avoid writing task output to spec progress
-      $stdout.stub :write
-    end
-
-    let :run_rake_task do
-      Rake::Task["gitlab:backup:restore"].reenable
-      Rake.application.invoke_task "gitlab:backup:restore"
+      allow($stdout).to receive :write
     end
 
     context 'gitlab version' do
       before do
         Dir.stub glob: []
-        Dir.stub :chdir
+        allow(Dir).to receive :chdir
         File.stub exists?: true
         Kernel.stub system: true
         FileUtils.stub cp_r: true
@@ -36,17 +36,66 @@ describe 'gitlab:app namespace rake task' do
 
       it 'should fail on mismatch' do
         YAML.stub load_file: {gitlab_version: "not #{gitlab_version}" }
-        expect { run_rake_task }.to raise_error SystemExit
+        expect { run_rake_task('gitlab:backup:restore') }.to(
+          raise_error SystemExit
+        )
       end
 
       it 'should invoke restoration on mach' do
         YAML.stub load_file: {gitlab_version: gitlab_version}
-        Rake::Task["gitlab:backup:db:restore"].should_receive :invoke
-        Rake::Task["gitlab:backup:repo:restore"].should_receive :invoke
-        Rake::Task["gitlab:shell:setup"].should_receive :invoke
-        expect { run_rake_task }.to_not raise_error
+        expect(Rake::Task["gitlab:backup:db:restore"]).to receive :invoke
+        expect(Rake::Task["gitlab:backup:repo:restore"]).to receive :invoke
+        expect(Rake::Task["gitlab:shell:setup"]).to receive :invoke
+        expect { run_rake_task('gitlab:backup:restore') }.to_not raise_error
       end
     end
 
   end # backup_restore task
+
+  describe 'backup_create' do
+    def tars_glob
+      Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar'))
+    end
+
+    before :all do
+      # Record the existing backup tars so we don't touch them
+      existing_tars = tars_glob
+
+      # Redirect STDOUT and run the rake task
+      orig_stdout = $stdout
+      $stdout = StringIO.new
+      run_rake_task('gitlab:backup:create')
+      $stdout = orig_stdout
+
+      @backup_tar = (tars_glob - existing_tars).first
+    end
+
+    after :all do
+      FileUtils.rm(@backup_tar)
+    end
+
+    it 'should set correct permissions on the tar file' do
+      expect(File.exist?(@backup_tar)).to be_truthy
+      expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600')
+    end
+
+    it 'should set correct permissions on the tar contents' do
+      tar_contents, exit_status = Gitlab::Popen.popen(
+        %W{tar -tvf #{@backup_tar} db uploads repositories}
+      )
+      expect(exit_status).to eq(0)
+      expect(tar_contents).to match('db/')
+      expect(tar_contents).to match('uploads/')
+      expect(tar_contents).to match('repositories/')
+      expect(tar_contents).not_to match(/^.{4,9}[rwx]/)
+    end
+
+    it 'should delete temp directories' do
+      temp_dirs = Dir.glob(
+        File.join(Gitlab.config.backup.path, '{db,repositories,uploads}')
+      )
+
+      expect(temp_dirs).to be_empty
+    end
+  end # backup_create task
 end # gitlab:app namespace
diff --git a/spec/tasks/gitlab/mail_google_schema_whitelisting.rb b/spec/tasks/gitlab/mail_google_schema_whitelisting.rb
new file mode 100644
index 0000000000000000000000000000000000000000..22e746870dc701cee6518b165970ff49df06a442
--- /dev/null
+++ b/spec/tasks/gitlab/mail_google_schema_whitelisting.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+require 'rake'
+
+describe 'gitlab:mail_google_schema_whitelisting rake task' do
+  before :all do
+    Rake.application.rake_require "tasks/gitlab/task_helpers"
+    Rake.application.rake_require "tasks/gitlab/mail_google_schema_whitelisting"
+    # empty task as env is already loaded
+    Rake::Task.define_task :environment
+  end
+
+  describe 'call' do
+    before do
+      # avoid writing task output to spec progress
+      allow($stdout).to receive :write
+    end
+
+    let :run_rake_task do
+      Rake::Task["gitlab:mail_google_schema_whitelisting"].reenable
+      Rake.application.invoke_task "gitlab:mail_google_schema_whitelisting"
+    end
+
+    it 'should run the task without errors' do
+      expect { run_rake_task }.to_not raise_error
+    end
+  end
+end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index 4273fd1019a50e3d79ee17e1badb586bf084f12c..df1a2b84a53c644d443e40f1d536e4f45ba31fc2 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -1,9 +1,13 @@
 require 'spec_helper'
 
 describe PostReceive do
+  let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" }
+  let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") }
+  let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) }
+  
   context "as a resque worker" do
     it "reponds to #perform" do
-      PostReceive.new.should respond_to(:perform)
+      expect(PostReceive.new).to respond_to(:perform)
     end
   end
 
@@ -13,33 +17,29 @@ describe PostReceive do
     let(:key_id) { key.shell_id }
 
     it "fetches the correct project" do
-      Project.should_receive(:find_with_namespace).with(project.path_with_namespace).and_return(project)
-      PostReceive.new.perform(pwd(project), key_id, changes)
+      expect(Project).to receive(:find_with_namespace).with(project.path_with_namespace).and_return(project)
+      PostReceive.new.perform(pwd(project), key_id, base64_changes)
     end
 
     it "does not run if the author is not in the project" do
-      Key.stub(:find_by).with(hash_including(id: anything())) { nil }
+      allow(Key).to receive(:find_by).with(hash_including(id: anything())) { nil }
 
-      project.should_not_receive(:execute_hooks)
+      expect(project).not_to receive(:execute_hooks)
 
-      PostReceive.new.perform(pwd(project), key_id, changes).should be_false
+      expect(PostReceive.new.perform(pwd(project), key_id, base64_changes)).to be_falsey
     end
 
     it "asks the project to trigger all hooks" do
       Project.stub(find_with_namespace: project)
-      project.should_receive(:execute_hooks)
-      project.should_receive(:execute_services)
-      project.should_receive(:update_merge_requests)
+      expect(project).to receive(:execute_hooks).twice
+      expect(project).to receive(:execute_services).twice
+      expect(project).to receive(:update_merge_requests)
 
-      PostReceive.new.perform(pwd(project), key_id, changes)
+      PostReceive.new.perform(pwd(project), key_id, base64_changes)
     end
   end
 
   def pwd(project)
     File.join(Gitlab.config.gitlab_shell.repos_path, project.path_with_namespace)
   end
-
-  def changes
-    'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master'
-  end
 end
diff --git a/vendor/assets/javascripts/chart-lib.min.js b/vendor/assets/javascripts/chart-lib.min.js
old mode 100755
new mode 100644
diff --git a/vendor/assets/javascripts/highlight.pack.js b/vendor/assets/javascripts/highlight.pack.js
deleted file mode 100644
index c09eac02df97a02e6be95be02ae06c378577b6ba..0000000000000000000000000000000000000000
--- a/vendor/assets/javascripts/highlight.pack.js
+++ /dev/null
@@ -1 +0,0 @@
-var hljs=new function(){function j(v){return v.replace(/&/gm,"&amp;").replace(/</gm,"&lt;").replace(/>/gm,"&gt;")}function t(v){return v.nodeName.toLowerCase()}function h(w,x){var v=w&&w.exec(x);return v&&v.index==0}function r(w){var v=(w.className+" "+(w.parentNode?w.parentNode.className:"")).split(/\s+/);v=v.map(function(x){return x.replace(/^lang(uage)?-/,"")});return v.filter(function(x){return i(x)||/no(-?)highlight/.test(x)})[0]}function o(x,y){var v={};for(var w in x){v[w]=x[w]}if(y){for(var w in y){v[w]=y[w]}}return v}function u(x){var v=[];(function w(y,z){for(var A=y.firstChild;A;A=A.nextSibling){if(A.nodeType==3){z+=A.nodeValue.length}else{if(A.nodeType==1){v.push({event:"start",offset:z,node:A});z=w(A,z);if(!t(A).match(/br|hr|img|input/)){v.push({event:"stop",offset:z,node:A})}}}}return z})(x,0);return v}function q(w,y,C){var x=0;var F="";var z=[];function B(){if(!w.length||!y.length){return w.length?w:y}if(w[0].offset!=y[0].offset){return(w[0].offset<y[0].offset)?w:y}return y[0].event=="start"?w:y}function A(H){function G(I){return" "+I.nodeName+'="'+j(I.value)+'"'}F+="<"+t(H)+Array.prototype.map.call(H.attributes,G).join("")+">"}function E(G){F+="</"+t(G)+">"}function v(G){(G.event=="start"?A:E)(G.node)}while(w.length||y.length){var D=B();F+=j(C.substr(x,D[0].offset-x));x=D[0].offset;if(D==w){z.reverse().forEach(E);do{v(D.splice(0,1)[0]);D=B()}while(D==w&&D.length&&D[0].offset==x);z.reverse().forEach(A)}else{if(D[0].event=="start"){z.push(D[0].node)}else{z.pop()}v(D.splice(0,1)[0])}}return F+j(C.substr(x))}function m(y){function v(z){return(z&&z.source)||z}function w(A,z){return RegExp(v(A),"m"+(y.cI?"i":"")+(z?"g":""))}function x(D,C){if(D.compiled){return}D.compiled=true;D.k=D.k||D.bK;if(D.k){var z={};var E=function(G,F){if(y.cI){F=F.toLowerCase()}F.split(" ").forEach(function(H){var I=H.split("|");z[I[0]]=[G,I[1]?Number(I[1]):1]})};if(typeof D.k=="string"){E("keyword",D.k)}else{Object.keys(D.k).forEach(function(F){E(F,D.k[F])})}D.k=z}D.lR=w(D.l||/\b[A-Za-z0-9_]+\b/,true);if(C){if(D.bK){D.b="\\b("+D.bK.split(" ").join("|")+")\\b"}if(!D.b){D.b=/\B|\b/}D.bR=w(D.b);if(!D.e&&!D.eW){D.e=/\B|\b/}if(D.e){D.eR=w(D.e)}D.tE=v(D.e)||"";if(D.eW&&C.tE){D.tE+=(D.e?"|":"")+C.tE}}if(D.i){D.iR=w(D.i)}if(D.r===undefined){D.r=1}if(!D.c){D.c=[]}var B=[];D.c.forEach(function(F){if(F.v){F.v.forEach(function(G){B.push(o(F,G))})}else{B.push(F=="self"?D:F)}});D.c=B;D.c.forEach(function(F){x(F,D)});if(D.starts){x(D.starts,C)}var A=D.c.map(function(F){return F.bK?"\\.?("+F.b+")\\.?":F.b}).concat([D.tE,D.i]).map(v).filter(Boolean);D.t=A.length?w(A.join("|"),true):{exec:function(F){return null}}}x(y)}function c(T,L,J,R){function v(V,W){for(var U=0;U<W.c.length;U++){if(h(W.c[U].bR,V)){return W.c[U]}}}function z(V,U){if(h(V.eR,U)){return V}if(V.eW){return z(V.parent,U)}}function A(U,V){return !J&&h(V.iR,U)}function E(W,U){var V=M.cI?U[0].toLowerCase():U[0];return W.k.hasOwnProperty(V)&&W.k[V]}function w(aa,Y,X,W){var U=W?"":b.classPrefix,V='<span class="'+U,Z=X?"":"</span>";V+=aa+'">';return V+Y+Z}function N(){if(!I.k){return j(C)}var U="";var X=0;I.lR.lastIndex=0;var V=I.lR.exec(C);while(V){U+=j(C.substr(X,V.index-X));var W=E(I,V);if(W){H+=W[1];U+=w(W[0],j(V[0]))}else{U+=j(V[0])}X=I.lR.lastIndex;V=I.lR.exec(C)}return U+j(C.substr(X))}function F(){if(I.sL&&!f[I.sL]){return j(C)}var U=I.sL?c(I.sL,C,true,S):e(C);if(I.r>0){H+=U.r}if(I.subLanguageMode=="continuous"){S=U.top}return w(U.language,U.value,false,true)}function Q(){return I.sL!==undefined?F():N()}function P(W,V){var U=W.cN?w(W.cN,"",true):"";if(W.rB){D+=U;C=""}else{if(W.eB){D+=j(V)+U;C=""}else{D+=U;C=V}}I=Object.create(W,{parent:{value:I}})}function G(U,Y){C+=U;if(Y===undefined){D+=Q();return 0}var W=v(Y,I);if(W){D+=Q();P(W,Y);return W.rB?0:Y.length}var X=z(I,Y);if(X){var V=I;if(!(V.rE||V.eE)){C+=Y}D+=Q();do{if(I.cN){D+="</span>"}H+=I.r;I=I.parent}while(I!=X.parent);if(V.eE){D+=j(Y)}C="";if(X.starts){P(X.starts,"")}return V.rE?0:Y.length}if(A(Y,I)){throw new Error('Illegal lexeme "'+Y+'" for mode "'+(I.cN||"<unnamed>")+'"')}C+=Y;return Y.length||1}var M=i(T);if(!M){throw new Error('Unknown language: "'+T+'"')}m(M);var I=R||M;var S;var D="";for(var K=I;K!=M;K=K.parent){if(K.cN){D=w(K.cN,"",true)+D}}var C="";var H=0;try{var B,y,x=0;while(true){I.t.lastIndex=x;B=I.t.exec(L);if(!B){break}y=G(L.substr(x,B.index-x),B[0]);x=B.index+y}G(L.substr(x));for(var K=I;K.parent;K=K.parent){if(K.cN){D+="</span>"}}return{r:H,value:D,language:T,top:I}}catch(O){if(O.message.indexOf("Illegal")!=-1){return{r:0,value:j(L)}}else{throw O}}}function e(y,x){x=x||b.languages||Object.keys(f);var v={r:0,value:j(y)};var w=v;x.forEach(function(z){if(!i(z)){return}var A=c(z,y,false);A.language=z;if(A.r>w.r){w=A}if(A.r>v.r){w=v;v=A}});if(w.language){v.second_best=w}return v}function g(v){if(b.tabReplace){v=v.replace(/^((<[^>]+>|\t)+)/gm,function(w,z,y,x){return z.replace(/\t/g,b.tabReplace)})}if(b.useBR){v=v.replace(/\n/g,"<br>")}return v}function p(A){var B=r(A);if(/no(-?)highlight/.test(B)){return}var y;if(b.useBR){y=document.createElementNS("http://www.w3.org/1999/xhtml","div");y.innerHTML=A.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")}else{y=A}var z=y.textContent;var v=B?c(B,z,true):e(z);var x=u(y);if(x.length){var w=document.createElementNS("http://www.w3.org/1999/xhtml","div");w.innerHTML=v.value;v.value=q(x,u(w),z)}v.value=g(v.value);A.innerHTML=v.value;A.className+=" hljs "+(!B&&v.language||"");A.result={language:v.language,re:v.r};if(v.second_best){A.second_best={language:v.second_best.language,re:v.second_best.r}}}var b={classPrefix:"hljs-",tabReplace:null,useBR:false,languages:undefined};function s(v){b=o(b,v)}function l(){if(l.called){return}l.called=true;var v=document.querySelectorAll("pre code");Array.prototype.forEach.call(v,p)}function a(){addEventListener("DOMContentLoaded",l,false);addEventListener("load",l,false)}var f={};var n={};function d(v,x){var w=f[v]=x(this);if(w.aliases){w.aliases.forEach(function(y){n[y]=v})}}function k(){return Object.keys(f)}function i(v){return f[v]||f[n[v]]}this.highlight=c;this.highlightAuto=e;this.fixMarkup=g;this.highlightBlock=p;this.configure=s;this.initHighlighting=l;this.initHighlightingOnLoad=a;this.registerLanguage=d;this.listLanguages=k;this.getLanguage=i;this.inherit=o;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE]};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE]};this.PWM={b:/\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/};this.CLCM={cN:"comment",b:"//",e:"$",c:[this.PWM]};this.CBCM={cN:"comment",b:"/\\*",e:"\\*/",c:[this.PWM]};this.HCM={cN:"comment",b:"#",e:"$",c:[this.PWM]};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.CSSNM={cN:"number",b:this.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0};this.RM={cN:"regexp",b:/\//,e:/\/[gim]*/,i:/\n/,c:[this.BE,{b:/\[/,e:/\]/,r:0,c:[this.BE]}]};this.TM={cN:"title",b:this.IR,r:0};this.UTM={cN:"title",b:this.UIR,r:0}}();hljs.registerLanguage("1c",function(b){var f="[a-zA-Zа-яА-Я][a-zA-Z0-9_а-яА-Я]*";var c="возврат дата для если и или иначе иначеесли исключение конецесли конецпопытки конецпроцедуры конецфункции конеццикла константа не перейти перем перечисление по пока попытка прервать продолжить процедура строка тогда фс функция цикл число экспорт";var e="ansitooem oemtoansi ввестивидсубконто ввестидату ввестизначение ввестиперечисление ввестипериод ввестиплансчетов ввестистроку ввестичисло вопрос восстановитьзначение врег выбранныйплансчетов вызватьисключение датагод датамесяц датачисло добавитьмесяц завершитьработусистемы заголовоксистемы записьжурналарегистрации запуститьприложение зафиксироватьтранзакцию значениевстроку значениевстрокувнутр значениевфайл значениеизстроки значениеизстрокивнутр значениеизфайла имякомпьютера имяпользователя каталогвременныхфайлов каталогиб каталогпользователя каталогпрограммы кодсимв командасистемы конгода конецпериодаби конецрассчитанногопериодаби конецстандартногоинтервала конквартала конмесяца коннедели лев лог лог10 макс максимальноеколичествосубконто мин монопольныйрежим названиеинтерфейса названиенабораправ назначитьвид назначитьсчет найти найтипомеченныенаудаление найтиссылки началопериодаби началостандартногоинтервала начатьтранзакцию начгода начквартала начмесяца начнедели номерднягода номерднянедели номернеделигода нрег обработкаожидания окр описаниеошибки основнойжурналрасчетов основнойплансчетов основнойязык открытьформу открытьформумодально отменитьтранзакцию очиститьокносообщений периодстр полноеимяпользователя получитьвремята получитьдатута получитьдокументта получитьзначенияотбора получитьпозициюта получитьпустоезначение получитьта прав праводоступа предупреждение префиксавтонумерации пустаястрока пустоезначение рабочаядаттьпустоезначение рабочаядата разделительстраниц разделительстрок разм разобратьпозициюдокумента рассчитатьрегистрына рассчитатьрегистрыпо сигнал симв символтабуляции создатьобъект сокрл сокрлп сокрп сообщить состояние сохранитьзначение сред статусвозврата стрдлина стрзаменить стрколичествострок стрполучитьстроку  стрчисловхождений сформироватьпозициюдокумента счетпокоду текущаядата текущеевремя типзначения типзначениястр удалитьобъекты установитьтана установитьтапо фиксшаблон формат цел шаблон";var a={cN:"dquote",b:'""'};var d={cN:"string",b:'"',e:'"|$',c:[a]};var g={cN:"string",b:"\\|",e:'"|$',c:[a]};return{cI:true,l:f,k:{keyword:c,built_in:e},c:[b.CLCM,b.NM,d,g,{cN:"function",b:"(процедура|функция)",e:"$",l:f,k:"процедура функция",c:[b.inherit(b.TM,{b:f}),{cN:"tail",eW:true,c:[{cN:"params",b:"\\(",e:"\\)",l:f,k:"знач",c:[d,g]},{cN:"export",b:"экспорт",eW:true,l:f,k:"экспорт",c:[b.CLCM]}]},b.CLCM]},{cN:"preprocessor",b:"#",e:"$"},{cN:"date",b:"'\\d{2}\\.\\d{2}\\.(\\d{2}|\\d{4})'"}]}});hljs.registerLanguage("actionscript",function(a){var c="[a-zA-Z_$][a-zA-Z0-9_$]*";var b="([*]|[a-zA-Z_$][a-zA-Z0-9_$]*)";var d={cN:"rest_arg",b:"[.]{3}",e:c,r:10};return{aliases:["as"],k:{keyword:"as break case catch class const continue default delete do dynamic each else extends final finally for function get if implements import in include instanceof interface internal is namespace native new override package private protected public return set static super switch this throw try typeof use var void while with",literal:"true false null undefined"},c:[a.ASM,a.QSM,a.CLCM,a.CBCM,a.CNM,{cN:"package",bK:"package",e:"{",c:[a.TM]},{cN:"class",bK:"class interface",e:"{",eE:true,c:[{bK:"extends implements"},a.TM]},{cN:"preprocessor",bK:"import include",e:";"},{cN:"function",bK:"function",e:"[{;]",eE:true,i:"\\S",c:[a.TM,{cN:"params",b:"\\(",e:"\\)",c:[a.ASM,a.QSM,a.CLCM,a.CBCM,d]},{cN:"type",b:":",e:b,r:10}]}]}});hljs.registerLanguage("apache",function(a){var b={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:true,c:[a.HCM,{cN:"tag",b:"</?",e:">"},{cN:"keyword",b:/\w+/,r:0,k:{common:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"sqbracket",b:"\\s\\[",e:"\\]$"},{cN:"cbracket",b:"[\\$%]\\{",e:"\\}",c:["self",b]},b,a.QSM]}}],i:/\S/}});hljs.registerLanguage("applescript",function(a){var b=a.inherit(a.QSM,{i:""});var d={cN:"params",b:"\\(",e:"\\)",c:["self",a.CNM,b]};var c=[{cN:"comment",b:"--",e:"$"},{cN:"comment",b:"\\(\\*",e:"\\*\\)",c:["self",{b:"--",e:"$"}]},a.HCM];return{aliases:["osascript"],k:{keyword:"about above after against and around as at back before beginning behind below beneath beside between but by considering contain contains continue copy div does eighth else end equal equals error every exit fifth first for fourth from front get given global if ignoring in into is it its last local me middle mod my ninth not of on onto or over prop property put ref reference repeat returning script second set seventh since sixth some tell tenth that the|0 then third through thru timeout times to transaction try until where while whose with without",constant:"AppleScript false linefeed return pi quote result space tab true",type:"alias application boolean class constant date file integer list number real record string text",command:"activate beep count delay launch log offset read round run say summarize write",property:"character characters contents day frontmost id item length month name paragraph paragraphs rest reverse running time version weekday word words year"},c:[b,a.CNM,{cN:"type",b:"\\bPOSIX file\\b"},{cN:"command",b:"\\b(clipboard info|the clipboard|info for|list (disks|folder)|mount volume|path to|(close|open for) access|(get|set) eof|current date|do shell script|get volume settings|random number|set volume|system attribute|system info|time to GMT|(load|run|store) script|scripting components|ASCII (character|number)|localized string|choose (application|color|file|file name|folder|from list|remote application|URL)|display (alert|dialog))\\b|^\\s*return\\b"},{cN:"constant",b:"\\b(text item delimiters|current application|missing value)\\b"},{cN:"keyword",b:"\\b(apart from|aside from|instead of|out of|greater than|isn't|(doesn't|does not) (equal|come before|come after|contain)|(greater|less) than( or equal)?|(starts?|ends|begins?) with|contained by|comes (before|after)|a (ref|reference))\\b"},{cN:"property",b:"\\b(POSIX path|(date|time) string|quoted form)\\b"},{cN:"function_start",bK:"on",i:"[${=;\\n]",c:[a.UTM,d]}].concat(c),i:"//"}});hljs.registerLanguage("xml",function(a){var c="[A-Za-z0-9\\._:-]+";var d={b:/<\?(php)?(?!\w)/,e:/\?>/,sL:"php",subLanguageMode:"continuous"};var b={eW:true,i:/</,r:0,c:[d,{cN:"attribute",b:c,r:0},{b:"=",r:0,c:[{cN:"value",v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s\/>]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xsl","plist"],cI:true,c:[{cN:"doctype",b:"<!DOCTYPE",e:">",r:10,c:[{b:"\\[",e:"\\]"}]},{cN:"comment",b:"<!--",e:"-->",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"<style(?=\\s|>|$)",e:">",k:{title:"style"},c:[b],starts:{e:"</style>",rE:true,sL:"css"}},{cN:"tag",b:"<script(?=\\s|>|$)",e:">",k:{title:"script"},c:[b],starts:{e:"<\/script>",rE:true,sL:"javascript"}},{b:"<%",e:"%>",sL:"vbscript"},d,{cN:"pi",b:/<\?\w+/,e:/\?>/,r:10},{cN:"tag",b:"</?",e:"/?>",c:[{cN:"title",b:/[^ \/><\n\t]+/,r:0},b]}]}});hljs.registerLanguage("asciidoc",function(a){return{c:[{cN:"comment",b:"^/{4,}\\n",e:"\\n/{4,}$",r:10},{cN:"comment",b:"^//",e:"$",r:0},{cN:"title",b:"^\\.\\w.*$"},{b:"^[=\\*]{4,}\\n",e:"\\n^[=\\*]{4,}$",r:10},{cN:"header",b:"^(={1,5}) .+?( \\1)?$",r:10},{cN:"header",b:"^[^\\[\\]\\n]+?\\n[=\\-~\\^\\+]{2,}$",r:10},{cN:"attribute",b:"^:.+?:",e:"\\s",eE:true,r:10},{cN:"attribute",b:"^\\[.+?\\]$",r:0},{cN:"blockquote",b:"^_{4,}\\n",e:"\\n_{4,}$",r:10},{cN:"code",b:"^[\\-\\.]{4,}\\n",e:"\\n[\\-\\.]{4,}$",r:10},{b:"^\\+{4,}\\n",e:"\\n\\+{4,}$",c:[{b:"<",e:">",sL:"xml",r:0}],r:10},{cN:"bullet",b:"^(\\*+|\\-+|\\.+|[^\\n]+?::)\\s+"},{cN:"label",b:"^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\\s+",r:10},{cN:"strong",b:"\\B\\*(?![\\*\\s])",e:"(\\n{2}|\\*)",c:[{b:"\\\\*\\w",r:0}]},{cN:"emphasis",b:"\\B'(?!['\\s])",e:"(\\n{2}|')",c:[{b:"\\\\'\\w",r:0}],r:0},{cN:"emphasis",b:"_(?![_\\s])",e:"(\\n{2}|_)",r:0},{cN:"smartquote",b:"``.+?''",r:10},{cN:"smartquote",b:"`.+?'",r:10},{cN:"code",b:"(`.+?`|\\+.+?\\+)",r:0},{cN:"code",b:"^[ \\t]",e:"$",r:0},{cN:"horizontal_rule",b:"^'{3,}[ \\t]*$",r:10},{b:"(link:)?(http|https|ftp|file|irc|image:?):\\S+\\[.*?\\]",rB:true,c:[{b:"(link|image:?):",r:0},{cN:"link_url",b:"\\w",e:"[^\\[]+",r:0},{cN:"link_label",b:"\\[",e:"\\]",eB:true,eE:true,r:0}],r:10}]}});hljs.registerLanguage("autohotkey",function(b){var d={cN:"escape",b:"`[\\s\\S]"};var c={cN:"comment",b:";",e:"$",r:0};var a=[{cN:"built_in",b:"A_[a-zA-Z0-9]+"},{cN:"built_in",bK:"ComSpec Clipboard ClipboardAll ErrorLevel"}];return{cI:true,k:{keyword:"Break Continue Else Gosub If Loop Return While",literal:"A true false NOT AND OR"},c:a.concat([d,b.inherit(b.QSM,{c:[d]}),c,{cN:"number",b:b.NR,r:0},{cN:"var_expand",b:"%",e:"%",i:"\\n",c:[d]},{cN:"label",c:[d],v:[{b:'^[^\\n";]+::(?!=)'},{b:'^[^\\n";]+:(?!=)',r:0}]},{b:",\\s*,",r:10}])}});hljs.registerLanguage("avrasm",function(a){return{cI:true,l:"\\.?"+a.IR,k:{keyword:"adc add adiw and andi asr bclr bld brbc brbs brcc brcs break breq brge brhc brhs brid brie brlo brlt brmi brne brpl brsh brtc brts brvc brvs bset bst call cbi cbr clc clh cli cln clr cls clt clv clz com cp cpc cpi cpse dec eicall eijmp elpm eor fmul fmuls fmulsu icall ijmp in inc jmp ld ldd ldi lds lpm lsl lsr mov movw mul muls mulsu neg nop or ori out pop push rcall ret reti rjmp rol ror sbc sbr sbrc sbrs sec seh sbi sbci sbic sbis sbiw sei sen ser ses set sev sez sleep spm st std sts sub subi swap tst wdr",built_in:"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 x|0 xh xl y|0 yh yl z|0 zh zl ucsr1c udr1 ucsr1a ucsr1b ubrr1l ubrr1h ucsr0c ubrr0h tccr3c tccr3a tccr3b tcnt3h tcnt3l ocr3ah ocr3al ocr3bh ocr3bl ocr3ch ocr3cl icr3h icr3l etimsk etifr tccr1c ocr1ch ocr1cl twcr twdr twar twsr twbr osccal xmcra xmcrb eicra spmcsr spmcr portg ddrg ping portf ddrf sreg sph spl xdiv rampz eicrb eimsk gimsk gicr eifr gifr timsk tifr mcucr mcucsr tccr0 tcnt0 ocr0 assr tccr1a tccr1b tcnt1h tcnt1l ocr1ah ocr1al ocr1bh ocr1bl icr1h icr1l tccr2 tcnt2 ocr2 ocdr wdtcr sfior eearh eearl eedr eecr porta ddra pina portb ddrb pinb portc ddrc pinc portd ddrd pind spdr spsr spcr udr0 ucsr0a ucsr0b ubrr0l acsr admux adcsr adch adcl porte ddre pine pinf",preprocessor:".byte .cseg .db .def .device .dseg .dw .endmacro .equ .eseg .exit .include .list .listmac .macro .nolist .org .set"},c:[a.CBCM,{cN:"comment",b:";",e:"$",r:0},a.CNM,a.BNM,{cN:"number",b:"\\b(\\$[a-zA-Z0-9]+|0o[0-7]+)"},a.QSM,{cN:"string",b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"},{cN:"label",b:"^[A-Za-z0-9_.$]+:"},{cN:"preprocessor",b:"#",e:"$"},{cN:"localvars",b:"@[0-9]+"}]}});hljs.registerLanguage("axapta",function(a){return{k:"false int abstract private char boolean static null if for true while long throw finally protected final return void enum else break new catch byte super case short default double public try this switch continue reverse firstfast firstonly forupdate nofetch sum avg minof maxof count order group by asc desc index hint like dispaly edit client server ttsbegin ttscommit str real date container anytype common div mod",c:[a.CLCM,a.CBCM,a.ASM,a.QSM,a.CNM,{cN:"preprocessor",b:"#",e:"$"},{cN:"class",bK:"class interface",e:"{",eE:true,i:":",c:[{bK:"extends implements"},a.UTM]}]}});hljs.registerLanguage("bash",function(b){var a={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)\}/}]};var d={cN:"string",b:/"/,e:/"/,c:[b.BE,a,{cN:"variable",b:/\$\(/,e:/\)/,c:[b.BE]}]};var c={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/-?[a-z\.]+/,k:{keyword:"if then else elif fi for break continue while in do done exit return set declare case esac export exec",literal:"true false",built_in:"printf echo read cd pwd pushd popd dirs let eval unset typeset readonly getopts source shopt caller type hash bind help sudo",operator:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"shebang",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:true,c:[b.inherit(b.TM,{b:/\w[\w\d_]*/})],r:0},b.HCM,b.NM,d,c,a]}});hljs.registerLanguage("brainfuck",function(b){var a={cN:"literal",b:"[\\+\\-]",r:0};return{aliases:["bf"],c:[{cN:"comment",b:"[^\\[\\]\\.,\\+\\-<> \r\n]",rE:true,e:"[\\[\\]\\.,\\+\\-<> \r\n]",r:0},{cN:"title",b:"[\\[\\]]",r:0},{cN:"string",b:"[\\.,]",r:0},{b:/\+\+|\-\-/,rB:true,c:[a]},a]}});hljs.registerLanguage("capnproto",function(a){return{aliases:["capnp"],k:{keyword:"struct enum interface union group import using const annotation extends in of on as with from fixed",built_in:"Void Bool Int8 Int16 Int32 Int64 UInt8 UInt16 UInt32 UInt64 Float32 Float64 Text Data AnyPointer AnyStruct Capability List",literal:"true false"},c:[a.QSM,a.NM,a.HCM,{cN:"shebang",b:/@0x[\w\d]{16};/,i:/\n/},{cN:"number",b:/@\d+\b/},{cN:"class",bK:"struct enum",e:/\{/,i:/\n/,c:[a.inherit(a.TM,{starts:{eW:true,eE:true}})]},{cN:"class",bK:"interface",e:/\{/,i:/\n/,c:[a.inherit(a.TM,{starts:{eW:true,eE:true}})]}]}});hljs.registerLanguage("clojure",function(j){var e={built_in:"def cond apply if-not if-let if not not= = < > <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"};var f="[a-zA-Z_0-9\\!\\.\\?\\-\\+\\*\\/\\<\\=\\>\\&\\#\\$';]+";var a="[\\s:\\(\\{]+\\d+(\\.\\d+)?";var d={cN:"number",b:a,r:0};var i=j.inherit(j.QSM,{i:null});var n={cN:"comment",b:";",e:"$",r:0};var m={cN:"collection",b:"[\\[\\{]",e:"[\\]\\}]"};var c={cN:"comment",b:"\\^"+f};var b={cN:"comment",b:"\\^\\{",e:"\\}"};var h={cN:"attribute",b:"[:]"+f};var l={cN:"list",b:"\\(",e:"\\)"};var g={eW:true,k:{literal:"true false nil"},r:0};var o={k:e,l:f,cN:"keyword",b:f,starts:g};l.c=[{cN:"comment",b:"comment"},o,g];g.c=[l,i,c,b,n,h,m,d];m.c=[l,i,c,n,h,m,d];return{aliases:["clj"],i:/\S/,c:[n,l,{cN:"prompt",b:/^=> /,starts:{e:/\n\n|\Z/}}]}});hljs.registerLanguage("cmake",function(a){return{aliases:["cmake.in"],cI:true,k:{keyword:"add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_subdirectory add_test aux_source_directory break build_command cmake_minimum_required cmake_policy configure_file create_test_sourcelist define_property else elseif enable_language enable_testing endforeach endfunction endif endmacro endwhile execute_process export find_file find_library find_package find_path find_program fltk_wrap_ui foreach function get_cmake_property get_directory_property get_filename_component get_property get_source_file_property get_target_property get_test_property if include include_directories include_external_msproject include_regular_expression install link_directories load_cache load_command macro mark_as_advanced message option output_required_files project qt_wrap_cpp qt_wrap_ui remove_definitions return separate_arguments set set_directory_properties set_property set_source_files_properties set_target_properties set_tests_properties site_name source_group string target_link_libraries try_compile try_run unset variable_watch while build_name exec_program export_library_dependencies install_files install_programs install_targets link_libraries make_directory remove subdir_depends subdirs use_mangled_mesa utility_source variable_requires write_file qt5_use_modules qt5_use_package qt5_wrap_cpp on off true false and or",operator:"equal less greater strless strgreater strequal matches"},c:[{cN:"envvar",b:"\\${",e:"}"},a.HCM,a.QSM,a.NM]}});hljs.registerLanguage("coffeescript",function(c){var b={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",reserved:"case default function var void with const let enum export import native __hasProp __extends __slice __bind __indexOf",built_in:"npm require console print module global window document"};var a="[A-Za-z$_][0-9A-Za-z$_]*";var f=c.inherit(c.TM,{b:a});var e={cN:"subst",b:/#\{/,e:/}/,k:b};var d=[c.BNM,c.inherit(c.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[c.BE]},{b:/'/,e:/'/,c:[c.BE]},{b:/"""/,e:/"""/,c:[c.BE,e]},{b:/"/,e:/"/,c:[c.BE,e]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[e,c.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{cN:"property",b:"@"+a},{b:"`",e:"`",eB:true,eE:true,sL:"javascript"}];e.c=d;return{aliases:["coffee","cson","iced"],k:b,i:/\/\*/,c:d.concat([{cN:"comment",b:"###",e:"###"},c.HCM,{cN:"function",b:"(^\\s*|\\B)("+a+"\\s*=\\s*)?(\\(.*\\))?\\s*\\B[-=]>",e:"[-=]>",rB:true,c:[f,{cN:"params",b:"\\([^\\(]",rB:true,c:[{b:/\(/,e:/\)/,k:b,c:["self"].concat(d)}]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:true,i:/[:="\[\]]/,c:[f]},f]},{cN:"attribute",b:a+":",e:":",rB:true,eE:true,r:0}])}});hljs.registerLanguage("cpp",function(a){var b={keyword:"false int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long throw volatile static protected bool template mutable if public friend do return goto auto void enum else break new extern using true class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue wchar_t inline delete alignof char16_t char32_t constexpr decltype noexcept nullptr static_assert thread_local restrict _Bool complex _Complex _Imaginary",built_in:"std string cin cout cerr clog stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf"};return{aliases:["c","h","c++","h++"],k:b,i:"</",c:[a.CLCM,a.CBCM,a.QSM,{cN:"string",b:"'\\\\?.",e:"'",i:"."},{cN:"number",b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},a.CNM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line pragma",c:[{b:'include\\s*[<"]',e:'[>"]',k:"include",i:"\\n"},a.CLCM]},{cN:"stl_container",b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:b,c:["self"]},{b:a.IR+"::"}]}});hljs.registerLanguage("cs",function(c){var b="abstract as base bool break byte case catch char checked const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual volatile void while async await protected public private internal ascending descending from get group into join let orderby partial select set value var where yield";var a=c.IR+"(<"+c.IR+">)?";return{aliases:["csharp"],k:b,i:/::/,c:[{cN:"comment",b:"///",e:"$",rB:true,c:[{cN:"xmlDocTag",v:[{b:"///",r:0},{b:"<!--|-->"},{b:"</?",e:">"}]}]},c.CLCM,c.CBCM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line region endregion pragma checksum"},{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},c.ASM,c.QSM,c.CNM,{bK:"class namespace interface",e:/[{;=]/,i:/[^\s:]/,c:[c.TM,c.CLCM,c.CBCM]},{bK:"new",e:/\s/,r:0},{cN:"function",b:"("+a+"\\s+)+"+c.IR+"\\s*\\(",rB:true,e:/[{;=]/,eE:true,k:b,c:[{b:c.IR+"\\s*\\(",rB:true,c:[c.TM]},{cN:"params",b:/\(/,e:/\)/,k:b,c:[c.ASM,c.QSM,c.CNM,c.CBCM]},c.CLCM,c.CBCM]}]}});hljs.registerLanguage("css",function(a){var b="[a-zA-Z-][a-zA-Z0-9_-]*";var c={cN:"function",b:b+"\\(",rB:true,eE:true,e:"\\("};return{cI:true,i:"[=/|']",c:[a.CBCM,{cN:"id",b:"\\#[A-Za-z0-9_-]+"},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"pseudo",b:":(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\\\"\\']+"},{cN:"at_rule",b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{cN:"at_rule",b:"@",e:"[{;]",c:[{cN:"keyword",b:/\S+/},{b:/\s/,eW:true,eE:true,r:0,c:[c,a.ASM,a.QSM,a.CSSNM]}]},{cN:"tag",b:b,r:0},{cN:"rules",b:"{",e:"}",i:"[^\\s]",r:0,c:[a.CBCM,{cN:"rule",b:"[^\\s]",rB:true,e:";",eW:true,c:[{cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:true,i:"[^\\s]",starts:{cN:"value",eW:true,eE:true,c:[c,a.CSSNM,a.QSM,a.ASM,a.CBCM,{cN:"hexcolor",b:"#[0-9A-Fa-f]+"},{cN:"important",b:"!important"}]}}]}]}]}});hljs.registerLanguage("d",function(x){var b={keyword:"abstract alias align asm assert auto body break byte case cast catch class const continue debug default delete deprecated do else enum export extern final finally for foreach foreach_reverse|10 goto if immutable import in inout int interface invariant is lazy macro mixin module new nothrow out override package pragma private protected public pure ref return scope shared static struct super switch synchronized template this throw try typedef typeid typeof union unittest version void volatile while with __FILE__ __LINE__ __gshared|10 __thread __traits __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__",built_in:"bool cdouble cent cfloat char creal dchar delegate double dstring float function idouble ifloat ireal long real short string ubyte ucent uint ulong ushort wchar wstring",literal:"false null true"};var c="(0|[1-9][\\d_]*)",q="(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)",h="0[bB][01_]+",v="([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)",y="0[xX]"+v,p="([eE][+-]?"+q+")",o="("+q+"(\\.\\d*|"+p+")|\\d+\\."+q+q+"|\\."+c+p+"?)",k="(0[xX]("+v+"\\."+v+"|\\.?"+v+")[pP][+-]?"+q+")",l="("+c+"|"+h+"|"+y+")",n="("+k+"|"+o+")";var z="\\\\(['\"\\?\\\\abfnrtv]|u[\\dA-Fa-f]{4}|[0-7]{1,3}|x[\\dA-Fa-f]{2}|U[\\dA-Fa-f]{8})|&[a-zA-Z\\d]{2,};";var m={cN:"number",b:"\\b"+l+"(L|u|U|Lu|LU|uL|UL)?",r:0};var j={cN:"number",b:"\\b("+n+"([fF]|L|i|[fF]i|Li)?|"+l+"(i|[fF]i|Li))",r:0};var s={cN:"string",b:"'("+z+"|.)",e:"'",i:"."};var r={b:z,r:0};var w={cN:"string",b:'"',c:[r],e:'"[cwd]?'};var f={cN:"string",b:'[rq]"',e:'"[cwd]?',r:5};var u={cN:"string",b:"`",e:"`[cwd]?"};var i={cN:"string",b:'x"[\\da-fA-F\\s\\n\\r]*"[cwd]?',r:10};var t={cN:"string",b:'q"\\{',e:'\\}"'};var e={cN:"shebang",b:"^#!",e:"$",r:5};var g={cN:"preprocessor",b:"#(line)",e:"$",r:5};var d={cN:"keyword",b:"@[a-zA-Z_][a-zA-Z_\\d]*"};var a={cN:"comment",b:"\\/\\+",c:["self"],e:"\\+\\/",r:10};return{l:x.UIR,k:b,c:[x.CLCM,x.CBCM,a,i,w,f,u,t,j,m,s,e,g,d]}});hljs.registerLanguage("markdown",function(a){return{aliases:["md","mkdown","mkd"],c:[{cN:"header",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"blockquote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"`.+?`"},{b:"^( {4}|\t)",e:"$",r:0}]},{cN:"horizontal_rule",b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:true,c:[{cN:"link_label",b:"\\[",e:"\\]",eB:true,rE:true,r:0},{cN:"link_url",b:"\\]\\(",e:"\\)",eB:true,eE:true},{cN:"link_reference",b:"\\]\\[",e:"\\]",eB:true,eE:true}],r:10},{b:"^\\[.+\\]:",rB:true,c:[{cN:"link_reference",b:"\\[",e:"\\]:",eB:true,eE:true,starts:{cN:"link_url",e:"$"}}]}]}});hljs.registerLanguage("dart",function(b){var d={cN:"subst",b:"\\$\\{",e:"}",k:"true false null this is new super"};var c={cN:"string",v:[{b:"r'''",e:"'''"},{b:'r"""',e:'"""'},{b:"r'",e:"'",i:"\\n"},{b:'r"',e:'"',i:"\\n"},{b:"'''",e:"'''",c:[b.BE,d]},{b:'"""',e:'"""',c:[b.BE,d]},{b:"'",e:"'",i:"\\n",c:[b.BE,d]},{b:'"',e:'"',i:"\\n",c:[b.BE,d]}]};d.c=[b.CNM,c];var a={keyword:"assert break case catch class const continue default do else enum extends false final finally for if in is new null rethrow return super switch this throw true try var void while with",literal:"abstract as dynamic export external factory get implements import library operator part set static typedef",built_in:"print Comparable DateTime Duration Function Iterable Iterator List Map Match Null Object Pattern RegExp Set Stopwatch String StringBuffer StringSink Symbol Type Uri bool double int num document window querySelector querySelectorAll Element ElementList"};return{k:a,c:[c,{cN:"dartdoc",b:"/\\*\\*",e:"\\*/",sL:"markdown",subLanguageMode:"continuous"},{cN:"dartdoc",b:"///",e:"$",sL:"markdown",subLanguageMode:"continuous"},b.CLCM,b.CBCM,{cN:"class",bK:"class interface",e:"{",eE:true,c:[{bK:"extends implements"},b.UTM]},b.CNM,{cN:"annotation",b:"@[A-Za-z]+"},{b:"=>"}]}});hljs.registerLanguage("delphi",function(b){var a="exports register file shl array record property for mod while set ally label uses raise not stored class safecall var interface or private static exit index inherited to else stdcall override shr asm far resourcestring finalization packed virtual out and protected library do xorwrite goto near function end div overload object unit begin string on inline repeat until destructor write message program with read initialization except default nil if case cdecl in downto threadvar of try pascal const external constructor type public then implementation finally published procedure";var e={cN:"comment",v:[{b:/\{/,e:/\}/,r:0},{b:/\(\*/,e:/\*\)/,r:10}]};var c={cN:"string",b:/'/,e:/'/,c:[{b:/''/}]};var d={cN:"string",b:/(#\d+)+/};var f={b:b.IR+"\\s*=\\s*class\\s*\\(",rB:true,c:[b.TM]};var g={cN:"function",bK:"function constructor destructor procedure",e:/[:;]/,k:"function constructor|10 destructor|10 procedure|10",c:[b.TM,{cN:"params",b:/\(/,e:/\)/,k:a,c:[c,d]},e]};return{cI:true,k:a,i:/("|\$[G-Zg-z]|\/\*|<\/)/,c:[e,b.CLCM,c,d,b.NM,f,g]}});hljs.registerLanguage("diff",function(a){return{aliases:["patch"],c:[{cN:"chunk",r:10,v:[{b:/^\@\@ +\-\d+,\d+ +\+\d+,\d+ +\@\@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"header",v:[{b:/Index: /,e:/$/},{b:/=====/,e:/=====$/},{b:/^\-\-\-/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+\+\+/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"change",b:"^\\!",e:"$"}]}});hljs.registerLanguage("django",function(a){var b={cN:"filter",b:/\|[A-Za-z]+\:?/,k:"truncatewords removetags linebreaksbr yesno get_digit timesince random striptags filesizeformat escape linebreaks length_is ljust rjust cut urlize fix_ampersands title floatformat capfirst pprint divisibleby add make_list unordered_list urlencode timeuntil urlizetrunc wordcount stringformat linenumbers slice date dictsort dictsortreversed default_if_none pluralize lower join center default truncatewords_html upper length phone2numeric wordwrap time addslashes slugify first escapejs force_escape iriencode last safe safeseq truncatechars localize unlocalize localtime utc timezone",c:[{cN:"argument",b:/"/,e:/"/},{cN:"argument",b:/'/,e:/'/}]};return{aliases:["jinja"],cI:true,sL:"xml",subLanguageMode:"continuous",c:[{cN:"template_comment",b:/\{%\s*comment\s*%}/,e:/\{%\s*endcomment\s*%}/},{cN:"template_comment",b:/\{#/,e:/#}/},{cN:"template_tag",b:/\{%/,e:/%}/,k:"comment endcomment load templatetag ifchanged endifchanged if endif firstof for endfor in ifnotequal endifnotequal widthratio extends include spaceless endspaceless regroup by as ifequal endifequal ssi now with cycle url filter endfilter debug block endblock else autoescape endautoescape csrf_token empty elif endwith static trans blocktrans endblocktrans get_static_prefix get_media_prefix plural get_current_language language get_available_languages get_current_language_bidi get_language_info get_language_info_list localize endlocalize localtime endlocaltime timezone endtimezone get_current_timezone verbatim",c:[b]},{cN:"variable",b:/\{\{/,e:/}}/,c:[b]}]}});hljs.registerLanguage("dos",function(a){var c={cN:"comment",b:/@?rem\b/,e:/$/,r:10};var b={cN:"label",b:"^\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\s+label)",r:0};return{aliases:["bat","cmd"],cI:true,k:{flow:"if else goto for in do call exit not exist errorlevel defined",operator:"equ neq lss leq gtr geq",keyword:"shift cd dir echo setlocal endlocal set pause copy",stream:"prn nul lpt3 lpt2 lpt1 con com4 com3 com2 com1 aux",winutils:"ping net ipconfig taskkill xcopy ren del",built_in:"append assoc at attrib break cacls cd chcp chdir chkdsk chkntfs cls cmd color comp compact convert date dir diskcomp diskcopy doskey erase fs find findstr format ftype graftabl help keyb label md mkdir mode more move path pause print popd pushd promt rd recover rem rename replace restore rmdir shiftsort start subst time title tree type ver verify vol",},c:[{cN:"envvar",b:/%%[^ ]|%[^ ]+?%|![^ ]+?!/},{cN:"function",b:b.b,e:"goto:eof",c:[a.inherit(a.TM,{b:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),c]},{cN:"number",b:"\\b\\d+",r:0},c]}});hljs.registerLanguage("dust",function(b){var a="if eq ne lt lte gt gte select default math sep";return{aliases:["dst"],cI:true,sL:"xml",subLanguageMode:"continuous",c:[{cN:"expression",b:"{",e:"}",r:0,c:[{cN:"begin-block",b:"#[a-zA-Z- .]+",k:a},{cN:"string",b:'"',e:'"'},{cN:"end-block",b:"\\/[a-zA-Z- .]+",k:a},{cN:"variable",b:"[a-zA-Z-.]+",k:a,r:0}]}]}});hljs.registerLanguage("elixir",function(e){var f="[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?";var g="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?";var i="and false then defined module in return redo retry end for true self when next until do begin unless nil break not case cond alias while ensure or include use alias fn quote";var c={cN:"subst",b:"#\\{",e:"}",l:f,k:i};var d={cN:"string",c:[e.BE,c],v:[{b:/'/,e:/'/},{b:/"/,e:/"/}]};var b={eW:true,rE:true,l:f,k:i,r:0};var h={cN:"function",bK:"def defmacro",e:/\bdo\b/,c:[e.inherit(e.TM,{b:g,starts:b})]};var j=e.inherit(h,{cN:"class",bK:"defmodule defrecord",e:/\bdo\b|$|;/});var a=[d,e.HCM,j,h,{cN:"constant",b:"(\\b[A-Z_]\\w*(.)?)+",r:0},{cN:"symbol",b:":",c:[d,{b:g}],r:0},{cN:"symbol",b:f+":",r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{b:"->"},{b:"("+e.RSR+")\\s*",c:[e.HCM,{cN:"regexp",i:"\\n",c:[e.BE,c],v:[{b:"/",e:"/[a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}],r:0}];c.c=a;b.c=a;return{l:f,k:i,c:a}});hljs.registerLanguage("erlang-repl",function(a){return{k:{special_functions:"spawn spawn_link self",reserved:"after and andalso|10 band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse|10 query receive rem try when xor"},c:[{cN:"prompt",b:"^[0-9]+> ",r:10},{cN:"comment",b:"%",e:"$"},{cN:"number",b:"\\b(\\d+#[a-fA-F0-9]+|\\d+(\\.\\d+)?([eE][-+]?\\d+)?)",r:0},a.ASM,a.QSM,{cN:"constant",b:"\\?(::)?([A-Z]\\w*(::)?)+"},{cN:"arrow",b:"->"},{cN:"ok",b:"ok"},{cN:"exclamation_mark",b:"!"},{cN:"function_or_atom",b:"(\\b[a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*)|(\\b[a-z'][a-zA-Z0-9_']*)",r:0},{cN:"variable",b:"[A-Z][a-zA-Z0-9_']*",r:0}]}});hljs.registerLanguage("erlang",function(i){var c="[a-z'][a-zA-Z0-9_']*";var o="("+c+":"+c+"|"+c+")";var f={keyword:"after and andalso|10 band begin bnot bor bsl bzr bxor case catch cond div end fun if let not of orelse|10 query receive rem try when xor",literal:"false true"};var l={cN:"comment",b:"%",e:"$"};var e={cN:"number",b:"\\b(\\d+#[a-fA-F0-9]+|\\d+(\\.\\d+)?([eE][-+]?\\d+)?)",r:0};var g={b:"fun\\s+"+c+"/\\d+"};var n={b:o+"\\(",e:"\\)",rB:true,r:0,c:[{cN:"function_name",b:o,r:0},{b:"\\(",e:"\\)",eW:true,rE:true,r:0}]};var h={cN:"tuple",b:"{",e:"}",r:0};var a={cN:"variable",b:"\\b_([A-Z][A-Za-z0-9_]*)?",r:0};var m={cN:"variable",b:"[A-Z][a-zA-Z0-9_]*",r:0};var b={b:"#"+i.UIR,r:0,rB:true,c:[{cN:"record_name",b:"#"+i.UIR,r:0},{b:"{",e:"}",r:0}]};var k={bK:"fun receive if try case",e:"end",k:f};k.c=[l,g,i.inherit(i.ASM,{cN:""}),k,n,i.QSM,e,h,a,m,b];var j=[l,g,k,n,i.QSM,e,h,a,m,b];n.c[1].c=j;h.c=j;b.c[1].c=j;var d={cN:"params",b:"\\(",e:"\\)",c:j};return{aliases:["erl"],k:f,i:"(</|\\*=|\\+=|-=|/\\*|\\*/|\\(\\*|\\*\\))",c:[{cN:"function",b:"^"+c+"\\s*\\(",e:"->",rB:true,i:"\\(|#|//|/\\*|\\\\|:|;",c:[d,i.inherit(i.TM,{b:c})],starts:{e:";|\\.",k:f,c:j}},l,{cN:"pp",b:"^-",e:"\\.",r:0,eE:true,rB:true,l:"-"+i.IR,k:"-module -record -undef -export -ifdef -ifndef -author -copyright -doc -vsn -import -include -include_lib -compile -define -else -endif -file -behaviour -behavior -spec",c:[d]},e,i.QSM,b,a,m,h,{b:/\.$/}]}});hljs.registerLanguage("fix",function(a){return{c:[{b:/[^\u2401\u0001]+/,e:/[\u2401\u0001]/,eE:true,rB:true,rE:false,c:[{b:/([^\u2401\u0001=]+)/,e:/=([^\u2401\u0001=]+)/,rE:true,rB:false,cN:"attribute"},{b:/=/,e:/([\u2401\u0001])/,eE:true,eB:true,cN:"string"}]}],cI:true}});hljs.registerLanguage("fsharp",function(a){var b={b:"<",e:">",c:[a.inherit(a.TM,{b:/'[a-zA-Z0-9_]+/})]};return{aliases:["fs"],k:"yield! return! let! do!abstract and as assert base begin class default delegate do done downcast downto elif else end exception extern false finally for fun function global if in inherit inline interface internal lazy let match member module mutable namespace new null of open or override private public rec return sig static struct then to true try type upcast use val void when while with yield",c:[{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},{cN:"string",b:'"""',e:'"""'},{cN:"comment",b:"\\(\\*",e:"\\*\\)"},{cN:"class",bK:"type",e:"\\(|=|$",eE:true,c:[a.UTM,b]},{cN:"annotation",b:"\\[<",e:">\\]",r:10},{cN:"attribute",b:"\\B('[A-Za-z])\\b",c:[a.BE]},a.CLCM,a.inherit(a.QSM,{i:null}),a.CNM]}});hljs.registerLanguage("gcode",function(a){var e="[A-Z_][A-Z0-9_.]*";var f="\\%";var c={literal:"",built_in:"",keyword:"IF DO WHILE ENDWHILE CALL ENDIF SUB ENDSUB GOTO REPEAT ENDREPEAT EQ LT GT NE GE LE OR XOR"};var b={cN:"preprocessor",b:"([O])([0-9]+)"};var d=[a.CLCM,{cN:"comment",b:/\(/,e:/\)/,c:[a.PWM]},a.CBCM,a.inherit(a.CNM,{b:"([-+]?([0-9]*\\.?[0-9]+\\.?))|"+a.CNR}),a.inherit(a.ASM,{i:null}),a.inherit(a.QSM,{i:null}),{cN:"keyword",b:"([G])([0-9]+\\.?[0-9]?)"},{cN:"title",b:"([M])([0-9]+\\.?[0-9]?)"},{cN:"title",b:"(VC|VS|#)",e:"(\\d+)"},{cN:"title",b:"(VZOFX|VZOFY|VZOFZ)"},{cN:"built_in",b:"(ATAN|ABS|ACOS|ASIN|SIN|COS|EXP|FIX|FUP|ROUND|LN|TAN)(\\[)",e:"([-+]?([0-9]*\\.?[0-9]+\\.?))(\\])"},{cN:"label",v:[{b:"N",e:"\\d+",i:"\\W"}]}];return{aliases:["nc"],cI:true,l:e,k:c,c:[{cN:"preprocessor",b:f},b].concat(d)}});hljs.registerLanguage("gherkin",function(a){return{aliases:["feature"],k:"Feature Background Ability Business Need Scenario Scenarios Scenario Outline Scenario Template Examples Given And Then But When",c:[{cN:"keyword",b:"\\*"},{cN:"comment",b:"@[^@\r\n\t ]+",e:"$"},{cN:"string",b:"\\|",e:"\\$"},{cN:"variable",b:"<",e:">",},a.HCM,{cN:"string",b:'"""',e:'"""'},a.QSM]}});hljs.registerLanguage("glsl",function(a){return{k:{keyword:"atomic_uint attribute bool break bvec2 bvec3 bvec4 case centroid coherent const continue default discard dmat2 dmat2x2 dmat2x3 dmat2x4 dmat3 dmat3x2 dmat3x3 dmat3x4 dmat4 dmat4x2 dmat4x3 dmat4x4 do double dvec2 dvec3 dvec4 else flat float for highp if iimage1D iimage1DArray iimage2D iimage2DArray iimage2DMS iimage2DMSArray iimage2DRect iimage3D iimageBuffer iimageCube iimageCubeArray image1D image1DArray image2D image2DArray image2DMS image2DMSArray image2DRect image3D imageBuffer imageCube imageCubeArray in inout int invariant isampler1D isampler1DArray isampler2D isampler2DArray isampler2DMS isampler2DMSArray isampler2DRect isampler3D isamplerBuffer isamplerCube isamplerCubeArray ivec2 ivec3 ivec4 layout lowp mat2 mat2x2 mat2x3 mat2x4 mat3 mat3x2 mat3x3 mat3x4 mat4 mat4x2 mat4x3 mat4x4 mediump noperspective out patch precision readonly restrict return sample sampler1D sampler1DArray sampler1DArrayShadow sampler1DShadow sampler2D sampler2DArray sampler2DArrayShadow sampler2DMS sampler2DMSArray sampler2DRect sampler2DRectShadow sampler2DShadow sampler3D samplerBuffer samplerCube samplerCubeArray samplerCubeArrayShadow samplerCubeShadow smooth struct subroutine switch uimage1D uimage1DArray uimage2D uimage2DArray uimage2DMS uimage2DMSArray uimage2DRect uimage3D uimageBuffer uimageCube uimageCubeArray uint uniform usampler1D usampler1DArray usampler2D usampler2DArray usampler2DMS usampler2DMSArray usampler2DRect usampler3D usamplerBuffer usamplerCube usamplerCubeArray uvec2 uvec3 uvec4 varying vec2 vec3 vec4 void volatile while writeonly",built_in:"gl_BackColor gl_BackLightModelProduct gl_BackLightProduct gl_BackMaterial gl_BackSecondaryColor gl_ClipDistance gl_ClipPlane gl_ClipVertex gl_Color gl_DepthRange gl_EyePlaneQ gl_EyePlaneR gl_EyePlaneS gl_EyePlaneT gl_Fog gl_FogCoord gl_FogFragCoord gl_FragColor gl_FragCoord gl_FragData gl_FragDepth gl_FrontColor gl_FrontFacing gl_FrontLightModelProduct gl_FrontLightProduct gl_FrontMaterial gl_FrontSecondaryColor gl_InstanceID gl_InvocationID gl_Layer gl_LightModel gl_LightSource gl_MaxAtomicCounterBindings gl_MaxAtomicCounterBufferSize gl_MaxClipDistances gl_MaxClipPlanes gl_MaxCombinedAtomicCounterBuffers gl_MaxCombinedAtomicCounters gl_MaxCombinedImageUniforms gl_MaxCombinedImageUnitsAndFragmentOutputs gl_MaxCombinedTextureImageUnits gl_MaxDrawBuffers gl_MaxFragmentAtomicCounterBuffers gl_MaxFragmentAtomicCounters gl_MaxFragmentImageUniforms gl_MaxFragmentInputComponents gl_MaxFragmentUniformComponents gl_MaxFragmentUniformVectors gl_MaxGeometryAtomicCounterBuffers gl_MaxGeometryAtomicCounters gl_MaxGeometryImageUniforms gl_MaxGeometryInputComponents gl_MaxGeometryOutputComponents gl_MaxGeometryOutputVertices gl_MaxGeometryTextureImageUnits gl_MaxGeometryTotalOutputComponents gl_MaxGeometryUniformComponents gl_MaxGeometryVaryingComponents gl_MaxImageSamples gl_MaxImageUnits gl_MaxLights gl_MaxPatchVertices gl_MaxProgramTexelOffset gl_MaxTessControlAtomicCounterBuffers gl_MaxTessControlAtomicCounters gl_MaxTessControlImageUniforms gl_MaxTessControlInputComponents gl_MaxTessControlOutputComponents gl_MaxTessControlTextureImageUnits gl_MaxTessControlTotalOutputComponents gl_MaxTessControlUniformComponents gl_MaxTessEvaluationAtomicCounterBuffers gl_MaxTessEvaluationAtomicCounters gl_MaxTessEvaluationImageUniforms gl_MaxTessEvaluationInputComponents gl_MaxTessEvaluationOutputComponents gl_MaxTessEvaluationTextureImageUnits gl_MaxTessEvaluationUniformComponents gl_MaxTessGenLevel gl_MaxTessPatchComponents gl_MaxTextureCoords gl_MaxTextureImageUnits gl_MaxTextureUnits gl_MaxVaryingComponents gl_MaxVaryingFloats gl_MaxVaryingVectors gl_MaxVertexAtomicCounterBuffers gl_MaxVertexAtomicCounters gl_MaxVertexAttribs gl_MaxVertexImageUniforms gl_MaxVertexOutputComponents gl_MaxVertexTextureImageUnits gl_MaxVertexUniformComponents gl_MaxVertexUniformVectors gl_MaxViewports gl_MinProgramTexelOffsetgl_ModelViewMatrix gl_ModelViewMatrixInverse gl_ModelViewMatrixInverseTranspose gl_ModelViewMatrixTranspose gl_ModelViewProjectionMatrix gl_ModelViewProjectionMatrixInverse gl_ModelViewProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixTranspose gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_Normal gl_NormalMatrix gl_NormalScale gl_ObjectPlaneQ gl_ObjectPlaneR gl_ObjectPlaneS gl_ObjectPlaneT gl_PatchVerticesIn gl_PerVertex gl_Point gl_PointCoord gl_PointSize gl_Position gl_PrimitiveID gl_PrimitiveIDIn gl_ProjectionMatrix gl_ProjectionMatrixInverse gl_ProjectionMatrixInverseTranspose gl_ProjectionMatrixTranspose gl_SampleID gl_SampleMask gl_SampleMaskIn gl_SamplePosition gl_SecondaryColor gl_TessCoord gl_TessLevelInner gl_TessLevelOuter gl_TexCoord gl_TextureEnvColor gl_TextureMatrixInverseTranspose gl_TextureMatrixTranspose gl_Vertex gl_VertexID gl_ViewportIndex gl_in gl_out EmitStreamVertex EmitVertex EndPrimitive EndStreamPrimitive abs acos acosh all any asin asinh atan atanh atomicCounter atomicCounterDecrement atomicCounterIncrement barrier bitCount bitfieldExtract bitfieldInsert bitfieldReverse ceil clamp cos cosh cross dFdx dFdy degrees determinant distance dot equal exp exp2 faceforward findLSB findMSB floatBitsToInt floatBitsToUint floor fma fract frexp ftransform fwidth greaterThan greaterThanEqual imageAtomicAdd imageAtomicAnd imageAtomicCompSwap imageAtomicExchange imageAtomicMax imageAtomicMin imageAtomicOr imageAtomicXor imageLoad imageStore imulExtended intBitsToFloat interpolateAtCentroid interpolateAtOffset interpolateAtSample inverse inversesqrt isinf isnan ldexp length lessThan lessThanEqual log log2 matrixCompMult max memoryBarrier min mix mod modf noise1 noise2 noise3 noise4 normalize not notEqual outerProduct packDouble2x32 packHalf2x16 packSnorm2x16 packSnorm4x8 packUnorm2x16 packUnorm4x8 pow radians reflect refract round roundEven shadow1D shadow1DLod shadow1DProj shadow1DProjLod shadow2D shadow2DLod shadow2DProj shadow2DProjLod sign sin sinh smoothstep sqrt step tan tanh texelFetch texelFetchOffset texture texture1D texture1DLod texture1DProj texture1DProjLod texture2D texture2DLod texture2DProj texture2DProjLod texture3D texture3DLod texture3DProj texture3DProjLod textureCube textureCubeLod textureGather textureGatherOffset textureGatherOffsets textureGrad textureGradOffset textureLod textureLodOffset textureOffset textureProj textureProjGrad textureProjGradOffset textureProjLod textureProjLodOffset textureProjOffset textureQueryLod textureSize transpose trunc uaddCarry uintBitsToFloat umulExtended unpackDouble2x32 unpackHalf2x16 unpackSnorm2x16 unpackSnorm4x8 unpackUnorm2x16 unpackUnorm4x8 usubBorrow gl_TextureMatrix gl_TextureMatrixInverse",literal:"true false"},i:'"',c:[a.CLCM,a.CBCM,a.CNM,{cN:"preprocessor",b:"#",e:"$"}]}});hljs.registerLanguage("go",function(a){var b={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer",constant:"true false iota nil",typename:"bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{aliases:["golang"],k:b,i:"</",c:[a.CLCM,a.CBCM,a.QSM,{cN:"string",b:"'",e:"[^\\\\]'"},{cN:"string",b:"`",e:"`"},{cN:"number",b:"[^a-zA-Z_0-9](\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s)(\\+|\\-)?\\d+)?",r:0},a.CNM]}});hljs.registerLanguage("gradle",function(a){return{cI:true,k:{keyword:"task project allprojects subprojects artifacts buildscript configurations dependencies repositories sourceSets description delete from into include exclude source classpath destinationDir includes options sourceCompatibility targetCompatibility group flatDir doLast doFirst flatten todir fromdir ant def abstract break case catch continue default do else extends final finally for if implements instanceof native new private protected public return static switch synchronized throw throws transient try volatile while strictfp package import false null super this true antlrtask checkstyle codenarc copy boolean byte char class double float int interface long short void compile runTime file fileTree abs any append asList asWritable call collect compareTo count div dump each eachByte eachFile eachLine every find findAll flatten getAt getErr getIn getOut getText grep immutable inject inspect intersect invokeMethods isCase join leftShift minus multiply newInputStream newOutputStream newPrintWriter newReader newWriter next plus pop power previous print println push putAt read readBytes readLines reverse reverseEach round size sort splitEachLine step subMap times toInteger toList tokenize upto waitForOrKill withPrintWriter withReader withStream withWriter withWriterAppend write writeLine"},c:[a.CLCM,a.CBCM,a.ASM,a.QSM,a.NM,a.RM]}});hljs.registerLanguage("groovy",function(a){return{k:{typename:"byte short char int long boolean float double void",literal:"true false null",keyword:"def as in assert trait super this abstract static volatile transient public private protected synchronized final class interface enum if else for while switch case break default continue throw throws try catch finally implements extends new import package return instanceof"},c:[a.CLCM,{cN:"javadoc",b:"/\\*\\*",e:"\\*//*",c:[{cN:"javadoctag",b:"@[A-Za-z]+"}]},a.CBCM,{cN:"string",b:'"""',e:'"""'},{cN:"string",b:"'''",e:"'''"},{cN:"string",b:"\\$/",e:"/\\$",r:10},a.ASM,{cN:"regexp",b:/~?\/[^\/\n]+\//,c:[a.BE]},a.QSM,{cN:"shebang",b:"^#!/usr/bin/env",e:"$",i:"\n"},a.BNM,{cN:"class",bK:"class interface trait enum",e:"{",i:":",c:[{bK:"extends implements"},a.UTM,]},a.CNM,{cN:"annotation",b:"@[A-Za-z]+"},{cN:"string",b:/[^\?]{0}[A-Za-z0-9_$]+ *:/},{b:/\?/,e:/\:/},{cN:"label",b:"^\\s*[A-Za-z0-9_$]+:"},]}});hljs.registerLanguage("ruby",function(f){var j="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?";var i="and false then defined module in return redo if BEGIN retry end for true self when next until do begin unless END rescue nil else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor";var b={cN:"yardoctag",b:"@[A-Za-z]+"};var c={cN:"value",b:"#<",e:">"};var k={cN:"comment",v:[{b:"#",e:"$",c:[b]},{b:"^\\=begin",e:"^\\=end",c:[b],r:10},{b:"^__END__",e:"\\n$"}]};var d={cN:"subst",b:"#\\{",e:"}",k:i};var e={cN:"string",c:[f.BE,d],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:"%[qw]?\\(",e:"\\)"},{b:"%[qw]?\\[",e:"\\]"},{b:"%[qw]?{",e:"}"},{b:"%[qw]?<",e:">"},{b:"%[qw]?/",e:"/"},{b:"%[qw]?%",e:"%"},{b:"%[qw]?-",e:"-"},{b:"%[qw]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/}]};var a={cN:"params",b:"\\(",e:"\\)",k:i};var h=[e,c,k,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[f.inherit(f.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{cN:"inheritance",b:"<\\s*",c:[{cN:"parent",b:"("+f.IR+"::)?"+f.IR}]},k]},{cN:"function",bK:"def",e:" |$|;",r:0,c:[f.inherit(f.TM,{b:j}),a,k]},{cN:"constant",b:"(::)?(\\b[A-Z]\\w*(::)?)+",r:0},{cN:"symbol",b:f.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":",c:[e,{b:j}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{b:"("+f.RSR+")\\s*",c:[c,k,{cN:"regexp",c:[f.BE,d],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}],r:0}];d.c=h;a.c=h;var g=[{b:/^\s*=>/,cN:"status",starts:{e:"$",c:h}},{cN:"prompt",b:/^\S[^=>\n]*>+/,starts:{e:"$",c:h}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:i,c:[k].concat(g).concat(h)}});hljs.registerLanguage("haml",function(a){return{cI:true,c:[{cN:"doctype",b:"^!!!( (5|1\\.1|Strict|Frameset|Basic|Mobile|RDFa|XML\\b.*))?$",r:10},{cN:"comment",b:"^\\s*(!=#|=#|-#|/).*$",r:0},{b:"^\\s*(-|=|!=)(?!#)",starts:{e:"\\n",sL:"ruby"}},{cN:"tag",b:"^\\s*%",c:[{cN:"title",b:"\\w+"},{cN:"value",b:"[#\\.]\\w+"},{b:"{\\s*",e:"\\s*}",eE:true,c:[{b:":\\w+\\s*=>",e:",\\s+",rB:true,eW:true,c:[{cN:"symbol",b:":\\w+"},{cN:"string",b:'"',e:'"'},{cN:"string",b:"'",e:"'"},{b:"\\w+",r:0}]}]},{b:"\\(\\s*",e:"\\s*\\)",eE:true,c:[{b:"\\w+\\s*=",e:"\\s+",rB:true,eW:true,c:[{cN:"attribute",b:"\\w+",r:0},{cN:"string",b:'"',e:'"'},{cN:"string",b:"'",e:"'"},{b:"\\w+",r:0}]}]}]},{cN:"bullet",b:"^\\s*[=~]\\s*",r:0},{b:"#{",starts:{e:"}",sL:"ruby"}}]}});hljs.registerLanguage("handlebars",function(b){var a="each in with if else unless bindattr action collection debugger log outlet template unbound view yield";return{aliases:["hbs","html.hbs","html.handlebars"],cI:true,sL:"xml",subLanguageMode:"continuous",c:[{cN:"expression",b:"{{",e:"}}",c:[{cN:"begin-block",b:"#[a-zA-Z- .]+",k:a},{cN:"string",b:'"',e:'"'},{cN:"end-block",b:"\\/[a-zA-Z- .]+",k:a},{cN:"variable",b:"[a-zA-Z-.]+",k:a}]}]}});hljs.registerLanguage("haskell",function(f){var g={cN:"comment",v:[{b:"--",e:"$"},{b:"{-",e:"-}",c:["self"]}]};var e={cN:"pragma",b:"{-#",e:"#-}"};var b={cN:"preprocessor",b:"^#",e:"$"};var d={cN:"type",b:"\\b[A-Z][\\w']*",r:0};var c={cN:"container",b:"\\(",e:"\\)",i:'"',c:[e,g,b,{cN:"type",b:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},f.inherit(f.TM,{b:"[_a-z][\\w']*"})]};var a={cN:"container",b:"{",e:"}",c:c.c};return{aliases:["hs"],k:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",c:[{cN:"module",b:"\\bmodule\\b",e:"where",k:"module where",c:[c,g],i:"\\W\\.|;"},{cN:"import",b:"\\bimport\\b",e:"$",k:"import|0 qualified as hiding",c:[c,g],i:"\\W\\.|;"},{cN:"class",b:"^(\\s*)?(class|instance)\\b",e:"where",k:"class family instance where",c:[d,c,g]},{cN:"typedef",b:"\\b(data|(new)?type)\\b",e:"$",k:"data family type newtype deriving",c:[e,g,d,c,a]},{cN:"default",bK:"default",e:"$",c:[d,c,g]},{cN:"infix",bK:"infix infixl infixr",e:"$",c:[f.CNM,g]},{cN:"foreign",b:"\\bforeign\\b",e:"$",k:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",c:[d,f.QSM,g]},{cN:"shebang",b:"#!\\/usr\\/bin\\/env runhaskell",e:"$"},e,g,b,f.QSM,f.CNM,d,f.inherit(f.TM,{b:"^[_a-z][\\w']*"}),{b:"->|<-"}]}});hljs.registerLanguage("haxe",function(a){var c="[a-zA-Z_$][a-zA-Z0-9_$]*";var b="([*]|[a-zA-Z_$][a-zA-Z0-9_$]*)";return{aliases:["hx"],k:{keyword:"break callback case cast catch class continue default do dynamic else enum extends extern for function here if implements import in inline interface never new override package private public return static super switch this throw trace try typedef untyped using var while",literal:"true false null"},c:[a.ASM,a.QSM,a.CLCM,a.CBCM,a.CNM,{cN:"class",bK:"class interface",e:"{",eE:true,c:[{bK:"extends implements"},a.TM]},{cN:"preprocessor",b:"#",e:"$",k:"if else elseif end error"},{cN:"function",bK:"function",e:"[{;]",eE:true,i:"\\S",c:[a.TM,{cN:"params",b:"\\(",e:"\\)",c:[a.ASM,a.QSM,a.CLCM,a.CBCM]},{cN:"type",b:":",e:b,r:10}]}]}});hljs.registerLanguage("http",function(a){return{i:"\\S",c:[{cN:"status",b:"^HTTP/[0-9\\.]+",e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{cN:"request",b:"^[A-Z]+ (.*?) HTTP/[0-9\\.]+$",rB:true,e:"$",c:[{cN:"string",b:" ",e:" ",eB:true,eE:true}]},{cN:"attribute",b:"^\\w",e:": ",eE:true,i:"\\n|\\s|=",starts:{cN:"string",e:"$"}},{b:"\\n\\n",starts:{sL:"",eW:true}}]}});hljs.registerLanguage("ini",function(a){return{cI:true,i:/\S/,c:[{cN:"comment",b:";",e:"$"},{cN:"title",b:"^\\[",e:"\\]"},{cN:"setting",b:"^[a-z0-9\\[\\]_-]+[ \\t]*=[ \\t]*",e:"$",c:[{cN:"value",eW:true,k:"on off true false yes no",c:[a.QSM,a.NM],r:0}]}]}});hljs.registerLanguage("java",function(c){var b=c.UIR+"(<"+c.UIR+">)?";var a="false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private";return{aliases:["jsp"],k:a,i:/<\//,c:[{cN:"javadoc",b:"/\\*\\*",e:"\\*/",r:0,c:[{cN:"javadoctag",b:"(^|\\s)@[A-Za-z]+"}]},c.CLCM,c.CBCM,c.ASM,c.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:true,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},c.UTM]},{bK:"new",e:/\s/,r:0},{cN:"function",b:"("+b+"\\s+)+"+c.UIR+"\\s*\\(",rB:true,e:/[{;=]/,eE:true,k:a,c:[{b:c.UIR+"\\s*\\(",rB:true,c:[c.UTM]},{cN:"params",b:/\(/,e:/\)/,k:a,c:[c.ASM,c.QSM,c.CNM,c.CBCM]},c.CLCM,c.CBCM]},c.CNM,{cN:"annotation",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("javascript",function(a){return{aliases:["js"],k:{keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document"},c:[{cN:"pi",b:/^\s*('|")use strict('|")/,r:10},a.ASM,a.QSM,a.CLCM,a.CBCM,a.CNM,{b:"("+a.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[a.CLCM,a.CBCM,a.RM,{b:/</,e:/>;/,r:0,sL:"xml"}],r:0},{cN:"function",bK:"function",e:/\{/,eE:true,c:[a.inherit(a.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,c:[a.CLCM,a.CBCM],i:/["'\(]/}],i:/\[|%/},{b:/\$[(.]/},{b:"\\."+a.IR,r:0}]}});hljs.registerLanguage("json",function(a){var e={literal:"true false null"};var d=[a.QSM,a.CNM];var c={cN:"value",e:",",eW:true,eE:true,c:d,k:e};var b={b:"{",e:"}",c:[{cN:"attribute",b:'\\s*"',e:'"\\s*:\\s*',eB:true,eE:true,c:[a.BE],i:"\\n",starts:c}],i:"\\S"};var f={b:"\\[",e:"\\]",c:[a.inherit(c,{cN:null})],i:"\\S"};d.splice(d.length,0,b,f);return{c:d,k:e,i:"\\S"}});hljs.registerLanguage("lasso",function(d){var b="[a-zA-Z_][a-zA-Z0-9_.]*";var i="<\\?(lasso(script)?|=)";var c="\\]|\\?>";var g={literal:"true false none minimal full all void and or not bw nbw ew new cn ncn lt lte gt gte eq neq rx nrx ft",built_in:"array date decimal duration integer map pair string tag xml null bytes list queue set stack staticarray tie local var variable global data self inherited",keyword:"error_code error_msg error_pop error_push error_reset cache database_names database_schemanames database_tablenames define_tag define_type email_batch encode_set html_comment handle handle_error header if inline iterate ljax_target link link_currentaction link_currentgroup link_currentrecord link_detail link_firstgroup link_firstrecord link_lastgroup link_lastrecord link_nextgroup link_nextrecord link_prevgroup link_prevrecord log loop namespace_using output_none portal private protect records referer referrer repeating resultset rows search_args search_arguments select sort_args sort_arguments thread_atomic value_list while abort case else if_empty if_false if_null if_true loop_abort loop_continue loop_count params params_up return return_value run_children soap_definetag soap_lastrequest soap_lastresponse tag_name ascending average by define descending do equals frozen group handle_failure import in into join let match max min on order parent protected provide public require returnhome skip split_thread sum take thread to trait type where with yield yieldhome"};var a={cN:"comment",b:"<!--",e:"-->",r:0};var j={cN:"preprocessor",b:"\\[noprocess\\]",starts:{cN:"markup",e:"\\[/noprocess\\]",rE:true,c:[a]}};var e={cN:"preprocessor",b:"\\[/noprocess|"+i};var h={cN:"variable",b:"'"+b+"'"};var f=[d.CLCM,{cN:"javadoc",b:"/\\*\\*!",e:"\\*/",c:[d.PWM]},d.CBCM,d.inherit(d.CNM,{b:d.CNR+"|-?(infinity|nan)\\b"}),d.inherit(d.ASM,{i:null}),d.inherit(d.QSM,{i:null}),{cN:"string",b:"`",e:"`"},{cN:"variable",v:[{b:"[#$]"+b},{b:"#",e:"\\d+",i:"\\W"}]},{cN:"tag",b:"::\\s*",e:b,i:"\\W"},{cN:"attribute",v:[{b:"-"+d.UIR,r:0},{b:"(\\.\\.\\.)"}]},{cN:"subst",v:[{b:"->\\s*",c:[h]},{b:":=|/(?!\\w)=?|[-+*%=<>&|!?\\\\]+",r:0}]},{cN:"built_in",b:"\\.\\.?",r:0,c:[h]},{cN:"class",bK:"define",rE:true,e:"\\(|=>",c:[d.inherit(d.TM,{b:d.UIR+"(=(?!>))?"})]}];return{aliases:["ls","lassoscript"],cI:true,l:b+"|&[lg]t;",k:g,c:[{cN:"preprocessor",b:c,r:0,starts:{cN:"markup",e:"\\[|"+i,rE:true,r:0,c:[a]}},j,e,{cN:"preprocessor",b:"\\[no_square_brackets",starts:{e:"\\[/no_square_brackets\\]",l:b+"|&[lg]t;",k:g,c:[{cN:"preprocessor",b:c,r:0,starts:{cN:"markup",e:i,rE:true,c:[a]}},j,e].concat(f)}},{cN:"preprocessor",b:"\\[",r:0},{cN:"shebang",b:"^#!.+lasso9\\b",r:10}].concat(f)}});hljs.registerLanguage("lisp",function(i){var l="[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*";var m="(\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s)(\\+|\\-)?\\d+)?";var k={cN:"shebang",b:"^#!",e:"$"};var b={cN:"literal",b:"\\b(t{1}|nil)\\b"};var e={cN:"number",v:[{b:m,r:0},{b:"#b[0-1]+(/[0-1]+)?"},{b:"#o[0-7]+(/[0-7]+)?"},{b:"#x[0-9a-f]+(/[0-9a-f]+)?"},{b:"#c\\("+m+" +"+m,e:"\\)"}]};var h=i.inherit(i.QSM,{i:null});var n={cN:"comment",b:";",e:"$",r:0};var g={cN:"variable",b:"\\*",e:"\\*"};var o={cN:"keyword",b:"[:&]"+l};var d={b:"\\(",e:"\\)",c:["self",b,h,e]};var a={cN:"quoted",c:[e,h,g,o,d],v:[{b:"['`]\\(",e:"\\)"},{b:"\\(quote ",e:"\\)",k:"quote"}]};var c={cN:"quoted",b:"'"+l};var j={cN:"list",b:"\\(",e:"\\)"};var f={eW:true,r:0};j.c=[{cN:"keyword",b:l},f];f.c=[a,c,j,b,e,h,n,g,o];return{i:/\S/,c:[e,k,b,h,n,a,c,j]}});hljs.registerLanguage("livecodeserver",function(a){var e={cN:"variable",b:"\\b[gtps][A-Z]+[A-Za-z0-9_\\-]*\\b|\\$_[A-Z]+",r:0};var b={cN:"comment",e:"$",v:[a.CBCM,a.HCM,{b:"--"},{b:"[^:]//"}]};var d=a.inherit(a.TM,{v:[{b:"\\b_*rig[A-Z]+[A-Za-z0-9_\\-]*"},{b:"\\b_[a-z0-9\\-]+"}]});var c=a.inherit(a.TM,{b:"\\b([A-Za-z0-9_\\-]+)\\b"});return{cI:false,k:{keyword:"after byte bytes english the until http forever descending using line real8 with seventh for stdout finally element word fourth before black ninth sixth characters chars stderr uInt1 uInt1s uInt2 uInt2s stdin string lines relative rel any fifth items from middle mid at else of catch then third it file milliseconds seconds second secs sec int1 int1s int4 int4s internet int2 int2s normal text item last long detailed effective uInt4 uInt4s repeat end repeat URL in try into switch to words https token binfile each tenth as ticks tick system real4 by dateItems without char character ascending eighth whole dateTime numeric short first ftp integer abbreviated abbr abbrev private case while if",constant:"SIX TEN FORMFEED NINE ZERO NONE SPACE FOUR FALSE COLON CRLF PI COMMA ENDOFFILE EOF EIGHT FIVE QUOTE EMPTY ONE TRUE RETURN CR LINEFEED RIGHT BACKSLASH NULL SEVEN TAB THREE TWO six ten formfeed nine zero none space four false colon crlf pi comma endoffile eof eight five quote empty one true return cr linefeed right backslash null seven tab three two RIVERSION RISTATE FILE_READ_MODE FILE_WRITE_MODE FILE_WRITE_MODE DIR_WRITE_MODE FILE_READ_UMASK FILE_WRITE_UMASK DIR_READ_UMASK DIR_WRITE_UMASK",operator:"div mod wrap and or bitAnd bitNot bitOr bitXor among not in a an within contains ends with begins the keys of keys",built_in:"put abs acos aliasReference annuity arrayDecode arrayEncode asin atan atan2 average avg base64Decode base64Encode baseConvert binaryDecode binaryEncode byteToNum cachedURL cachedURLs charToNum cipherNames commandNames compound compress constantNames cos date dateFormat decompress directories diskSpace DNSServers exp exp1 exp2 exp10 extents files flushEvents folders format functionNames global globals hasMemory hostAddress hostAddressToName hostName hostNameToAddress isNumber ISOToMac itemOffset keys len length libURLErrorData libUrlFormData libURLftpCommand libURLLastHTTPHeaders libURLLastRHHeaders libUrlMultipartFormAddPart libUrlMultipartFormData libURLVersion lineOffset ln ln1 localNames log log2 log10 longFilePath lower macToISO matchChunk matchText matrixMultiply max md5Digest median merge millisec millisecs millisecond milliseconds min monthNames num number numToByte numToChar offset open openfiles openProcesses openProcessIDs openSockets paramCount param params peerAddress pendingMessages platform processID random randomBytes replaceText result revCreateXMLTree revCreateXMLTreeFromFile revCurrentRecord revCurrentRecordIsFirst revCurrentRecordIsLast revDatabaseColumnCount revDatabaseColumnIsNull revDatabaseColumnLengths revDatabaseColumnNames revDatabaseColumnNamed revDatabaseColumnNumbered revDatabaseColumnTypes revDatabaseConnectResult revDatabaseCursors revDatabaseID revDatabaseTableNames revDatabaseType revDataFromQuery revdb_closeCursor revdb_columnbynumber revdb_columncount revdb_columnisnull revdb_columnlengths revdb_columnnames revdb_columntypes revdb_commit revdb_connect revdb_connections revdb_connectionerr revdb_currentrecord revdb_cursorconnection revdb_cursorerr revdb_cursors revdb_dbtype revdb_disconnect revdb_execute revdb_iseof revdb_isbof revdb_movefirst revdb_movelast revdb_movenext revdb_moveprev revdb_query revdb_querylist revdb_recordcount revdb_rollback revdb_tablenames revGetDatabaseDriverPath revNumberOfRecords revOpenDatabase revOpenDatabases revQueryDatabase revQueryDatabaseBlob revQueryResult revQueryIsAtStart revQueryIsAtEnd revUnixFromMacPath revXMLAttribute revXMLAttributes revXMLAttributeValues revXMLChildContents revXMLChildNames revXMLFirstChild revXMLMatchingNode revXMLNextSibling revXMLNodeContents revXMLNumberOfChildren revXMLParent revXMLPreviousSibling revXMLRootNode revXMLRPC_CreateRequest revXMLRPC_Documents revXMLRPC_Error revXMLRPC_Execute revXMLRPC_GetHost revXMLRPC_GetMethod revXMLRPC_GetParam revXMLText revXMLRPC_GetParamCount revXMLRPC_GetParamNode revXMLRPC_GetParamType revXMLRPC_GetPath revXMLRPC_GetPort revXMLRPC_GetProtocol revXMLRPC_GetRequest revXMLRPC_GetResponse revXMLRPC_GetSocket revXMLTree revXMLTrees revXMLValidateDTD revZipDescribeItem revZipEnumerateItems revZipOpenArchives round sec secs seconds sha1Digest shell shortFilePath sin specialFolderPath sqrt standardDeviation statRound stdDev sum sysError systemVersion tan tempName tick ticks time to toLower toUpper transpose trunc uniDecode uniEncode upper URLDecode URLEncode URLStatus value variableNames version waitDepth weekdayNames wordOffset add breakpoint cancel clear local variable file word line folder directory URL close socket process combine constant convert create new alias folder directory decrypt delete variable word line folder directory URL dispatch divide do encrypt filter get include intersect kill libURLDownloadToFile libURLFollowHttpRedirects libURLftpUpload libURLftpUploadFile libURLresetAll libUrlSetAuthCallback libURLSetCustomHTTPHeaders libUrlSetExpect100 libURLSetFTPListCommand libURLSetFTPMode libURLSetFTPStopTime libURLSetStatusCallback load multiply socket process post seek rel relative read from process rename replace require resetAll revAddXMLNode revAppendXML revCloseCursor revCloseDatabase revCommitDatabase revCopyFile revCopyFolder revCopyXMLNode revDeleteFolder revDeleteXMLNode revDeleteAllXMLTrees revDeleteXMLTree revExecuteSQL revGoURL revInsertXMLNode revMoveFolder revMoveToFirstRecord revMoveToLastRecord revMoveToNextRecord revMoveToPreviousRecord revMoveToRecord revMoveXMLNode revPutIntoXMLNode revRollBackDatabase revSetDatabaseDriverPath revSetXMLAttribute revXMLRPC_AddParam revXMLRPC_DeleteAllDocuments revXMLAddDTD revXMLRPC_Free revXMLRPC_FreeAll revXMLRPC_DeleteDocument revXMLRPC_DeleteParam revXMLRPC_SetHost revXMLRPC_SetMethod revXMLRPC_SetPort revXMLRPC_SetProtocol revXMLRPC_SetSocket revZipAddItemWithData revZipAddItemWithFile revZipAddUncompressedItemWithData revZipAddUncompressedItemWithFile revZipCancel revZipCloseArchive revZipDeleteItem revZipExtractItemToFile revZipExtractItemToVariable revZipSetProgressCallback revZipRenameItem revZipReplaceItemWithData revZipReplaceItemWithFile revZipOpenArchive send set sort split subtract union unload wait write"},c:[e,{cN:"keyword",b:"\\bend\\sif\\b"},{cN:"function",bK:"function",e:"$",c:[e,c,a.ASM,a.QSM,a.BNM,a.CNM,d]},{cN:"function",bK:"end",e:"$",c:[c,d]},{cN:"command",bK:"command on",e:"$",c:[e,c,a.ASM,a.QSM,a.BNM,a.CNM,d]},{cN:"command",bK:"end",e:"$",c:[c,d]},{cN:"preprocessor",b:"<\\?rev|<\\?lc|<\\?livecode",r:10},{cN:"preprocessor",b:"<\\?"},{cN:"preprocessor",b:"\\?>"},b,a.ASM,a.QSM,a.BNM,a.CNM,d],i:";$|^\\[|^="}});hljs.registerLanguage("lua",function(b){var a="\\[=*\\[";var e="\\]=*\\]";var c={b:a,e:e,c:["self"]};var d=[{cN:"comment",b:"--(?!"+a+")",e:"$"},{cN:"comment",b:"--"+a,e:e,c:[c],r:10}];return{l:b.UIR,k:{keyword:"and break do else elseif end false for if in local nil not or repeat return then true until while",built_in:"_G _VERSION assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall coroutine debug io math os package string table"},c:d.concat([{cN:"function",bK:"function",e:"\\)",c:[b.inherit(b.TM,{b:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{cN:"params",b:"\\(",eW:true,c:d}].concat(d)},b.CNM,b.ASM,b.QSM,{cN:"string",b:a,e:e,c:[c],r:5}])}});hljs.registerLanguage("makefile",function(a){var b={cN:"variable",b:/\$\(/,e:/\)/,c:[a.BE]};return{aliases:["mk","mak"],c:[a.HCM,{b:/^\w+\s*\W*=/,rB:true,r:0,starts:{cN:"constant",e:/\s*\W*=/,eE:true,starts:{e:/$/,r:0,c:[b]}}},{cN:"title",b:/^[\w]+:\s*$/},{cN:"phony",b:/^\.PHONY:/,e:/$/,k:".PHONY",l:/[\.\w]+/},{b:/^\t+/,e:/$/,r:0,c:[a.QSM,b]}]}});hljs.registerLanguage("mathematica",function(a){return{aliases:["mma"],l:"(\\$|\\b)"+a.IR+"\\b",k:"AbelianGroup Abort AbortKernels AbortProtect Above Abs Absolute AbsoluteCorrelation AbsoluteCorrelationFunction AbsoluteCurrentValue AbsoluteDashing AbsoluteFileName AbsoluteOptions AbsolutePointSize AbsoluteThickness AbsoluteTime AbsoluteTiming AccountingForm Accumulate Accuracy AccuracyGoal ActionDelay ActionMenu ActionMenuBox ActionMenuBoxOptions Active ActiveItem ActiveStyle AcyclicGraphQ AddOnHelpPath AddTo AdjacencyGraph AdjacencyList AdjacencyMatrix AdjustmentBox AdjustmentBoxOptions AdjustTimeSeriesForecast AffineTransform After AiryAi AiryAiPrime AiryAiZero AiryBi AiryBiPrime AiryBiZero AlgebraicIntegerQ AlgebraicNumber AlgebraicNumberDenominator AlgebraicNumberNorm AlgebraicNumberPolynomial AlgebraicNumberTrace AlgebraicRules AlgebraicRulesData Algebraics AlgebraicUnitQ Alignment AlignmentMarker AlignmentPoint All AllowedDimensions AllowGroupClose AllowInlineCells AllowKernelInitialization AllowReverseGroupClose AllowScriptLevelChange AlphaChannel AlternatingGroup AlternativeHypothesis Alternatives AmbientLight Analytic AnchoredSearch And AndersonDarlingTest AngerJ AngleBracket AngularGauge Animate AnimationCycleOffset AnimationCycleRepetitions AnimationDirection AnimationDisplayTime AnimationRate AnimationRepetitions AnimationRunning Animator AnimatorBox AnimatorBoxOptions AnimatorElements Annotation Annuity AnnuityDue Antialiasing Antisymmetric Apart ApartSquareFree Appearance AppearanceElements AppellF1 Append AppendTo Apply ArcCos ArcCosh ArcCot ArcCoth ArcCsc ArcCsch ArcSec ArcSech ArcSin ArcSinDistribution ArcSinh ArcTan ArcTanh Arg ArgMax ArgMin ArgumentCountQ ARIMAProcess ArithmeticGeometricMean ARMAProcess ARProcess Array ArrayComponents ArrayDepth ArrayFlatten ArrayPad ArrayPlot ArrayQ ArrayReshape ArrayRules Arrays Arrow Arrow3DBox ArrowBox Arrowheads AspectRatio AspectRatioFixed Assert Assuming Assumptions AstronomicalData Asynchronous AsynchronousTaskObject AsynchronousTasks AtomQ Attributes AugmentedSymmetricPolynomial AutoAction AutoDelete AutoEvaluateEvents AutoGeneratedPackage AutoIndent AutoIndentSpacings AutoItalicWords AutoloadPath AutoMatch Automatic AutomaticImageSize AutoMultiplicationSymbol AutoNumberFormatting AutoOpenNotebooks AutoOpenPalettes AutorunSequencing AutoScaling AutoScroll AutoSpacing AutoStyleOptions AutoStyleWords Axes AxesEdge AxesLabel AxesOrigin AxesStyle Axis BabyMonsterGroupB Back Background BackgroundTasksSettings Backslash Backsubstitution Backward Band BandpassFilter BandstopFilter BarabasiAlbertGraphDistribution BarChart BarChart3D BarLegend BarlowProschanImportance BarnesG BarOrigin BarSpacing BartlettHannWindow BartlettWindow BaseForm Baseline BaselinePosition BaseStyle BatesDistribution BattleLemarieWavelet Because BeckmannDistribution Beep Before Begin BeginDialogPacket BeginFrontEndInteractionPacket BeginPackage BellB BellY Below BenfordDistribution BeniniDistribution BenktanderGibratDistribution BenktanderWeibullDistribution BernoulliB BernoulliDistribution BernoulliGraphDistribution BernoulliProcess BernsteinBasis BesselFilterModel BesselI BesselJ BesselJZero BesselK BesselY BesselYZero Beta BetaBinomialDistribution BetaDistribution BetaNegativeBinomialDistribution BetaPrimeDistribution BetaRegularized BetweennessCentrality BezierCurve BezierCurve3DBox BezierCurve3DBoxOptions BezierCurveBox BezierCurveBoxOptions BezierFunction BilateralFilter Binarize BinaryFormat BinaryImageQ BinaryRead BinaryReadList BinaryWrite BinCounts BinLists Binomial BinomialDistribution BinomialProcess BinormalDistribution BiorthogonalSplineWavelet BipartiteGraphQ BirnbaumImportance BirnbaumSaundersDistribution BitAnd BitClear BitGet BitLength BitNot BitOr BitSet BitShiftLeft BitShiftRight BitXor Black BlackmanHarrisWindow BlackmanNuttallWindow BlackmanWindow Blank BlankForm BlankNullSequence BlankSequence Blend Block BlockRandom BlomqvistBeta BlomqvistBetaTest Blue Blur BodePlot BohmanWindow Bold Bookmarks Boole BooleanConsecutiveFunction BooleanConvert BooleanCountingFunction BooleanFunction BooleanGraph BooleanMaxterms BooleanMinimize BooleanMinterms Booleans BooleanTable BooleanVariables BorderDimensions BorelTannerDistribution Bottom BottomHatTransform BoundaryStyle Bounds Box BoxBaselineShift BoxData BoxDimensions Boxed Boxes BoxForm BoxFormFormatTypes BoxFrame BoxID BoxMargins BoxMatrix BoxRatios BoxRotation BoxRotationPoint BoxStyle BoxWhiskerChart Bra BracketingBar BraKet BrayCurtisDistance BreadthFirstScan Break Brown BrownForsytheTest BrownianBridgeProcess BrowserCategory BSplineBasis BSplineCurve BSplineCurve3DBox BSplineCurveBox BSplineCurveBoxOptions BSplineFunction BSplineSurface BSplineSurface3DBox BubbleChart BubbleChart3D BubbleScale BubbleSizes BulletGauge BusinessDayQ ButterflyGraph ButterworthFilterModel Button ButtonBar ButtonBox ButtonBoxOptions ButtonCell ButtonContents ButtonData ButtonEvaluator ButtonExpandable ButtonFrame ButtonFunction ButtonMargins ButtonMinHeight ButtonNote ButtonNotebook ButtonSource ButtonStyle ButtonStyleMenuListing Byte ByteCount ByteOrdering C CachedValue CacheGraphics CalendarData CalendarType CallPacket CanberraDistance Cancel CancelButton CandlestickChart Cap CapForm CapitalDifferentialD CardinalBSplineBasis CarmichaelLambda Cases Cashflow Casoratian Catalan CatalanNumber Catch CauchyDistribution CauchyWindow CayleyGraph CDF CDFDeploy CDFInformation CDFWavelet Ceiling Cell CellAutoOverwrite CellBaseline CellBoundingBox CellBracketOptions CellChangeTimes CellContents CellContext CellDingbat CellDynamicExpression CellEditDuplicate CellElementsBoundingBox CellElementSpacings CellEpilog CellEvaluationDuplicate CellEvaluationFunction CellEventActions CellFrame CellFrameColor CellFrameLabelMargins CellFrameLabels CellFrameMargins CellGroup CellGroupData CellGrouping CellGroupingRules CellHorizontalScrolling CellID CellLabel CellLabelAutoDelete CellLabelMargins CellLabelPositioning CellMargins CellObject CellOpen CellPrint CellProlog Cells CellSize CellStyle CellTags CellularAutomaton CensoredDistribution Censoring Center CenterDot CentralMoment CentralMomentGeneratingFunction CForm ChampernowneNumber ChanVeseBinarize Character CharacterEncoding CharacterEncodingsPath CharacteristicFunction CharacteristicPolynomial CharacterRange Characters ChartBaseStyle ChartElementData ChartElementDataFunction ChartElementFunction ChartElements ChartLabels ChartLayout ChartLegends ChartStyle Chebyshev1FilterModel Chebyshev2FilterModel ChebyshevDistance ChebyshevT ChebyshevU Check CheckAbort CheckAll Checkbox CheckboxBar CheckboxBox CheckboxBoxOptions ChemicalData ChessboardDistance ChiDistribution ChineseRemainder ChiSquareDistribution ChoiceButtons ChoiceDialog CholeskyDecomposition Chop Circle CircleBox CircleDot CircleMinus CirclePlus CircleTimes CirculantGraph CityData Clear ClearAll ClearAttributes ClearSystemCache ClebschGordan ClickPane Clip ClipboardNotebook ClipFill ClippingStyle ClipPlanes ClipRange Clock ClockGauge ClockwiseContourIntegral Close Closed CloseKernels ClosenessCentrality Closing ClosingAutoSave ClosingEvent ClusteringComponents CMYKColor Coarse Coefficient CoefficientArrays CoefficientDomain CoefficientList CoefficientRules CoifletWavelet Collect Colon ColonForm ColorCombine ColorConvert ColorData ColorDataFunction ColorFunction ColorFunctionScaling Colorize ColorNegate ColorOutput ColorProfileData ColorQuantize ColorReplace ColorRules ColorSelectorSettings ColorSeparate ColorSetter ColorSetterBox ColorSetterBoxOptions ColorSlider ColorSpace Column ColumnAlignments ColumnBackgrounds ColumnForm ColumnLines ColumnsEqual ColumnSpacings ColumnWidths CommonDefaultFormatTypes Commonest CommonestFilter CommonUnits CommunityBoundaryStyle CommunityGraphPlot CommunityLabels CommunityRegionStyle CompatibleUnitQ CompilationOptions CompilationTarget Compile Compiled CompiledFunction Complement CompleteGraph CompleteGraphQ CompleteKaryTree CompletionsListPacket Complex Complexes ComplexExpand ComplexInfinity ComplexityFunction ComponentMeasurements ComponentwiseContextMenu Compose ComposeList ComposeSeries Composition CompoundExpression CompoundPoissonDistribution CompoundPoissonProcess CompoundRenewalProcess Compress CompressedData Condition ConditionalExpression Conditioned Cone ConeBox ConfidenceLevel ConfidenceRange ConfidenceTransform ConfigurationPath Congruent Conjugate ConjugateTranspose Conjunction Connect ConnectedComponents ConnectedGraphQ ConnesWindow ConoverTest ConsoleMessage ConsoleMessagePacket ConsolePrint Constant ConstantArray Constants ConstrainedMax ConstrainedMin ContentPadding ContentsBoundingBox ContentSelectable ContentSize Context ContextMenu Contexts ContextToFilename ContextToFileName Continuation Continue ContinuedFraction ContinuedFractionK ContinuousAction ContinuousMarkovProcess ContinuousTimeModelQ ContinuousWaveletData ContinuousWaveletTransform ContourDetect ContourGraphics ContourIntegral ContourLabels ContourLines ContourPlot ContourPlot3D Contours ContourShading ContourSmoothing ContourStyle ContraharmonicMean Control ControlActive ControlAlignment ControllabilityGramian ControllabilityMatrix ControllableDecomposition ControllableModelQ ControllerDuration ControllerInformation ControllerInformationData ControllerLinking ControllerManipulate ControllerMethod ControllerPath ControllerState ControlPlacement ControlsRendering ControlType Convergents ConversionOptions ConversionRules ConvertToBitmapPacket ConvertToPostScript ConvertToPostScriptPacket Convolve ConwayGroupCo1 ConwayGroupCo2 ConwayGroupCo3 CoordinateChartData CoordinatesToolOptions CoordinateTransform CoordinateTransformData CoprimeQ Coproduct CopulaDistribution Copyable CopyDirectory CopyFile CopyTag CopyToClipboard CornerFilter CornerNeighbors Correlation CorrelationDistance CorrelationFunction CorrelationTest Cos Cosh CoshIntegral CosineDistance CosineWindow CosIntegral Cot Coth Count CounterAssignments CounterBox CounterBoxOptions CounterClockwiseContourIntegral CounterEvaluator CounterFunction CounterIncrements CounterStyle CounterStyleMenuListing CountRoots CountryData Covariance CovarianceEstimatorFunction CovarianceFunction CoxianDistribution CoxIngersollRossProcess CoxModel CoxModelFit CramerVonMisesTest CreateArchive CreateDialog CreateDirectory CreateDocument CreateIntermediateDirectories CreatePalette CreatePalettePacket CreateScheduledTask CreateTemporary CreateWindow CriticalityFailureImportance CriticalitySuccessImportance CriticalSection Cross CrossingDetect CrossMatrix Csc Csch CubeRoot Cubics Cuboid CuboidBox Cumulant CumulantGeneratingFunction Cup CupCap Curl CurlyDoubleQuote CurlyQuote CurrentImage CurrentlySpeakingPacket CurrentValue CurvatureFlowFilter CurveClosed Cyan CycleGraph CycleIndexPolynomial Cycles CyclicGroup Cyclotomic Cylinder CylinderBox CylindricalDecomposition D DagumDistribution DamerauLevenshteinDistance DampingFactor Darker Dashed Dashing DataCompression DataDistribution DataRange DataReversed Date DateDelimiters DateDifference DateFunction DateList DateListLogPlot DateListPlot DatePattern DatePlus DateRange DateString DateTicksFormat DaubechiesWavelet DavisDistribution DawsonF DayCount DayCountConvention DayMatchQ DayName DayPlus DayRange DayRound DeBruijnGraph Debug DebugTag Decimal DeclareKnownSymbols DeclarePackage Decompose Decrement DedekindEta Default DefaultAxesStyle DefaultBaseStyle DefaultBoxStyle DefaultButton DefaultColor DefaultControlPlacement DefaultDuplicateCellStyle DefaultDuration DefaultElement DefaultFaceGridsStyle DefaultFieldHintStyle DefaultFont DefaultFontProperties DefaultFormatType DefaultFormatTypeForStyle DefaultFrameStyle DefaultFrameTicksStyle DefaultGridLinesStyle DefaultInlineFormatType DefaultInputFormatType DefaultLabelStyle DefaultMenuStyle DefaultNaturalLanguage DefaultNewCellStyle DefaultNewInlineCellStyle DefaultNotebook DefaultOptions DefaultOutputFormatType DefaultStyle DefaultStyleDefinitions DefaultTextFormatType DefaultTextInlineFormatType DefaultTicksStyle DefaultTooltipStyle DefaultValues Defer DefineExternal DefineInputStreamMethod DefineOutputStreamMethod Definition Degree DegreeCentrality DegreeGraphDistribution DegreeLexicographic DegreeReverseLexicographic Deinitialization Del Deletable Delete DeleteBorderComponents DeleteCases DeleteContents DeleteDirectory DeleteDuplicates DeleteFile DeleteSmallComponents DeleteWithContents DeletionWarning Delimiter DelimiterFlashTime DelimiterMatching Delimiters Denominator DensityGraphics DensityHistogram DensityPlot DependentVariables Deploy Deployed Depth DepthFirstScan Derivative DerivativeFilter DescriptorStateSpace DesignMatrix Det DGaussianWavelet DiacriticalPositioning Diagonal DiagonalMatrix Dialog DialogIndent DialogInput DialogLevel DialogNotebook DialogProlog DialogReturn DialogSymbols Diamond DiamondMatrix DiceDissimilarity DictionaryLookup DifferenceDelta DifferenceOrder DifferenceRoot DifferenceRootReduce Differences DifferentialD DifferentialRoot DifferentialRootReduce DifferentiatorFilter DigitBlock DigitBlockMinimum DigitCharacter DigitCount DigitQ DihedralGroup Dilation Dimensions DiracComb DiracDelta DirectedEdge DirectedEdges DirectedGraph DirectedGraphQ DirectedInfinity Direction Directive Directory DirectoryName DirectoryQ DirectoryStack DirichletCharacter DirichletConvolve DirichletDistribution DirichletL DirichletTransform DirichletWindow DisableConsolePrintPacket DiscreteChirpZTransform DiscreteConvolve DiscreteDelta DiscreteHadamardTransform DiscreteIndicator DiscreteLQEstimatorGains DiscreteLQRegulatorGains DiscreteLyapunovSolve DiscreteMarkovProcess DiscretePlot DiscretePlot3D DiscreteRatio DiscreteRiccatiSolve DiscreteShift DiscreteTimeModelQ DiscreteUniformDistribution DiscreteVariables DiscreteWaveletData DiscreteWaveletPacketTransform DiscreteWaveletTransform Discriminant Disjunction Disk DiskBox DiskMatrix Dispatch DispersionEstimatorFunction Display DisplayAllSteps DisplayEndPacket DisplayFlushImagePacket DisplayForm DisplayFunction DisplayPacket DisplayRules DisplaySetSizePacket DisplayString DisplayTemporary DisplayWith DisplayWithRef DisplayWithVariable DistanceFunction DistanceTransform Distribute Distributed DistributedContexts DistributeDefinitions DistributionChart DistributionDomain DistributionFitTest DistributionParameterAssumptions DistributionParameterQ Dithering Div Divergence Divide DivideBy Dividers Divisible Divisors DivisorSigma DivisorSum DMSList DMSString Do DockedCells DocumentNotebook DominantColors DOSTextFormat Dot DotDashed DotEqual Dotted DoubleBracketingBar DoubleContourIntegral DoubleDownArrow DoubleLeftArrow DoubleLeftRightArrow DoubleLeftTee DoubleLongLeftArrow DoubleLongLeftRightArrow DoubleLongRightArrow DoubleRightArrow DoubleRightTee DoubleUpArrow DoubleUpDownArrow DoubleVerticalBar DoublyInfinite Down DownArrow DownArrowBar DownArrowUpArrow DownLeftRightVector DownLeftTeeVector DownLeftVector DownLeftVectorBar DownRightTeeVector DownRightVector DownRightVectorBar Downsample DownTee DownTeeArrow DownValues DragAndDrop DrawEdges DrawFrontFaces DrawHighlighted Drop DSolve Dt DualLinearProgramming DualSystemsModel DumpGet DumpSave DuplicateFreeQ Dynamic DynamicBox DynamicBoxOptions DynamicEvaluationTimeout DynamicLocation DynamicModule DynamicModuleBox DynamicModuleBoxOptions DynamicModuleParent DynamicModuleValues DynamicName DynamicNamespace DynamicReference DynamicSetting DynamicUpdating DynamicWrapper DynamicWrapperBox DynamicWrapperBoxOptions E EccentricityCentrality EdgeAdd EdgeBetweennessCentrality EdgeCapacity EdgeCapForm EdgeColor EdgeConnectivity EdgeCost EdgeCount EdgeCoverQ EdgeDashing EdgeDelete EdgeDetect EdgeForm EdgeIndex EdgeJoinForm EdgeLabeling EdgeLabels EdgeLabelStyle EdgeList EdgeOpacity EdgeQ EdgeRenderingFunction EdgeRules EdgeShapeFunction EdgeStyle EdgeThickness EdgeWeight Editable EditButtonSettings EditCellTagsSettings EditDistance EffectiveInterest Eigensystem Eigenvalues EigenvectorCentrality Eigenvectors Element ElementData Eliminate EliminationOrder EllipticE EllipticExp EllipticExpPrime EllipticF EllipticFilterModel EllipticK EllipticLog EllipticNomeQ EllipticPi EllipticReducedHalfPeriods EllipticTheta EllipticThetaPrime EmitSound EmphasizeSyntaxErrors EmpiricalDistribution Empty EmptyGraphQ EnableConsolePrintPacket Enabled Encode End EndAdd EndDialogPacket EndFrontEndInteractionPacket EndOfFile EndOfLine EndOfString EndPackage EngineeringForm Enter EnterExpressionPacket EnterTextPacket Entropy EntropyFilter Environment Epilog Equal EqualColumns EqualRows EqualTilde EquatedTo Equilibrium EquirippleFilterKernel Equivalent Erf Erfc Erfi ErlangB ErlangC ErlangDistribution Erosion ErrorBox ErrorBoxOptions ErrorNorm ErrorPacket ErrorsDialogSettings EstimatedDistribution EstimatedProcess EstimatorGains EstimatorRegulator EuclideanDistance EulerE EulerGamma EulerianGraphQ EulerPhi Evaluatable Evaluate Evaluated EvaluatePacket EvaluationCell EvaluationCompletionAction EvaluationElements EvaluationMode EvaluationMonitor EvaluationNotebook EvaluationObject EvaluationOrder Evaluator EvaluatorNames EvenQ EventData EventEvaluator EventHandler EventHandlerTag EventLabels ExactBlackmanWindow ExactNumberQ ExactRootIsolation ExampleData Except ExcludedForms ExcludePods Exclusions ExclusionsStyle Exists Exit ExitDialog Exp Expand ExpandAll ExpandDenominator ExpandFileName ExpandNumerator Expectation ExpectationE ExpectedValue ExpGammaDistribution ExpIntegralE ExpIntegralEi Exponent ExponentFunction ExponentialDistribution ExponentialFamily ExponentialGeneratingFunction ExponentialMovingAverage ExponentialPowerDistribution ExponentPosition ExponentStep Export ExportAutoReplacements ExportPacket ExportString Expression ExpressionCell ExpressionPacket ExpToTrig ExtendedGCD Extension ExtentElementFunction ExtentMarkers ExtentSize ExternalCall ExternalDataCharacterEncoding Extract ExtractArchive ExtremeValueDistribution FaceForm FaceGrids FaceGridsStyle Factor FactorComplete Factorial Factorial2 FactorialMoment FactorialMomentGeneratingFunction FactorialPower FactorInteger FactorList FactorSquareFree FactorSquareFreeList FactorTerms FactorTermsList Fail FailureDistribution False FARIMAProcess FEDisableConsolePrintPacket FeedbackSector FeedbackSectorStyle FeedbackType FEEnableConsolePrintPacket Fibonacci FieldHint FieldHintStyle FieldMasked FieldSize File FileBaseName FileByteCount FileDate FileExistsQ FileExtension FileFormat FileHash FileInformation FileName FileNameDepth FileNameDialogSettings FileNameDrop FileNameJoin FileNames FileNameSetter FileNameSplit FileNameTake FilePrint FileType FilledCurve FilledCurveBox Filling FillingStyle FillingTransform FilterRules FinancialBond FinancialData FinancialDerivative FinancialIndicator Find FindArgMax FindArgMin FindClique FindClusters FindCurvePath FindDistributionParameters FindDivisions FindEdgeCover FindEdgeCut FindEulerianCycle FindFaces FindFile FindFit FindGeneratingFunction FindGeoLocation FindGeometricTransform FindGraphCommunities FindGraphIsomorphism FindGraphPartition FindHamiltonianCycle FindIndependentEdgeSet FindIndependentVertexSet FindInstance FindIntegerNullVector FindKClan FindKClique FindKClub FindKPlex FindLibrary FindLinearRecurrence FindList FindMaximum FindMaximumFlow FindMaxValue FindMinimum FindMinimumCostFlow FindMinimumCut FindMinValue FindPermutation FindPostmanTour FindProcessParameters FindRoot FindSequenceFunction FindSettings FindShortestPath FindShortestTour FindThreshold FindVertexCover FindVertexCut Fine FinishDynamic FiniteAbelianGroupCount FiniteGroupCount FiniteGroupData First FirstPassageTimeDistribution FischerGroupFi22 FischerGroupFi23 FischerGroupFi24Prime FisherHypergeometricDistribution FisherRatioTest FisherZDistribution Fit FitAll FittedModel FixedPoint FixedPointList FlashSelection Flat Flatten FlattenAt FlatTopWindow FlipView Floor FlushPrintOutputPacket Fold FoldList Font FontColor FontFamily FontForm FontName FontOpacity FontPostScriptName FontProperties FontReencoding FontSize FontSlant FontSubstitutions FontTracking FontVariations FontWeight For ForAll Format FormatRules FormatType FormatTypeAutoConvert FormatValues FormBox FormBoxOptions FortranForm Forward ForwardBackward Fourier FourierCoefficient FourierCosCoefficient FourierCosSeries FourierCosTransform FourierDCT FourierDCTFilter FourierDCTMatrix FourierDST FourierDSTMatrix FourierMatrix FourierParameters FourierSequenceTransform FourierSeries FourierSinCoefficient FourierSinSeries FourierSinTransform FourierTransform FourierTrigSeries FractionalBrownianMotionProcess FractionalPart FractionBox FractionBoxOptions FractionLine Frame FrameBox FrameBoxOptions Framed FrameInset FrameLabel Frameless FrameMargins FrameStyle FrameTicks FrameTicksStyle FRatioDistribution FrechetDistribution FreeQ FrequencySamplingFilterKernel FresnelC FresnelS Friday FrobeniusNumber FrobeniusSolve FromCharacterCode FromCoefficientRules FromContinuedFraction FromDate FromDigits FromDMS Front FrontEndDynamicExpression FrontEndEventActions FrontEndExecute FrontEndObject FrontEndResource FrontEndResourceString FrontEndStackSize FrontEndToken FrontEndTokenExecute FrontEndValueCache FrontEndVersion FrontFaceColor FrontFaceOpacity Full FullAxes FullDefinition FullForm FullGraphics FullOptions FullSimplify Function FunctionExpand FunctionInterpolation FunctionSpace FussellVeselyImportance GaborFilter GaborMatrix GaborWavelet GainMargins GainPhaseMargins Gamma GammaDistribution GammaRegularized GapPenalty Gather GatherBy GaugeFaceElementFunction GaugeFaceStyle GaugeFrameElementFunction GaugeFrameSize GaugeFrameStyle GaugeLabels GaugeMarkers GaugeStyle GaussianFilter GaussianIntegers GaussianMatrix GaussianWindow GCD GegenbauerC General GeneralizedLinearModelFit GenerateConditions GeneratedCell GeneratedParameters GeneratingFunction Generic GenericCylindricalDecomposition GenomeData GenomeLookup GeodesicClosing GeodesicDilation GeodesicErosion GeodesicOpening GeoDestination GeodesyData GeoDirection GeoDistance GeoGridPosition GeometricBrownianMotionProcess GeometricDistribution GeometricMean GeometricMeanFilter GeometricTransformation GeometricTransformation3DBox GeometricTransformation3DBoxOptions GeometricTransformationBox GeometricTransformationBoxOptions GeoPosition GeoPositionENU GeoPositionXYZ GeoProjectionData GestureHandler GestureHandlerTag Get GetBoundingBoxSizePacket GetContext GetEnvironment GetFileName GetFrontEndOptionsDataPacket GetLinebreakInformationPacket GetMenusPacket GetPageBreakInformationPacket Glaisher GlobalClusteringCoefficient GlobalPreferences GlobalSession Glow GoldenRatio GompertzMakehamDistribution GoodmanKruskalGamma GoodmanKruskalGammaTest Goto Grad Gradient GradientFilter GradientOrientationFilter Graph GraphAssortativity GraphCenter GraphComplement GraphData GraphDensity GraphDiameter GraphDifference GraphDisjointUnion GraphDistance GraphDistanceMatrix GraphElementData GraphEmbedding GraphHighlight GraphHighlightStyle GraphHub Graphics Graphics3D Graphics3DBox Graphics3DBoxOptions GraphicsArray GraphicsBaseline GraphicsBox GraphicsBoxOptions GraphicsColor GraphicsColumn GraphicsComplex GraphicsComplex3DBox GraphicsComplex3DBoxOptions GraphicsComplexBox GraphicsComplexBoxOptions GraphicsContents GraphicsData GraphicsGrid GraphicsGridBox GraphicsGroup GraphicsGroup3DBox GraphicsGroup3DBoxOptions GraphicsGroupBox GraphicsGroupBoxOptions GraphicsGrouping GraphicsHighlightColor GraphicsRow GraphicsSpacing GraphicsStyle GraphIntersection GraphLayout GraphLinkEfficiency GraphPeriphery GraphPlot GraphPlot3D GraphPower GraphPropertyDistribution GraphQ GraphRadius GraphReciprocity GraphRoot GraphStyle GraphUnion Gray GrayLevel GreatCircleDistance Greater GreaterEqual GreaterEqualLess GreaterFullEqual GreaterGreater GreaterLess GreaterSlantEqual GreaterTilde Green Grid GridBaseline GridBox GridBoxAlignment GridBoxBackground GridBoxDividers GridBoxFrame GridBoxItemSize GridBoxItemStyle GridBoxOptions GridBoxSpacings GridCreationSettings GridDefaultElement GridElementStyleOptions GridFrame GridFrameMargins GridGraph GridLines GridLinesStyle GroebnerBasis GroupActionBase GroupCentralizer GroupElementFromWord GroupElementPosition GroupElementQ GroupElements GroupElementToWord GroupGenerators GroupMultiplicationTable GroupOrbits GroupOrder GroupPageBreakWithin GroupSetwiseStabilizer GroupStabilizer GroupStabilizerChain Gudermannian GumbelDistribution HaarWavelet HadamardMatrix HalfNormalDistribution HamiltonianGraphQ HammingDistance HammingWindow HankelH1 HankelH2 HankelMatrix HannPoissonWindow HannWindow HaradaNortonGroupHN HararyGraph HarmonicMean HarmonicMeanFilter HarmonicNumber Hash HashTable Haversine HazardFunction Head HeadCompose Heads HeavisideLambda HeavisidePi HeavisideTheta HeldGroupHe HeldPart HelpBrowserLookup HelpBrowserNotebook HelpBrowserSettings HermiteDecomposition HermiteH HermitianMatrixQ HessenbergDecomposition Hessian HexadecimalCharacter Hexahedron HexahedronBox HexahedronBoxOptions HiddenSurface HighlightGraph HighlightImage HighpassFilter HigmanSimsGroupHS HilbertFilter HilbertMatrix Histogram Histogram3D HistogramDistribution HistogramList HistogramTransform HistogramTransformInterpolation HitMissTransform HITSCentrality HodgeDual HoeffdingD HoeffdingDTest Hold HoldAll HoldAllComplete HoldComplete HoldFirst HoldForm HoldPattern HoldRest HolidayCalendar HomeDirectory HomePage Horizontal HorizontalForm HorizontalGauge HorizontalScrollPosition HornerForm HotellingTSquareDistribution HoytDistribution HTMLSave Hue HumpDownHump HumpEqual HurwitzLerchPhi HurwitzZeta HyperbolicDistribution HypercubeGraph HyperexponentialDistribution Hyperfactorial Hypergeometric0F1 Hypergeometric0F1Regularized Hypergeometric1F1 Hypergeometric1F1Regularized Hypergeometric2F1 Hypergeometric2F1Regularized HypergeometricDistribution HypergeometricPFQ HypergeometricPFQRegularized HypergeometricU Hyperlink HyperlinkCreationSettings Hyphenation HyphenationOptions HypoexponentialDistribution HypothesisTestData I Identity IdentityMatrix If IgnoreCase Im Image Image3D Image3DSlices ImageAccumulate ImageAdd ImageAdjust ImageAlign ImageApply ImageAspectRatio ImageAssemble ImageCache ImageCacheValid ImageCapture ImageChannels ImageClip ImageColorSpace ImageCompose ImageConvolve ImageCooccurrence ImageCorners ImageCorrelate ImageCorrespondingPoints ImageCrop ImageData ImageDataPacket ImageDeconvolve ImageDemosaic ImageDifference ImageDimensions ImageDistance ImageEffect ImageFeatureTrack ImageFileApply ImageFileFilter ImageFileScan ImageFilter ImageForestingComponents ImageForwardTransformation ImageHistogram ImageKeypoints ImageLevels ImageLines ImageMargins ImageMarkers ImageMeasurements ImageMultiply ImageOffset ImagePad ImagePadding ImagePartition ImagePeriodogram ImagePerspectiveTransformation ImageQ ImageRangeCache ImageReflect ImageRegion ImageResize ImageResolution ImageRotate ImageRotated ImageScaled ImageScan ImageSize ImageSizeAction ImageSizeCache ImageSizeMultipliers ImageSizeRaw ImageSubtract ImageTake ImageTransformation ImageTrim ImageType ImageValue ImageValuePositions Implies Import ImportAutoReplacements ImportString ImprovementImportance In IncidenceGraph IncidenceList IncidenceMatrix IncludeConstantBasis IncludeFileExtension IncludePods IncludeSingularTerm Increment Indent IndentingNewlineSpacings IndentMaxFraction IndependenceTest IndependentEdgeSetQ IndependentUnit IndependentVertexSetQ Indeterminate IndexCreationOptions Indexed IndexGraph IndexTag Inequality InexactNumberQ InexactNumbers Infinity Infix Information Inherited InheritScope Initialization InitializationCell InitializationCellEvaluation InitializationCellWarning InlineCounterAssignments InlineCounterIncrements InlineRules Inner Inpaint Input InputAliases InputAssumptions InputAutoReplacements InputField InputFieldBox InputFieldBoxOptions InputForm InputGrouping InputNamePacket InputNotebook InputPacket InputSettings InputStream InputString InputStringPacket InputToBoxFormPacket Insert InsertionPointObject InsertResults Inset Inset3DBox Inset3DBoxOptions InsetBox InsetBoxOptions Install InstallService InString Integer IntegerDigits IntegerExponent IntegerLength IntegerPart IntegerPartitions IntegerQ Integers IntegerString Integral Integrate Interactive InteractiveTradingChart Interlaced Interleaving InternallyBalancedDecomposition InterpolatingFunction InterpolatingPolynomial Interpolation InterpolationOrder InterpolationPoints InterpolationPrecision Interpretation InterpretationBox InterpretationBoxOptions InterpretationFunction InterpretTemplate InterquartileRange Interrupt InterruptSettings Intersection Interval IntervalIntersection IntervalMemberQ IntervalUnion Inverse InverseBetaRegularized InverseCDF InverseChiSquareDistribution InverseContinuousWaveletTransform InverseDistanceTransform InverseEllipticNomeQ InverseErf InverseErfc InverseFourier InverseFourierCosTransform InverseFourierSequenceTransform InverseFourierSinTransform InverseFourierTransform InverseFunction InverseFunctions InverseGammaDistribution InverseGammaRegularized InverseGaussianDistribution InverseGudermannian InverseHaversine InverseJacobiCD InverseJacobiCN InverseJacobiCS InverseJacobiDC InverseJacobiDN InverseJacobiDS InverseJacobiNC InverseJacobiND InverseJacobiNS InverseJacobiSC InverseJacobiSD InverseJacobiSN InverseLaplaceTransform InversePermutation InverseRadon InverseSeries InverseSurvivalFunction InverseWaveletTransform InverseWeierstrassP InverseZTransform Invisible InvisibleApplication InvisibleTimes IrreduciblePolynomialQ IsolatingInterval IsomorphicGraphQ IsotopeData Italic Item ItemBox ItemBoxOptions ItemSize ItemStyle ItoProcess JaccardDissimilarity JacobiAmplitude Jacobian JacobiCD JacobiCN JacobiCS JacobiDC JacobiDN JacobiDS JacobiNC JacobiND JacobiNS JacobiP JacobiSC JacobiSD JacobiSN JacobiSymbol JacobiZeta JankoGroupJ1 JankoGroupJ2 JankoGroupJ3 JankoGroupJ4 JarqueBeraALMTest JohnsonDistribution Join Joined JoinedCurve JoinedCurveBox JoinForm JordanDecomposition JordanModelDecomposition K KagiChart KaiserBesselWindow KaiserWindow KalmanEstimator KalmanFilter KarhunenLoeveDecomposition KaryTree KatzCentrality KCoreComponents KDistribution KelvinBei KelvinBer KelvinKei KelvinKer KendallTau KendallTauTest KernelExecute KernelMixtureDistribution KernelObject Kernels Ket Khinchin KirchhoffGraph KirchhoffMatrix KleinInvariantJ KnightTourGraph KnotData KnownUnitQ KolmogorovSmirnovTest KroneckerDelta KroneckerModelDecomposition KroneckerProduct KroneckerSymbol KuiperTest KumaraswamyDistribution Kurtosis KuwaharaFilter Label Labeled LabeledSlider LabelingFunction LabelStyle LaguerreL LambdaComponents LambertW LanczosWindow LandauDistribution Language LanguageCategory LaplaceDistribution LaplaceTransform Laplacian LaplacianFilter LaplacianGaussianFilter Large Larger Last Latitude LatitudeLongitude LatticeData LatticeReduce Launch LaunchKernels LayeredGraphPlot LayerSizeFunction LayoutInformation LCM LeafCount LeapYearQ LeastSquares LeastSquaresFilterKernel Left LeftArrow LeftArrowBar LeftArrowRightArrow LeftDownTeeVector LeftDownVector LeftDownVectorBar LeftRightArrow LeftRightVector LeftTee LeftTeeArrow LeftTeeVector LeftTriangle LeftTriangleBar LeftTriangleEqual LeftUpDownVector LeftUpTeeVector LeftUpVector LeftUpVectorBar LeftVector LeftVectorBar LegendAppearance Legended LegendFunction LegendLabel LegendLayout LegendMargins LegendMarkers LegendMarkerSize LegendreP LegendreQ LegendreType Length LengthWhile LerchPhi Less LessEqual LessEqualGreater LessFullEqual LessGreater LessLess LessSlantEqual LessTilde LetterCharacter LetterQ Level LeveneTest LeviCivitaTensor LevyDistribution Lexicographic LibraryFunction LibraryFunctionError LibraryFunctionInformation LibraryFunctionLoad LibraryFunctionUnload LibraryLoad LibraryUnload LicenseID LiftingFilterData LiftingWaveletTransform LightBlue LightBrown LightCyan Lighter LightGray LightGreen Lighting LightingAngle LightMagenta LightOrange LightPink LightPurple LightRed LightSources LightYellow Likelihood Limit LimitsPositioning LimitsPositioningTokens LindleyDistribution Line Line3DBox LinearFilter LinearFractionalTransform LinearModelFit LinearOffsetFunction LinearProgramming LinearRecurrence LinearSolve LinearSolveFunction LineBox LineBreak LinebreakAdjustments LineBreakChart LineBreakWithin LineColor LineForm LineGraph LineIndent LineIndentMaxFraction LineIntegralConvolutionPlot LineIntegralConvolutionScale LineLegend LineOpacity LineSpacing LineWrapParts LinkActivate LinkClose LinkConnect LinkConnectedQ LinkCreate LinkError LinkFlush LinkFunction LinkHost LinkInterrupt LinkLaunch LinkMode LinkObject LinkOpen LinkOptions LinkPatterns LinkProtocol LinkRead LinkReadHeld LinkReadyQ Links LinkWrite LinkWriteHeld LiouvilleLambda List Listable ListAnimate ListContourPlot ListContourPlot3D ListConvolve ListCorrelate ListCurvePathPlot ListDeconvolve ListDensityPlot Listen ListFourierSequenceTransform ListInterpolation ListLineIntegralConvolutionPlot ListLinePlot ListLogLinearPlot ListLogLogPlot ListLogPlot ListPicker ListPickerBox ListPickerBoxBackground ListPickerBoxOptions ListPlay ListPlot ListPlot3D ListPointPlot3D ListPolarPlot ListQ ListStreamDensityPlot ListStreamPlot ListSurfacePlot3D ListVectorDensityPlot ListVectorPlot ListVectorPlot3D ListZTransform Literal LiteralSearch LocalClusteringCoefficient LocalizeVariables LocationEquivalenceTest LocationTest Locator LocatorAutoCreate LocatorBox LocatorBoxOptions LocatorCentering LocatorPane LocatorPaneBox LocatorPaneBoxOptions LocatorRegion Locked Log Log10 Log2 LogBarnesG LogGamma LogGammaDistribution LogicalExpand LogIntegral LogisticDistribution LogitModelFit LogLikelihood LogLinearPlot LogLogisticDistribution LogLogPlot LogMultinormalDistribution LogNormalDistribution LogPlot LogRankTest LogSeriesDistribution LongEqual Longest LongestAscendingSequence LongestCommonSequence LongestCommonSequencePositions LongestCommonSubsequence LongestCommonSubsequencePositions LongestMatch LongForm Longitude LongLeftArrow LongLeftRightArrow LongRightArrow Loopback LoopFreeGraphQ LowerCaseQ LowerLeftArrow LowerRightArrow LowerTriangularize LowpassFilter LQEstimatorGains LQGRegulator LQOutputRegulatorGains LQRegulatorGains LUBackSubstitution LucasL LuccioSamiComponents LUDecomposition LyapunovSolve LyonsGroupLy MachineID MachineName MachineNumberQ MachinePrecision MacintoshSystemPageSetup Magenta Magnification Magnify MainSolve MaintainDynamicCaches Majority MakeBoxes MakeExpression MakeRules MangoldtLambda ManhattanDistance Manipulate Manipulator MannWhitneyTest MantissaExponent Manual Map MapAll MapAt MapIndexed MAProcess MapThread MarcumQ MardiaCombinedTest MardiaKurtosisTest MardiaSkewnessTest MarginalDistribution MarkovProcessProperties Masking MatchingDissimilarity MatchLocalNameQ MatchLocalNames MatchQ Material MathematicaNotation MathieuC MathieuCharacteristicA MathieuCharacteristicB MathieuCharacteristicExponent MathieuCPrime MathieuGroupM11 MathieuGroupM12 MathieuGroupM22 MathieuGroupM23 MathieuGroupM24 MathieuS MathieuSPrime MathMLForm MathMLText Matrices MatrixExp MatrixForm MatrixFunction MatrixLog MatrixPlot MatrixPower MatrixQ MatrixRank Max MaxBend MaxDetect MaxExtraBandwidths MaxExtraConditions MaxFeatures MaxFilter Maximize MaxIterations MaxMemoryUsed MaxMixtureKernels MaxPlotPoints MaxPoints MaxRecursion MaxStableDistribution MaxStepFraction MaxSteps MaxStepSize MaxValue MaxwellDistribution McLaughlinGroupMcL Mean MeanClusteringCoefficient MeanDegreeConnectivity MeanDeviation MeanFilter MeanGraphDistance MeanNeighborDegree MeanShift MeanShiftFilter Median MedianDeviation MedianFilter Medium MeijerG MeixnerDistribution MemberQ MemoryConstrained MemoryInUse Menu MenuAppearance MenuCommandKey MenuEvaluator MenuItem MenuPacket MenuSortingValue MenuStyle MenuView MergeDifferences Mesh MeshFunctions MeshRange MeshShading MeshStyle Message MessageDialog MessageList MessageName MessageOptions MessagePacket Messages MessagesNotebook MetaCharacters MetaInformation Method MethodOptions MexicanHatWavelet MeyerWavelet Min MinDetect MinFilter MinimalPolynomial MinimalStateSpaceModel Minimize Minors MinRecursion MinSize MinStableDistribution Minus MinusPlus MinValue Missing MissingDataMethod MittagLefflerE MixedRadix MixedRadixQuantity MixtureDistribution Mod Modal Mode Modular ModularLambda Module Modulus MoebiusMu Moment Momentary MomentConvert MomentEvaluate MomentGeneratingFunction Monday Monitor MonomialList MonomialOrder MonsterGroupM MorletWavelet MorphologicalBinarize MorphologicalBranchPoints MorphologicalComponents MorphologicalEulerNumber MorphologicalGraph MorphologicalPerimeter MorphologicalTransform Most MouseAnnotation MouseAppearance MouseAppearanceTag MouseButtons Mouseover MousePointerNote MousePosition MovingAverage MovingMedian MoyalDistribution MultiedgeStyle MultilaunchWarning MultiLetterItalics MultiLetterStyle MultilineFunction Multinomial MultinomialDistribution MultinormalDistribution MultiplicativeOrder Multiplicity Multiselection MultivariateHypergeometricDistribution MultivariatePoissonDistribution MultivariateTDistribution N NakagamiDistribution NameQ Names NamespaceBox Nand NArgMax NArgMin NBernoulliB NCache NDSolve NDSolveValue Nearest NearestFunction NeedCurrentFrontEndPackagePacket NeedCurrentFrontEndSymbolsPacket NeedlemanWunschSimilarity Needs Negative NegativeBinomialDistribution NegativeMultinomialDistribution NeighborhoodGraph Nest NestedGreaterGreater NestedLessLess NestedScriptRules NestList NestWhile NestWhileList NevilleThetaC NevilleThetaD NevilleThetaN NevilleThetaS NewPrimitiveStyle NExpectation Next NextPrime NHoldAll NHoldFirst NHoldRest NicholsGridLines NicholsPlot NIntegrate NMaximize NMaxValue NMinimize NMinValue NominalVariables NonAssociative NoncentralBetaDistribution NoncentralChiSquareDistribution NoncentralFRatioDistribution NoncentralStudentTDistribution NonCommutativeMultiply NonConstants None NonlinearModelFit NonlocalMeansFilter NonNegative NonPositive Nor NorlundB Norm Normal NormalDistribution NormalGrouping Normalize NormalizedSquaredEuclideanDistance NormalsFunction NormFunction Not NotCongruent NotCupCap NotDoubleVerticalBar Notebook NotebookApply NotebookAutoSave NotebookClose NotebookConvertSettings NotebookCreate NotebookCreateReturnObject NotebookDefault NotebookDelete NotebookDirectory NotebookDynamicExpression NotebookEvaluate NotebookEventActions NotebookFileName NotebookFind NotebookFindReturnObject NotebookGet NotebookGetLayoutInformationPacket NotebookGetMisspellingsPacket NotebookInformation NotebookInterfaceObject NotebookLocate NotebookObject NotebookOpen NotebookOpenReturnObject NotebookPath NotebookPrint NotebookPut NotebookPutReturnObject NotebookRead NotebookResetGeneratedCells Notebooks NotebookSave NotebookSaveAs NotebookSelection NotebookSetupLayoutInformationPacket NotebooksMenu NotebookWrite NotElement NotEqualTilde NotExists NotGreater NotGreaterEqual NotGreaterFullEqual NotGreaterGreater NotGreaterLess NotGreaterSlantEqual NotGreaterTilde NotHumpDownHump NotHumpEqual NotLeftTriangle NotLeftTriangleBar NotLeftTriangleEqual NotLess NotLessEqual NotLessFullEqual NotLessGreater NotLessLess NotLessSlantEqual NotLessTilde NotNestedGreaterGreater NotNestedLessLess NotPrecedes NotPrecedesEqual NotPrecedesSlantEqual NotPrecedesTilde NotReverseElement NotRightTriangle NotRightTriangleBar NotRightTriangleEqual NotSquareSubset NotSquareSubsetEqual NotSquareSuperset NotSquareSupersetEqual NotSubset NotSubsetEqual NotSucceeds NotSucceedsEqual NotSucceedsSlantEqual NotSucceedsTilde NotSuperset NotSupersetEqual NotTilde NotTildeEqual NotTildeFullEqual NotTildeTilde NotVerticalBar NProbability NProduct NProductFactors NRoots NSolve NSum NSumTerms Null NullRecords NullSpace NullWords Number NumberFieldClassNumber NumberFieldDiscriminant NumberFieldFundamentalUnits NumberFieldIntegralBasis NumberFieldNormRepresentatives NumberFieldRegulator NumberFieldRootsOfUnity NumberFieldSignature NumberForm NumberFormat NumberMarks NumberMultiplier NumberPadding NumberPoint NumberQ NumberSeparator NumberSigns NumberString Numerator NumericFunction NumericQ NuttallWindow NValues NyquistGridLines NyquistPlot O ObservabilityGramian ObservabilityMatrix ObservableDecomposition ObservableModelQ OddQ Off Offset OLEData On ONanGroupON OneIdentity Opacity Open OpenAppend Opener OpenerBox OpenerBoxOptions OpenerView OpenFunctionInspectorPacket Opening OpenRead OpenSpecialOptions OpenTemporary OpenWrite Operate OperatingSystem OptimumFlowData Optional OptionInspectorSettings OptionQ Options OptionsPacket OptionsPattern OptionValue OptionValueBox OptionValueBoxOptions Or Orange Order OrderDistribution OrderedQ Ordering Orderless OrnsteinUhlenbeckProcess Orthogonalize Out Outer OutputAutoOverwrite OutputControllabilityMatrix OutputControllableModelQ OutputForm OutputFormData OutputGrouping OutputMathEditExpression OutputNamePacket OutputResponse OutputSizeLimit OutputStream Over OverBar OverDot Overflow OverHat Overlaps Overlay OverlayBox OverlayBoxOptions Overscript OverscriptBox OverscriptBoxOptions OverTilde OverVector OwenT OwnValues PackingMethod PaddedForm Padding PadeApproximant PadLeft PadRight PageBreakAbove PageBreakBelow PageBreakWithin PageFooterLines PageFooters PageHeaderLines PageHeaders PageHeight PageRankCentrality PageWidth PairedBarChart PairedHistogram PairedSmoothHistogram PairedTTest PairedZTest PaletteNotebook PalettePath Pane PaneBox PaneBoxOptions Panel PanelBox PanelBoxOptions Paneled PaneSelector PaneSelectorBox PaneSelectorBoxOptions PaperWidth ParabolicCylinderD ParagraphIndent ParagraphSpacing ParallelArray ParallelCombine ParallelDo ParallelEvaluate Parallelization Parallelize ParallelMap ParallelNeeds ParallelProduct ParallelSubmit ParallelSum ParallelTable ParallelTry Parameter ParameterEstimator ParameterMixtureDistribution ParameterVariables ParametricFunction ParametricNDSolve ParametricNDSolveValue ParametricPlot ParametricPlot3D ParentConnect ParentDirectory ParentForm Parenthesize ParentList ParetoDistribution Part PartialCorrelationFunction PartialD ParticleData Partition PartitionsP PartitionsQ ParzenWindow PascalDistribution PassEventsDown PassEventsUp Paste PasteBoxFormInlineCells PasteButton Path PathGraph PathGraphQ Pattern PatternSequence PatternTest PauliMatrix PaulWavelet Pause PausedTime PDF PearsonChiSquareTest PearsonCorrelationTest PearsonDistribution PerformanceGoal PeriodicInterpolation Periodogram PeriodogramArray PermutationCycles PermutationCyclesQ PermutationGroup PermutationLength PermutationList PermutationListQ PermutationMax PermutationMin PermutationOrder PermutationPower PermutationProduct PermutationReplace Permutations PermutationSupport Permute PeronaMalikFilter Perpendicular PERTDistribution PetersenGraph PhaseMargins Pi Pick PIDData PIDDerivativeFilter PIDFeedforward PIDTune Piecewise PiecewiseExpand PieChart PieChart3D PillaiTrace PillaiTraceTest Pink Pivoting PixelConstrained PixelValue PixelValuePositions Placed Placeholder PlaceholderReplace Plain PlanarGraphQ Play PlayRange Plot Plot3D Plot3Matrix PlotDivision PlotJoined PlotLabel PlotLayout PlotLegends PlotMarkers PlotPoints PlotRange PlotRangeClipping PlotRangePadding PlotRegion PlotStyle Plus PlusMinus Pochhammer PodStates PodWidth Point Point3DBox PointBox PointFigureChart PointForm PointLegend PointSize PoissonConsulDistribution PoissonDistribution PoissonProcess PoissonWindow PolarAxes PolarAxesOrigin PolarGridLines PolarPlot PolarTicks PoleZeroMarkers PolyaAeppliDistribution PolyGamma Polygon Polygon3DBox Polygon3DBoxOptions PolygonBox PolygonBoxOptions PolygonHoleScale PolygonIntersections PolygonScale PolyhedronData PolyLog PolynomialExtendedGCD PolynomialForm PolynomialGCD PolynomialLCM PolynomialMod PolynomialQ PolynomialQuotient PolynomialQuotientRemainder PolynomialReduce PolynomialRemainder Polynomials PopupMenu PopupMenuBox PopupMenuBoxOptions PopupView PopupWindow Position Positive PositiveDefiniteMatrixQ PossibleZeroQ Postfix PostScript Power PowerDistribution PowerExpand PowerMod PowerModList PowerSpectralDensity PowersRepresentations PowerSymmetricPolynomial Precedence PrecedenceForm Precedes PrecedesEqual PrecedesSlantEqual PrecedesTilde Precision PrecisionGoal PreDecrement PredictionRoot PreemptProtect PreferencesPath Prefix PreIncrement Prepend PrependTo PreserveImageOptions Previous PriceGraphDistribution PrimaryPlaceholder Prime PrimeNu PrimeOmega PrimePi PrimePowerQ PrimeQ Primes PrimeZetaP PrimitiveRoot PrincipalComponents PrincipalValue Print PrintAction PrintForm PrintingCopies PrintingOptions PrintingPageRange PrintingStartingPageNumber PrintingStyleEnvironment PrintPrecision PrintTemporary Prism PrismBox PrismBoxOptions PrivateCellOptions PrivateEvaluationOptions PrivateFontOptions PrivateFrontEndOptions PrivateNotebookOptions PrivatePaths Probability ProbabilityDistribution ProbabilityPlot ProbabilityPr ProbabilityScalePlot ProbitModelFit ProcessEstimator ProcessParameterAssumptions ProcessParameterQ ProcessStateDomain ProcessTimeDomain Product ProductDistribution ProductLog ProgressIndicator ProgressIndicatorBox ProgressIndicatorBoxOptions Projection Prolog PromptForm Properties Property PropertyList PropertyValue Proportion Proportional Protect Protected ProteinData Pruning PseudoInverse Purple Put PutAppend Pyramid PyramidBox PyramidBoxOptions QBinomial QFactorial QGamma QHypergeometricPFQ QPochhammer QPolyGamma QRDecomposition QuadraticIrrationalQ Quantile QuantilePlot Quantity QuantityForm QuantityMagnitude QuantityQ QuantityUnit Quartics QuartileDeviation Quartiles QuartileSkewness QueueingNetworkProcess QueueingProcess QueueProperties Quiet Quit Quotient QuotientRemainder RadialityCentrality RadicalBox RadicalBoxOptions RadioButton RadioButtonBar RadioButtonBox RadioButtonBoxOptions Radon RamanujanTau RamanujanTauL RamanujanTauTheta RamanujanTauZ Random RandomChoice RandomComplex RandomFunction RandomGraph RandomImage RandomInteger RandomPermutation RandomPrime RandomReal RandomSample RandomSeed RandomVariate RandomWalkProcess Range RangeFilter RangeSpecification RankedMax RankedMin Raster Raster3D Raster3DBox Raster3DBoxOptions RasterArray RasterBox RasterBoxOptions Rasterize RasterSize Rational RationalFunctions Rationalize Rationals Ratios Raw RawArray RawBoxes RawData RawMedium RayleighDistribution Re Read ReadList ReadProtected Real RealBlockDiagonalForm RealDigits RealExponent Reals Reap Record RecordLists RecordSeparators Rectangle RectangleBox RectangleBoxOptions RectangleChart RectangleChart3D RecurrenceFilter RecurrenceTable RecurringDigitsForm Red Reduce RefBox ReferenceLineStyle ReferenceMarkers ReferenceMarkerStyle Refine ReflectionMatrix ReflectionTransform Refresh RefreshRate RegionBinarize RegionFunction RegionPlot RegionPlot3D RegularExpression Regularization Reinstall Release ReleaseHold ReliabilityDistribution ReliefImage ReliefPlot Remove RemoveAlphaChannel RemoveAsynchronousTask Removed RemoveInputStreamMethod RemoveOutputStreamMethod RemoveProperty RemoveScheduledTask RenameDirectory RenameFile RenderAll RenderingOptions RenewalProcess RenkoChart Repeated RepeatedNull RepeatedString Replace ReplaceAll ReplaceHeldPart ReplaceImageValue ReplaceList ReplacePart ReplacePixelValue ReplaceRepeated Resampling Rescale RescalingTransform ResetDirectory ResetMenusPacket ResetScheduledTask Residue Resolve Rest Resultant ResumePacket Return ReturnExpressionPacket ReturnInputFormPacket ReturnPacket ReturnTextPacket Reverse ReverseBiorthogonalSplineWavelet ReverseElement ReverseEquilibrium ReverseGraph ReverseUpEquilibrium RevolutionAxis RevolutionPlot3D RGBColor RiccatiSolve RiceDistribution RidgeFilter RiemannR RiemannSiegelTheta RiemannSiegelZ Riffle Right RightArrow RightArrowBar RightArrowLeftArrow RightCosetRepresentative RightDownTeeVector RightDownVector RightDownVectorBar RightTee RightTeeArrow RightTeeVector RightTriangle RightTriangleBar RightTriangleEqual RightUpDownVector RightUpTeeVector RightUpVector RightUpVectorBar RightVector RightVectorBar RiskAchievementImportance RiskReductionImportance RogersTanimotoDissimilarity Root RootApproximant RootIntervals RootLocusPlot RootMeanSquare RootOfUnityQ RootReduce Roots RootSum Rotate RotateLabel RotateLeft RotateRight RotationAction RotationBox RotationBoxOptions RotationMatrix RotationTransform Round RoundImplies RoundingRadius Row RowAlignments RowBackgrounds RowBox RowHeights RowLines RowMinHeight RowReduce RowsEqual RowSpacings RSolve RudvalisGroupRu Rule RuleCondition RuleDelayed RuleForm RulerUnits Run RunScheduledTask RunThrough RuntimeAttributes RuntimeOptions RussellRaoDissimilarity SameQ SameTest SampleDepth SampledSoundFunction SampledSoundList SampleRate SamplingPeriod SARIMAProcess SARMAProcess SatisfiabilityCount SatisfiabilityInstances SatisfiableQ Saturday Save Saveable SaveAutoDelete SaveDefinitions SawtoothWave Scale Scaled ScaleDivisions ScaledMousePosition ScaleOrigin ScalePadding ScaleRanges ScaleRangeStyle ScalingFunctions ScalingMatrix ScalingTransform Scan ScheduledTaskActiveQ ScheduledTaskData ScheduledTaskObject ScheduledTasks SchurDecomposition ScientificForm ScreenRectangle ScreenStyleEnvironment ScriptBaselineShifts ScriptLevel ScriptMinSize ScriptRules ScriptSizeMultipliers Scrollbars ScrollingOptions ScrollPosition Sec Sech SechDistribution SectionGrouping SectorChart SectorChart3D SectorOrigin SectorSpacing SeedRandom Select Selectable SelectComponents SelectedCells SelectedNotebook Selection SelectionAnimate SelectionCell SelectionCellCreateCell SelectionCellDefaultStyle SelectionCellParentStyle SelectionCreateCell SelectionDebuggerTag SelectionDuplicateCell SelectionEvaluate SelectionEvaluateCreateCell SelectionMove SelectionPlaceholder SelectionSetStyle SelectWithContents SelfLoops SelfLoopStyle SemialgebraicComponentInstances SendMail Sequence SequenceAlignment SequenceForm SequenceHold SequenceLimit Series SeriesCoefficient SeriesData SessionTime Set SetAccuracy SetAlphaChannel SetAttributes Setbacks SetBoxFormNamesPacket SetDelayed SetDirectory SetEnvironment SetEvaluationNotebook SetFileDate SetFileLoadingContext SetNotebookStatusLine SetOptions SetOptionsPacket SetPrecision SetProperty SetSelectedNotebook SetSharedFunction SetSharedVariable SetSpeechParametersPacket SetStreamPosition SetSystemOptions Setter SetterBar SetterBox SetterBoxOptions Setting SetValue Shading Shallow ShannonWavelet ShapiroWilkTest Share Sharpen ShearingMatrix ShearingTransform ShenCastanMatrix Short ShortDownArrow Shortest ShortestMatch ShortestPathFunction ShortLeftArrow ShortRightArrow ShortUpArrow Show ShowAutoStyles ShowCellBracket ShowCellLabel ShowCellTags ShowClosedCellArea ShowContents ShowControls ShowCursorTracker ShowGroupOpenCloseIcon ShowGroupOpener ShowInvisibleCharacters ShowPageBreaks ShowPredictiveInterface ShowSelection ShowShortBoxForm ShowSpecialCharacters ShowStringCharacters ShowSyntaxStyles ShrinkingDelay ShrinkWrapBoundingBox SiegelTheta SiegelTukeyTest Sign Signature SignedRankTest SignificanceLevel SignPadding SignTest SimilarityRules SimpleGraph SimpleGraphQ Simplify Sin Sinc SinghMaddalaDistribution SingleEvaluation SingleLetterItalics SingleLetterStyle SingularValueDecomposition SingularValueList SingularValuePlot SingularValues Sinh SinhIntegral SinIntegral SixJSymbol Skeleton SkeletonTransform SkellamDistribution Skewness SkewNormalDistribution Skip SliceDistribution Slider Slider2D Slider2DBox Slider2DBoxOptions SliderBox SliderBoxOptions SlideView Slot SlotSequence Small SmallCircle Smaller SmithDelayCompensator SmithWatermanSimilarity SmoothDensityHistogram SmoothHistogram SmoothHistogram3D SmoothKernelDistribution SocialMediaData Socket SokalSneathDissimilarity Solve SolveAlways SolveDelayed Sort SortBy Sound SoundAndGraphics SoundNote SoundVolume Sow Space SpaceForm Spacer Spacings Span SpanAdjustments SpanCharacterRounding SpanFromAbove SpanFromBoth SpanFromLeft SpanLineThickness SpanMaxSize SpanMinSize SpanningCharacters SpanSymmetric SparseArray SpatialGraphDistribution Speak SpeakTextPacket SpearmanRankTest SpearmanRho Spectrogram SpectrogramArray Specularity SpellingCorrection SpellingDictionaries SpellingDictionariesPath SpellingOptions SpellingSuggestionsPacket Sphere SphereBox SphericalBesselJ SphericalBesselY SphericalHankelH1 SphericalHankelH2 SphericalHarmonicY SphericalPlot3D SphericalRegion SpheroidalEigenvalue SpheroidalJoiningFactor SpheroidalPS SpheroidalPSPrime SpheroidalQS SpheroidalQSPrime SpheroidalRadialFactor SpheroidalS1 SpheroidalS1Prime SpheroidalS2 SpheroidalS2Prime Splice SplicedDistribution SplineClosed SplineDegree SplineKnots SplineWeights Split SplitBy SpokenString Sqrt SqrtBox SqrtBoxOptions Square SquaredEuclideanDistance SquareFreeQ SquareIntersection SquaresR SquareSubset SquareSubsetEqual SquareSuperset SquareSupersetEqual SquareUnion SquareWave StabilityMargins StabilityMarginsStyle StableDistribution Stack StackBegin StackComplete StackInhibit StandardDeviation StandardDeviationFilter StandardForm Standardize StandbyDistribution Star StarGraph StartAsynchronousTask StartingStepSize StartOfLine StartOfString StartScheduledTask StartupSound StateDimensions StateFeedbackGains StateOutputEstimator StateResponse StateSpaceModel StateSpaceRealization StateSpaceTransform StationaryDistribution StationaryWaveletPacketTransform StationaryWaveletTransform StatusArea StatusCentrality StepMonitor StieltjesGamma StirlingS1 StirlingS2 StopAsynchronousTask StopScheduledTask StrataVariables StratonovichProcess StreamColorFunction StreamColorFunctionScaling StreamDensityPlot StreamPlot StreamPoints StreamPosition Streams StreamScale StreamStyle String StringBreak StringByteCount StringCases StringCount StringDrop StringExpression StringForm StringFormat StringFreeQ StringInsert StringJoin StringLength StringMatchQ StringPosition StringQ StringReplace StringReplaceList StringReplacePart StringReverse StringRotateLeft StringRotateRight StringSkeleton StringSplit StringTake StringToStream StringTrim StripBoxes StripOnInput StripWrapperBoxes StrokeForm StructuralImportance StructuredArray StructuredSelection StruveH StruveL Stub StudentTDistribution Style StyleBox StyleBoxAutoDelete StyleBoxOptions StyleData StyleDefinitions StyleForm StyleKeyMapping StyleMenuListing StyleNameDialogSettings StyleNames StylePrint StyleSheetPath Subfactorial Subgraph SubMinus SubPlus SubresultantPolynomialRemainders SubresultantPolynomials Subresultants Subscript SubscriptBox SubscriptBoxOptions Subscripted Subset SubsetEqual Subsets SubStar Subsuperscript SubsuperscriptBox SubsuperscriptBoxOptions Subtract SubtractFrom SubValues Succeeds SucceedsEqual SucceedsSlantEqual SucceedsTilde SuchThat Sum SumConvergence Sunday SuperDagger SuperMinus SuperPlus Superscript SuperscriptBox SuperscriptBoxOptions Superset SupersetEqual SuperStar Surd SurdForm SurfaceColor SurfaceGraphics SurvivalDistribution SurvivalFunction SurvivalModel SurvivalModelFit SuspendPacket SuzukiDistribution SuzukiGroupSuz SwatchLegend Switch Symbol SymbolName SymletWavelet Symmetric SymmetricGroup SymmetricMatrixQ SymmetricPolynomial SymmetricReduction Symmetrize SymmetrizedArray SymmetrizedArrayRules SymmetrizedDependentComponents SymmetrizedIndependentComponents SymmetrizedReplacePart SynchronousInitialization SynchronousUpdating Syntax SyntaxForm SyntaxInformation SyntaxLength SyntaxPacket SyntaxQ SystemDialogInput SystemException SystemHelpPath SystemInformation SystemInformationData SystemOpen SystemOptions SystemsModelDelay SystemsModelDelayApproximate SystemsModelDelete SystemsModelDimensions SystemsModelExtract SystemsModelFeedbackConnect SystemsModelLabels SystemsModelOrder SystemsModelParallelConnect SystemsModelSeriesConnect SystemsModelStateFeedbackConnect SystemStub Tab TabFilling Table TableAlignments TableDepth TableDirections TableForm TableHeadings TableSpacing TableView TableViewBox TabSpacings TabView TabViewBox TabViewBoxOptions TagBox TagBoxNote TagBoxOptions TaggingRules TagSet TagSetDelayed TagStyle TagUnset Take TakeWhile Tally Tan Tanh TargetFunctions TargetUnits TautologyQ TelegraphProcess TemplateBox TemplateBoxOptions TemplateSlotSequence TemporalData Temporary TemporaryVariable TensorContract TensorDimensions TensorExpand TensorProduct TensorQ TensorRank TensorReduce TensorSymmetry TensorTranspose TensorWedge Tetrahedron TetrahedronBox TetrahedronBoxOptions TeXForm TeXSave Text Text3DBox Text3DBoxOptions TextAlignment TextBand TextBoundingBox TextBox TextCell TextClipboardType TextData TextForm TextJustification TextLine TextPacket TextParagraph TextRecognize TextRendering TextStyle Texture TextureCoordinateFunction TextureCoordinateScaling Therefore ThermometerGauge Thick Thickness Thin Thinning ThisLink ThompsonGroupTh Thread ThreeJSymbol Threshold Through Throw Thumbnail Thursday Ticks TicksStyle Tilde TildeEqual TildeFullEqual TildeTilde TimeConstrained TimeConstraint Times TimesBy TimeSeriesForecast TimeSeriesInvertibility TimeUsed TimeValue TimeZone Timing Tiny TitleGrouping TitsGroupT ToBoxes ToCharacterCode ToColor ToContinuousTimeModel ToDate ToDiscreteTimeModel ToeplitzMatrix ToExpression ToFileName Together Toggle ToggleFalse Toggler TogglerBar TogglerBox TogglerBoxOptions ToHeldExpression ToInvertibleTimeSeries TokenWords Tolerance ToLowerCase ToNumberField TooBig Tooltip TooltipBox TooltipBoxOptions TooltipDelay TooltipStyle Top TopHatTransform TopologicalSort ToRadicals ToRules ToString Total TotalHeight TotalVariationFilter TotalWidth TouchscreenAutoZoom TouchscreenControlPlacement ToUpperCase Tr Trace TraceAbove TraceAction TraceBackward TraceDepth TraceDialog TraceForward TraceInternal TraceLevel TraceOff TraceOn TraceOriginal TracePrint TraceScan TrackedSymbols TradingChart TraditionalForm TraditionalFunctionNotation TraditionalNotation TraditionalOrder TransferFunctionCancel TransferFunctionExpand TransferFunctionFactor TransferFunctionModel TransferFunctionPoles TransferFunctionTransform TransferFunctionZeros TransformationFunction TransformationFunctions TransformationMatrix TransformedDistribution TransformedField Translate TranslationTransform TransparentColor Transpose TreeForm TreeGraph TreeGraphQ TreePlot TrendStyle TriangleWave TriangularDistribution Trig TrigExpand TrigFactor TrigFactorList Trigger TrigReduce TrigToExp TrimmedMean True TrueQ TruncatedDistribution TsallisQExponentialDistribution TsallisQGaussianDistribution TTest Tube TubeBezierCurveBox TubeBezierCurveBoxOptions TubeBox TubeBSplineCurveBox TubeBSplineCurveBoxOptions Tuesday TukeyLambdaDistribution TukeyWindow Tuples TuranGraph TuringMachine Transparent UnateQ Uncompress Undefined UnderBar Underflow Underlined Underoverscript UnderoverscriptBox UnderoverscriptBoxOptions Underscript UnderscriptBox UnderscriptBoxOptions UndirectedEdge UndirectedGraph UndirectedGraphQ UndocumentedTestFEParserPacket UndocumentedTestGetSelectionPacket Unequal Unevaluated UniformDistribution UniformGraphDistribution UniformSumDistribution Uninstall Union UnionPlus Unique UnitBox UnitConvert UnitDimensions Unitize UnitRootTest UnitSimplify UnitStep UnitTriangle UnitVector Unprotect UnsameQ UnsavedVariables Unset UnsetShared UntrackedVariables Up UpArrow UpArrowBar UpArrowDownArrow Update UpdateDynamicObjects UpdateDynamicObjectsSynchronous UpdateInterval UpDownArrow UpEquilibrium UpperCaseQ UpperLeftArrow UpperRightArrow UpperTriangularize Upsample UpSet UpSetDelayed UpTee UpTeeArrow UpValues URL URLFetch URLFetchAsynchronous URLSave URLSaveAsynchronous UseGraphicsRange Using UsingFrontEnd V2Get ValidationLength Value ValueBox ValueBoxOptions ValueForm ValueQ ValuesData Variables Variance VarianceEquivalenceTest VarianceEstimatorFunction VarianceGammaDistribution VarianceTest VectorAngle VectorColorFunction VectorColorFunctionScaling VectorDensityPlot VectorGlyphData VectorPlot VectorPlot3D VectorPoints VectorQ Vectors VectorScale VectorStyle Vee Verbatim Verbose VerboseConvertToPostScriptPacket VerifyConvergence VerifySolutions VerifyTestAssumptions Version VersionNumber VertexAdd VertexCapacity VertexColors VertexComponent VertexConnectivity VertexCoordinateRules VertexCoordinates VertexCorrelationSimilarity VertexCosineSimilarity VertexCount VertexCoverQ VertexDataCoordinates VertexDegree VertexDelete VertexDiceSimilarity VertexEccentricity VertexInComponent VertexInDegree VertexIndex VertexJaccardSimilarity VertexLabeling VertexLabels VertexLabelStyle VertexList VertexNormals VertexOutComponent VertexOutDegree VertexQ VertexRenderingFunction VertexReplace VertexShape VertexShapeFunction VertexSize VertexStyle VertexTextureCoordinates VertexWeight Vertical VerticalBar VerticalForm VerticalGauge VerticalSeparator VerticalSlider VerticalTilde ViewAngle ViewCenter ViewMatrix ViewPoint ViewPointSelectorSettings ViewPort ViewRange ViewVector ViewVertical VirtualGroupData Visible VisibleCell VoigtDistribution VonMisesDistribution WaitAll WaitAsynchronousTask WaitNext WaitUntil WakebyDistribution WalleniusHypergeometricDistribution WaringYuleDistribution WatershedComponents WatsonUSquareTest WattsStrogatzGraphDistribution WaveletBestBasis WaveletFilterCoefficients WaveletImagePlot WaveletListPlot WaveletMapIndexed WaveletMatrixPlot WaveletPhi WaveletPsi WaveletScale WaveletScalogram WaveletThreshold WeaklyConnectedComponents WeaklyConnectedGraphQ WeakStationarity WeatherData WeberE Wedge Wednesday WeibullDistribution WeierstrassHalfPeriods WeierstrassInvariants WeierstrassP WeierstrassPPrime WeierstrassSigma WeierstrassZeta WeightedAdjacencyGraph WeightedAdjacencyMatrix WeightedData WeightedGraphQ Weights WelchWindow WheelGraph WhenEvent Which While White Whitespace WhitespaceCharacter WhittakerM WhittakerW WienerFilter WienerProcess WignerD WignerSemicircleDistribution WilksW WilksWTest WindowClickSelect WindowElements WindowFloating WindowFrame WindowFrameElements WindowMargins WindowMovable WindowOpacity WindowSelected WindowSize WindowStatusArea WindowTitle WindowToolbars WindowWidth With WolframAlpha WolframAlphaDate WolframAlphaQuantity WolframAlphaResult Word WordBoundary WordCharacter WordData WordSearch WordSeparators WorkingPrecision Write WriteString Wronskian XMLElement XMLObject Xnor Xor Yellow YuleDissimilarity ZernikeR ZeroSymmetric ZeroTest ZeroWidthTimes Zeta ZetaZero ZipfDistribution ZTest ZTransform $Aborted $ActivationGroupID $ActivationKey $ActivationUserRegistered $AddOnsDirectory $AssertFunction $Assumptions $AsynchronousTask $BaseDirectory $BatchInput $BatchOutput $BoxForms $ByteOrdering $Canceled $CharacterEncoding $CharacterEncodings $CommandLine $CompilationTarget $ConditionHold $ConfiguredKernels $Context $ContextPath $ControlActiveSetting $CreationDate $CurrentLink $DateStringFormat $DefaultFont $DefaultFrontEnd $DefaultImagingDevice $DefaultPath $Display $DisplayFunction $DistributedContexts $DynamicEvaluation $Echo $Epilog $ExportFormats $Failed $FinancialDataSource $FormatType $FrontEnd $FrontEndSession $GeoLocation $HistoryLength $HomeDirectory $HTTPCookies $IgnoreEOF $ImagingDevices $ImportFormats $InitialDirectory $Input $InputFileName $InputStreamMethods $Inspector $InstallationDate $InstallationDirectory $InterfaceEnvironment $IterationLimit $KernelCount $KernelID $Language $LaunchDirectory $LibraryPath $LicenseExpirationDate $LicenseID $LicenseProcesses $LicenseServer $LicenseSubprocesses $LicenseType $Line $Linked $LinkSupported $LoadedFiles $MachineAddresses $MachineDomain $MachineDomains $MachineEpsilon $MachineID $MachineName $MachinePrecision $MachineType $MaxExtraPrecision $MaxLicenseProcesses $MaxLicenseSubprocesses $MaxMachineNumber $MaxNumber $MaxPiecewiseCases $MaxPrecision $MaxRootDegree $MessageGroups $MessageList $MessagePrePrint $Messages $MinMachineNumber $MinNumber $MinorReleaseNumber $MinPrecision $ModuleNumber $NetworkLicense $NewMessage $NewSymbol $Notebooks $NumberMarks $Off $OperatingSystem $Output $OutputForms $OutputSizeLimit $OutputStreamMethods $Packages $ParentLink $ParentProcessID $PasswordFile $PatchLevelID $Path $PathnameSeparator $PerformanceGoal $PipeSupported $Post $Pre $PreferencesDirectory $PrePrint $PreRead $PrintForms $PrintLiteral $ProcessID $ProcessorCount $ProcessorType $ProductInformation $ProgramName $RandomState $RecursionLimit $ReleaseNumber $RootDirectory $ScheduledTask $ScriptCommandLine $SessionID $SetParentLink $SharedFunctions $SharedVariables $SoundDisplay $SoundDisplayFunction $SuppressInputFormHeads $SynchronousEvaluation $SyntaxHandler $System $SystemCharacterEncoding $SystemID $SystemWordLength $TemporaryDirectory $TemporaryPrefix $TextStyle $TimedOut $TimeUnit $TimeZone $TopDirectory $TraceOff $TraceOn $TracePattern $TracePostAction $TracePreAction $Urgent $UserAddOnsDirectory $UserBaseDirectory $UserDocumentsDirectory $UserName $Version $VersionNumber",c:[{cN:"comment",b:/\(\*/,e:/\*\)/},a.ASM,a.QSM,a.CNM,{cN:"list",b:/\{/,e:/\}/,i:/:/}]}});hljs.registerLanguage("matlab",function(a){var b=[a.CNM,{cN:"string",b:"'",e:"'",c:[a.BE,{b:"''"}]}];return{k:{keyword:"break case catch classdef continue else elseif end enumerated events for function global if methods otherwise parfor persistent properties return spmd switch try while",built_in:"sin sind sinh asin asind asinh cos cosd cosh acos acosd acosh tan tand tanh atan atand atan2 atanh sec secd sech asec asecd asech csc cscd csch acsc acscd acsch cot cotd coth acot acotd acoth hypot exp expm1 log log1p log10 log2 pow2 realpow reallog realsqrt sqrt nthroot nextpow2 abs angle complex conj imag real unwrap isreal cplxpair fix floor ceil round mod rem sign airy besselj bessely besselh besseli besselk beta betainc betaln ellipj ellipke erf erfc erfcx erfinv expint gamma gammainc gammaln psi legendre cross dot factor isprime primes gcd lcm rat rats perms nchoosek factorial cart2sph cart2pol pol2cart sph2cart hsv2rgb rgb2hsv zeros ones eye repmat rand randn linspace logspace freqspace meshgrid accumarray size length ndims numel disp isempty isequal isequalwithequalnans cat reshape diag blkdiag tril triu fliplr flipud flipdim rot90 find sub2ind ind2sub bsxfun ndgrid permute ipermute shiftdim circshift squeeze isscalar isvector ans eps realmax realmin pi i inf nan isnan isinf isfinite j why compan gallery hadamard hankel hilb invhilb magic pascal rosser toeplitz vander wilkinson"},i:'(//|"|#|/\\*|\\s+/\\w+)',c:[{cN:"function",bK:"function",e:"$",c:[a.UTM,{cN:"params",b:"\\(",e:"\\)"},{cN:"params",b:"\\[",e:"\\]"}]},{cN:"transposed_variable",b:"[a-zA-Z_][a-zA-Z_0-9]*('+[\\.']*|[\\.']+)",e:"",r:0},{cN:"matrix",b:"\\[",e:"\\]'*[\\.']*",c:b,r:0},{cN:"cell",b:"\\{",c:b,i:/:/,v:[{e:/\}'[\.']*/},{e:/\}/,r:0}]},{cN:"comment",b:"\\%",e:"$"}].concat(b)}});hljs.registerLanguage("mel",function(a){return{k:"int float string vector matrix if else switch case default while do for in break continue global proc return about abs addAttr addAttributeEditorNodeHelp addDynamic addNewShelfTab addPP addPanelCategory addPrefixToName advanceToNextDrivenKey affectedNet affects aimConstraint air alias aliasAttr align alignCtx alignCurve alignSurface allViewFit ambientLight angle angleBetween animCone animCurveEditor animDisplay animView annotate appendStringArray applicationName applyAttrPreset applyTake arcLenDimContext arcLengthDimension arclen arrayMapper art3dPaintCtx artAttrCtx artAttrPaintVertexCtx artAttrSkinPaintCtx artAttrTool artBuildPaintMenu artFluidAttrCtx artPuttyCtx artSelectCtx artSetPaintCtx artUserPaintCtx assignCommand assignInputDevice assignViewportFactories attachCurve attachDeviceAttr attachSurface attrColorSliderGrp attrCompatibility attrControlGrp attrEnumOptionMenu attrEnumOptionMenuGrp attrFieldGrp attrFieldSliderGrp attrNavigationControlGrp attrPresetEditWin attributeExists attributeInfo attributeMenu attributeQuery autoKeyframe autoPlace bakeClip bakeFluidShading bakePartialHistory bakeResults bakeSimulation basename basenameEx batchRender bessel bevel bevelPlus binMembership bindSkin blend2 blendShape blendShapeEditor blendShapePanel blendTwoAttr blindDataType boneLattice boundary boxDollyCtx boxZoomCtx bufferCurve buildBookmarkMenu buildKeyframeMenu button buttonManip CBG cacheFile cacheFileCombine cacheFileMerge cacheFileTrack camera cameraView canCreateManip canvas capitalizeString catch catchQuiet ceil changeSubdivComponentDisplayLevel changeSubdivRegion channelBox character characterMap characterOutlineEditor characterize chdir checkBox checkBoxGrp checkDefaultRenderGlobals choice circle circularFillet clamp clear clearCache clip clipEditor clipEditorCurrentTimeCtx clipSchedule clipSchedulerOutliner clipTrimBefore closeCurve closeSurface cluster cmdFileOutput cmdScrollFieldExecuter cmdScrollFieldReporter cmdShell coarsenSubdivSelectionList collision color colorAtPoint colorEditor colorIndex colorIndexSliderGrp colorSliderButtonGrp colorSliderGrp columnLayout commandEcho commandLine commandPort compactHairSystem componentEditor compositingInterop computePolysetVolume condition cone confirmDialog connectAttr connectControl connectDynamic connectJoint connectionInfo constrain constrainValue constructionHistory container containsMultibyte contextInfo control convertFromOldLayers convertIffToPsd convertLightmap convertSolidTx convertTessellation convertUnit copyArray copyFlexor copyKey copySkinWeights cos cpButton cpCache cpClothSet cpCollision cpConstraint cpConvClothToMesh cpForces cpGetSolverAttr cpPanel cpProperty cpRigidCollisionFilter cpSeam cpSetEdit cpSetSolverAttr cpSolver cpSolverTypes cpTool cpUpdateClothUVs createDisplayLayer createDrawCtx createEditor createLayeredPsdFile createMotionField createNewShelf createNode createRenderLayer createSubdivRegion cross crossProduct ctxAbort ctxCompletion ctxEditMode ctxTraverse currentCtx currentTime currentTimeCtx currentUnit curve curveAddPtCtx curveCVCtx curveEPCtx curveEditorCtx curveIntersect curveMoveEPCtx curveOnSurface curveSketchCtx cutKey cycleCheck cylinder dagPose date defaultLightListCheckBox defaultNavigation defineDataServer defineVirtualDevice deformer deg_to_rad delete deleteAttr deleteShadingGroupsAndMaterials deleteShelfTab deleteUI deleteUnusedBrushes delrandstr detachCurve detachDeviceAttr detachSurface deviceEditor devicePanel dgInfo dgdirty dgeval dgtimer dimWhen directKeyCtx directionalLight dirmap dirname disable disconnectAttr disconnectJoint diskCache displacementToPoly displayAffected displayColor displayCull displayLevelOfDetail displayPref displayRGBColor displaySmoothness displayStats displayString displaySurface distanceDimContext distanceDimension doBlur dolly dollyCtx dopeSheetEditor dot dotProduct doubleProfileBirailSurface drag dragAttrContext draggerContext dropoffLocator duplicate duplicateCurve duplicateSurface dynCache dynControl dynExport dynExpression dynGlobals dynPaintEditor dynParticleCtx dynPref dynRelEdPanel dynRelEditor dynamicLoad editAttrLimits editDisplayLayerGlobals editDisplayLayerMembers editRenderLayerAdjustment editRenderLayerGlobals editRenderLayerMembers editor editorTemplate effector emit emitter enableDevice encodeString endString endsWith env equivalent equivalentTol erf error eval evalDeferred evalEcho event exactWorldBoundingBox exclusiveLightCheckBox exec executeForEachObject exists exp expression expressionEditorListen extendCurve extendSurface extrude fcheck fclose feof fflush fgetline fgetword file fileBrowserDialog fileDialog fileExtension fileInfo filetest filletCurve filter filterCurve filterExpand filterStudioImport findAllIntersections findAnimCurves findKeyframe findMenuItem findRelatedSkinCluster finder firstParentOf fitBspline flexor floatEq floatField floatFieldGrp floatScrollBar floatSlider floatSlider2 floatSliderButtonGrp floatSliderGrp floor flow fluidCacheInfo fluidEmitter fluidVoxelInfo flushUndo fmod fontDialog fopen formLayout format fprint frameLayout fread freeFormFillet frewind fromNativePath fwrite gamma gauss geometryConstraint getApplicationVersionAsFloat getAttr getClassification getDefaultBrush getFileList getFluidAttr getInputDeviceRange getMayaPanelTypes getModifiers getPanel getParticleAttr getPluginResource getenv getpid glRender glRenderEditor globalStitch gmatch goal gotoBindPose grabColor gradientControl gradientControlNoAttr graphDollyCtx graphSelectContext graphTrackCtx gravity grid gridLayout group groupObjectsByName HfAddAttractorToAS HfAssignAS HfBuildEqualMap HfBuildFurFiles HfBuildFurImages HfCancelAFR HfConnectASToHF HfCreateAttractor HfDeleteAS HfEditAS HfPerformCreateAS HfRemoveAttractorFromAS HfSelectAttached HfSelectAttractors HfUnAssignAS hardenPointCurve hardware hardwareRenderPanel headsUpDisplay headsUpMessage help helpLine hermite hide hilite hitTest hotBox hotkey hotkeyCheck hsv_to_rgb hudButton hudSlider hudSliderButton hwReflectionMap hwRender hwRenderLoad hyperGraph hyperPanel hyperShade hypot iconTextButton iconTextCheckBox iconTextRadioButton iconTextRadioCollection iconTextScrollList iconTextStaticLabel ikHandle ikHandleCtx ikHandleDisplayScale ikSolver ikSplineHandleCtx ikSystem ikSystemInfo ikfkDisplayMethod illustratorCurves image imfPlugins inheritTransform insertJoint insertJointCtx insertKeyCtx insertKnotCurve insertKnotSurface instance instanceable instancer intField intFieldGrp intScrollBar intSlider intSliderGrp interToUI internalVar intersect iprEngine isAnimCurve isConnected isDirty isParentOf isSameObject isTrue isValidObjectName isValidString isValidUiName isolateSelect itemFilter itemFilterAttr itemFilterRender itemFilterType joint jointCluster jointCtx jointDisplayScale jointLattice keyTangent keyframe keyframeOutliner keyframeRegionCurrentTimeCtx keyframeRegionDirectKeyCtx keyframeRegionDollyCtx keyframeRegionInsertKeyCtx keyframeRegionMoveKeyCtx keyframeRegionScaleKeyCtx keyframeRegionSelectKeyCtx keyframeRegionSetKeyCtx keyframeRegionTrackCtx keyframeStats lassoContext lattice latticeDeformKeyCtx launch launchImageEditor layerButton layeredShaderPort layeredTexturePort layout layoutDialog lightList lightListEditor lightListPanel lightlink lineIntersection linearPrecision linstep listAnimatable listAttr listCameras listConnections listDeviceAttachments listHistory listInputDeviceAxes listInputDeviceButtons listInputDevices listMenuAnnotation listNodeTypes listPanelCategories listRelatives listSets listTransforms listUnselected listerEditor loadFluid loadNewShelf loadPlugin loadPluginLanguageResources loadPrefObjects localizedPanelLabel lockNode loft log longNameOf lookThru ls lsThroughFilter lsType lsUI Mayatomr mag makeIdentity makeLive makePaintable makeRoll makeSingleSurface makeTubeOn makebot manipMoveContext manipMoveLimitsCtx manipOptions manipRotateContext manipRotateLimitsCtx manipScaleContext manipScaleLimitsCtx marker match max memory menu menuBarLayout menuEditor menuItem menuItemToShelf menuSet menuSetPref messageLine min minimizeApp mirrorJoint modelCurrentTimeCtx modelEditor modelPanel mouse movIn movOut move moveIKtoFK moveKeyCtx moveVertexAlongDirection multiProfileBirailSurface mute nParticle nameCommand nameField namespace namespaceInfo newPanelItems newton nodeCast nodeIconButton nodeOutliner nodePreset nodeType noise nonLinear normalConstraint normalize nurbsBoolean nurbsCopyUVSet nurbsCube nurbsEditUV nurbsPlane nurbsSelect nurbsSquare nurbsToPoly nurbsToPolygonsPref nurbsToSubdiv nurbsToSubdivPref nurbsUVSet nurbsViewDirectionVector objExists objectCenter objectLayer objectType objectTypeUI obsoleteProc oceanNurbsPreviewPlane offsetCurve offsetCurveOnSurface offsetSurface openGLExtension openMayaPref optionMenu optionMenuGrp optionVar orbit orbitCtx orientConstraint outlinerEditor outlinerPanel overrideModifier paintEffectsDisplay pairBlend palettePort paneLayout panel panelConfiguration panelHistory paramDimContext paramDimension paramLocator parent parentConstraint particle particleExists particleInstancer particleRenderInfo partition pasteKey pathAnimation pause pclose percent performanceOptions pfxstrokes pickWalk picture pixelMove planarSrf plane play playbackOptions playblast plugAttr plugNode pluginInfo pluginResourceUtil pointConstraint pointCurveConstraint pointLight pointMatrixMult pointOnCurve pointOnSurface pointPosition poleVectorConstraint polyAppend polyAppendFacetCtx polyAppendVertex polyAutoProjection polyAverageNormal polyAverageVertex polyBevel polyBlendColor polyBlindData polyBoolOp polyBridgeEdge polyCacheMonitor polyCheck polyChipOff polyClipboard polyCloseBorder polyCollapseEdge polyCollapseFacet polyColorBlindData polyColorDel polyColorPerVertex polyColorSet polyCompare polyCone polyCopyUV polyCrease polyCreaseCtx polyCreateFacet polyCreateFacetCtx polyCube polyCut polyCutCtx polyCylinder polyCylindricalProjection polyDelEdge polyDelFacet polyDelVertex polyDuplicateAndConnect polyDuplicateEdge polyEditUV polyEditUVShell polyEvaluate polyExtrudeEdge polyExtrudeFacet polyExtrudeVertex polyFlipEdge polyFlipUV polyForceUV polyGeoSampler polyHelix polyInfo polyInstallAction polyLayoutUV polyListComponentConversion polyMapCut polyMapDel polyMapSew polyMapSewMove polyMergeEdge polyMergeEdgeCtx polyMergeFacet polyMergeFacetCtx polyMergeUV polyMergeVertex polyMirrorFace polyMoveEdge polyMoveFacet polyMoveFacetUV polyMoveUV polyMoveVertex polyNormal polyNormalPerVertex polyNormalizeUV polyOptUvs polyOptions polyOutput polyPipe polyPlanarProjection polyPlane polyPlatonicSolid polyPoke polyPrimitive polyPrism polyProjection polyPyramid polyQuad polyQueryBlindData polyReduce polySelect polySelectConstraint polySelectConstraintMonitor polySelectCtx polySelectEditCtx polySeparate polySetToFaceNormal polySewEdge polyShortestPathCtx polySmooth polySoftEdge polySphere polySphericalProjection polySplit polySplitCtx polySplitEdge polySplitRing polySplitVertex polyStraightenUVBorder polySubdivideEdge polySubdivideFacet polyToSubdiv polyTorus polyTransfer polyTriangulate polyUVSet polyUnite polyWedgeFace popen popupMenu pose pow preloadRefEd print progressBar progressWindow projFileViewer projectCurve projectTangent projectionContext projectionManip promptDialog propModCtx propMove psdChannelOutliner psdEditTextureFile psdExport psdTextureFile putenv pwd python querySubdiv quit rad_to_deg radial radioButton radioButtonGrp radioCollection radioMenuItemCollection rampColorPort rand randomizeFollicles randstate rangeControl readTake rebuildCurve rebuildSurface recordAttr recordDevice redo reference referenceEdit referenceQuery refineSubdivSelectionList refresh refreshAE registerPluginResource rehash reloadImage removeJoint removeMultiInstance removePanelCategory rename renameAttr renameSelectionList renameUI render renderGlobalsNode renderInfo renderLayerButton renderLayerParent renderLayerPostProcess renderLayerUnparent renderManip renderPartition renderQualityNode renderSettings renderThumbnailUpdate renderWindowEditor renderWindowSelectContext renderer reorder reorderDeformers requires reroot resampleFluid resetAE resetPfxToPolyCamera resetTool resolutionNode retarget reverseCurve reverseSurface revolve rgb_to_hsv rigidBody rigidSolver roll rollCtx rootOf rot rotate rotationInterpolation roundConstantRadius rowColumnLayout rowLayout runTimeCommand runup sampleImage saveAllShelves saveAttrPreset saveFluid saveImage saveInitialState saveMenu savePrefObjects savePrefs saveShelf saveToolSettings scale scaleBrushBrightness scaleComponents scaleConstraint scaleKey scaleKeyCtx sceneEditor sceneUIReplacement scmh scriptCtx scriptEditorInfo scriptJob scriptNode scriptTable scriptToShelf scriptedPanel scriptedPanelType scrollField scrollLayout sculpt searchPathArray seed selLoadSettings select selectContext selectCurveCV selectKey selectKeyCtx selectKeyframeRegionCtx selectMode selectPref selectPriority selectType selectedNodes selectionConnection separator setAttr setAttrEnumResource setAttrMapping setAttrNiceNameResource setConstraintRestPosition setDefaultShadingGroup setDrivenKeyframe setDynamic setEditCtx setEditor setFluidAttr setFocus setInfinity setInputDeviceMapping setKeyCtx setKeyPath setKeyframe setKeyframeBlendshapeTargetWts setMenuMode setNodeNiceNameResource setNodeTypeFlag setParent setParticleAttr setPfxToPolyCamera setPluginResource setProject setStampDensity setStartupMessage setState setToolTo setUITemplate setXformManip sets shadingConnection shadingGeometryRelCtx shadingLightRelCtx shadingNetworkCompare shadingNode shapeCompare shelfButton shelfLayout shelfTabLayout shellField shortNameOf showHelp showHidden showManipCtx showSelectionInTitle showShadingGroupAttrEditor showWindow sign simplify sin singleProfileBirailSurface size sizeBytes skinCluster skinPercent smoothCurve smoothTangentSurface smoothstep snap2to2 snapKey snapMode snapTogetherCtx snapshot soft softMod softModCtx sort sound soundControl source spaceLocator sphere sphrand spotLight spotLightPreviewPort spreadSheetEditor spring sqrt squareSurface srtContext stackTrace startString startsWith stitchAndExplodeShell stitchSurface stitchSurfacePoints strcmp stringArrayCatenate stringArrayContains stringArrayCount stringArrayInsertAtIndex stringArrayIntersector stringArrayRemove stringArrayRemoveAtIndex stringArrayRemoveDuplicates stringArrayRemoveExact stringArrayToString stringToStringArray strip stripPrefixFromName stroke subdAutoProjection subdCleanTopology subdCollapse subdDuplicateAndConnect subdEditUV subdListComponentConversion subdMapCut subdMapSewMove subdMatchTopology subdMirror subdToBlind subdToPoly subdTransferUVsToCache subdiv subdivCrease subdivDisplaySmoothness substitute substituteAllString substituteGeometry substring surface surfaceSampler surfaceShaderList swatchDisplayPort switchTable symbolButton symbolCheckBox sysFile system tabLayout tan tangentConstraint texLatticeDeformContext texManipContext texMoveContext texMoveUVShellContext texRotateContext texScaleContext texSelectContext texSelectShortestPathCtx texSmudgeUVContext texWinToolCtx text textCurves textField textFieldButtonGrp textFieldGrp textManip textScrollList textToShelf textureDisplacePlane textureHairColor texturePlacementContext textureWindow threadCount threePointArcCtx timeControl timePort timerX toNativePath toggle toggleAxis toggleWindowVisibility tokenize tokenizeList tolerance tolower toolButton toolCollection toolDropped toolHasOptions toolPropertyWindow torus toupper trace track trackCtx transferAttributes transformCompare transformLimits translator trim trunc truncateFluidCache truncateHairCache tumble tumbleCtx turbulence twoPointArcCtx uiRes uiTemplate unassignInputDevice undo undoInfo ungroup uniform unit unloadPlugin untangleUV untitledFileName untrim upAxis updateAE userCtx uvLink uvSnapshot validateShelfName vectorize view2dToolCtx viewCamera viewClipPlane viewFit viewHeadOn viewLookAt viewManip viewPlace viewSet visor volumeAxis vortex waitCursor warning webBrowser webBrowserPrefs whatIs window windowPref wire wireContext workspace wrinkle wrinkleContext writeTake xbmLangPathList xform",i:"</",c:[a.CNM,a.ASM,a.QSM,{cN:"string",b:"`",e:"`",c:[a.BE]},{cN:"variable",v:[{b:"\\$\\d"},{b:"[\\$\\%\\@](\\^\\w\\b|#\\w+|[^\\s\\w{]|{\\w+}|\\w+)"},{b:"\\*(\\^\\w\\b|#\\w+|[^\\s\\w{]|{\\w+}|\\w+)",r:0}]},a.CLCM,a.CBCM]}});hljs.registerLanguage("mizar",function(a){return{k:["environ vocabularies notations constructors definitions registrations theorems schemes requirements","begin end definition registration cluster existence pred func defpred deffunc theorem proof","let take assume then thus hence ex for st holds consider reconsider such that and in provided of as from","be being by means equals implies iff redefine define now not or attr is mode suppose per cases set","thesis contradiction scheme reserve struct","correctness compatibility coherence symmetry assymetry reflexivity irreflexivity","connectedness uniqueness commutativity idempotence involutiveness projectivity"].join(" "),c:[{cN:"comment",b:"::",e:"$"}]}});hljs.registerLanguage("monkey",function(a){var b={v:[{cN:"number",b:"[$][a-fA-F0-9]+"},a.NM]};return{cI:true,k:{keyword:"public private property continue exit extern new try catch eachin not abstract final select case default const local global field end if then else elseif endif while wend repeat until forever for to step next return module inline throw",built_in:"DebugLog DebugStop Error Print ACos ACosr ASin ASinr ATan ATan2 ATan2r ATanr Abs Abs Ceil Clamp Clamp Cos Cosr Exp Floor Log Max Max Min Min Pow Sgn Sgn Sin Sinr Sqrt Tan Tanr Seed PI HALFPI TWOPI",literal:"true false null and or shl shr mod"},c:[{cN:"comment",b:"#rem",e:"#end"},{cN:"comment",b:"'",e:"$",r:0},{cN:"function",bK:"function method",e:"[(=:]|$",i:/\n/,c:[a.UTM,]},{cN:"class",bK:"class interface",e:"$",c:[{bK:"extends implements"},a.UTM]},{cN:"variable",b:"\\b(self|super)\\b"},{cN:"preprocessor",bK:"import",e:"$"},{cN:"preprocessor",b:"\\s*#",e:"$",k:"if else elseif endif end then"},{cN:"pi",b:"^\\s*strict\\b"},{bK:"alias",e:"=",c:[a.UTM]},a.QSM,b]}});hljs.registerLanguage("nginx",function(c){var b={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+c.UIR}]};var a={eW:true,l:"[a-z/_]+",k:{built_in:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[c.HCM,{cN:"string",c:[c.BE,b],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{cN:"url",b:"([a-z]+):/",e:"\\s",eW:true,eE:true,c:[b]},{cN:"regexp",c:[c.BE,b],v:[{b:"\\s\\^",e:"\\s|{|;",rE:true},{b:"~\\*?\\s+",e:"\\s|{|;",rE:true},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},b]};return{aliases:["nginxconf"],c:[c.HCM,{b:c.UIR+"\\s",e:";|{",rB:true,c:[{cN:"title",b:c.UIR,starts:a}],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("nimrod",function(a){return{k:{keyword:"addr and as asm bind block break|0 case|0 cast const|0 continue|0 converter discard distinct|10 div do elif else|0 end|0 enum|0 except export finally for from generic if|0 import|0 in include|0 interface is isnot|10 iterator|10 let|0 macro method|10 mixin mod nil not notin|10 object|0 of or out proc|10 ptr raise ref|10 return shl shr static template|10 try|0 tuple type|0 using|0 var|0 when while|0 with without xor yield",literal:"shared guarded stdin stdout stderr result|10 true false"},c:[{cN:"decorator",b:/{\./,e:/\.}/,r:10},{cN:"string",b:/[a-zA-Z]\w*"/,e:/"/,c:[{b:/""/}]},{cN:"string",b:/([a-zA-Z]\w*)?"""/,e:/"""/},{cN:"string",b:/"/,e:/"/,i:/\n/,c:[{b:/\\./}]},{cN:"type",b:/\b[A-Z]\w+\b/,r:0},{cN:"type",b:/\b(int|int8|int16|int32|int64|uint|uint8|uint16|uint32|uint64|float|float32|float64|bool|char|string|cstring|pointer|expr|stmt|void|auto|any|range|array|openarray|varargs|seq|set|clong|culong|cchar|cschar|cshort|cint|csize|clonglong|cfloat|cdouble|clongdouble|cuchar|cushort|cuint|culonglong|cstringarray|semistatic)\b/},{cN:"number",b:/\b(0[xX][0-9a-fA-F][_0-9a-fA-F]*)('?[iIuU](8|16|32|64))?/,r:0},{cN:"number",b:/\b(0o[0-7][_0-7]*)('?[iIuUfF](8|16|32|64))?/,r:0},{cN:"number",b:/\b(0(b|B)[01][_01]*)('?[iIuUfF](8|16|32|64))?/,r:0},{cN:"number",b:/\b(\d[_\d]*)('?[iIuUfF](8|16|32|64))?/,r:0},a.HCM]}});hljs.registerLanguage("nix",function(b){var a={keyword:"rec with let in inherit assert if else then",constant:"true false or and null",built_in:"import abort baseNameOf dirOf isNull builtins map removeAttrs throw toString derivation"};var g={cN:"subst",b:/\$\{/,e:/\}/,k:a};var d={cN:"variable",b:/[a-zA-Z0-9-_]+(\s*=)/};var e={cN:"string",b:"''",e:"''",c:[g]};var f={cN:"string",b:'"',e:'"',c:[g]};var c=[b.NM,b.HCM,b.CBCM,e,f,d];g.c=c;return{aliases:["nixos"],k:a,c:c}});hljs.registerLanguage("nsis",function(a){var c={cN:"symbol",b:"\\$(ADMINTOOLS|APPDATA|CDBURN_AREA|CMDLINE|COMMONFILES32|COMMONFILES64|COMMONFILES|COOKIES|DESKTOP|DOCUMENTS|EXEDIR|EXEFILE|EXEPATH|FAVORITES|FONTS|HISTORY|HWNDPARENT|INSTDIR|INTERNET_CACHE|LANGUAGE|LOCALAPPDATA|MUSIC|NETHOOD|OUTDIR|PICTURES|PLUGINSDIR|PRINTHOOD|PROFILE|PROGRAMFILES32|PROGRAMFILES64|PROGRAMFILES|QUICKLAUNCH|RECENT|RESOURCES_LOCALIZED|RESOURCES|SENDTO|SMPROGRAMS|SMSTARTUP|STARTMENU|SYSDIR|TEMP|TEMPLATES|VIDEOS|WINDIR)"};var b={cN:"constant",b:"\\$+{[a-zA-Z0-9_]+}"};var f={cN:"variable",b:"\\$+[a-zA-Z0-9_]+",i:"\\(\\){}"};var e={cN:"constant",b:"\\$+\\([a-zA-Z0-9_]+\\)"};var g={cN:"params",b:"(ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HKCR|HKCU|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM|HKPD|HKU|IDABORT|IDCANCEL|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SYSTEM|TEMPORARY)"};var d={cN:"constant",b:"\\!(addincludedir|addplugindir|appendfile|cd|define|delfile|echo|else|endif|error|execute|finalize|getdllversionsystem|ifdef|ifmacrodef|ifmacrondef|ifndef|if|include|insertmacro|macroend|macro|packhdr|searchparse|searchreplace|tempfile|undef|verbose|warning)"};return{cI:false,k:{keyword:"Abort AddBrandingImage AddSize AllowRootDirInstall AllowSkipFiles AutoCloseWindow BGFont BGGradient BrandingText BringToFront Call CallInstDLL Caption ChangeUI CheckBitmap ClearErrors CompletedText ComponentText CopyFiles CRCCheck CreateDirectory CreateFont CreateShortCut Delete DeleteINISec DeleteINIStr DeleteRegKey DeleteRegValue DetailPrint DetailsButtonText DirText DirVar DirVerify EnableWindow EnumRegKey EnumRegValue Exch Exec ExecShell ExecWait ExpandEnvStrings File FileBufSize FileClose FileErrorText FileOpen FileRead FileReadByte FileReadUTF16LE FileReadWord FileSeek FileWrite FileWriteByte FileWriteUTF16LE FileWriteWord FindClose FindFirst FindNext FindWindow FlushINI FunctionEnd GetCurInstType GetCurrentAddress GetDlgItem GetDLLVersion GetDLLVersionLocal GetErrorLevel GetFileTime GetFileTimeLocal GetFullPathName GetFunctionAddress GetInstDirError GetLabelAddress GetTempFileName Goto HideWindow Icon IfAbort IfErrors IfFileExists IfRebootFlag IfSilent InitPluginsDir InstallButtonText InstallColors InstallDir InstallDirRegKey InstProgressFlags InstType InstTypeGetText InstTypeSetText IntCmp IntCmpU IntFmt IntOp IsWindow LangString LicenseBkColor LicenseData LicenseForceSelection LicenseLangString LicenseText LoadLanguageFile LockWindow LogSet LogText ManifestDPIAware ManifestSupportedOS MessageBox MiscButtonText Name Nop OutFile Page PageCallbacks PageExEnd Pop Push Quit ReadEnvStr ReadINIStr ReadRegDWORD ReadRegStr Reboot RegDLL Rename RequestExecutionLevel ReserveFile Return RMDir SearchPath SectionEnd SectionGetFlags SectionGetInstTypes SectionGetSize SectionGetText SectionGroupEnd SectionIn SectionSetFlags SectionSetInstTypes SectionSetSize SectionSetText SendMessage SetAutoClose SetBrandingImage SetCompress SetCompressor SetCompressorDictSize SetCtlColors SetCurInstType SetDatablockOptimize SetDateSave SetDetailsPrint SetDetailsView SetErrorLevel SetErrors SetFileAttributes SetFont SetOutPath SetOverwrite SetPluginUnload SetRebootFlag SetRegView SetShellVarContext SetSilent ShowInstDetails ShowUninstDetails ShowWindow SilentInstall SilentUnInstall Sleep SpaceTexts StrCmp StrCmpS StrCpy StrLen SubCaption SubSectionEnd Unicode UninstallButtonText UninstallCaption UninstallIcon UninstallSubCaption UninstallText UninstPage UnRegDLL Var VIAddVersionKey VIFileVersion VIProductVersion WindowIcon WriteINIStr WriteRegBin WriteRegDWORD WriteRegExpandStr WriteRegStr WriteUninstaller XPStyle",literal:"admin all auto both colored current false force hide highest lastused leave listonly none normal notset off on open print show silent silentlog smooth textonly true user "},c:[a.HCM,a.CBCM,{cN:"string",b:'"',e:'"',i:"\\n",c:[{cN:"symbol",b:"\\$(\\\\(n|r|t)|\\$)"},c,b,f,e]},{cN:"comment",b:";",e:"$",r:0},{cN:"function",bK:"Function PageEx Section SectionGroup SubSection",e:"$"},d,b,f,e,g,a.NM,{cN:"literal",b:a.IR+"::"+a.IR}]}});hljs.registerLanguage("objectivec",function(a){var d={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"NSString NSData NSDictionary CGRect CGPoint UIButton UILabel UITextView UIWebView MKMapView NSView NSViewController NSWindow NSWindowController NSSet NSUUID NSIndexSet UISegmentedControl NSObject UITableViewDelegate UITableViewDataSource NSThread UIActivityIndicator UITabbar UIToolBar UIBarButtonItem UIImageView NSAutoreleasePool UITableView BOOL NSInteger CGFloat NSException NSLog NSMutableString NSMutableArray NSMutableDictionary NSURL NSIndexPath CGSize UITableViewCell UIView UIViewController UINavigationBar UINavigationController UITabBarController UIPopoverController UIPopoverControllerDelegate UIImage NSNumber UISearchBar NSFetchedResultsController NSFetchedResultsChangeType UIScrollView UIScrollViewDelegate UIEdgeInsets UIColor UIFont UIApplication NSNotFound NSNotificationCenter NSNotification UILocalNotification NSBundle NSFileManager NSTimeInterval NSDate NSCalendar NSUserDefaults UIWindow NSRange NSArray NSError NSURLRequest NSURLConnection NSURLSession NSURLSessionDataTask NSURLSessionDownloadTask NSURLSessionUploadTask NSURLResponseUIInterfaceOrientation MPMoviePlayerController dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"};var c=/[a-zA-Z@][a-zA-Z0-9_]*/;var b="@interface @class @protocol @implementation";return{aliases:["m","mm","objc","obj-c"],k:d,l:c,i:"</",c:[a.CLCM,a.CBCM,a.CNM,a.QSM,{cN:"string",v:[{b:'@"',e:'"',i:"\\n",c:[a.BE]},{b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"}]},{cN:"preprocessor",b:"#",e:"$",c:[{cN:"title",v:[{b:'"',e:'"'},{b:"<",e:">"}]}]},{cN:"class",b:"("+b.split(" ").join("|")+")\\b",e:"({|$)",eE:true,k:b,l:c,c:[a.UTM]},{cN:"variable",b:"\\."+a.UIR,r:0}]}});hljs.registerLanguage("ocaml",function(a){return{aliases:["ml"],k:{keyword:"and as assert asr begin class constraint do done downto else end exception external false for fun function functor if in include inherit initializer land lazy let lor lsl lsr lxor match method mod module mutable new object of open or private rec ref sig struct then to true try type val virtual when while with parser value",built_in:"bool char float int list unit array exn option int32 int64 nativeint format4 format6 lazy_t in_channel out_channel string"},i:/\/\//,c:[{cN:"string",b:'"""',e:'"""'},{cN:"comment",b:"\\(\\*",e:"\\*\\)",c:["self"]},{cN:"class",bK:"type",e:"\\(|=|$",eE:true,c:[a.UTM]},{cN:"annotation",b:"\\[<",e:">\\]"},a.CBCM,a.inherit(a.ASM,{i:null}),a.inherit(a.QSM,{i:null}),a.CNM]}});hljs.registerLanguage("oxygene",function(b){var g="abstract add and array as asc aspect assembly async begin break block by case class concat const copy constructor continue create default delegate desc distinct div do downto dynamic each else empty end ensure enum equals event except exit extension external false final finalize finalizer finally flags for forward from function future global group has if implementation implements implies in index inherited inline interface into invariants is iterator join locked locking loop matching method mod module namespace nested new nil not notify nullable of old on operator or order out override parallel params partial pinned private procedure property protected public queryable raise read readonly record reintroduce remove repeat require result reverse sealed select self sequence set shl shr skip static step soft take then to true try tuple type union unit unsafe until uses using var virtual raises volatile where while with write xor yield await mapped deprecated stdcall cdecl pascal register safecall overload library platform reference packed strict published autoreleasepool selector strong weak unretained";var a={cN:"comment",b:"{",e:"}",r:0};var e={cN:"comment",b:"\\(\\*",e:"\\*\\)",r:10};var c={cN:"string",b:"'",e:"'",c:[{b:"''"}]};var d={cN:"string",b:"(#\\d+)+"};var f={cN:"function",bK:"function constructor destructor procedure method",e:"[:;]",k:"function constructor|10 destructor|10 procedure|10 method|10",c:[b.TM,{cN:"params",b:"\\(",e:"\\)",k:g,c:[c,d]},a,e]};return{cI:true,k:g,i:'("|\\$[G-Zg-z]|\\/\\*|</)',c:[a,e,b.CLCM,c,d,b.NM,f,{cN:"class",b:"=\\bclass\\b",e:"end;",k:g,c:[c,d,a,e,b.CLCM,f]}]}});hljs.registerLanguage("parser3",function(a){return{sL:"xml",r:0,c:[{cN:"comment",b:"^#",e:"$"},{cN:"comment",b:"\\^rem{",e:"}",r:10,c:[{b:"{",e:"}",c:["self"]}]},{cN:"preprocessor",b:"^@(?:BASE|USE|CLASS|OPTIONS)$",r:10},{cN:"title",b:"@[\\w\\-]+\\[[\\w^;\\-]*\\](?:\\[[\\w^;\\-]*\\])?(?:.*)$"},{cN:"variable",b:"\\$\\{?[\\w\\-\\.\\:]+\\}?"},{cN:"keyword",b:"\\^[\\w\\-\\.\\:]+"},{cN:"number",b:"\\^#[0-9a-fA-F]+"},a.CNM]}});hljs.registerLanguage("perl",function(c){var d="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when";var f={cN:"subst",b:"[$@]\\{",e:"\\}",k:d};var g={b:"->{",e:"}"};var a={cN:"variable",v:[{b:/\$\d/},{b:/[\$\%\@](\^\w\b|#\w+(\:\:\w+)*|{\w+}|\w+(\:\:\w*)*)/},{b:/[\$\%\@][^\s\w{]/,r:0}]};var e={cN:"comment",b:"^(__END__|__DATA__)",e:"\\n$",r:5};var h=[c.BE,f,a];var b=[a,c.HCM,e,{cN:"comment",b:"^\\=\\w",e:"\\=cut",eW:true},g,{cN:"string",c:h,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[c.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[c.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+c.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[c.HCM,e,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[c.BE],r:0}]},{cN:"sub",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",r:5},{cN:"operator",b:"-\\w\\b",r:0}];f.c=b;g.c=b;return{aliases:["pl"],k:d,c:b}});hljs.registerLanguage("php",function(b){var e={cN:"variable",b:"(\\$|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*"};var a={cN:"preprocessor",b:/<\?(php)?|\?>/};var c={cN:"string",c:[b.BE,a],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},b.inherit(b.ASM,{i:null}),b.inherit(b.QSM,{i:null})]};var d={v:[b.BNM,b.CNM]};return{aliases:["php3","php4","php5","php6"],cI:true,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[b.CLCM,b.HCM,{cN:"comment",b:"/\\*",e:"\\*/",c:[{cN:"phpdoc",b:"\\s@[A-Za-z]+"},a]},{cN:"comment",b:"__halt_compiler.+?;",eW:true,k:"__halt_compiler",l:b.UIR},{cN:"string",b:"<<<['\"]?\\w+['\"]?$",e:"^\\w+;",c:[b.BE]},a,e,{cN:"function",bK:"function",e:/[;{]/,eE:true,i:"\\$|\\[|%",c:[b.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",e,b.CBCM,c,d]}]},{cN:"class",bK:"class interface",e:"{",eE:true,i:/[:\(\$"]/,c:[{bK:"extends implements"},b.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[b.UTM]},{bK:"use",e:";",c:[b.UTM]},{b:"=>"},c,d]}});hljs.registerLanguage("profile",function(a){return{c:[a.CNM,{cN:"built_in",b:"{",e:"}$",eB:true,eE:true,c:[a.ASM,a.QSM],r:0},{cN:"filename",b:"[a-zA-Z_][\\da-zA-Z_]+\\.[\\da-zA-Z_]{1,3}",e:":",eE:true},{cN:"header",b:"(ncalls|tottime|cumtime)",e:"$",k:"ncalls tottime|10 cumtime|10 filename",r:10},{cN:"summary",b:"function calls",e:"$",c:[a.CNM],r:10},a.ASM,a.QSM,{cN:"function",b:"\\(",e:"\\)$",c:[a.UTM],r:0}]}});hljs.registerLanguage("protobuf",function(a){return{k:{keyword:"package import option optional required repeated group",built_in:"double float int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 sfixed32 sfixed64 bool string bytes",literal:"true false"},c:[a.QSM,a.NM,a.CLCM,{cN:"class",bK:"message enum service",e:/\{/,i:/\n/,c:[a.inherit(a.TM,{starts:{eW:true,eE:true}})]},{cN:"function",bK:"rpc",e:/;/,eE:true,k:"rpc returns"},{cN:"constant",b:/^\s*[A-Z_]+/,e:/\s*=/,eE:true}]}});hljs.registerLanguage("python",function(a){var f={cN:"prompt",b:/^(>>>|\.\.\.) /};var b={cN:"string",c:[a.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[f],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[f],r:10},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},a.ASM,a.QSM]};var d={cN:"number",r:0,v:[{b:a.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:a.CNR+"[lLjJ]?"}]};var e={cN:"params",b:/\(/,e:/\)/,c:["self",f,d,b]};var c={e:/:/,i:/[${=;\n]/,c:[a.UTM,e]};return{aliases:["py","gyp"],k:{keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},i:/(<\/|->|\?)/,c:[f,d,b,a.HCM,a.inherit(c,{cN:"function",bK:"def",r:10}),a.inherit(c,{cN:"class",bK:"class"}),{cN:"decorator",b:/@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("q",function(a){var b={keyword:"do while select delete by update from",constant:"0b 1b",built_in:"neg not null string reciprocal floor ceiling signum mod xbar xlog and or each scan over prior mmu lsq inv md5 ltime gtime count first var dev med cov cor all any rand sums prds mins maxs fills deltas ratios avgs differ prev next rank reverse iasc idesc asc desc msum mcount mavg mdev xrank mmin mmax xprev rotate distinct group where flip type key til get value attr cut set upsert raze union inter except cross sv vs sublist enlist read0 read1 hopen hclose hdel hsym hcount peach system ltrim rtrim trim lower upper ssr view tables views cols xcols keys xkey xcol xasc xdesc fkeys meta lj aj aj0 ij pj asof uj ww wj wj1 fby xgroup ungroup ej save load rsave rload show csv parse eval min max avg wavg wsum sin cos tan sum",typename:"`float `double int `timestamp `timespan `datetime `time `boolean `symbol `char `byte `short `long `real `month `date `minute `second `guid"};return{aliases:["k","kdb"],k:b,l:/\b(`?)[A-Za-z0-9_]+\b/,c:[a.CLCM,a.QSM,a.CNM]}});hljs.registerLanguage("r",function(a){var b="([a-zA-Z]|\\.[a-zA-Z.])[a-zA-Z0-9._]*";return{c:[a.HCM,{b:b,l:b,k:{keyword:"function if in break next repeat else for return switch while try tryCatch|10 stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass ...|10",literal:"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10"},r:0},{cN:"number",b:"0[xX][0-9a-fA-F]+[Li]?\\b",r:0},{cN:"number",b:"\\d+(?:[eE][+\\-]?\\d*)?L\\b",r:0},{cN:"number",b:"\\d+\\.(?!\\d)(?:i\\b)?",r:0},{cN:"number",b:"\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b",r:0},{cN:"number",b:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b",r:0},{b:"`",e:"`",r:0},{cN:"string",c:[a.BE],v:[{b:'"',e:'"'},{b:"'",e:"'"}]}]}});hljs.registerLanguage("rib",function(a){return{k:"ArchiveRecord AreaLightSource Atmosphere Attribute AttributeBegin AttributeEnd Basis Begin Blobby Bound Clipping ClippingPlane Color ColorSamples ConcatTransform Cone CoordinateSystem CoordSysTransform CropWindow Curves Cylinder DepthOfField Detail DetailRange Disk Displacement Display End ErrorHandler Exposure Exterior Format FrameAspectRatio FrameBegin FrameEnd GeneralPolygon GeometricApproximation Geometry Hider Hyperboloid Identity Illuminate Imager Interior LightSource MakeCubeFaceEnvironment MakeLatLongEnvironment MakeShadow MakeTexture Matte MotionBegin MotionEnd NuPatch ObjectBegin ObjectEnd ObjectInstance Opacity Option Orientation Paraboloid Patch PatchMesh Perspective PixelFilter PixelSamples PixelVariance Points PointsGeneralPolygons PointsPolygons Polygon Procedural Projection Quantize ReadArchive RelativeDetail ReverseOrientation Rotate Scale ScreenWindow ShadingInterpolation ShadingRate Shutter Sides Skew SolidBegin SolidEnd Sphere SubdivisionMesh Surface TextureCoordinates Torus Transform TransformBegin TransformEnd TransformPoints Translate TrimCurve WorldBegin WorldEnd",i:"</",c:[a.HCM,a.CNM,a.ASM,a.QSM]}});hljs.registerLanguage("rsl",function(a){return{k:{keyword:"float color point normal vector matrix while for if do return else break extern continue",built_in:"abs acos ambient area asin atan atmosphere attribute calculatenormal ceil cellnoise clamp comp concat cos degrees depth Deriv diffuse distance Du Dv environment exp faceforward filterstep floor format fresnel incident length lightsource log match max min mod noise normalize ntransform opposite option phong pnoise pow printf ptlined radians random reflect refract renderinfo round setcomp setxcomp setycomp setzcomp shadow sign sin smoothstep specular specularbrdf spline sqrt step tan texture textureinfo trace transform vtransform xcomp ycomp zcomp"},i:"</",c:[a.CLCM,a.CBCM,a.QSM,a.ASM,a.CNM,{cN:"preprocessor",b:"#",e:"$"},{cN:"shader",bK:"surface displacement light volume imager",e:"\\("},{cN:"shading",bK:"illuminate illuminance gather",e:"\\("}]}});hljs.registerLanguage("ruleslanguage",function(a){return{k:{keyword:"BILL_PERIOD BILL_START BILL_STOP RS_EFFECTIVE_START RS_EFFECTIVE_STOP RS_JURIS_CODE RS_OPCO_CODE INTDADDATTRIBUTE|5 INTDADDVMSG|5 INTDBLOCKOP|5 INTDBLOCKOPNA|5 INTDCLOSE|5 INTDCOUNT|5 INTDCOUNTSTATUSCODE|5 INTDCREATEMASK|5 INTDCREATEDAYMASK|5 INTDCREATEFACTORMASK|5 INTDCREATEHANDLE|5 INTDCREATEOVERRIDEDAYMASK|5 INTDCREATEOVERRIDEMASK|5 INTDCREATESTATUSCODEMASK|5 INTDCREATETOUPERIOD|5 INTDDELETE|5 INTDDIPTEST|5 INTDEXPORT|5 INTDGETERRORCODE|5 INTDGETERRORMESSAGE|5 INTDISEQUAL|5 INTDJOIN|5 INTDLOAD|5 INTDLOADACTUALCUT|5 INTDLOADDATES|5 INTDLOADHIST|5 INTDLOADLIST|5 INTDLOADLISTDATES|5 INTDLOADLISTENERGY|5 INTDLOADLISTHIST|5 INTDLOADRELATEDCHANNEL|5 INTDLOADSP|5 INTDLOADSTAGING|5 INTDLOADUOM|5 INTDLOADUOMDATES|5 INTDLOADUOMHIST|5 INTDLOADVERSION|5 INTDOPEN|5 INTDREADFIRST|5 INTDREADNEXT|5 INTDRECCOUNT|5 INTDRELEASE|5 INTDREPLACE|5 INTDROLLAVG|5 INTDROLLPEAK|5 INTDSCALAROP|5 INTDSCALE|5 INTDSETATTRIBUTE|5 INTDSETDSTPARTICIPANT|5 INTDSETSTRING|5 INTDSETVALUE|5 INTDSETVALUESTATUS|5 INTDSHIFTSTARTTIME|5 INTDSMOOTH|5 INTDSORT|5 INTDSPIKETEST|5 INTDSUBSET|5 INTDTOU|5 INTDTOURELEASE|5 INTDTOUVALUE|5 INTDUPDATESTATS|5 INTDVALUE|5 STDEV INTDDELETEEX|5 INTDLOADEXACTUAL|5 INTDLOADEXCUT|5 INTDLOADEXDATES|5 INTDLOADEX|5 INTDLOADEXRELATEDCHANNEL|5 INTDSAVEEX|5 MVLOAD|5 MVLOADACCT|5 MVLOADACCTDATES|5 MVLOADACCTHIST|5 MVLOADDATES|5 MVLOADHIST|5 MVLOADLIST|5 MVLOADLISTDATES|5 MVLOADLISTHIST|5 IF FOR NEXT DONE SELECT END CALL ABORT CLEAR CHANNEL FACTOR LIST NUMBER OVERRIDE SET WEEK DISTRIBUTIONNODE ELSE WHEN THEN OTHERWISE IENUM CSV INCLUDE LEAVE RIDER SAVE DELETE NOVALUE SECTION WARN SAVE_UPDATE DETERMINANT LABEL REPORT REVENUE EACH IN FROM TOTAL CHARGE BLOCK AND OR CSV_FILE RATE_CODE AUXILIARY_DEMAND UIDACCOUNT RS BILL_PERIOD_SELECT HOURS_PER_MONTH INTD_ERROR_STOP SEASON_SCHEDULE_NAME ACCOUNTFACTOR ARRAYUPPERBOUND CALLSTOREDPROC GETADOCONNECTION GETCONNECT GETDATASOURCE GETQUALIFIER GETUSERID HASVALUE LISTCOUNT LISTOP LISTUPDATE LISTVALUE PRORATEFACTOR RSPRORATE SETBINPATH SETDBMONITOR WQ_OPEN BILLINGHOURS DATE DATEFROMFLOAT DATETIMEFROMSTRING DATETIMETOSTRING DATETOFLOAT DAY DAYDIFF DAYNAME DBDATETIME HOUR MINUTE MONTH MONTHDIFF MONTHHOURS MONTHNAME ROUNDDATE SAMEWEEKDAYLASTYEAR SECOND WEEKDAY WEEKDIFF YEAR YEARDAY YEARSTR COMPSUM HISTCOUNT HISTMAX HISTMIN HISTMINNZ HISTVALUE MAXNRANGE MAXRANGE MINRANGE COMPIKVA COMPKVA COMPKVARFROMKQKW COMPLF IDATTR FLAG LF2KW LF2KWH MAXKW POWERFACTOR READING2USAGE AVGSEASON MAXSEASON MONTHLYMERGE SEASONVALUE SUMSEASON ACCTREADDATES ACCTTABLELOAD CONFIGADD CONFIGGET CREATEOBJECT CREATEREPORT EMAILCLIENT EXPBLKMDMUSAGE EXPMDMUSAGE EXPORT_USAGE FACTORINEFFECT GETUSERSPECIFIEDSTOP INEFFECT ISHOLIDAY RUNRATE SAVE_PROFILE SETREPORTTITLE USEREXIT WATFORRUNRATE TO TABLE ACOS ASIN ATAN ATAN2 BITAND CEIL COS COSECANT COSH COTANGENT DIVQUOT DIVREM EXP FABS FLOOR FMOD FREPM FREXPN LOG LOG10 MAX MAXN MIN MINNZ MODF POW ROUND ROUND2VALUE ROUNDINT SECANT SIN SINH SQROOT TAN TANH FLOAT2STRING FLOAT2STRINGNC INSTR LEFT LEN LTRIM MID RIGHT RTRIM STRING STRINGNC TOLOWER TOUPPER TRIM NUMDAYS READ_DATE STAGING",built_in:"IDENTIFIER OPTIONS XML_ELEMENT XML_OP XML_ELEMENT_OF DOMDOCCREATE DOMDOCLOADFILE DOMDOCLOADXML DOMDOCSAVEFILE DOMDOCGETROOT DOMDOCADDPI DOMNODEGETNAME DOMNODEGETTYPE DOMNODEGETVALUE DOMNODEGETCHILDCT DOMNODEGETFIRSTCHILD DOMNODEGETSIBLING DOMNODECREATECHILDELEMENT DOMNODESETATTRIBUTE DOMNODEGETCHILDELEMENTCT DOMNODEGETFIRSTCHILDELEMENT DOMNODEGETSIBLINGELEMENT DOMNODEGETATTRIBUTECT DOMNODEGETATTRIBUTEI DOMNODEGETATTRIBUTEBYNAME DOMNODEGETBYNAME"},c:[a.CLCM,a.CBCM,a.ASM,a.QSM,a.CNM,{cN:"array",b:"#[a-zA-Z .]+"}]}});hljs.registerLanguage("rust",function(a){return{aliases:["rs"],k:{keyword:"alignof as be box break const continue crate do else enum extern false fn for if impl in let loop match mod mut offsetof once priv proc pub pure ref return self sizeof static struct super trait true type typeof unsafe unsized use virtual while yield int i8 i16 i32 i64 uint u8 u32 u64 float f32 f64 str char bool",built_in:"assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! fail! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln!"},l:a.IR+"!?",i:"</",c:[a.CLCM,a.CBCM,a.inherit(a.QSM,{i:null}),{cN:"string",b:/r(#*)".*?"\1(?!#)/},{cN:"string",b:/'\\?(x\w{2}|u\w{4}|U\w{8}|.)'/},{b:/'[a-zA-Z_][a-zA-Z0-9_]*/},{cN:"number",b:"\\b(0[xb][A-Za-z0-9_]+|[0-9_]+(\\.[0-9_]+)?([uif](8|16|32|64)?)?)",r:0},{cN:"function",bK:"fn",e:"(\\(|<)",eE:true,c:[a.UTM]},{cN:"preprocessor",b:"#\\[",e:"\\]"},{bK:"type",e:"(=|<)",c:[a.UTM],i:"\\S"},{bK:"trait enum",e:"({|<)",c:[a.UTM],i:"\\S"},{b:a.IR+"::"},{b:"->"}]}});hljs.registerLanguage("scala",function(d){var b={cN:"annotation",b:"@[A-Za-z]+"};var c={cN:"string",b:'u?r?"""',e:'"""',r:10};var a={cN:"symbol",b:"'\\w[\\w\\d_]*(?!')"};var e={cN:"type",b:"\\b[A-Z][A-Za-z0-9_]*",r:0};var h={cN:"title",b:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,r:0};var i={cN:"class",bK:"class object trait type",e:/[:={\[(\n;]/,c:[{cN:"keyword",bK:"extends with",r:10},h]};var g={cN:"function",bK:"def val",e:/[:={\[(\n;]/,c:[h]};var f={cN:"javadoc",b:"/\\*\\*",e:"\\*/",c:[{cN:"javadoctag",b:"@[A-Za-z]+"}],r:10};return{k:{literal:"true false null",keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit"},c:[d.CLCM,d.CBCM,c,d.QSM,a,e,g,i,d.CNM,b]}});hljs.registerLanguage("scheme",function(k){var m="[^\\(\\)\\[\\]\\{\\}\",'`;#|\\\\\\s]+";var d="(\\-|\\+)?\\d+([./]\\d+)?";var h=d+"[+\\-]"+d+"i";var e={built_in:"case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules ' * + , ,@ - ... / ; < <= = => > >= ` abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string<? string=? string>=? string>? string? substring symbol->string symbol? tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?"};var n={cN:"shebang",b:"^#!",e:"$"};var f={cN:"literal",b:"(#t|#f|#\\\\"+m+"|#\\\\.)"};var g={cN:"number",v:[{b:d,r:0},{b:h,r:0},{b:"#b[0-1]+(/[0-1]+)?"},{b:"#o[0-7]+(/[0-7]+)?"},{b:"#x[0-9a-f]+(/[0-9a-f]+)?"}]};var j=k.QSM;var b={cN:"regexp",b:'#[pr]x"',e:'[^\\\\]"'};var o={cN:"comment",v:[{b:";",e:"$",r:0},{b:"#\\|",e:"\\|#"}]};var c={b:m,r:0};var a={cN:"variable",b:"'"+m};var i={eW:true,r:0};var l={cN:"list",v:[{b:"\\(",e:"\\)"},{b:"\\[",e:"\\]"}],c:[{cN:"keyword",b:m,l:m,k:e},i]};i.c=[f,g,j,o,c,a,l];return{i:/\S/,c:[n,g,j,o,a,l]}});hljs.registerLanguage("scilab",function(a){var b=[a.CNM,{cN:"string",b:"'|\"",e:"'|\"",c:[a.BE,{b:"''"}]}];return{aliases:["sci"],k:{keyword:"abort break case clear catch continue do elseif else endfunction end for functionglobal if pause return resume select try then while%f %F %t %T %pi %eps %inf %nan %e %i %z %s",built_in:"abs and acos asin atan ceil cd chdir clearglobal cosh cos cumprod deff disp errorexec execstr exists exp eye gettext floor fprintf fread fsolve imag isdef isemptyisinfisnan isvector lasterror length load linspace list listfiles log10 log2 logmax min msprintf mclose mopen ones or pathconvert poly printf prod pwd rand realround sinh sin size gsort sprintf sqrt strcat strcmps tring sum system tanh tantype typename warning zeros matrix"},i:'("|#|/\\*|\\s+/\\w+)',c:[{cN:"function",bK:"function endfunction",e:"$",k:"function endfunction|10",c:[a.UTM,{cN:"params",b:"\\(",e:"\\)"}]},{cN:"transposed_variable",b:"[a-zA-Z_][a-zA-Z_0-9]*('+[\\.']*|[\\.']+)",e:"",r:0},{cN:"matrix",b:"\\[",e:"\\]'*[\\.']*",r:0,c:b},{cN:"comment",b:"//",e:"$"}].concat(b)}});hljs.registerLanguage("scss",function(a){var c="[a-zA-Z-][a-zA-Z0-9_-]*";var f={cN:"variable",b:"(\\$"+c+")\\b"};var d={cN:"function",b:c+"\\(",rB:true,eE:true,e:"\\("};var b={cN:"hexcolor",b:"#[0-9A-Fa-f]+"};var e={cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:true,i:"[^\\s]",starts:{cN:"value",eW:true,eE:true,c:[d,b,a.CSSNM,a.QSM,a.ASM,a.CBCM,{cN:"important",b:"!important"}]}};return{cI:true,i:"[=/|']",c:[a.CLCM,a.CBCM,d,{cN:"id",b:"\\#[A-Za-z0-9_-]+",r:0},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"tag",b:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b",r:0},{cN:"pseudo",b:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)"},{cN:"pseudo",b:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)"},f,{cN:"attribute",b:"\\b(z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b",i:"[^\\s]"},{cN:"value",b:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{cN:"value",b:":",e:";",c:[d,f,b,a.CSSNM,a.QSM,a.ASM,{cN:"important",b:"!important"}]},{cN:"at_rule",b:"@",e:"[{;]",k:"mixin include extend for if else each while charset import debug media page content font-face namespace warn",c:[d,f,a.QSM,a.ASM,b,a.CSSNM,{cN:"preprocessor",b:"\\s[A-Za-z0-9_.-]+",r:0}]}]}});hljs.registerLanguage("smalltalk",function(a){var b="[a-z][a-zA-Z0-9_]*";var d={cN:"char",b:"\\$.{1}"};var c={cN:"symbol",b:"#"+a.UIR};return{aliases:["st"],k:"self super nil true false thisContext",c:[{cN:"comment",b:'"',e:'"'},a.ASM,{cN:"class",b:"\\b[A-Z][A-Za-z0-9_]*",r:0},{cN:"method",b:b+":",r:0},a.CNM,c,d,{cN:"localvars",b:"\\|[ ]*"+b+"([ ]+"+b+")*[ ]*\\|",rB:true,e:/\|/,i:/\S/,c:[{b:"(\\|[ ]*)?"+b}]},{cN:"array",b:"\\#\\(",e:"\\)",c:[a.ASM,d,a.CNM,c]}]}});hljs.registerLanguage("sql",function(a){var b={cN:"comment",b:"--",e:"$"};return{cI:true,i:/[<>]/,c:[{cN:"operator",bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate savepoint release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup",e:/;/,eW:true,k:{keyword:"abs absolute acos action add adddate addtime aes_decrypt aes_encrypt after aggregate all allocate alter analyze and any are as asc ascii asin assertion at atan atan2 atn2 authorization authors avg backup before begin benchmark between bin binlog bit_and bit_count bit_length bit_or bit_xor both by cache call cascade cascaded case cast catalog ceil ceiling chain change changed char_length character_length charindex charset check checksum checksum_agg choose close coalesce coercibility collate collation collationproperty column columns columns_updated commit compress concat concat_ws concurrent connect connection connection_id consistent constraint constraints continue contributors conv convert convert_tz corresponding cos cot count count_big crc32 create cross cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime data database databases datalength date_add date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts datetimeoffsetfromparts day dayname dayofmonth dayofweek dayofyear deallocate declare decode default deferrable deferred degrees delayed delete des_decrypt des_encrypt des_key_file desc describe descriptor diagnostics difference disconnect distinct distinctrow div do domain double drop dumpfile each else elt enclosed encode encrypt end end-exec engine engines eomonth errors escape escaped event eventdata events except exception exec execute exists exp explain export_set extended external extract fast fetch field fields find_in_set first first_value floor flush for force foreign format found found_rows from from_base64 from_days from_unixtime full function get get_format get_lock getdate getutcdate global go goto grant grants greatest group group_concat grouping grouping_id gtid_subset gtid_subtract handler having help hex high_priority hosts hour ident_current ident_incr ident_seed identified identity if ifnull ignore iif ilike immediate in index indicator inet6_aton inet6_ntoa inet_aton inet_ntoa infile initially inner innodb input insert install instr intersect into is is_free_lock is_ipv4 is_ipv4_compat is_ipv4_mapped is_not is_not_null is_used_lock isdate isnull isolation join key kill language last last_day last_insert_id last_value lcase lead leading least leaves left len lenght level like limit lines ln load load_file local localtime localtimestamp locate lock log log10 log2 logfile logs low_priority lower lpad ltrim make_set makedate maketime master master_pos_wait match matched max md5 medium merge microsecond mid min minute mod mode module month monthname mutex name_const names national natural nchar next no no_write_to_binlog not now nullif nvarchar oct octet_length of old_password on only open optimize option optionally or ord order outer outfile output pad parse partial partition password patindex percent_rank percentile_cont percentile_disc period_add period_diff pi plugin position pow power pragma precision prepare preserve primary prior privileges procedure procedure_analyze processlist profile profiles public publishingservername purge quarter query quick quote quotename radians rand read references regexp relative relaylog release release_lock rename repair repeat replace replicate reset restore restrict return returns reverse revoke right rlike rollback rollup round row row_count rows rpad rtrim savepoint schema scroll sec_to_time second section select serializable server session session_user set sha sha1 sha2 share show sign sin size slave sleep smalldatetimefromparts snapshot some soname soundex sounds_like space sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sql_variant_property sqlstate sqrt square start starting status std stddev stddev_pop stddev_samp stdev stdevp stop str str_to_date straight_join strcmp string stuff subdate substr substring subtime subtring_index sum switchoffset sysdate sysdatetime sysdatetimeoffset system_user sysutcdatetime table tables tablespace tan temporary terminated tertiary_weights then time time_format time_to_sec timediff timefromparts timestamp timestampadd timestampdiff timezone_hour timezone_minute to to_base64 to_days to_seconds todatetimeoffset trailing transaction translation trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse ucase uncompress uncompressed_length unhex unicode uninstall union unique unix_timestamp unknown unlock update upgrade upped upper usage use user user_resources using utc_date utc_time utc_timestamp uuid uuid_short validate_password_strength value values var var_pop var_samp variables variance varp version view warnings week weekday weekofyear weight_string when whenever where with work write xml xor year yearweek zon",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int integer interval number numeric real serial smallint varchar varying int8 serial8 text"},c:[{cN:"string",b:"'",e:"'",c:[a.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[a.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[a.BE]},a.CNM,a.CBCM,b]},a.CBCM,b]}});hljs.registerLanguage("swift",function(a){var e={keyword:"class deinit enum extension func import init let protocol static struct subscript typealias var break case continue default do else fallthrough if in for return switch where while as dynamicType is new super self Self Type __COLUMN__ __FILE__ __FUNCTION__ __LINE__ associativity didSet get infix inout left mutating none nonmutating operator override postfix precedence prefix right set unowned unowned safe unsafe weak willSet",literal:"true false nil",built_in:"abs advance alignof alignofValue assert bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC bridgeToObjectiveCUnconditional c contains count countElements countLeadingZeros debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords enumerate equal false filter find getBridgedObjectiveCType getVaList indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC isUniquelyReferenced join lexicographicalCompare map max maxElement min minElement nil numericCast partition posix print println quickSort reduce reflect reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split startsWith strideof strideofValue swap swift toString transcode true underestimateCount unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer withUnsafePointerToObject withUnsafePointers withVaList"};var g={cN:"type",b:"\\b[A-Z][\\w']*",r:0};var b={cN:"comment",b:"/\\*",e:"\\*/",c:[a.PWM,"self"]};var c={cN:"subst",b:/\\\(/,e:"\\)",k:e,c:[]};var f={cN:"number",b:"\\b([\\d_]+(\\.[\\deE_]+)?|0x[a-fA-F0-9_]+(\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\b",r:0};var d=a.inherit(a.QSM,{c:[c,a.BE]});c.c=[f];return{k:e,c:[d,a.CLCM,b,g,f,{cN:"func",bK:"func",e:"{",eE:true,c:[a.inherit(a.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/,i:/\(/}),{cN:"generics",b:/\</,e:/\>/,i:/\>/},{cN:"params",b:/\(/,e:/\)/,k:e,c:["self",f,d,a.CBCM,{b:":"}],i:/["']/}],i:/\[|%/},{cN:"class",k:"struct protocol class extension enum",b:"(struct|protocol|class(?! (func|var))|extension|enum)",e:"\\{",eE:true,c:[a.inherit(a.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/})]},{cN:"preprocessor",b:"(@assignment|@class_protocol|@exported|@final|@lazy|@noreturn|@NSCopying|@NSManaged|@objc|@optional|@required|@auto_closure|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix)"},]}});hljs.registerLanguage("tex",function(a){var d={cN:"command",b:"\\\\[a-zA-Zа-яА-я]+[\\*]?"};var c={cN:"command",b:"\\\\[^a-zA-Zа-яА-я0-9]"};var b={cN:"special",b:"[{}\\[\\]\\&#~]",r:0};return{c:[{b:"\\\\[a-zA-Zа-яА-я]+[\\*]? *= *-?\\d*\\.?\\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?",rB:true,c:[d,c,{cN:"number",b:" *=",e:"-?\\d*\\.?\\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?",eB:true}],r:10},d,c,b,{cN:"formula",b:"\\$\\$",e:"\\$\\$",c:[d,c,b],r:0},{cN:"formula",b:"\\$",e:"\\$",c:[d,c,b],r:0},{cN:"comment",b:"%",e:"$",r:0}]}});hljs.registerLanguage("thrift",function(a){var b="bool byte i16 i32 i64 double string binary";return{k:{keyword:"namespace const typedef struct enum service exception void oneway set list map required optional",built_in:b,literal:"true false"},c:[a.QSM,a.NM,a.CLCM,a.CBCM,{cN:"class",bK:"struct enum service exception",e:/\{/,i:/\n/,c:[a.inherit(a.TM,{starts:{eW:true,eE:true}})]},{cN:"stl_container",b:"\\b(set|list|map)\\s*<",e:">",k:b,c:["self"]}]}});hljs.registerLanguage("typescript",function(a){return{aliases:["ts"],k:{keyword:"in if for while finally var new function|0 do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class public private get set super interface extendsstatic constructor implements enum export import declare",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document any number boolean string void",},c:[{cN:"pi",b:/^\s*('|")use strict('|")/,r:0},a.ASM,a.QSM,a.CLCM,a.CBCM,a.CNM,{b:"("+a.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[a.CLCM,a.CBCM,a.RM,{b:/</,e:/>;/,r:0,sL:"xml"}],r:0},{cN:"function",bK:"function",e:/\{/,eE:true,c:[a.inherit(a.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,c:[a.CLCM,a.CBCM],i:/["'\(]/}],i:/\[|%/,r:0},{cN:"constructor",bK:"constructor",e:/\{/,eE:true,r:10},{cN:"module",bK:"module",e:/\{/,eE:true,},{cN:"interface",bK:"interface",e:/\{/,eE:true,},{b:/\$[(.]/},{b:"\\."+a.IR,r:0}]}});hljs.registerLanguage("vala",function(a){return{k:{keyword:"char uchar unichar int uint long ulong short ushort int8 int16 int32 int64 uint8 uint16 uint32 uint64 float double bool struct enum string void weak unowned owned async signal static abstract interface override while do for foreach else switch case break default return try catch public private protected internal using new this get set const stdout stdin stderr var",built_in:"DBus GLib CCode Gee Object",literal:"false true null"},c:[{cN:"class",bK:"class interface delegate namespace",e:"{",eE:true,i:"[^,:\\n\\s\\.]",c:[a.UTM]},a.CLCM,a.CBCM,{cN:"string",b:'"""',e:'"""',r:5},a.ASM,a.QSM,a.CNM,{cN:"preprocessor",b:"^#",e:"$",r:2},{cN:"constant",b:" [A-Z_]+ ",r:0}]}});hljs.registerLanguage("vbnet",function(a){return{aliases:["vb"],cI:true,k:{keyword:"addhandler addressof alias and andalso aggregate ansi as assembly auto binary by byref byval call case catch class compare const continue custom declare default delegate dim distinct do each equals else elseif end enum erase error event exit explicit finally for friend from function get global goto group handles if implements imports in inherits interface into is isfalse isnot istrue join key let lib like loop me mid mod module mustinherit mustoverride mybase myclass namespace narrowing new next not notinheritable notoverridable of off on operator option optional or order orelse overloads overridable overrides paramarray partial preserve private property protected public raiseevent readonly redim rem removehandler resume return select set shadows shared skip static step stop structure strict sub synclock take text then throw to try unicode until using when where while widening with withevents writeonly xor",built_in:"boolean byte cbool cbyte cchar cdate cdec cdbl char cint clng cobj csbyte cshort csng cstr ctype date decimal directcast double gettype getxmlnamespace iif integer long object sbyte short single string trycast typeof uinteger ulong ushort",literal:"true false nothing"},i:"//|{|}|endif|gosub|variant|wend",c:[a.inherit(a.QSM,{c:[{b:'""'}]}),{cN:"comment",b:"'",e:"$",rB:true,c:[{cN:"xmlDocTag",b:"'''|<!--|-->"},{cN:"xmlDocTag",b:"</?",e:">"}]},a.CNM,{cN:"preprocessor",b:"#",e:"$",k:"if else elseif end region externalsource"}]}});hljs.registerLanguage("vbscript",function(a){return{aliases:["vbs"],cI:true,k:{keyword:"call class const dim do loop erase execute executeglobal exit for each next function if then else on error option explicit new private property let get public randomize redim rem select case set stop sub while wend with end to elseif is or xor and not class_initialize class_terminate default preserve in me byval byref step resume goto",built_in:"lcase month vartype instrrev ubound setlocale getobject rgb getref string weekdayname rnd dateadd monthname now day minute isarray cbool round formatcurrency conversions csng timevalue second year space abs clng timeserial fixs len asc isempty maths dateserial atn timer isobject filter weekday datevalue ccur isdate instr datediff formatdatetime replace isnull right sgn array snumeric log cdbl hex chr lbound msgbox ucase getlocale cos cdate cbyte rtrim join hour oct typename trim strcomp int createobject loadpicture tan formatnumber mid scriptenginebuildversion scriptengine split scriptengineminorversion cint sin datepart ltrim sqr scriptenginemajorversion time derived eval date formatpercent exp inputbox left ascw chrw regexp server response request cstr err",literal:"true false null nothing empty"},i:"//",c:[a.inherit(a.QSM,{c:[{b:'""'}]}),{cN:"comment",b:/'/,e:/$/,r:0},a.CNM]}});hljs.registerLanguage("vhdl",function(a){return{cI:true,k:{keyword:"abs access after alias all and architecture array assert attribute begin block body buffer bus case component configuration constant context cover disconnect downto default else elsif end entity exit fairness file for force function generate generic group guarded if impure in inertial inout is label library linkage literal loop map mod nand new next nor not null of on open or others out package port postponed procedure process property protected pure range record register reject release rem report restrict restrict_guarantee return rol ror select sequence severity shared signal sla sll sra srl strong subtype then to transport type unaffected units until use variable vmode vprop vunit wait when while with xnor xor",typename:"boolean bit character severity_level integer time delay_length natural positive string bit_vector file_open_kind file_open_status std_ulogic std_ulogic_vector std_logic std_logic_vector unsigned signed boolean_vector integer_vector real_vector time_vector"},i:"{",c:[a.CBCM,{cN:"comment",b:"--",e:"$"},a.QSM,a.CNM,{cN:"literal",b:"'(U|X|0|1|Z|W|L|H|-)'",c:[a.BE]},{cN:"attribute",b:"'[A-Za-z](_?[A-Za-z0-9])*",c:[a.BE]}]}});hljs.registerLanguage("vim",function(a){return{l:/[!#@\w]+/,k:{keyword:"N|0 P|0 X|0 a|0 ab abc abo al am an|0 ar arga argd arge argdo argg argl argu as au aug aun b|0 bN ba bad bd be bel bf bl bm bn bo bp br brea breaka breakd breakl bro bufdo buffers bun bw c|0 cN cNf ca cabc caddb cad caddf cal cat cb cc ccl cd ce cex cf cfir cgetb cgete cg changes chd che checkt cl cla clo cm cmapc cme cn cnew cnf cno cnorea cnoreme co col colo com comc comp con conf cope cp cpf cq cr cs cst cu cuna cunme cw d|0 delm deb debugg delc delf dif diffg diffo diffp diffpu diffs diffthis dig di dl dell dj dli do doautoa dp dr ds dsp e|0 ea ec echoe echoh echom echon el elsei em en endfo endf endt endw ene ex exe exi exu f|0 files filet fin fina fini fir fix fo foldc foldd folddoc foldo for fu g|0 go gr grepa gu gv ha h|0 helpf helpg helpt hi hid his i|0 ia iabc if ij il im imapc ime ino inorea inoreme int is isp iu iuna iunme j|0 ju k|0 keepa kee keepj lN lNf l|0 lad laddb laddf la lan lat lb lc lch lcl lcs le lefta let lex lf lfir lgetb lgete lg lgr lgrepa lh ll lla lli lmak lm lmapc lne lnew lnf ln loadk lo loc lockv lol lope lp lpf lr ls lt lu lua luad luaf lv lvimgrepa lw m|0 ma mak map mapc marks mat me menut mes mk mks mksp mkv mkvie mod mz mzf nbc nb nbs n|0 new nm nmapc nme nn nnoreme noa no noh norea noreme norm nu nun nunme ol o|0 om omapc ome on ono onoreme opt ou ounme ow p|0 profd prof pro promptr pc ped pe perld po popu pp pre prev ps pt ptN ptf ptj ptl ptn ptp ptr pts pu pw py3 python3 py3d py3f py pyd pyf q|0 quita qa r|0 rec red redi redr redraws reg res ret retu rew ri rightb rub rubyd rubyf rund ru rv s|0 sN san sa sal sav sb sbN sba sbf sbl sbm sbn sbp sbr scrip scripte scs se setf setg setl sf sfir sh sim sig sil sl sla sm smap smapc sme sn sni sno snor snoreme sor so spelld spe spelli spellr spellu spellw sp spr sre st sta startg startr star stopi stj sts sun sunm sunme sus sv sw sy synti sync t|0 tN tabN tabc tabdo tabe tabf tabfir tabl tabm tabnew tabn tabo tabp tabr tabs tab ta tags tc tcld tclf te tf th tj tl tm tn to tp tr try ts tu u|0 undoj undol una unh unl unlo unm unme uns up v|0 ve verb vert vim vimgrepa vi viu vie vm vmapc vme vne vn vnoreme vs vu vunme windo w|0 wN wa wh wi winc winp wn wp wq wqa ws wu wv x|0 xa xmapc xm xme xn xnoreme xu xunme y|0 z|0 ~ Next Print append abbreviate abclear aboveleft all amenu anoremenu args argadd argdelete argedit argglobal arglocal argument ascii autocmd augroup aunmenu buffer bNext ball badd bdelete behave belowright bfirst blast bmodified bnext botright bprevious brewind break breakadd breakdel breaklist browse bunload bwipeout change cNext cNfile cabbrev cabclear caddbuffer caddexpr caddfile call catch cbuffer cclose center cexpr cfile cfirst cgetbuffer cgetexpr cgetfile chdir checkpath checktime clist clast close cmap cmapclear cmenu cnext cnewer cnfile cnoremap cnoreabbrev cnoremenu copy colder colorscheme command comclear compiler continue confirm copen cprevious cpfile cquit crewind cscope cstag cunmap cunabbrev cunmenu cwindow delete delmarks debug debuggreedy delcommand delfunction diffupdate diffget diffoff diffpatch diffput diffsplit digraphs display deletel djump dlist doautocmd doautoall deletep drop dsearch dsplit edit earlier echo echoerr echohl echomsg else elseif emenu endif endfor endfunction endtry endwhile enew execute exit exusage file filetype find finally finish first fixdel fold foldclose folddoopen folddoclosed foldopen function global goto grep grepadd gui gvim hardcopy help helpfind helpgrep helptags highlight hide history insert iabbrev iabclear ijump ilist imap imapclear imenu inoremap inoreabbrev inoremenu intro isearch isplit iunmap iunabbrev iunmenu join jumps keepalt keepmarks keepjumps lNext lNfile list laddexpr laddbuffer laddfile last language later lbuffer lcd lchdir lclose lcscope left leftabove lexpr lfile lfirst lgetbuffer lgetexpr lgetfile lgrep lgrepadd lhelpgrep llast llist lmake lmap lmapclear lnext lnewer lnfile lnoremap loadkeymap loadview lockmarks lockvar lolder lopen lprevious lpfile lrewind ltag lunmap luado luafile lvimgrep lvimgrepadd lwindow move mark make mapclear match menu menutranslate messages mkexrc mksession mkspell mkvimrc mkview mode mzscheme mzfile nbclose nbkey nbsart next nmap nmapclear nmenu nnoremap nnoremenu noautocmd noremap nohlsearch noreabbrev noremenu normal number nunmap nunmenu oldfiles open omap omapclear omenu only onoremap onoremenu options ounmap ounmenu ownsyntax print profdel profile promptfind promptrepl pclose pedit perl perldo pop popup ppop preserve previous psearch ptag ptNext ptfirst ptjump ptlast ptnext ptprevious ptrewind ptselect put pwd py3do py3file python pydo pyfile quit quitall qall read recover redo redir redraw redrawstatus registers resize retab return rewind right rightbelow ruby rubydo rubyfile rundo runtime rviminfo substitute sNext sandbox sargument sall saveas sbuffer sbNext sball sbfirst sblast sbmodified sbnext sbprevious sbrewind scriptnames scriptencoding scscope set setfiletype setglobal setlocal sfind sfirst shell simalt sign silent sleep slast smagic smapclear smenu snext sniff snomagic snoremap snoremenu sort source spelldump spellgood spellinfo spellrepall spellundo spellwrong split sprevious srewind stop stag startgreplace startreplace startinsert stopinsert stjump stselect sunhide sunmap sunmenu suspend sview swapname syntax syntime syncbind tNext tabNext tabclose tabedit tabfind tabfirst tablast tabmove tabnext tabonly tabprevious tabrewind tag tcl tcldo tclfile tearoff tfirst throw tjump tlast tmenu tnext topleft tprevious trewind tselect tunmenu undo undojoin undolist unabbreviate unhide unlet unlockvar unmap unmenu unsilent update vglobal version verbose vertical vimgrep vimgrepadd visual viusage view vmap vmapclear vmenu vnew vnoremap vnoremenu vsplit vunmap vunmenu write wNext wall while winsize wincmd winpos wnext wprevious wqall wsverb wundo wviminfo xit xall xmapclear xmap xmenu xnoremap xnoremenu xunmap xunmenu yank",built_in:"abs acos add and append argc argidx argv asin atan atan2 browse browsedir bufexists buflisted bufloaded bufname bufnr bufwinnr byte2line byteidx call ceil changenr char2nr cindent clearmatches col complete complete_add complete_check confirm copy cos cosh count cscope_connection cursor deepcopy delete did_filetype diff_filler diff_hlID empty escape eval eventhandler executable exists exp expand extend feedkeys filereadable filewritable filter finddir findfile float2nr floor fmod fnameescape fnamemodify foldclosed foldclosedend foldlevel foldtext foldtextresult foreground function garbagecollect get getbufline getbufvar getchar getcharmod getcmdline getcmdpos getcmdtype getcwd getfontname getfperm getfsize getftime getftype getline getloclist getmatches getpid getpos getqflist getreg getregtype gettabvar gettabwinvar getwinposx getwinposy getwinvar glob globpath has has_key haslocaldir hasmapto histadd histdel histget histnr hlexists hlID hostname iconv indent index input inputdialog inputlist inputrestore inputsave inputsecret insert invert isdirectory islocked items join keys len libcall libcallnr line line2byte lispindent localtime log log10 luaeval map maparg mapcheck match matchadd matcharg matchdelete matchend matchlist matchstr max min mkdir mode mzeval nextnonblank nr2char or pathshorten pow prevnonblank printf pumvisible py3eval pyeval range readfile reltime reltimestr remote_expr remote_foreground remote_peek remote_read remote_send remove rename repeat resolve reverse round screenattr screenchar screencol screenrow search searchdecl searchpair searchpairpos searchpos server2client serverlist setbufvar setcmdpos setline setloclist setmatches setpos setqflist setreg settabvar settabwinvar setwinvar sha256 shellescape shiftwidth simplify sin sinh sort soundfold spellbadword spellsuggest split sqrt str2float str2nr strchars strdisplaywidth strftime stridx string strlen strpart strridx strtrans strwidth submatch substitute synconcealed synID synIDattr synIDtrans synstack system tabpagebuflist tabpagenr tabpagewinnr tagfiles taglist tan tanh tempname tolower toupper tr trunc type undofile undotree values virtcol visualmode wildmenumode winbufnr wincol winheight winline winnr winrestcmd winrestview winsaveview winwidth writefile xor"},i:/[{:]/,c:[a.NM,a.ASM,{cN:"string",b:/"((\\")|[^"\n])*("|\n)/},{cN:"variable",b:/[bwtglsav]:[\w\d_]*/},{cN:"function",bK:"function function!",e:"$",r:0,c:[a.TM,{cN:"params",b:"\\(",e:"\\)"}]}]}});hljs.registerLanguage("x86asm",function(a){return{cI:true,l:"\\.?"+a.IR,k:{keyword:"lock rep repe repz repne repnz xaquire xrelease bnd nobnd aaa aad aam aas adc add and arpl bb0_reset bb1_reset bound bsf bsr bswap bt btc btr bts call cbw cdq cdqe clc cld cli clts cmc cmp cmpsb cmpsd cmpsq cmpsw cmpxchg cmpxchg486 cmpxchg8b cmpxchg16b cpuid cpu_read cpu_write cqo cwd cwde daa das dec div dmint emms enter equ f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcmovb fcmovbe fcmove fcmovnb fcmovnbe fcmovne fcmovnu fcmovu fcom fcomi fcomip fcomp fcompp fcos fdecstp fdisi fdiv fdivp fdivr fdivrp femms feni ffree ffreep fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit fist fistp fisttp fisub fisubr fld fld1 fldcw fldenv fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex fndisi fneni fninit fnop fnsave fnstcw fnstenv fnstsw fpatan fprem fprem1 fptan frndint frstor fsave fscale fsetpm fsin fsincos fsqrt fst fstcw fstenv fstp fstsw fsub fsubp fsubr fsubrp ftst fucom fucomi fucomip fucomp fucompp fxam fxch fxtract fyl2x fyl2xp1 hlt ibts icebp idiv imul in inc incbin insb insd insw int int01 int1 int03 int3 into invd invpcid invlpg invlpga iret iretd iretq iretw jcxz jecxz jrcxz jmp jmpe lahf lar lds lea leave les lfence lfs lgdt lgs lidt lldt lmsw loadall loadall286 lodsb lodsd lodsq lodsw loop loope loopne loopnz loopz lsl lss ltr mfence monitor mov movd movq movsb movsd movsq movsw movsx movsxd movzx mul mwait neg nop not or out outsb outsd outsw packssdw packsswb packuswb paddb paddd paddsb paddsiw paddsw paddusb paddusw paddw pand pandn pause paveb pavgusb pcmpeqb pcmpeqd pcmpeqw pcmpgtb pcmpgtd pcmpgtw pdistib pf2id pfacc pfadd pfcmpeq pfcmpge pfcmpgt pfmax pfmin pfmul pfrcp pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd pmachriw pmaddwd pmagw pmulhriw pmulhrwa pmulhrwc pmulhw pmullw pmvgezb pmvlzb pmvnzb pmvzb pop popa popad popaw popf popfd popfq popfw por prefetch prefetchw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb psubd psubsb psubsiw psubsw psubusb psubusw psubw punpckhbw punpckhdq punpckhwd punpcklbw punpckldq punpcklwd push pusha pushad pushaw pushf pushfd pushfq pushfw pxor rcl rcr rdshr rdmsr rdpmc rdtsc rdtscp ret retf retn rol ror rdm rsdc rsldt rsm rsts sahf sal salc sar sbb scasb scasd scasq scasw sfence sgdt shl shld shr shrd sidt sldt skinit smi smint smintold smsw stc std sti stosb stosd stosq stosw str sub svdc svldt svts swapgs syscall sysenter sysexit sysret test ud0 ud1 ud2b ud2 ud2a umov verr verw fwait wbinvd wrshr wrmsr xadd xbts xchg xlatb xlat xor cmove cmovz cmovne cmovnz cmova cmovnbe cmovae cmovnb cmovb cmovnae cmovbe cmovna cmovg cmovnle cmovge cmovnl cmovl cmovnge cmovle cmovng cmovc cmovnc cmovo cmovno cmovs cmovns cmovp cmovpe cmovnp cmovpo je jz jne jnz ja jnbe jae jnb jb jnae jbe jna jg jnle jge jnl jl jnge jle jng jc jnc jo jno js jns jpo jnp jpe jp sete setz setne setnz seta setnbe setae setnb setnc setb setnae setcset setbe setna setg setnle setge setnl setl setnge setle setng sets setns seto setno setpe setp setpo setnp addps addss andnps andps cmpeqps cmpeqss cmpleps cmpless cmpltps cmpltss cmpneqps cmpneqss cmpnleps cmpnless cmpnltps cmpnltss cmpordps cmpordss cmpunordps cmpunordss cmpps cmpss comiss cvtpi2ps cvtps2pi cvtsi2ss cvtss2si cvttps2pi cvttss2si divps divss ldmxcsr maxps maxss minps minss movaps movhps movlhps movlps movhlps movmskps movntps movss movups mulps mulss orps rcpps rcpss rsqrtps rsqrtss shufps sqrtps sqrtss stmxcsr subps subss ucomiss unpckhps unpcklps xorps fxrstor fxrstor64 fxsave fxsave64 xgetbv xsetbv xsave xsave64 xsaveopt xsaveopt64 xrstor xrstor64 prefetchnta prefetcht0 prefetcht1 prefetcht2 maskmovq movntq pavgb pavgw pextrw pinsrw pmaxsw pmaxub pminsw pminub pmovmskb pmulhuw psadbw pshufw pf2iw pfnacc pfpnacc pi2fw pswapd maskmovdqu clflush movntdq movnti movntpd movdqa movdqu movdq2q movq2dq paddq pmuludq pshufd pshufhw pshuflw pslldq psrldq psubq punpckhqdq punpcklqdq addpd addsd andnpd andpd cmpeqpd cmpeqsd cmplepd cmplesd cmpltpd cmpltsd cmpneqpd cmpneqsd cmpnlepd cmpnlesd cmpnltpd cmpnltsd cmpordpd cmpordsd cmpunordpd cmpunordsd cmppd comisd cvtdq2pd cvtdq2ps cvtpd2dq cvtpd2pi cvtpd2ps cvtpi2pd cvtps2dq cvtps2pd cvtsd2si cvtsd2ss cvtsi2sd cvtss2sd cvttpd2pi cvttpd2dq cvttps2dq cvttsd2si divpd divsd maxpd maxsd minpd minsd movapd movhpd movlpd movmskpd movupd mulpd mulsd orpd shufpd sqrtpd sqrtsd subpd subsd ucomisd unpckhpd unpcklpd xorpd addsubpd addsubps haddpd haddps hsubpd hsubps lddqu movddup movshdup movsldup clgi stgi vmcall vmclear vmfunc vmlaunch vmload vmmcall vmptrld vmptrst vmread vmresume vmrun vmsave vmwrite vmxoff vmxon invept invvpid pabsb pabsw pabsd palignr phaddw phaddd phaddsw phsubw phsubd phsubsw pmaddubsw pmulhrsw pshufb psignb psignw psignd extrq insertq movntsd movntss lzcnt blendpd blendps blendvpd blendvps dppd dpps extractps insertps movntdqa mpsadbw packusdw pblendvb pblendw pcmpeqq pextrb pextrd pextrq phminposuw pinsrb pinsrd pinsrq pmaxsb pmaxsd pmaxud pmaxuw pminsb pminsd pminud pminuw pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq pmuldq pmulld ptest roundpd roundps roundsd roundss crc32 pcmpestri pcmpestrm pcmpistri pcmpistrm pcmpgtq popcnt getsec pfrcpv pfrsqrtv movbe aesenc aesenclast aesdec aesdeclast aesimc aeskeygenassist vaesenc vaesenclast vaesdec vaesdeclast vaesimc vaeskeygenassist vaddpd vaddps vaddsd vaddss vaddsubpd vaddsubps vandpd vandps vandnpd vandnps vblendpd vblendps vblendvpd vblendvps vbroadcastss vbroadcastsd vbroadcastf128 vcmpeq_ospd vcmpeqpd vcmplt_ospd vcmpltpd vcmple_ospd vcmplepd vcmpunord_qpd vcmpunordpd vcmpneq_uqpd vcmpneqpd vcmpnlt_uspd vcmpnltpd vcmpnle_uspd vcmpnlepd vcmpord_qpd vcmpordpd vcmpeq_uqpd vcmpnge_uspd vcmpngepd vcmpngt_uspd vcmpngtpd vcmpfalse_oqpd vcmpfalsepd vcmpneq_oqpd vcmpge_ospd vcmpgepd vcmpgt_ospd vcmpgtpd vcmptrue_uqpd vcmptruepd vcmplt_oqpd vcmple_oqpd vcmpunord_spd vcmpneq_uspd vcmpnlt_uqpd vcmpnle_uqpd vcmpord_spd vcmpeq_uspd vcmpnge_uqpd vcmpngt_uqpd vcmpfalse_ospd vcmpneq_ospd vcmpge_oqpd vcmpgt_oqpd vcmptrue_uspd vcmppd vcmpeq_osps vcmpeqps vcmplt_osps vcmpltps vcmple_osps vcmpleps vcmpunord_qps vcmpunordps vcmpneq_uqps vcmpneqps vcmpnlt_usps vcmpnltps vcmpnle_usps vcmpnleps vcmpord_qps vcmpordps vcmpeq_uqps vcmpnge_usps vcmpngeps vcmpngt_usps vcmpngtps vcmpfalse_oqps vcmpfalseps vcmpneq_oqps vcmpge_osps vcmpgeps vcmpgt_osps vcmpgtps vcmptrue_uqps vcmptrueps vcmplt_oqps vcmple_oqps vcmpunord_sps vcmpneq_usps vcmpnlt_uqps vcmpnle_uqps vcmpord_sps vcmpeq_usps vcmpnge_uqps vcmpngt_uqps vcmpfalse_osps vcmpneq_osps vcmpge_oqps vcmpgt_oqps vcmptrue_usps vcmpps vcmpeq_ossd vcmpeqsd vcmplt_ossd vcmpltsd vcmple_ossd vcmplesd vcmpunord_qsd vcmpunordsd vcmpneq_uqsd vcmpneqsd vcmpnlt_ussd vcmpnltsd vcmpnle_ussd vcmpnlesd vcmpord_qsd vcmpordsd vcmpeq_uqsd vcmpnge_ussd vcmpngesd vcmpngt_ussd vcmpngtsd vcmpfalse_oqsd vcmpfalsesd vcmpneq_oqsd vcmpge_ossd vcmpgesd vcmpgt_ossd vcmpgtsd vcmptrue_uqsd vcmptruesd vcmplt_oqsd vcmple_oqsd vcmpunord_ssd vcmpneq_ussd vcmpnlt_uqsd vcmpnle_uqsd vcmpord_ssd vcmpeq_ussd vcmpnge_uqsd vcmpngt_uqsd vcmpfalse_ossd vcmpneq_ossd vcmpge_oqsd vcmpgt_oqsd vcmptrue_ussd vcmpsd vcmpeq_osss vcmpeqss vcmplt_osss vcmpltss vcmple_osss vcmpless vcmpunord_qss vcmpunordss vcmpneq_uqss vcmpneqss vcmpnlt_usss vcmpnltss vcmpnle_usss vcmpnless vcmpord_qss vcmpordss vcmpeq_uqss vcmpnge_usss vcmpngess vcmpngt_usss vcmpngtss vcmpfalse_oqss vcmpfalsess vcmpneq_oqss vcmpge_osss vcmpgess vcmpgt_osss vcmpgtss vcmptrue_uqss vcmptruess vcmplt_oqss vcmple_oqss vcmpunord_sss vcmpneq_usss vcmpnlt_uqss vcmpnle_uqss vcmpord_sss vcmpeq_usss vcmpnge_uqss vcmpngt_uqss vcmpfalse_osss vcmpneq_osss vcmpge_oqss vcmpgt_oqss vcmptrue_usss vcmpss vcomisd vcomiss vcvtdq2pd vcvtdq2ps vcvtpd2dq vcvtpd2ps vcvtps2dq vcvtps2pd vcvtsd2si vcvtsd2ss vcvtsi2sd vcvtsi2ss vcvtss2sd vcvtss2si vcvttpd2dq vcvttps2dq vcvttsd2si vcvttss2si vdivpd vdivps vdivsd vdivss vdppd vdpps vextractf128 vextractps vhaddpd vhaddps vhsubpd vhsubps vinsertf128 vinsertps vlddqu vldqqu vldmxcsr vmaskmovdqu vmaskmovps vmaskmovpd vmaxpd vmaxps vmaxsd vmaxss vminpd vminps vminsd vminss vmovapd vmovaps vmovd vmovq vmovddup vmovdqa vmovqqa vmovdqu vmovqqu vmovhlps vmovhpd vmovhps vmovlhps vmovlpd vmovlps vmovmskpd vmovmskps vmovntdq vmovntqq vmovntdqa vmovntpd vmovntps vmovsd vmovshdup vmovsldup vmovss vmovupd vmovups vmpsadbw vmulpd vmulps vmulsd vmulss vorpd vorps vpabsb vpabsw vpabsd vpacksswb vpackssdw vpackuswb vpackusdw vpaddb vpaddw vpaddd vpaddq vpaddsb vpaddsw vpaddusb vpaddusw vpalignr vpand vpandn vpavgb vpavgw vpblendvb vpblendw vpcmpestri vpcmpestrm vpcmpistri vpcmpistrm vpcmpeqb vpcmpeqw vpcmpeqd vpcmpeqq vpcmpgtb vpcmpgtw vpcmpgtd vpcmpgtq vpermilpd vpermilps vperm2f128 vpextrb vpextrw vpextrd vpextrq vphaddw vphaddd vphaddsw vphminposuw vphsubw vphsubd vphsubsw vpinsrb vpinsrw vpinsrd vpinsrq vpmaddwd vpmaddubsw vpmaxsb vpmaxsw vpmaxsd vpmaxub vpmaxuw vpmaxud vpminsb vpminsw vpminsd vpminub vpminuw vpminud vpmovmskb vpmovsxbw vpmovsxbd vpmovsxbq vpmovsxwd vpmovsxwq vpmovsxdq vpmovzxbw vpmovzxbd vpmovzxbq vpmovzxwd vpmovzxwq vpmovzxdq vpmulhuw vpmulhrsw vpmulhw vpmullw vpmulld vpmuludq vpmuldq vpor vpsadbw vpshufb vpshufd vpshufhw vpshuflw vpsignb vpsignw vpsignd vpslldq vpsrldq vpsllw vpslld vpsllq vpsraw vpsrad vpsrlw vpsrld vpsrlq vptest vpsubb vpsubw vpsubd vpsubq vpsubsb vpsubsw vpsubusb vpsubusw vpunpckhbw vpunpckhwd vpunpckhdq vpunpckhqdq vpunpcklbw vpunpcklwd vpunpckldq vpunpcklqdq vpxor vrcpps vrcpss vrsqrtps vrsqrtss vroundpd vroundps vroundsd vroundss vshufpd vshufps vsqrtpd vsqrtps vsqrtsd vsqrtss vstmxcsr vsubpd vsubps vsubsd vsubss vtestps vtestpd vucomisd vucomiss vunpckhpd vunpckhps vunpcklpd vunpcklps vxorpd vxorps vzeroall vzeroupper pclmullqlqdq pclmulhqlqdq pclmullqhqdq pclmulhqhqdq pclmulqdq vpclmullqlqdq vpclmulhqlqdq vpclmullqhqdq vpclmulhqhqdq vpclmulqdq vfmadd132ps vfmadd132pd vfmadd312ps vfmadd312pd vfmadd213ps vfmadd213pd vfmadd123ps vfmadd123pd vfmadd231ps vfmadd231pd vfmadd321ps vfmadd321pd vfmaddsub132ps vfmaddsub132pd vfmaddsub312ps vfmaddsub312pd vfmaddsub213ps vfmaddsub213pd vfmaddsub123ps vfmaddsub123pd vfmaddsub231ps vfmaddsub231pd vfmaddsub321ps vfmaddsub321pd vfmsub132ps vfmsub132pd vfmsub312ps vfmsub312pd vfmsub213ps vfmsub213pd vfmsub123ps vfmsub123pd vfmsub231ps vfmsub231pd vfmsub321ps vfmsub321pd vfmsubadd132ps vfmsubadd132pd vfmsubadd312ps vfmsubadd312pd vfmsubadd213ps vfmsubadd213pd vfmsubadd123ps vfmsubadd123pd vfmsubadd231ps vfmsubadd231pd vfmsubadd321ps vfmsubadd321pd vfnmadd132ps vfnmadd132pd vfnmadd312ps vfnmadd312pd vfnmadd213ps vfnmadd213pd vfnmadd123ps vfnmadd123pd vfnmadd231ps vfnmadd231pd vfnmadd321ps vfnmadd321pd vfnmsub132ps vfnmsub132pd vfnmsub312ps vfnmsub312pd vfnmsub213ps vfnmsub213pd vfnmsub123ps vfnmsub123pd vfnmsub231ps vfnmsub231pd vfnmsub321ps vfnmsub321pd vfmadd132ss vfmadd132sd vfmadd312ss vfmadd312sd vfmadd213ss vfmadd213sd vfmadd123ss vfmadd123sd vfmadd231ss vfmadd231sd vfmadd321ss vfmadd321sd vfmsub132ss vfmsub132sd vfmsub312ss vfmsub312sd vfmsub213ss vfmsub213sd vfmsub123ss vfmsub123sd vfmsub231ss vfmsub231sd vfmsub321ss vfmsub321sd vfnmadd132ss vfnmadd132sd vfnmadd312ss vfnmadd312sd vfnmadd213ss vfnmadd213sd vfnmadd123ss vfnmadd123sd vfnmadd231ss vfnmadd231sd vfnmadd321ss vfnmadd321sd vfnmsub132ss vfnmsub132sd vfnmsub312ss vfnmsub312sd vfnmsub213ss vfnmsub213sd vfnmsub123ss vfnmsub123sd vfnmsub231ss vfnmsub231sd vfnmsub321ss vfnmsub321sd rdfsbase rdgsbase rdrand wrfsbase wrgsbase vcvtph2ps vcvtps2ph adcx adox rdseed clac stac xstore xcryptecb xcryptcbc xcryptctr xcryptcfb xcryptofb montmul xsha1 xsha256 llwpcb slwpcb lwpval lwpins vfmaddpd vfmaddps vfmaddsd vfmaddss vfmaddsubpd vfmaddsubps vfmsubaddpd vfmsubaddps vfmsubpd vfmsubps vfmsubsd vfmsubss vfnmaddpd vfnmaddps vfnmaddsd vfnmaddss vfnmsubpd vfnmsubps vfnmsubsd vfnmsubss vfrczpd vfrczps vfrczsd vfrczss vpcmov vpcomb vpcomd vpcomq vpcomub vpcomud vpcomuq vpcomuw vpcomw vphaddbd vphaddbq vphaddbw vphadddq vphaddubd vphaddubq vphaddubw vphaddudq vphadduwd vphadduwq vphaddwd vphaddwq vphsubbw vphsubdq vphsubwd vpmacsdd vpmacsdqh vpmacsdql vpmacssdd vpmacssdqh vpmacssdql vpmacsswd vpmacssww vpmacswd vpmacsww vpmadcsswd vpmadcswd vpperm vprotb vprotd vprotq vprotw vpshab vpshad vpshaq vpshaw vpshlb vpshld vpshlq vpshlw vbroadcasti128 vpblendd vpbroadcastb vpbroadcastw vpbroadcastd vpbroadcastq vpermd vpermpd vpermps vpermq vperm2i128 vextracti128 vinserti128 vpmaskmovd vpmaskmovq vpsllvd vpsllvq vpsravd vpsrlvd vpsrlvq vgatherdpd vgatherqpd vgatherdps vgatherqps vpgatherdd vpgatherqd vpgatherdq vpgatherqq xabort xbegin xend xtest andn bextr blci blcic blsi blsic blcfill blsfill blcmsk blsmsk blsr blcs bzhi mulx pdep pext rorx sarx shlx shrx tzcnt tzmsk t1mskc valignd valignq vblendmpd vblendmps vbroadcastf32x4 vbroadcastf64x4 vbroadcasti32x4 vbroadcasti64x4 vcompresspd vcompressps vcvtpd2udq vcvtps2udq vcvtsd2usi vcvtss2usi vcvttpd2udq vcvttps2udq vcvttsd2usi vcvttss2usi vcvtudq2pd vcvtudq2ps vcvtusi2sd vcvtusi2ss vexpandpd vexpandps vextractf32x4 vextractf64x4 vextracti32x4 vextracti64x4 vfixupimmpd vfixupimmps vfixupimmsd vfixupimmss vgetexppd vgetexpps vgetexpsd vgetexpss vgetmantpd vgetmantps vgetmantsd vgetmantss vinsertf32x4 vinsertf64x4 vinserti32x4 vinserti64x4 vmovdqa32 vmovdqa64 vmovdqu32 vmovdqu64 vpabsq vpandd vpandnd vpandnq vpandq vpblendmd vpblendmq vpcmpltd vpcmpled vpcmpneqd vpcmpnltd vpcmpnled vpcmpd vpcmpltq vpcmpleq vpcmpneqq vpcmpnltq vpcmpnleq vpcmpq vpcmpequd vpcmpltud vpcmpleud vpcmpnequd vpcmpnltud vpcmpnleud vpcmpud vpcmpequq vpcmpltuq vpcmpleuq vpcmpnequq vpcmpnltuq vpcmpnleuq vpcmpuq vpcompressd vpcompressq vpermi2d vpermi2pd vpermi2ps vpermi2q vpermt2d vpermt2pd vpermt2ps vpermt2q vpexpandd vpexpandq vpmaxsq vpmaxuq vpminsq vpminuq vpmovdb vpmovdw vpmovqb vpmovqd vpmovqw vpmovsdb vpmovsdw vpmovsqb vpmovsqd vpmovsqw vpmovusdb vpmovusdw vpmovusqb vpmovusqd vpmovusqw vpord vporq vprold vprolq vprolvd vprolvq vprord vprorq vprorvd vprorvq vpscatterdd vpscatterdq vpscatterqd vpscatterqq vpsraq vpsravq vpternlogd vpternlogq vptestmd vptestmq vptestnmd vptestnmq vpxord vpxorq vrcp14pd vrcp14ps vrcp14sd vrcp14ss vrndscalepd vrndscaleps vrndscalesd vrndscaless vrsqrt14pd vrsqrt14ps vrsqrt14sd vrsqrt14ss vscalefpd vscalefps vscalefsd vscalefss vscatterdpd vscatterdps vscatterqpd vscatterqps vshuff32x4 vshuff64x2 vshufi32x4 vshufi64x2 kandnw kandw kmovw knotw kortestw korw kshiftlw kshiftrw kunpckbw kxnorw kxorw vpbroadcastmb2q vpbroadcastmw2d vpconflictd vpconflictq vplzcntd vplzcntq vexp2pd vexp2ps vrcp28pd vrcp28ps vrcp28sd vrcp28ss vrsqrt28pd vrsqrt28ps vrsqrt28sd vrsqrt28ss vgatherpf0dpd vgatherpf0dps vgatherpf0qpd vgatherpf0qps vgatherpf1dpd vgatherpf1dps vgatherpf1qpd vgatherpf1qps vscatterpf0dpd vscatterpf0dps vscatterpf0qpd vscatterpf0qps vscatterpf1dpd vscatterpf1dps vscatterpf1qpd vscatterpf1qps prefetchwt1 bndmk bndcl bndcu bndcn bndmov bndldx bndstx sha1rnds4 sha1nexte sha1msg1 sha1msg2 sha256rnds2 sha256msg1 sha256msg2 hint_nop0 hint_nop1 hint_nop2 hint_nop3 hint_nop4 hint_nop5 hint_nop6 hint_nop7 hint_nop8 hint_nop9 hint_nop10 hint_nop11 hint_nop12 hint_nop13 hint_nop14 hint_nop15 hint_nop16 hint_nop17 hint_nop18 hint_nop19 hint_nop20 hint_nop21 hint_nop22 hint_nop23 hint_nop24 hint_nop25 hint_nop26 hint_nop27 hint_nop28 hint_nop29 hint_nop30 hint_nop31 hint_nop32 hint_nop33 hint_nop34 hint_nop35 hint_nop36 hint_nop37 hint_nop38 hint_nop39 hint_nop40 hint_nop41 hint_nop42 hint_nop43 hint_nop44 hint_nop45 hint_nop46 hint_nop47 hint_nop48 hint_nop49 hint_nop50 hint_nop51 hint_nop52 hint_nop53 hint_nop54 hint_nop55 hint_nop56 hint_nop57 hint_nop58 hint_nop59 hint_nop60 hint_nop61 hint_nop62 hint_nop63",literal:"ip eip rip al ah bl bh cl ch dl dh sil dil bpl spl r8b r9b r10b r11b r12b r13b r14b r15b ax bx cx dx si di bp sp r8w r9w r10w r11w r12w r13w r14w r15w eax ebx ecx edx esi edi ebp esp eip r8d r9d r10d r11d r12d r13d r14d r15d rax rbx rcx rdx rsi rdi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 cs ds es fs gs ss st st0 st1 st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 xmm0  xmm1  xmm2  xmm3  xmm4  xmm5  xmm6  xmm7  xmm8  xmm9 xmm10  xmm11 xmm12 xmm13 xmm14 xmm15 xmm16 xmm17 xmm18 xmm19 xmm20 xmm21 xmm22 xmm23 xmm24 xmm25 xmm26 xmm27 xmm28 xmm29 xmm30 xmm31 ymm0  ymm1  ymm2  ymm3  ymm4  ymm5  ymm6  ymm7  ymm8  ymm9 ymm10  ymm11 ymm12 ymm13 ymm14 ymm15 ymm16 ymm17 ymm18 ymm19 ymm20 ymm21 ymm22 ymm23 ymm24 ymm25 ymm26 ymm27 ymm28 ymm29 ymm30 ymm31 zmm0  zmm1  zmm2  zmm3  zmm4  zmm5  zmm6  zmm7  zmm8  zmm9 zmm10  zmm11 zmm12 zmm13 zmm14 zmm15 zmm16 zmm17 zmm18 zmm19 zmm20 zmm21 zmm22 zmm23 zmm24 zmm25 zmm26 zmm27 zmm28 zmm29 zmm30 zmm31 k0 k1 k2 k3 k4 k5 k6 k7 bnd0 bnd1 bnd2 bnd3 cr0 cr1 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr8 tr3 tr4 tr5 tr6 tr7 r0 r1 r2 r3 r4 r5 r6 r7 r0b r1b r2b r3b r4b r5b r6b r7b r0w r1w r2w r3w r4w r5w r6w r7w r0d r1d r2d r3d r4d r5d r6d r7d r0h r1h r2h r3h r0l r1l r2l r3l r4l r5l r6l r7l r8l r9l r10l r11l r12l r13l r14l r15l",pseudo:"db dw dd dq dt ddq do dy dz resb resw resd resq rest resdq reso resy resz incbin equ times",preprocessor:"%define %xdefine %+ %undef %defstr %deftok %assign %strcat %strlen %substr %rotate %elif %else %endif %ifmacro %ifctx %ifidn %ifidni %ifid %ifnum %ifstr %iftoken %ifempty %ifenv %error %warning %fatal %rep %endrep %include %push %pop %repl %pathsearch %depend %use %arg %stacksize %local %line %comment %endcomment .nolist byte word dword qword nosplit rel abs seg wrt strict near far a32 ptr __FILE__ __LINE__ __SECT__  __BITS__ __OUTPUT_FORMAT__ __DATE__ __TIME__ __DATE_NUM__ __TIME_NUM__ __UTC_DATE__ __UTC_TIME__ __UTC_DATE_NUM__ __UTC_TIME_NUM__  __PASS__ struc endstruc istruc at iend align alignb sectalign daz nodaz up down zero default option assume public ",built_in:"bits use16 use32 use64 default section segment absolute extern global common cpu float __utf16__ __utf16le__ __utf16be__ __utf32__ __utf32le__ __utf32be__ __float8__ __float16__ __float32__ __float64__ __float80m__ __float80e__ __float128l__ __float128h__ __Infinity__ __QNaN__ __SNaN__ Inf NaN QNaN SNaN float8 float16 float32 float64 float80m float80e float128l float128h __FLOAT_DAZ__ __FLOAT_ROUND__ __FLOAT__"},c:[{cN:"comment",b:";",e:"$",r:0},{cN:"number",b:"\\b(?:([0-9][0-9_]*)?\\.[0-9_]*(?:[eE][+-]?[0-9_]+)?|(0[Xx])?[0-9][0-9_]*\\.?[0-9_]*(?:[pP](?:[+-]?[0-9_]+)?)?)\\b",r:0},{cN:"number",b:"\\$[0-9][0-9A-Fa-f]*",r:0},{cN:"number",b:"\\b(?:[0-9A-Fa-f][0-9A-Fa-f_]*[HhXx]|[0-9][0-9_]*[DdTt]?|[0-7][0-7_]*[QqOo]|[0-1][0-1_]*[BbYy])\\b"},{cN:"number",b:"\\b(?:0[HhXx][0-9A-Fa-f_]+|0[DdTt][0-9_]+|0[QqOo][0-7_]+|0[BbYy][0-1_]+)\\b"},a.QSM,{cN:"string",b:"'",e:"[^\\\\]'",r:0},{cN:"string",b:"`",e:"[^\\\\]`",r:0},{cN:"string",b:"\\.[A-Za-z0-9]+",r:0},{cN:"label",b:"^\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\s+label)",r:0},{cN:"label",b:"^\\s*%%[A-Za-z0-9_$#@~.?]*:",r:0},{cN:"argument",b:"%[0-9]+",r:0},{cN:"built_in",b:"%!S+",r:0}]}});
\ No newline at end of file
diff --git a/vendor/assets/javascripts/jquery.sticky-kit.min.js b/vendor/assets/javascripts/jquery.sticky-kit.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..e8bb207c5a5f096bafa3a694f88ae1ca1da6a839
--- /dev/null
+++ b/vendor/assets/javascripts/jquery.sticky-kit.min.js
@@ -0,0 +1,9 @@
+/*
+ Sticky-kit v1.1.1 | WTFPL | Leaf Corcoran 2014 | http://leafo.net
+*/
+(function(){var k,e;k=this.jQuery||window.jQuery;e=k(window);k.fn.stick_in_parent=function(d){var v,y,n,p,h,C,s,G,q,H;null==d&&(d={});s=d.sticky_class;y=d.inner_scrolling;C=d.recalc_every;h=d.parent;p=d.offset_top;n=d.spacer;v=d.bottoming;null==p&&(p=0);null==h&&(h=void 0);null==y&&(y=!0);null==s&&(s="is_stuck");null==v&&(v=!0);G=function(a,d,q,z,D,t,r,E){var u,F,m,A,c,f,B,w,x,g,b;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);f=a.parent();null!=h&&(f=f.closest(h));if(!f.length)throw"failed to find stick parent";
+u=m=!1;(g=null!=n?n&&a.closest(n):k("<div />"))&&g.css("position",a.css("position"));B=function(){var c,e,l;if(!E&&(c=parseInt(f.css("border-top-width"),10),e=parseInt(f.css("padding-top"),10),d=parseInt(f.css("padding-bottom"),10),q=f.offset().top+c+e,z=f.height(),m&&(u=m=!1,null==n&&(a.insertAfter(g),g.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(s),l=!0),D=a.offset().top-parseInt(a.css("margin-top"),10)-p,t=a.outerHeight(!0),r=a.css("float"),g&&g.css({width:a.outerWidth(!0),
+height:t,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),l))return b()};B();if(t!==z)return A=void 0,c=p,x=C,b=function(){var b,k,l,h;if(!E&&(null!=x&&(--x,0>=x&&(x=C,B())),l=e.scrollTop(),null!=A&&(k=l-A),A=l,m?(v&&(h=l+t+c>z+q,u&&!h&&(u=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),l<D&&(m=!1,c=p,null==n&&("left"!==r&&"right"!==r||a.insertAfter(g),g.detach()),b={position:"",width:"",top:""},a.css(b).removeClass(s).trigger("sticky_kit:unstick")),
+y&&(b=e.height(),t+p>b&&!u&&(c-=k,c=Math.max(b-t,c),c=Math.min(p,c),m&&a.css({top:c+"px"})))):l>D&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(s),null==n&&(a.after(g),"left"!==r&&"right"!==r||g.append(a)),a.trigger("sticky_kit:stick")),m&&v&&(null==h&&(h=l+t+c>z+q),!u&&h)))return u=!0,"static"===f.css("position")&&f.css({position:"relative"}),a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},
+w=function(){B();return b()},F=function(){E=!0;e.off("touchmove",b);e.off("scroll",b);e.off("resize",w);k(document.body).off("sticky_kit:recalc",w);a.off("sticky_kit:detach",F);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});f.position("position","");if(m)return null==n&&("left"!==r&&"right"!==r||a.insertAfter(g),g.remove()),a.removeClass(s)},e.on("touchmove",b),e.on("scroll",b),e.on("resize",w),k(document.body).on("sticky_kit:recalc",w),a.on("sticky_kit:detach",F),setTimeout(b,
+0)}};q=0;for(H=this.length;q<H;q++)d=this[q],G(k(d));return this}}).call(this);
diff --git a/vendor/assets/javascripts/pwstrength-bootstrap-1.2.2.js b/vendor/assets/javascripts/pwstrength-bootstrap-1.2.2.js
deleted file mode 100644
index ee374a07fab69a5e925e79c69029bf9d0f9c30c6..0000000000000000000000000000000000000000
--- a/vendor/assets/javascripts/pwstrength-bootstrap-1.2.2.js
+++ /dev/null
@@ -1,659 +0,0 @@
-/*!
- * jQuery Password Strength plugin for Twitter Bootstrap
- *
- * Copyright (c) 2008-2013 Tane Piper
- * Copyright (c) 2013 Alejandro Blanco
- * Dual licensed under the MIT and GPL licenses.
- */
-
-(function (jQuery) {
-// Source: src/rules.js
-
-  var rulesEngine = {};
-
-  try {
-    if (!jQuery && module && module.exports) {
-      var jQuery = require("jquery"),
-        jsdom = require("jsdom").jsdom;
-      jQuery = jQuery(jsdom().parentWindow);
-    }
-  } catch (ignore) {}
-
-  (function ($, rulesEngine) {
-    "use strict";
-    var validation = {};
-
-    rulesEngine.forbiddenSequences = [
-      "0123456789", "abcdefghijklmnopqrstuvwxyz", "qwertyuiop", "asdfghjkl",
-      "zxcvbnm", "!@#$%^&*()_+"
-    ];
-
-    validation.wordNotEmail = function (options, word, score) {
-      if (word.match(/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i)) {
-        return score;
-      }
-      return 0;
-    };
-
-    validation.wordLength = function (options, word, score) {
-      var wordlen = word.length,
-        lenScore = Math.pow(wordlen, options.rules.raisePower);
-      if (wordlen < options.common.minChar) {
-        lenScore = (lenScore + score);
-      }
-      return lenScore;
-    };
-
-    validation.wordSimilarToUsername = function (options, word, score) {
-      var username = $(options.common.usernameField).val();
-      if (username && word.toLowerCase().match(username.toLowerCase())) {
-        return score;
-      }
-      return 0;
-    };
-
-    validation.wordTwoCharacterClasses = function (options, word, score) {
-      if (word.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) ||
-        (word.match(/([a-zA-Z])/) && word.match(/([0-9])/)) ||
-        (word.match(/(.[!,@,#,$,%,\^,&,*,?,_,~])/) && word.match(/[a-zA-Z0-9_]/))) {
-        return score;
-      }
-      return 0;
-    };
-
-    validation.wordRepetitions = function (options, word, score) {
-      if (word.match(/(.)\1\1/)) { return score; }
-      return 0;
-    };
-
-    validation.wordSequences = function (options, word, score) {
-      var found = false,
-        j;
-      if (word.length > 2) {
-        $.each(rulesEngine.forbiddenSequences, function (idx, seq) {
-          var sequences = [seq, seq.split('').reverse().join('')];
-          $.each(sequences, function (idx, sequence) {
-            for (j = 0; j < (word.length - 2); j += 1) { // iterate the word trough a sliding window of size 3:
-              if (sequence.indexOf(word.toLowerCase().substring(j, j + 3)) > -1) {
-                found = true;
-              }
-            }
-          });
-        });
-        if (found) { return score; }
-      }
-      return 0;
-    };
-
-    validation.wordLowercase = function (options, word, score) {
-      return word.match(/[a-z]/) && score;
-    };
-
-    validation.wordUppercase = function (options, word, score) {
-      return word.match(/[A-Z]/) && score;
-    };
-
-    validation.wordOneNumber = function (options, word, score) {
-      return word.match(/\d+/) && score;
-    };
-
-    validation.wordThreeNumbers = function (options, word, score) {
-      return word.match(/(.*[0-9].*[0-9].*[0-9])/) && score;
-    };
-
-    validation.wordOneSpecialChar = function (options, word, score) {
-      return word.match(/.[!,@,#,$,%,\^,&,*,?,_,~]/) && score;
-    };
-
-    validation.wordTwoSpecialChar = function (options, word, score) {
-      return word.match(/(.*[!,@,#,$,%,\^,&,*,?,_,~].*[!,@,#,$,%,\^,&,*,?,_,~])/) && score;
-    };
-
-    validation.wordUpperLowerCombo = function (options, word, score) {
-      return word.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) && score;
-    };
-
-    validation.wordLetterNumberCombo = function (options, word, score) {
-      return word.match(/([a-zA-Z])/) && word.match(/([0-9])/) && score;
-    };
-
-    validation.wordLetterNumberCharCombo = function (options, word, score) {
-      return word.match(/([a-zA-Z0-9].*[!,@,#,$,%,\^,&,*,?,_,~])|([!,@,#,$,%,\^,&,*,?,_,~].*[a-zA-Z0-9])/) && score;
-    };
-
-    rulesEngine.validation = validation;
-
-    rulesEngine.executeRules = function (options, word) {
-      var totalScore = 0;
-
-      $.each(options.rules.activated, function (rule, active) {
-        if (active) {
-          var score = options.rules.scores[rule],
-            funct = rulesEngine.validation[rule],
-            result,
-            errorMessage;
-
-          if (!$.isFunction(funct)) {
-            funct = options.rules.extra[rule];
-          }
-
-          if ($.isFunction(funct)) {
-            result = funct(options, word, score);
-            if (result) {
-              totalScore += result;
-            }
-            if (result < 0 || (!$.isNumeric(result) && !result)) {
-              errorMessage = options.ui.spanError(options, rule);
-              if (errorMessage.length > 0) {
-                options.instances.errors.push(errorMessage);
-              }
-            }
-          }
-        }
-      });
-
-      return totalScore;
-    };
-  }(jQuery, rulesEngine));
-
-  try {
-    if (module && module.exports) {
-      module.exports = rulesEngine;
-    }
-  } catch (ignore) {}
-
-// Source: src/options.js
-
-
-
-
-  var defaultOptions = {};
-
-  defaultOptions.common = {};
-  defaultOptions.common.minChar = 6;
-  defaultOptions.common.usernameField = "#username";
-  defaultOptions.common.userInputs = [
-    // Selectors for input fields with user input
-  ];
-  defaultOptions.common.onLoad = undefined;
-  defaultOptions.common.onKeyUp = undefined;
-  defaultOptions.common.zxcvbn = false;
-  defaultOptions.common.debug = false;
-
-  defaultOptions.rules = {};
-  defaultOptions.rules.extra = {};
-  defaultOptions.rules.scores = {
-    wordNotEmail: -100,
-    wordLength: -50,
-    wordSimilarToUsername: -100,
-    wordSequences: -50,
-    wordTwoCharacterClasses: 2,
-    wordRepetitions: -25,
-    wordLowercase: 1,
-    wordUppercase: 3,
-    wordOneNumber: 3,
-    wordThreeNumbers: 5,
-    wordOneSpecialChar: 3,
-    wordTwoSpecialChar: 5,
-    wordUpperLowerCombo: 2,
-    wordLetterNumberCombo: 2,
-    wordLetterNumberCharCombo: 2
-  };
-  defaultOptions.rules.activated = {
-    wordNotEmail: true,
-    wordLength: true,
-    wordSimilarToUsername: true,
-    wordSequences: true,
-    wordTwoCharacterClasses: false,
-    wordRepetitions: false,
-    wordLowercase: true,
-    wordUppercase: true,
-    wordOneNumber: true,
-    wordThreeNumbers: true,
-    wordOneSpecialChar: true,
-    wordTwoSpecialChar: true,
-    wordUpperLowerCombo: true,
-    wordLetterNumberCombo: true,
-    wordLetterNumberCharCombo: true
-  };
-  defaultOptions.rules.raisePower = 1.4;
-
-  defaultOptions.ui = {};
-  defaultOptions.ui.bootstrap2 = false;
-  defaultOptions.ui.showProgressBar = true;
-  defaultOptions.ui.showPopover = false;
-  defaultOptions.ui.showStatus = false;
-  defaultOptions.ui.spanError = function (options, key) {
-    "use strict";
-    var text = options.ui.errorMessages[key];
-    if (!text) { return ''; }
-    return '<span style="color: #d52929">' + text + '</span>';
-  };
-  defaultOptions.ui.errorMessages = {
-    wordLength: "Your password is too short",
-    wordNotEmail: "Do not use your email as your password",
-    wordSimilarToUsername: "Your password cannot contain your username",
-    wordTwoCharacterClasses: "Use different character classes",
-    wordRepetitions: "Too many repetitions",
-    wordSequences: "Your password contains sequences"
-  };
-  defaultOptions.ui.verdicts = ["Weak", "Normal", "Medium", "Strong", "Very Strong"];
-  defaultOptions.ui.showVerdicts = true;
-  defaultOptions.ui.showVerdictsInsideProgressBar = false;
-  defaultOptions.ui.showErrors = false;
-  defaultOptions.ui.container = undefined;
-  defaultOptions.ui.viewports = {
-    progress: undefined,
-    verdict: undefined,
-    errors: undefined
-  };
-  defaultOptions.ui.scores = [14, 26, 38, 50];
-
-// Source: src/ui.js
-
-
-
-
-  var ui = {};
-
-  (function ($, ui) {
-    "use strict";
-
-    var barClasses = ["danger", "warning", "success"],
-      statusClasses = ["error", "warning", "success"];
-
-    ui.getContainer = function (options, $el) {
-      var $container;
-
-      $container = $(options.ui.container);
-      if (!($container && $container.length === 1)) {
-        $container = $el.parent();
-      }
-      return $container;
-    };
-
-    ui.findElement = function ($container, viewport, cssSelector) {
-      if (viewport) {
-        return $container.find(viewport).find(cssSelector);
-      }
-      return $container.find(cssSelector);
-    };
-
-    ui.getUIElements = function (options, $el) {
-      var $container, result;
-
-      if (options.instances.viewports) {
-        return options.instances.viewports;
-      }
-
-      $container = ui.getContainer(options, $el);
-
-      result = {};
-      result.$progressbar = ui.findElement($container, options.ui.viewports.progress, "div.progress");
-      if (options.ui.showVerdictsInsideProgressBar) {
-        result.$verdict = result.$progressbar.find("span.password-verdict");
-      }
-
-      if (!options.ui.showPopover) {
-        if (!options.ui.showVerdictsInsideProgressBar) {
-          result.$verdict = ui.findElement($container, options.ui.viewports.verdict, "span.password-verdict");
-        }
-        result.$errors = ui.findElement($container, options.ui.viewports.errors, "ul.error-list");
-      }
-
-      options.instances.viewports = result;
-      return result;
-    };
-
-    ui.initProgressBar = function (options, $el) {
-      var $container = ui.getContainer(options, $el),
-        progressbar = "<div class='progress'><div class='";
-
-      if (!options.ui.bootstrap2) {
-        progressbar += "progress-";
-      }
-      progressbar += "bar'>";
-      if (options.ui.showVerdictsInsideProgressBar) {
-        progressbar += "<span class='password-verdict'></span>";
-      }
-      progressbar += "</div></div>";
-
-      if (options.ui.viewports.progress) {
-        $container.find(options.ui.viewports.progress).append(progressbar);
-      } else {
-        $(progressbar).insertAfter($el);
-      }
-    };
-
-    ui.initHelper = function (options, $el, html, viewport) {
-      var $container = ui.getContainer(options, $el);
-      if (viewport) {
-        $container.find(viewport).append(html);
-      } else {
-        $(html).insertAfter($el);
-      }
-    };
-
-    ui.initVerdict = function (options, $el) {
-      ui.initHelper(options, $el, "<span class='password-verdict'></span>",
-        options.ui.viewports.verdict);
-    };
-
-    ui.initErrorList = function (options, $el) {
-      ui.initHelper(options, $el, "<ul class='error-list'></ul>",
-        options.ui.viewports.errors);
-    };
-
-    ui.initPopover = function (options, $el) {
-      $el.popover("destroy");
-      $el.popover({
-        html: true,
-        placement: "top",
-        trigger: "manual",
-        content: " "
-      });
-    };
-
-    ui.initUI = function (options, $el) {
-      if (options.ui.showPopover) {
-        ui.initPopover(options, $el);
-      } else {
-        if (options.ui.showErrors) { ui.initErrorList(options, $el); }
-        if (options.ui.showVerdicts && !options.ui.showVerdictsInsideProgressBar) {
-          ui.initVerdict(options, $el);
-        }
-      }
-      if (options.ui.showProgressBar) {
-        ui.initProgressBar(options, $el);
-      }
-    };
-
-    ui.possibleProgressBarClasses = ["danger", "warning", "success"];
-
-    ui.updateProgressBar = function (options, $el, cssClass, percentage) {
-      var $progressbar = ui.getUIElements(options, $el).$progressbar,
-        $bar = $progressbar.find(".progress-bar"),
-        cssPrefix = "progress-";
-
-      if (options.ui.bootstrap2) {
-        $bar = $progressbar.find(".bar");
-        cssPrefix = "";
-      }
-
-      $.each(ui.possibleProgressBarClasses, function (idx, value) {
-        $bar.removeClass(cssPrefix + "bar-" + value);
-      });
-      $bar.addClass(cssPrefix + "bar-" + barClasses[cssClass]);
-      $bar.css("width", percentage + '%');
-    };
-
-    ui.updateVerdict = function (options, $el, text) {
-      var $verdict = ui.getUIElements(options, $el).$verdict;
-      $verdict.text(text);
-    };
-
-    ui.updateErrors = function (options, $el) {
-      var $errors = ui.getUIElements(options, $el).$errors,
-        html = "";
-      $.each(options.instances.errors, function (idx, err) {
-        html += "<li>" + err + "</li>";
-      });
-      $errors.html(html);
-    };
-
-    ui.updatePopover = function (options, $el, verdictText) {
-      var popover = $el.data("bs.popover"),
-        html = "",
-        hide = true;
-
-      if (options.ui.showVerdicts &&
-        !options.ui.showVerdictsInsideProgressBar &&
-        verdictText.length > 0) {
-        html = "<h5><span class='password-verdict'>" + verdictText +
-          "</span></h5>";
-        hide = false;
-      }
-      if (options.ui.showErrors) {
-        html += "<div><ul class='error-list' style='margin-bottom: 0; margin-left: -20px'>";
-        $.each(options.instances.errors, function (idx, err) {
-          html += "<li>" + err + "</li>";
-          hide = false;
-        });
-        html += "</ul></div>";
-      }
-
-      if (hide) {
-        $el.popover("hide");
-        return;
-      }
-
-      if (options.ui.bootstrap2) { popover = $el.data("popover"); }
-
-      if (popover.$arrow && popover.$arrow.parents("body").length > 0) {
-        $el.find("+ .popover .popover-content").html(html);
-      } else {
-        // It's hidden
-        popover.options.content = html;
-        $el.popover("show");
-      }
-    };
-
-    ui.updateFieldStatus = function (options, $el, cssClass) {
-      var targetClass = options.ui.bootstrap2 ? ".control-group" : ".form-group",
-        $container = $el.parents(targetClass).first();
-
-      $.each(statusClasses, function (idx, css) {
-        if (!options.ui.bootstrap2) { css = "has-" + css; }
-        $container.removeClass(css);
-      });
-
-      cssClass = statusClasses[cssClass];
-      if (!options.ui.bootstrap2) { cssClass = "has-" + cssClass; }
-      $container.addClass(cssClass);
-    };
-
-    ui.percentage = function (score, maximun) {
-      var result = Math.floor(100 * score / maximun);
-      result = result < 0 ? 0 : result;
-      result = result > 100 ? 100 : result;
-      return result;
-    };
-
-    ui.getVerdictAndCssClass = function (options, score) {
-      var cssClass, verdictText, level;
-
-      if (score <= 0) {
-        cssClass = 0;
-        level = -1;
-        verdictText = options.ui.verdicts[0];
-      } else if (score < options.ui.scores[0]) {
-        cssClass = 0;
-        level = 0;
-        verdictText = options.ui.verdicts[0];
-      } else if (score < options.ui.scores[1]) {
-        cssClass = 0;
-        level = 1;
-        verdictText = options.ui.verdicts[1];
-      } else if (score < options.ui.scores[2]) {
-        cssClass = 1;
-        level = 2;
-        verdictText = options.ui.verdicts[2];
-      } else if (score < options.ui.scores[3]) {
-        cssClass = 1;
-        level = 3;
-        verdictText = options.ui.verdicts[3];
-      } else {
-        cssClass = 2;
-        level = 4;
-        verdictText = options.ui.verdicts[4];
-      }
-
-      return [verdictText, cssClass, level];
-    };
-
-    ui.updateUI = function (options, $el, score) {
-      var cssClass, barPercentage, verdictText;
-
-      cssClass = ui.getVerdictAndCssClass(options, score);
-      verdictText = cssClass[0];
-      cssClass = cssClass[1];
-
-      if (options.ui.showProgressBar) {
-        barPercentage = ui.percentage(score, options.ui.scores[3]);
-        ui.updateProgressBar(options, $el, cssClass, barPercentage);
-        if (options.ui.showVerdictsInsideProgressBar) {
-          ui.updateVerdict(options, $el, verdictText);
-        }
-      }
-
-      if (options.ui.showStatus) {
-        ui.updateFieldStatus(options, $el, cssClass);
-      }
-
-      if (options.ui.showPopover) {
-        ui.updatePopover(options, $el, verdictText);
-      } else {
-        if (options.ui.showVerdicts && !options.ui.showVerdictsInsideProgressBar) {
-          ui.updateVerdict(options, $el, verdictText);
-        }
-        if (options.ui.showErrors) {
-          ui.updateErrors(options, $el);
-        }
-      }
-    };
-  }(jQuery, ui));
-
-// Source: src/methods.js
-
-
-
-
-  var methods = {};
-
-  (function ($, methods) {
-    "use strict";
-    var onKeyUp, applyToAll;
-
-    onKeyUp = function (event) {
-      var $el = $(event.target),
-        options = $el.data("pwstrength-bootstrap"),
-        word = $el.val(),
-        userInputs,
-        verdictText,
-        verdictLevel,
-        score;
-
-      if (options === undefined) { return; }
-
-      options.instances.errors = [];
-      if (options.common.zxcvbn) {
-        userInputs = [];
-        $.each(options.common.userInputs, function (idx, selector) {
-          userInputs.push($(selector).val());
-        });
-        userInputs.push($(options.common.usernameField).val());
-        score = zxcvbn(word, userInputs).entropy;
-      } else {
-        score = rulesEngine.executeRules(options, word);
-      }
-      ui.updateUI(options, $el, score);
-      verdictText = ui.getVerdictAndCssClass(options, score);
-      verdictLevel = verdictText[2];
-      verdictText = verdictText[0];
-
-      if (options.common.debug) { console.log(score + ' - ' + verdictText); }
-
-      if ($.isFunction(options.common.onKeyUp)) {
-        options.common.onKeyUp(event, {
-          score: score,
-          verdictText: verdictText,
-          verdictLevel: verdictLevel
-        });
-      }
-    };
-
-    methods.init = function (settings) {
-      this.each(function (idx, el) {
-        // Make it deep extend (first param) so it extends too the
-        // rules and other inside objects
-        var clonedDefaults = $.extend(true, {}, defaultOptions),
-          localOptions = $.extend(true, clonedDefaults, settings),
-          $el = $(el);
-
-        localOptions.instances = {};
-        $el.data("pwstrength-bootstrap", localOptions);
-        $el.on("keyup", onKeyUp);
-        $el.on("change", onKeyUp);
-        $el.on("onpaste", onKeyUp);
-
-        ui.initUI(localOptions, $el);
-        if ($.trim($el.val())) { // Not empty, calculate the strength
-          $el.trigger("keyup");
-        }
-
-        if ($.isFunction(localOptions.common.onLoad)) {
-          localOptions.common.onLoad();
-        }
-      });
-
-      return this;
-    };
-
-    methods.destroy = function () {
-      this.each(function (idx, el) {
-        var $el = $(el),
-          options = $el.data("pwstrength-bootstrap"),
-          elements = ui.getUIElements(options, $el);
-        elements.$progressbar.remove();
-        elements.$verdict.remove();
-        elements.$errors.remove();
-        $el.removeData("pwstrength-bootstrap");
-      });
-    };
-
-    methods.forceUpdate = function () {
-      this.each(function (idx, el) {
-        var event = { target: el };
-        onKeyUp(event);
-      });
-    };
-
-    methods.addRule = function (name, method, score, active) {
-      this.each(function (idx, el) {
-        var options = $(el).data("pwstrength-bootstrap");
-
-        options.rules.activated[name] = active;
-        options.rules.scores[name] = score;
-        options.rules.extra[name] = method;
-      });
-    };
-
-    applyToAll = function (rule, prop, value) {
-      this.each(function (idx, el) {
-        $(el).data("pwstrength-bootstrap").rules[prop][rule] = value;
-      });
-    };
-
-    methods.changeScore = function (rule, score) {
-      applyToAll.call(this, rule, "scores", score);
-    };
-
-    methods.ruleActive = function (rule, active) {
-      applyToAll.call(this, rule, "activated", active);
-    };
-
-    $.fn.pwstrength = function (method) {
-      var result;
-
-      if (methods[method]) {
-        result = methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
-      } else if (typeof method === "object" || !method) {
-        result = methods.init.apply(this, arguments);
-      } else {
-        $.error("Method " +  method + " does not exist on jQuery.pwstrength-bootstrap");
-      }
-
-      return result;
-    };
-  }(jQuery, methods));
-}(jQuery));
\ No newline at end of file
diff --git a/vendor/assets/stylesheets/highlightjs.min.css b/vendor/assets/stylesheets/highlightjs.min.css
deleted file mode 100644
index f2429be6228c35364f067f72a05260aec642c93c..0000000000000000000000000000000000000000
--- a/vendor/assets/stylesheets/highlightjs.min.css
+++ /dev/null
@@ -1 +0,0 @@
-.hljs{display:block;padding:.5em;background:#f0f0f0}.hljs,.hljs-subst,.hljs-tag .hljs-title,.lisp .hljs-title,.clojure .hljs-built_in,.nginx .hljs-title{color:black}.hljs-string,.hljs-title,.hljs-constant,.hljs-parent,.hljs-tag .hljs-value,.hljs-rules .hljs-value,.hljs-rules .hljs-value .hljs-number,.hljs-preprocessor,.hljs-pragma,.haml .hljs-symbol,.ruby .hljs-symbol,.ruby .hljs-symbol .hljs-string,.hljs-aggregate,.hljs-template_tag,.django .hljs-variable,.smalltalk .hljs-class,.hljs-addition,.hljs-flow,.hljs-stream,.bash .hljs-variable,.apache .hljs-tag,.apache .hljs-cbracket,.tex .hljs-command,.tex .hljs-special,.erlang_repl .hljs-function_or_atom,.asciidoc .hljs-header,.markdown .hljs-header,.coffeescript .hljs-attribute{color:#800}.smartquote,.hljs-comment,.hljs-annotation,.hljs-template_comment,.diff .hljs-header,.hljs-chunk,.asciidoc .hljs-blockquote,.markdown .hljs-blockquote{color:#888}.hljs-number,.hljs-date,.hljs-regexp,.hljs-literal,.hljs-hexcolor,.smalltalk .hljs-symbol,.smalltalk .hljs-char,.go .hljs-constant,.hljs-change,.lasso .hljs-variable,.makefile .hljs-variable,.asciidoc .hljs-bullet,.markdown .hljs-bullet,.asciidoc .hljs-link_url,.markdown .hljs-link_url{color:#080}.hljs-label,.hljs-javadoc,.ruby .hljs-string,.hljs-decorator,.hljs-filter .hljs-argument,.hljs-localvars,.hljs-array,.hljs-attr_selector,.hljs-important,.hljs-pseudo,.hljs-pi,.haml .hljs-bullet,.hljs-doctype,.hljs-deletion,.hljs-envvar,.hljs-shebang,.apache .hljs-sqbracket,.nginx .hljs-built_in,.tex .hljs-formula,.erlang_repl .hljs-reserved,.hljs-prompt,.asciidoc .hljs-link_label,.markdown .hljs-link_label,.vhdl .hljs-attribute,.clojure .hljs-attribute,.asciidoc .hljs-attribute,.lasso .hljs-attribute,.coffeescript .hljs-property,.hljs-phony{color:#88F}.hljs-keyword,.hljs-id,.hljs-title,.hljs-built_in,.hljs-aggregate,.css .hljs-tag,.hljs-javadoctag,.hljs-phpdoc,.hljs-yardoctag,.smalltalk .hljs-class,.hljs-winutils,.bash .hljs-variable,.apache .hljs-tag,.go .hljs-typename,.tex .hljs-command,.asciidoc .hljs-strong,.markdown .hljs-strong,.hljs-request,.hljs-status{font-weight:bold}.asciidoc .hljs-emphasis,.markdown .hljs-emphasis{font-style:italic}.nginx .hljs-built_in{font-weight:normal}.coffeescript .javascript,.javascript .xml,.lasso .markup,.tex .hljs-formula,.xml .javascript,.xml .vbscript,.xml .css,.xml .hljs-cdata{opacity:.5}
\ No newline at end of file
diff --git a/vendor/plugins/.gitkeep b/vendor/plugins/.gitkeep
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000