Commit 6234b327 authored by Lin Jen-Shin's avatar Lin Jen-Shin

Merge remote-tracking branch 'upstream/master' into artifacts-from-ref-and-build-name

* upstream/master: (516 commits)
  Rename `run` task helper method to prevent conflict with StateMachine
  Add a method in Project to return a cached value of total count of projects
  Add Changelog entry for Grape upgrade [ci skip]
  Fix Grape tests.
  Retain old behavior
  Update Grape from 0.13.0 to 0.15.0.
  adds second batch of tests changed to active tense
  fixes part1 of files to start using active tense
  Clarify the features for generating default label sets
  Update tree view to sort folders with submodules
  Memoize CI config node validator to prevent leaks
  fix MR source project assignment
  remove offending empty line
  Rails prefers require_dependency so that it won't require twice:
  use Unix line endings for API documentation
  use long options for curl examples in API documentation (!5703)
  Prefixes removed branches name with PR number when importing PR from GH
  Update CHANGELOG
  Remove SHA suffix for removed branches name when importing PR from GH
  add linting script for documentation
  ...
parents 80c22e4c 9db46cc8
CHANGELOG merge=union
\ No newline at end of file
CHANGELOG merge=union
*.js.es6 gitlab-language=javascript
......@@ -30,6 +30,7 @@
/config/secrets.yml
/config/sidekiq.yml
/coverage/*
/coverage-javascript/
/db/*.sqlite3
/db/*.sqlite3-journal
/db/data.yml
......
......@@ -28,6 +28,7 @@ stages:
- prepare
- test
- post-test
- pages
# Prepare and merge knapsack tests
.knapsack-state: &knapsack-state
......@@ -40,6 +41,7 @@ stages:
paths:
- knapsack/
artifacts:
expire_in: 31d
paths:
- knapsack/
......@@ -81,8 +83,10 @@ update-knapsack:
- cp knapsack/rspec_report.json ${KNAPSACK_REPORT_PATH}
- knapsack rspec
artifacts:
expire_in: 31d
paths:
- knapsack/
- coverage/
.spinach-knapsack: &spinach-knapsack
stage: test
......@@ -97,8 +101,10 @@ update-knapsack:
- cp knapsack/spinach_report.json ${KNAPSACK_REPORT_PATH}
- knapsack spinach "-r rerun" || retry '[ ! -e tmp/spinach-rerun.txt ] || bundle exec spinach -r rerun $(cat tmp/spinach-rerun.txt)'
artifacts:
expire_in: 31d
paths:
- knapsack/
- coverage/
rspec 0 20: *rspec-knapsack
rspec 1 20: *rspec-knapsack
......@@ -186,14 +192,14 @@ spinach 9 10 ruby23: *spinach-knapsack-ruby23
# Other generic tests
.static-analyses-variables: &static-analyses-variables
.ruby-static-analysis: &ruby-static-analysis
variables:
SIMPLECOV: "false"
USE_DB: "false"
USE_BUNDLE_INSTALL: "true"
.exec: &exec
<<: *static-analyses-variables
<<: *ruby-static-analysis
stage: test
script:
- bundle exec $CI_BUILD_NAME
......@@ -216,20 +222,54 @@ teaspoon:
stage: test
<<: *use-db
script:
- curl --silent --location https://deb.nodesource.com/setup_6.x | bash -
- apt-get install --assume-yes nodejs
- npm install --global istanbul
- teaspoon
artifacts:
name: coverage-javascript
expire_in: 31d
paths:
- coverage-javascript/default/
lint-doc:
stage: test
image: "phusion/baseimage:latest"
before_script: []
script:
- scripts/lint-doc.sh
bundler:audit:
stage: test
<<: *static-analyses-variables
<<: *ruby-static-analysis
only:
- master
script:
- "bundle exec bundle-audit check --update --ignore OSVDB-115941"
coverage:
stage: post-test
services: []
variables:
USE_DB: "false"
USE_BUNDLE_INSTALL: "true"
script:
- bundle exec scripts/merge-simplecov
artifacts:
name: coverage
expire_in: 31d
paths:
- coverage/index.html
- coverage/assets/
# Notify slack in the end
notify:slack:
stage: post-test
variables:
USE_DB: "false"
USE_BUNDLE_INSTALL: "false"
script:
- ./scripts/notify_slack.sh "#builds" "Build on \`$CI_BUILD_REF_NAME\` failed! Commit \`$(git log -1 --oneline)\` See <https://gitlab.com/gitlab-org/$(basename "$PWD")/commit/"$CI_BUILD_REF"/builds>"
when: on_failure
......@@ -238,3 +278,20 @@ notify:slack:
- tags@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
- tags@gitlab-org/gitlab-ee
pages:
before_script: []
stage: pages
dependencies:
- coverage
- teaspoon
script:
- mv public/ .public/
- mkdir public/
- mv coverage public/coverage-ruby
- mv coverage-javascript/default/ public/coverage-javascript/
artifacts:
paths:
- public
only:
- master
......@@ -149,19 +149,19 @@ Style/EmptyLinesAroundAccessModifier:
# Keeps track of empty lines around block bodies.
Style/EmptyLinesAroundBlockBody:
Enabled: false
Enabled: true
# Keeps track of empty lines around class bodies.
Style/EmptyLinesAroundClassBody:
Enabled: false
Enabled: true
# Keeps track of empty lines around module bodies.
Style/EmptyLinesAroundModuleBody:
Enabled: false
Enabled: true
# Keeps track of empty lines around method bodies.
Style/EmptyLinesAroundMethodBody:
Enabled: false
Enabled: true
# Avoid the use of END blocks.
Style/EndBlock:
......@@ -373,6 +373,10 @@ Style/SpaceAfterNot:
Style/SpaceAfterSemicolon:
Enabled: true
# Use space around equals in parameter default
Style/SpaceAroundEqualsInParameterDefault:
Enabled: true
# Use a space around keywords if appropriate.
Style/SpaceAroundKeyword:
Enabled: true
......@@ -510,6 +514,15 @@ Metrics/PerceivedComplexity:
#################### Lint ################################
# Checks for useless access modifiers.
Lint/UselessAccessModifier:
Enabled: true
# Checks for attempts to use `private` or `protected` to set the visibility
# of a class method, which does not work.
Lint/IneffectiveAccessModifier:
Enabled: false
# Checks for ambiguous operators in the first argument of a method invocation
# without parentheses.
Lint/AmbiguousOperator:
......
......@@ -19,10 +19,6 @@ Lint/AssignmentInCondition:
Lint/HandleExceptions:
Enabled: false
# Offense count: 21
Lint/IneffectiveAccessModifier:
Enabled: false
# Offense count: 2
Lint/Loop:
Enabled: false
......@@ -48,10 +44,6 @@ Lint/UnusedBlockArgument:
Lint/UnusedMethodArgument:
Enabled: false
# Offense count: 11
Lint/UselessAccessModifier:
Enabled: false
# Offense count: 12
# Cop supports --auto-correct.
Performance/PushSplat:
......@@ -347,13 +339,6 @@ Style/SingleLineBlockParams:
Style/SingleLineMethods:
Enabled: false
# Offense count: 14
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: space, no_space
Style/SpaceAroundEqualsInParameterDefault:
Enabled: false
# Offense count: 119
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
......
# .simplecov
SimpleCov.start 'rails' do
merge_timeout 3600
end
This diff is collapsed.
......@@ -41,6 +41,8 @@ abbreviation.
If you have read this guide and want to know how the GitLab [core team]
operates please see [the GitLab contributing process](PROCESS.md).
- [GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
## Contributor license agreement
By submitting code as an individual you agree to the
......@@ -334,6 +336,10 @@ request is as follows:
1. If your code creates new files on disk please read the
[shared files guidelines](doc/development/shared_files.md).
1. When writing commit messages please follow [these](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) [guidelines](http://chris.beams.io/posts/git-commit/).
1. If your merge request adds one or more migrations, make sure to execute all
migrations on a fresh database before the MR is reviewed. If the review leads
to large changes in the MR, do this again once the review is complete.
1. For more complex migrations, write tests.
The **official merge window** is in the beginning of the month from the 1st to
the 7th day of the month. This is the best time to submit an MR and get
......@@ -459,8 +465,10 @@ merge request:
- multi-line method chaining style **Option B**: dot `.` on previous line
- string literal quoting style **Option A**: single quoted by default
1. [Rails](https://github.com/bbatsov/rails-style-guide)
1. [Newlines styleguide][newlines-styleguide]
1. [Testing](doc/development/testing.md)
1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style/coffeescript)
1. [JavaScript (ES6)](https://github.com/airbnb/javascript)
1. [JavaScript (ES5)](https://github.com/airbnb/javascript/tree/master/es5)
1. [SCSS styleguide][scss-styleguide]
1. [Shell commands](doc/development/shell_commands.md) created by GitLab
contributors to enhance security
......@@ -530,6 +538,7 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
[doc-styleguide]: doc/development/doc_styleguide.md "Documentation styleguide"
[scss-styleguide]: doc/development/scss_styleguide.md "SCSS styleguide"
[newlines-styleguide]: doc/development/newlines_styleguide.md "Newlines styleguide"
[gitlab-design]: https://gitlab.com/gitlab-org/gitlab-design
[free Antetype viewer (Mac OSX only)]: https://itunes.apple.com/us/app/antetype-viewer/id824152298?mt=12
[`gitlab8.atype` file]: https://gitlab.com/gitlab-org/gitlab-design/tree/master/current/
......
......@@ -9,6 +9,7 @@ gem 'responders', '~> 2.0'
# Specify a sprockets version due to increased performance
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/6069
gem 'sprockets', '~> 3.6.0'
gem 'sprockets-es6'
# Default values for AR models
gem 'default_value_for', '~> 3.0.0'
......@@ -52,7 +53,7 @@ gem 'browser', '~> 2.2'
# Extracting information from a git repository
# Provide access to Gitlab::Git library
gem 'gitlab_git', '~> 10.3.2'
gem 'gitlab_git', '~> 10.4.5'
# LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes
......@@ -68,7 +69,7 @@ gem 'gollum-rugged_adapter', '~> 0.4.2', require: false
gem 'github-linguist', '~> 4.7.0', require: 'linguist'
# API
gem 'grape', '~> 0.13.0'
gem 'grape', '~> 0.15.0'
gem 'grape-entity', '~> 0.4.2'
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
......@@ -153,7 +154,7 @@ gem 'settingslogic', '~> 2.0.9'
# Misc
gem 'version_sorter', '~> 2.0.0'
gem 'version_sorter', '~> 2.1.0'
# Cache
gem 'redis-rails', '~> 4.0.0'
......@@ -224,7 +225,7 @@ gem 'addressable', '~> 2.3.8'
gem 'bootstrap-sass', '~> 3.3.0'
gem 'font-awesome-rails', '~> 4.6.1'
gem 'gemojione', '~> 3.0'
gem 'gon', '~> 6.0.1'
gem 'gon', '~> 6.1.0'
gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 4.1.0'
gem 'jquery-ui-rails', '~> 5.0.0'
......@@ -252,7 +253,7 @@ group :development do
gem 'letter_opener_web', '~> 1.3.0'
gem 'rerun', '~> 0.11.0'
gem 'bullet', '~> 5.0.0', require: false
gem 'bullet', '~> 5.2.0', require: false
gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false
gem 'web-console', '~> 2.0'
......@@ -274,7 +275,7 @@ group :development, :test do
gem 'awesome_print', '~> 1.2.0', require: false
gem 'fuubar', '~> 2.0.0'
gem 'database_cleaner', '~> 1.4.0'
gem 'database_cleaner', '~> 1.5.0'
gem 'factory_girl_rails', '~> 4.6.0'
gem 'rspec-rails', '~> 3.5.0'
gem 'rspec-retry', '~> 0.4.5'
......@@ -302,7 +303,7 @@ group :development, :test do
gem 'rubocop', '~> 0.41.2', require: false
gem 'rubocop-rspec', '~> 1.5.0', require: false
gem 'scss_lint', '~> 0.47.0', require: false
gem 'simplecov', '~> 0.11.0', require: false
gem 'simplecov', '0.12.0', require: false
gem 'flog', '~> 4.3.2', require: false
gem 'flay', '~> 2.6.1', require: false
gem 'bundler-audit', '~> 0.5.0', require: false
......@@ -325,7 +326,7 @@ group :production do
gem 'gitlab_meta', '7.0'
end
gem 'newrelic_rpm', '~> 3.14'
gem 'newrelic_rpm', '~> 3.16'
gem 'octokit', '~> 4.3.0'
......@@ -333,6 +334,8 @@ gem 'mail_room', '~> 0.8'
gem 'email_reply_parser', '~> 0.5.8'
gem 'ruby-prof', '~> 0.15.9'
## CI
gem 'activerecord-session_store', '~> 1.0.0'
gem 'nested_form', '~> 0.3.2'
......
......@@ -59,7 +59,7 @@ GEM
oauth2 (~> 1.0)
asciidoctor (1.5.3)
ast (2.3.0)
attr_encrypted (3.0.1)
attr_encrypted (3.0.3)
encryptor (~> 3.0.0)
attr_required (1.0.0)
autoprefixer-rails (6.2.3)
......@@ -85,6 +85,10 @@ GEM
faraday (~> 0.9)
faraday_middleware (~> 0.10)
nokogiri (~> 1.6)
babel-source (5.8.35)
babel-transpiler (0.7.0)
babel-source (>= 4.0, < 6)
execjs (~> 2.0)
babosa (1.0.2)
base32 (0.3.2)
bcrypt (3.1.11)
......@@ -100,9 +104,9 @@ GEM
brakeman (3.3.2)
browser (2.2.0)
builder (3.2.2)
bullet (5.0.0)
bullet (5.2.0)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.9.0)
uniform_notifier (~> 1.10.0)
bundler-audit (0.5.0)
bundler (~> 1.2)
thor (~> 0.18)
......@@ -149,11 +153,11 @@ GEM
d3_rails (3.5.11)
railties (>= 3.1.0)
daemons (1.2.3)
database_cleaner (1.4.1)
database_cleaner (1.5.3)
debug_inspector (0.0.2)
debugger-ruby_core_source (1.3.8)
default_value_for (3.0.1)
activerecord (>= 3.2.0, < 5.0)
default_value_for (3.0.2)
activerecord (>= 3.2.0, < 5.1)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
devise (4.1.1)
......@@ -274,7 +278,7 @@ GEM
diff-lcs (~> 1.1)
mime-types (>= 1.16, < 3)
posix-spawn (~> 0.3)
gitlab_git (10.3.2)
gitlab_git (10.4.5)
activesupport (~> 4.0)
charlock_holmes (~> 0.7.3)
github-linguist (~> 4.7.0)
......@@ -299,12 +303,12 @@ GEM
gollum-rugged_adapter (0.4.2)
mime-types (>= 1.15)
rugged (~> 0.24.0, >= 0.21.3)
gon (6.0.1)
gon (6.1.0)
actionpack (>= 3.0)
json
multi_json
request_store (>= 1.0)
grape (0.13.0)
grape (0.15.0)
activesupport
builder
hashie (>= 2.1.0)
......@@ -400,7 +404,7 @@ GEM
nested_form (0.3.2)
net-ldap (0.12.1)
net-ssh (3.0.1)
newrelic_rpm (3.14.1.311)
newrelic_rpm (3.16.0.318)
nokogiri (1.6.8)
mini_portile2 (~> 2.1.0)
pkg-config (~> 1.1.7)
......@@ -505,7 +509,7 @@ GEM
rack-cors (0.4.0)
rack-mount (0.8.3)
rack (>= 1.0.0)
rack-oauth2 (1.2.1)
rack-oauth2 (1.2.3)
activesupport (>= 2.3)
attr_required (>= 0.0.5)
httpclient (>= 2.4)
......@@ -571,7 +575,7 @@ GEM
redis-store (~> 1.1.0)
redis-store (1.1.7)
redis (>= 2.2)
request_store (1.3.0)
request_store (1.3.1)
rerun (0.11.0)
listen (~> 3.0)
responders (2.1.1)
......@@ -616,6 +620,7 @@ GEM
rubocop (>= 0.40.0)
ruby-fogbugz (0.2.1)
crack (~> 0.4)
ruby-prof (0.15.9)
ruby-progressbar (1.8.1)
ruby-saml (1.3.0)
nokogiri (>= 1.5.10)
......@@ -668,9 +673,9 @@ GEM
rufus-scheduler (>= 2.0.24)
sidekiq (>= 4.0.0)
simple_oauth (0.1.9)
simplecov (0.11.2)
simplecov (0.12.0)
docile (~> 1.1.0)
json (~> 1.8)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
sinatra (1.4.7)
......@@ -700,6 +705,10 @@ GEM
sprockets (3.6.3)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-es6 (0.9.0)
babel-source (>= 5.8.11)
babel-transpiler
sprockets (>= 3.0.0)
sprockets-rails (3.1.1)
actionpack (>= 4.0)
activesupport (>= 4.0)
......@@ -766,10 +775,10 @@ GEM
unicorn-worker-killer (0.4.4)
get_process_mem (~> 0)
unicorn (>= 4, < 6)
uniform_notifier (1.9.0)
uniform_notifier (1.10.0)
uuid (2.3.8)
macaddr (~> 1.0)
version_sorter (2.0.0)
version_sorter (2.1.0)
virtus (1.0.5)
axiom-types (~> 0.1)
coercible (~> 1.0)
......@@ -821,7 +830,7 @@ DEPENDENCIES
bootstrap-sass (~> 3.3.0)
brakeman (~> 3.3.0)
browser (~> 2.2)
bullet (~> 5.0.0)
bullet (~> 5.2.0)
bundler-audit (~> 0.5.0)
byebug (~> 8.2.1)
capybara (~> 2.6.2)
......@@ -833,7 +842,7 @@ DEPENDENCIES
connection_pool (~> 2.0)
creole (~> 0.5.0)
d3_rails (~> 3.5.0)
database_cleaner (~> 1.4.0)
database_cleaner (~> 1.5.0)
default_value_for (~> 3.0.0)
devise (~> 4.0)
devise-two-factor (~> 3.0.0)
......@@ -861,13 +870,13 @@ DEPENDENCIES
github-linguist (~> 4.7.0)
github-markup (~> 1.4)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab_git (~> 10.3.2)
gitlab_git (~> 10.4.5)
gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.2)
gollum-rugged_adapter (~> 0.4.2)
gon (~> 6.0.1)
grape (~> 0.13.0)
gon (~> 6.1.0)
grape (~> 0.15.0)
grape-entity (~> 0.4.2)
hamlit (~> 2.5)
health_check (~> 2.1.0)
......@@ -893,7 +902,7 @@ DEPENDENCIES
mysql2 (~> 0.3.16)
nested_form (~> 0.3.2)
net-ssh (~> 3.0.1)
newrelic_rpm (~> 3.14)
newrelic_rpm (~> 3.16)
nokogiri (~> 1.6.7, >= 1.6.7.2)
oauth2 (~> 1.2.0)
octokit (~> 4.3.0)
......@@ -940,6 +949,7 @@ DEPENDENCIES
rubocop (~> 0.41.2)
rubocop-rspec (~> 1.5.0)
ruby-fogbugz (~> 0.2.1)
ruby-prof (~> 0.15.9)
sanitize (~> 2.0)
sass-rails (~> 5.0.0)
scss_lint (~> 0.47.0)
......@@ -952,7 +962,7 @@ DEPENDENCIES
shoulda-matchers (~> 2.8.0)
sidekiq (~> 4.0)
sidekiq-cron (~> 0.4.0)
simplecov (~> 0.11.0)
simplecov (= 0.12.0)
sinatra (~> 1.4.4)
six (~> 0.2.0)
slack-notifier (~> 1.2.0)
......@@ -963,6 +973,7 @@ DEPENDENCIES
spring-commands-spinach (~> 1.1.0)
spring-commands-teaspoon (~> 0.0.2)
sprockets (~> 3.6.0)
sprockets-es6
state_machines-activerecord (~> 0.4.0)
sys-filesystem (~> 1.1.6)
task_list (~> 1.0.2)
......@@ -978,7 +989,7 @@ DEPENDENCIES
unf (~> 0.1.4)
unicorn (~> 4.9.0)
unicorn-worker-killer (~> 0.4.2)
version_sorter (~> 2.0.0)
version_sorter (~> 2.1.0)
virtus (~> 1.0.1)
vmstat (~> 2.1.1)
web-console (~> 2.0)
......
......@@ -8,6 +8,8 @@ treatment, etc.). And so that maintainers know what to expect from contributors
(use the latest version, ensure that the issue is addressed, friendly treatment,
etc.).
- [GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
## Common actions
### Issue team
......
......@@ -287,7 +287,7 @@
$('.page-with-sidebar').toggleClass('page-sidebar-collapsed page-sidebar-expanded').removeClass('page-sidebar-pinned');
$('.navbar-fixed-top').removeClass('header-pinned-nav');
}
return $document.off('click', '.js-nav-pin').on('click', '.js-nav-pin', function(e) {
$document.off('click', '.js-nav-pin').on('click', '.js-nav-pin', function(e) {
var $page, $pinBtn, $tooltip, $topNav, doPinNav, tooltipText;
e.preventDefault();
$pinBtn = $(e.currentTarget);
......@@ -315,6 +315,8 @@
$tooltip.find('.tooltip-inner').text(tooltipText);
return $pinBtn.attr('title', tooltipText).tooltip('fixTitle');
});
});
// Custom time ago
gl.utils.shortTimeAgo($('.js-short-timeago'));
});
}).call(this);
......@@ -128,7 +128,7 @@
$date = $('.js-artifacts-remove');
if ($date.length) {
date = $date.text();
return $date.text($.timefor(new Date(date), ' '));
return $date.text($.timefor(new Date(date.replace(/-/g, '/')), ' '));
}
};
......
......@@ -10,7 +10,7 @@
$(document).off('click', '.js-unfold');
$(document).on('click', '.js-unfold', (function(_this) {
return function(event) {
var line_number, link, offset, old_line, params, prev_new_line, prev_old_line, ref, ref1, since, target, to, unfold, unfoldBottom;
var line_number, link, file, offset, old_line, params, prev_new_line, prev_old_line, ref, ref1, since, target, to, unfold, unfoldBottom;
target = $(event.target);
unfoldBottom = target.hasClass('js-unfold-bottom');
unfold = true;
......@@ -31,14 +31,16 @@
unfold = false;
}
}
link = target.parents('.diff-file').attr('data-blob-diff-path');
file = target.parents('.diff-file');
link = file.data('blob-diff-path');
params = {
since: since,
to: to,
bottom: unfoldBottom,
offset: offset,
unfold: unfold,
indent: 1
indent: 1,
view: file.data('view')
};
return $.get(link, params, function(response) {
return target.parent().replaceWith(response);
......@@ -48,26 +50,13 @@
}
Diff.prototype.lineNumbers = function(line) {
var i, l, len, line_number, line_numbers, lines, results;
if (!line.children().length) {
return [0, 0];
}
lines = line.children().slice(0, 2);
line_numbers = (function() {
var i, len, results;
results = [];
for (i = 0, len = lines.length; i < len; i++) {
l = lines[i];
results.push($(l).attr('data-linenumber'));
}
return results;
})();
results = [];
for (i = 0, len = line_numbers.length; i < len; i++) {
line_number = line_numbers[i];
results.push(parseInt(line_number));
}
return results;
return line.find('.diff-line-num').map(function() {
return parseInt($(this).data('linenumber'));
});
};
return Diff;
......
......@@ -171,6 +171,11 @@
break;
case 'search:show':
new Search();
break;
case 'projects:protected_branches:index':
new gl.ProtectedBranchCreate();
new gl.ProtectedBranchEditList();
break;
}
switch (path.first()) {
case 'admin':
......
......@@ -47,8 +47,8 @@
}
}
},
setup: function(wrap) {
this.input = $('.js-gfm-input');
setup: function(input) {
this.input = input || $('.js-gfm-input');
this.destroyAtWho();
this.setupAtWho();
if (this.dataSource) {
......
......@@ -28,38 +28,43 @@
};
})(this));
timeout = "";
this.input.on("keyup", (function(_this) {
return function(e) {
this.input
.on('keydown', function (e) {
var keyCode = e.which;
if (keyCode === 13) {
e.preventDefault()
}
})
.on('keyup', function(e) {
var keyCode;
keyCode = e.which;
if (ARROW_KEY_CODES.indexOf(keyCode) >= 0) {
return;
}
if (_this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.addClass(HAS_VALUE_CLASS);
} else if (_this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
} else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.removeClass(HAS_VALUE_CLASS);
}
if (keyCode === 13) {
return false;
}
if (_this.options.remote) {
if (this.options.remote) {
clearTimeout(timeout);
return timeout = setTimeout(function() {
var blur_field;
blur_field = _this.shouldBlur(keyCode);
if (blur_field && _this.filterInputBlur) {
_this.input.blur();
var blurField = this.shouldBlur(keyCode);
if (blurField && this.filterInputBlur) {
this.input.blur();
}
return _this.options.query(_this.input.val(), function(data) {
return _this.options.callback(data);
});
}, 250);
return this.options.query(this.input.val(), function(data) {
return this.options.callback(data);
}.bind(this));
}.bind(this), 250);
} else {
return _this.filter(_this.input.val());
return this.filter(this.input.val());
}
};
})(this));
}.bind(this));
}
GitLabDropdownFilter.prototype.shouldBlur = function(keyCode) {
......@@ -382,6 +387,7 @@
GitLabDropdown.prototype.opened = function() {
var contentHtml;
currentIndex = -1;
this.addArrowKeyEvent();
if (this.options.setIndeterminateIds) {
this.options.setIndeterminateIds.call(this);
......@@ -601,7 +607,7 @@
return this.dropdown.before($input);
};
GitLabDropdown.prototype.selectRowAtIndex = function(e, index) {
GitLabDropdown.prototype.selectRowAtIndex = function(index) {
var $el, selector;
selector = ".dropdown-content li:not(.divider,.dropdown-header,.separator):eq(" + index + ") a";
if (this.dropdown.find(".dropdown-toggle-page").length) {
......@@ -609,8 +615,6 @@
}
$el = $(selector, this.dropdown);
if ($el.length) {
e.preventDefault();
e.stopImmediatePropagation();
return $el.first().trigger('click');
}
};
......@@ -619,7 +623,7 @@
var $input, ARROW_KEY_CODES, selector;
ARROW_KEY_CODES = [38, 40];
$input = this.dropdown.find(".dropdown-input-field");
selector = '.dropdown-content li:not(.divider,.dropdown-header,.separator)';
selector = '.dropdown-content li:not(.divider,.dropdown-header,.separator):visible';
if (this.dropdown.find(".dropdown-toggle-page").length) {
selector = ".dropdown-page-one " + selector;
}
......@@ -647,7 +651,7 @@
return false;
}
if (currentKeyCode === 13 && currentIndex !== -1) {
return _this.selectRowAtIndex(e, currentIndex);
return _this.selectRowAtIndex($('.is-focused', _this.dropdown).closest('li').index() - 1);
}
};
})(this));
......
......@@ -21,7 +21,7 @@
this.form.find('.div-dropzone').remove();
this.form.addClass('gfm-form');
disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button'));
GitLab.GfmAutoComplete.setup();
GitLab.GfmAutoComplete.setup(this.form.find('.js-gfm-input'));
new DropzoneInput(this.form);
autosize(this.textarea);
this.addEventListeners();
......
......@@ -66,4 +66,12 @@
})();
$(function() {
if ($('.js-importer-status').length) {
var jobsImportPath = $('.js-importer-status').data('jobs-import-path');
var importPath = $('.js-importer-status').data('import-path');
new ImporterStatus(jobsImportPath, importPath);
}
});
}).call(this);
......@@ -8,13 +8,16 @@
base.utils = {};
}
w.gl.utils.days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
w.gl.utils.formatDate = function(datetime) {
return dateFormat(datetime, 'mmm d, yyyy h:MMtt Z');
};
w.gl.utils.getDayName = function(date) {
return this.days[date.getDay()];
};
return w.gl.utils.localTimeAgo = function($timeagoEls, setTimeago) {
w.gl.utils.localTimeAgo = function($timeagoEls, setTimeago) {
if (setTimeago == null) {
setTimeago = true;
}
......@@ -31,6 +34,39 @@
});
}
};
w.gl.utils.shortTimeAgo = function($el) {
var shortLocale, tmpLocale;
shortLocale = {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: 'ago',
suffixFromNow: 'from now',
seconds: '1 min',
minute: '1 min',
minutes: '%d mins',
hour: '1 hr',
hours: '%d hrs',
day: '1 day',
days: '%d days',
month: '1 month',
months: '%d months',
year: '1 year',
years: '%d years',
wordSeparator: ' ',
numbers: []
};
tmpLocale = $.timeago.settings.strings;
$el.each(function(el) {
var $el1;
$el1 = $(this);
return $el1.attr('title', gl.utils.formatDate($el.attr('datetime')));
});
$.timeago.settings.strings = shortLocale;
$el.timeago();
$.timeago.settings.strings = tmpLocale;
};
})(window);
}).call(this);
function md5 (str) {
// http://kevin.vanzonneveld.net
// + original by: Webtoolkit.info (http://www.webtoolkit.info/)
// + namespaced by: Michael White (http://getsprink.com)
// + tweaked by: Jack
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + input by: Brett Zamir (http://brett-zamir.me)
// + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// - depends on: utf8_encode
// * example 1: md5('Kevin van Zonneveld');
// * returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
var xl;
var rotateLeft = function (lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
};
var addUnsigned = function (lX, lY) {
var lX4, lY4, lX8, lY8, lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) {
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
}
if (lX4 | lY4) {
if (lResult & 0x40000000) {
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
}
} else {
return (lResult ^ lX8 ^ lY8);
}
};
var _F = function (x, y, z) {
return (x & y) | ((~x) & z);
};
var _G = function (x, y, z) {
return (x & z) | (y & (~z));
};
var _H = function (x, y, z) {
return (x ^ y ^ z);
};
var _I = function (x, y, z) {
return (y ^ (x | (~z)));
};
var _FF = function (a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var _GG = function (a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var _HH = function (a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var _II = function (a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var convertToWordArray = function (str) {
var lWordCount;
var lMessageLength = str.length;
var lNumberOfWords_temp1 = lMessageLength + 8;
var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
var lWordArray = new Array(lNumberOfWords - 1);
var lBytePosition = 0;
var lByteCount = 0;
while (lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
return lWordArray;
};
var wordToHex = function (lValue) {
var wordToHexValue = "",
wordToHexValue_temp = "",
lByte, lCount;
for (lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255;
wordToHexValue_temp = "0" + lByte.toString(16);
wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2);
}
return wordToHexValue;
};
var x = [],
k, AA, BB, CC, DD, a, b, c, d, S11 = 7,
S12 = 12,
S13 = 17,
S14 = 22,
S21 = 5,
S22 = 9,
S23 = 14,
S24 = 20,
S31 = 4,
S32 = 11,
S33 = 16,
S34 = 23,
S41 = 6,
S42 = 10,
S43 = 15,
S44 = 21;
str = this.utf8_encode(str);
x = convertToWordArray(str);
a = 0x67452301;
b = 0xEFCDAB89;
c = 0x98BADCFE;
d = 0x10325476;
xl = x.length;
for (k = 0; k < xl; k += 16) {
AA = a;
BB = b;
CC = c;
DD = d;
a = _FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
d = _FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
c = _FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
b = _FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
a = _FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
d = _FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
c = _FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
b = _FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
a = _FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
d = _FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
c = _FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
b = _FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
a = _FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
d = _FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
c = _FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
b = _FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
a = _GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
d = _GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
c = _GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
b = _GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
a = _GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
d = _GG(d, a, b, c, x[k + 10], S22, 0x2441453);
c = _GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
b = _GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
a = _GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
d = _GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
c = _GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
b = _GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
a = _GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
d = _GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
c = _GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
b = _GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
a = _HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
d = _HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
c = _HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
b = _HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
a = _HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
d = _HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
c = _HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
b = _HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
a = _HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
d = _HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
c = _HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
b = _HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
a = _HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
d = _HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
c = _HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
b = _HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
a = _II(a, b, c, d, x[k + 0], S41, 0xF4292244);
d = _II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
c = _II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
b = _II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
a = _II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
d = _II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
c = _II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
b = _II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
a = _II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
d = _II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
c = _II(c, d, a, b, x[k + 6], S43, 0xA3014314);
b = _II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
a = _II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
d = _II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
c = _II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
b = _II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
a = addUnsigned(a, AA);
b = addUnsigned(b, BB);
c = addUnsigned(c, CC);
d = addUnsigned(d, DD);
}
var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
return temp.toLowerCase();
}
function utf8_encode (argString) {
// http://kevin.vanzonneveld.net
// + original by: Webtoolkit.info (http://www.webtoolkit.info/)
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + improved by: sowberry
// + tweaked by: Jack
// + bugfixed by: Onno Marsman
// + improved by: Yves Sucaet
// + bugfixed by: Onno Marsman
// + bugfixed by: Ulrich
// + bugfixed by: Rafal Kukawski
// + improved by: kirilloid
// + bugfixed by: kirilloid
// * example 1: utf8_encode('Kevin van Zonneveld');
// * returns 1: 'Kevin van Zonneveld'
if (argString === null || typeof argString === "undefined") {
return "";
}
var string = (argString + ''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
var utftext = '',
start, end, stringl = 0;
start = end = 0;
stringl = string.length;
for (var n = 0; n < stringl; n++) {
var c1 = string.charCodeAt(n);
var enc = null;
if (c1 < 128) {
end++;
} else if (c1 > 127 && c1 < 2048) {
enc = String.fromCharCode(
(c1 >> 6) | 192,
( c1 & 63) | 128
);
} else if (c1 & 0xF800 != 0xD800) {
enc = String.fromCharCode(
(c1 >> 12) | 224,
((c1 >> 6) & 63) | 128,
( c1 & 63) | 128
);
} else { // surrogate pairs
if (c1 & 0xFC00 != 0xD800) { throw new RangeError("Unmatched trail surrogate at " + n); }
var c2 = string.charCodeAt(++n);
if (c2 & 0xFC00 != 0xDC00) { throw new RangeError("Unmatched lead surrogate at " + (n-1)); }
c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000;
enc = String.fromCharCode(
(c1 >> 18) | 240,
((c1 >> 12) & 63) | 128,
((c1 >> 6) & 63) | 128,
( c1 & 63) | 128
);
}
if (enc !== null) {
if (end > start) {
utftext += string.slice(start, end);
}
utftext += enc;
start = end = n + 1;
}
}
if (end > start) {
utftext += string.slice(start, stringl);
}
return utftext;
}
......@@ -89,8 +89,14 @@
toggleLabel: function(obj, $el) {
return $el.text().trim();
},
clicked: function(e) {
return $dropdown.closest('form').submit();
clicked: function(selected, $el, e) {
e.preventDefault()
if ($('input[name="ref"]').length) {
var $form = $dropdown.closest('form'),
action = $form.attr('action'),
divider = action.indexOf('?') < 0 ? '?' : '&';
Turbolinks.visit(action + '' + divider + '' + $form.serialize());
}
}
});
});
......
(global => {
global.gl = global.gl || {};
gl.ProtectedBranchAccessDropdown = class {
constructor(options) {
const { $dropdown, data, onSelect } = options;
$dropdown.glDropdown({
data: data,
selectable: true,
inputId: $dropdown.data('input-id'),
fieldName: $dropdown.data('field-name'),
toggleLabel(item) {
return item.text;
},
clicked(item, $el, e) {
e.preventDefault();
onSelect();
}
});
}
}
})(window);
(global => {
global.gl = global.gl || {};
gl.ProtectedBranchCreate = class {
constructor() {
this.$wrap = this.$form = $('#new_protected_branch');
this.buildDropdowns();
}
buildDropdowns() {
const $allowedToMergeDropdown = this.$wrap.find('.js-allowed-to-merge');
const $allowedToPushDropdown = this.$wrap.find('.js-allowed-to-push');
// Cache callback
this.onSelectCallback = this.onSelect.bind(this);
// Allowed to Merge dropdown
new gl.ProtectedBranchAccessDropdown({
$dropdown: $allowedToMergeDropdown,
data: gon.merge_access_levels,
onSelect: this.onSelectCallback
});
// Allowed to Push dropdown
new gl.ProtectedBranchAccessDropdown({
$dropdown: $allowedToPushDropdown,
data: gon.push_access_levels,
onSelect: this.onSelectCallback
});
// Select default
$allowedToPushDropdown.data('glDropdown').selectRowAtIndex(0);
$allowedToMergeDropdown.data('glDropdown').selectRowAtIndex(0);
// Protected branch dropdown
new ProtectedBranchDropdown({
$dropdown: this.$wrap.find('.js-protected-branch-select'),
onSelect: this.onSelectCallback
});
}
// This will run after clicked callback
onSelect() {
// Enable submit button
const $branchInput = this.$wrap.find('input[name="protected_branch[name]"]');
const $allowedToMergeInput = this.$wrap.find('input[name="protected_branch[merge_access_level_attributes][access_level]"]');
const $allowedToPushInput = this.$wrap.find('input[name="protected_branch[push_access_level_attributes][access_level]"]');
if ($branchInput.val() && $allowedToMergeInput.val() && $allowedToPushInput.val()){
this.$form.find('input[type="submit"]').removeAttr('disabled');
}
}
}
})(window);
class ProtectedBranchDropdown {
constructor(options) {
this.onSelect = options.onSelect;
this.$dropdown = options.$dropdown;
this.$dropdownContainer = this.$dropdown.parent();
this.$dropdownFooter = this.$dropdownContainer.find('.dropdown-footer');
this.$protectedBranch = this.$dropdownContainer.find('.create-new-protected-branch');
this.buildDropdown();
this.bindEvents();
// Hide footer
this.$dropdownFooter.addClass('hidden');
}
buildDropdown() {
this.$dropdown.glDropdown({
data: this.getProtectedBranches.bind(this),
filterable: true,
remote: false,
search: {
fields: ['title']
},
selectable: true,
toggleLabel(selected) {
return (selected && 'id' in selected) ? selected.title : 'Protected Branch';
},
fieldName: 'protected_branch[name]',
text(protectedBranch) {
return _.escape(protectedBranch.title);
},
id(protectedBranch) {
return _.escape(protectedBranch.id);
},
onFilter: this.toggleCreateNewButton.bind(this),
clicked: (item, $el, e) => {
e.preventDefault();
this.onSelect();
}
});
}
bindEvents() {
this.$protectedBranch.on('click', this.onClickCreateWildcard.bind(this));
}
onClickCreateWildcard() {
this.$dropdown.data('glDropdown').remote.execute();
this.$dropdown.data('glDropdown').selectRowAtIndex(0);
}
getProtectedBranches(term, callback) {
if (this.selectedBranch) {
callback(gon.open_branches.concat(this.selectedBranch));
} else {
callback(gon.open_branches);
}
}
toggleCreateNewButton(branchName) {
this.selectedBranch = {
title: branchName,
id: branchName,
text: branchName
};
if (branchName) {
this.$dropdownContainer
.find('.create-new-protected-branch code')
.text(branchName);
}
this.$dropdownFooter.toggleClass('hidden', !branchName);
}
}
(global => {
global.gl = global.gl || {};
gl.ProtectedBranchEdit = class {
constructor(options) {
this.$wrap = options.$wrap;
this.$allowedToMergeDropdown = this.$wrap.find('.js-allowed-to-merge');
this.$allowedToPushDropdown = this.$wrap.find('.js-allowed-to-push');
this.buildDropdowns();
}
buildDropdowns() {
// Allowed to merge dropdown
new gl.ProtectedBranchAccessDropdown({
$dropdown: this.$allowedToMergeDropdown,
data: gon.merge_access_levels,
onSelect: this.onSelect.bind(this)
});
// Allowed to push dropdown
new gl.ProtectedBranchAccessDropdown({
$dropdown: this.$allowedToPushDropdown,
data: gon.push_access_levels,
onSelect: this.onSelect.bind(this)
});
}
onSelect() {
const $allowedToMergeInput = this.$wrap.find(`input[name="${this.$allowedToMergeDropdown.data('fieldName')}"]`);
const $allowedToPushInput = this.$wrap.find(`input[name="${this.$allowedToPushDropdown.data('fieldName')}"]`);
$.ajax({
type: 'POST',
url: this.$wrap.data('url'),
dataType: 'json',
data: {
_method: 'PATCH',
id: this.$wrap.data('banchId'),
protected_branch: {
merge_access_level_attributes: {
access_level: $allowedToMergeInput.val()
},
push_access_level_attributes: {
access_level: $allowedToPushInput.val()
}
}
},
success: () => {
this.$wrap.effect('highlight');
},
error() {
$.scrollTo(0);
new Flash('Failed to update branch!');
}
});
}
}
})(window);
(global => {
global.gl = global.gl || {};
gl.ProtectedBranchEditList = class {
constructor() {
this.$wrap = $('.protected-branches-list');
// Build edit forms
this.$wrap.find('.js-protected-branch-edit-form').each((i, el) => {
new gl.ProtectedBranchEdit({
$wrap: $(el)
});
});
}
}
})(window);
(function() {
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
this.ProtectedBranchSelect = (function() {
function ProtectedBranchSelect(currentProject) {
this.toggleCreateNewButton = bind(this.toggleCreateNewButton, this);
this.getProtectedBranches = bind(this.getProtectedBranches, this);
$('.dropdown-footer').hide();
this.dropdown = $('.js-protected-branch-select').glDropdown({
data: this.getProtectedBranches,
filterable: true,
remote: false,
search: {
fields: ['title']
},
selectable: true,
toggleLabel: function(selected) {
if (selected && 'id' in selected) {
return selected.title;
} else {
return 'Protected Branch';
}
},
fieldName: 'protected_branch[name]',
text: function(protected_branch) {
return _.escape(protected_branch.title);
},
id: function(protected_branch) {
return _.escape(protected_branch.id);
},
onFilter: this.toggleCreateNewButton,
clicked: function() {
return $('.protect-branch-btn').attr('disabled', false);
}
});
$('.create-new-protected-branch').on('click', (function(_this) {
return function(event) {
_this.dropdown.data('glDropdown').remote.execute();
return _this.dropdown.data('glDropdown').selectRowAtIndex(event, 0);
};
})(this));
}
ProtectedBranchSelect.prototype.getProtectedBranches = function(term, callback) {
if (this.selectedBranch) {
return callback(gon.open_branches.concat(this.selectedBranch));
} else {
return callback(gon.open_branches);
}
};
ProtectedBranchSelect.prototype.toggleCreateNewButton = function(branchName) {
this.selectedBranch = {
title: branchName,
id: branchName,
text: branchName
};
if (branchName === '') {
$('.protected-branch-select-footer-list').addClass('hidden');
return $('.dropdown-footer').hide();
} else {
$('.create-new-protected-branch').text("Create Protected Branch: " + branchName);
$('.protected-branch-select-footer-list').removeClass('hidden');
return $('.dropdown-footer').show();
}
};
return ProtectedBranchSelect;
})();
}).call(this);
(function() {
$(function() {
return $(".protected-branches-list :checkbox").change(function(e) {
var can_push, id, name, obj, url;
name = $(this).attr("name");
if (name === "developers_can_push" || name === "developers_can_merge") {
id = $(this).val();
can_push = $(this).is(":checked");
url = $(this).data("url");
return $.ajax({
type: "PATCH",
url: url,
dataType: "json",
data: {
id: id,
protected_branch: (
obj = {},
obj["" + name] = can_push,
obj
)
},
success: function() {
var row;
row = $(e.target);
return row.closest('tr').effect('highlight');
},
error: function() {
return new Flash("Failed to update branch!", "alert");
}
});
}
});
});
}).call(this);
......@@ -13,14 +13,15 @@
}
$('.js-user-search').each((function(_this) {
return function(i, dropdown) {
var options = {};
var $block, $collapsedSidebar, $dropdown, $loading, $selectbox, $value, abilityName, assignTo, assigneeTemplate, collapsedAssigneeTemplate, defaultLabel, firstUser, issueURL, selectedId, showAnyUser, showNullUser;
$dropdown = $(dropdown);
_this.projectId = $dropdown.data('project-id');
_this.showCurrentUser = $dropdown.data('current-user');
options.projectId = $dropdown.data('project-id');
options.showCurrentUser = $dropdown.data('current-user');
showNullUser = $dropdown.data('null-user');
showAnyUser = $dropdown.data('any-user');
firstUser = $dropdown.data('first-user');
_this.authorId = $dropdown.data('author-id');
options.authorId = $dropdown.data('author-id');
selectedId = $dropdown.data('selected');
defaultLabel = $dropdown.data('default-label');
issueURL = $dropdown.data('issueUpdate');
......@@ -75,7 +76,7 @@
data: function(term, callback) {
var isAuthorFilter;
isAuthorFilter = $('.js-author-search');
return _this.users(term, function(users) {
return _this.users(term, options, function(users) {
var anyUser, index, j, len, name, obj, showDivider;
if (term.length === 0) {
showDivider = 0;
......@@ -185,10 +186,14 @@
$('.ajax-users-select').each((function(_this) {
return function(i, select) {
var firstUser, showAnyUser, showEmailUser, showNullUser;
_this.projectId = $(select).data('project-id');
_this.groupId = $(select).data('group-id');
_this.showCurrentUser = $(select).data('current-user');
_this.authorId = $(select).data('author-id');
var options = {};
options.skipLdap = $(select).hasClass('skip_ldap');
options.projectId = $(select).data('project-id');
options.groupId = $(select).data('group-id');
options.showCurrentUser = $(select).data('current-user');
options.pushCodeToProtectedBranches = $(select).data('push-code-to-protected-branches');
options.authorId = $(select).data('author-id');
options.skipUsers = $(select).data('skip-users');
showNullUser = $(select).data('null-user');
showAnyUser = $(select).data('any-user');
showEmailUser = $(select).data('email-user');
......@@ -198,7 +203,7 @@
multiple: $(select).hasClass('multiselect'),
minimumInputLength: 0,
query: function(query) {
return _this.users(query.term, function(users) {
return _this.users(query.term, options, function(users) {
var anyUser, data, emailUser, index, j, len, name, nullUser, obj, ref;
data = {
results: users
......@@ -308,7 +313,7 @@
});
};
UsersSelect.prototype.users = function(query, callback) {
UsersSelect.prototype.users = function(query, options, callback) {
var url;
url = this.buildUrl(this.usersPath);
return $.ajax({
......@@ -317,10 +322,13 @@
search: query,
per_page: 20,
active: true,
project_id: this.projectId,
group_id: this.groupId,
current_user: this.showCurrentUser,
author_id: this.authorId
project_id: options.projectId || null,
group_id: options.groupId || null,
skip_ldap: options.skipLdap || null,
current_user: options.showCurrentUser || null,
push_code_to_protected_branches: options.pushCodeToProtectedBranches || null,
author_id: options.authorId || null,
skip_users: options.skipUsers || null
},
dataType: "json"
}).done(function(users) {
......
......@@ -135,6 +135,15 @@
@include btn-green;
}
&.btn-inverted {
&.btn-success,
&.btn-new,
&.btn-create,
&.btn-save {
@include btn-outline($white-light, $green-normal, $green-normal, $green-light, $white-light, $green-light);
}
}
&.btn-gray {
@include btn-gray;
}
......
......@@ -72,6 +72,14 @@
&.large {
width: 200px;
}
&.wide {
width: 100%;
+ .dropdown-select {
width: 100%;
}
}
}
.dropdown-menu,
......@@ -350,6 +358,7 @@
.dropdown-input-field, .default-dropdown-input {
width: 100%;
min-height: 30px;
padding: 0 7px;
color: $dropdown-input-color;
line-height: 30px;
......
......@@ -114,6 +114,12 @@ ul.content-list {
font-size: $list-font-size;
color: $list-text-color;
&.no-description {
.title {
line-height: $list-text-height;
}
}
.title {
font-weight: 600;
}
......@@ -134,12 +140,11 @@ ul.content-list {
}
.controls {
padding-top: 1px;
float: right;
> .control-text {
margin-right: $gl-padding-top;
line-height: 40px;
line-height: $list-text-height;
&:last-child {
margin-right: 0;
......@@ -150,7 +155,7 @@ ul.content-list {
> .btn-group {
margin-right: $gl-padding-top;
display: inline-block;
margin-top: 4px;
margin-top: 3px;
margin-bottom: 4px;
&:last-child {
......
......@@ -182,7 +182,6 @@
> form {
display: inline-block;
margin-top: -1px;
}
.icon-label {
......@@ -193,7 +192,6 @@
height: 35px;
display: inline-block;
position: relative;
top: 2px;
margin-right: $gl-padding-top;
/* Medium devices (desktops, 992px and up) */
......
......@@ -23,4 +23,9 @@
margin-top: $gl-padding;
}
}
.panel-title {
font-size: inherit;
line-height: inherit;
}
}
......@@ -43,6 +43,7 @@ $gl-header-color: $gl-title-color;
$list-font-size: $gl-font-size;
$list-title-color: $gl-title-color;
$list-text-color: $gl-text-color;
$list-text-height: 42px;
/*
* Markdown
......
......@@ -10,83 +10,48 @@
// preference): plain class selectors, type (element name) selectors, or
// explicit child selectors.
table.code {
width: 100%;
.code {
background-color: #fff;
font-family: monospace;
border: none;
border-collapse: separate;
margin: 0;
padding: 0;
font-size: $code_font_size;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
> tr > td {
> tr {
line-height: $code_line_height;
font-family: monospace;
font-size: $code_font_size;
&.diff-line-num {
margin: 0;
padding: 0;
border: none;
padding: 0 5px;
border-right: 1px solid;
text-align: right;
min-width: 35px;
max-width: 50px;
width: 35px;
}
&.line_content {
display: block;
margin: 0;
padding: 0 0.5em;
border: none;
white-space: pre;
}
}
}
.line-numbers, .diff-line-num {
.diff-line-num {
padding: 0 5px;
text-align: right;
width: 35px;
background-color: $background-color;
}
.diff-line-num, .diff-line-num a {
color: $black-transparent;
}
pre.code, .diff-line-num {
border-color: $table-border-gray;
}
border-right: 1px solid $table-border-gray;
.code.white, pre.code, .line_content {
background-color: #fff;
color: #333;
}
.diff-line-num {
&.old {
background-color: $line-number-old;
border-color: $line-removed-dark;
border-right-color: $line-removed-dark;
}
&.new {
background-color: $line-number-new;
border-color: $line-added-dark;
}
&.hll:not(.empty-cell) {
background-color: $line-number-select;
border-color: $line-select-yellow-dark;
border-right-color: $line-added-dark;
}
}
.line_content {
padding-left: 0.5em;
padding-right: 0.5em;
white-space: pre;
&.old {
background-color: $line-removed;
> .line > span.idiff, > .line > span > span.idiff {
> .line > span.idiff,
> .line > span > span.idiff {
background-color: $line-removed-dark;
}
}
......@@ -94,7 +59,8 @@ pre.code, .diff-line-num {
&.new {
background-color: $line-added;
> .line > span.idiff, > .line > span > span.idiff {
> .line > span.idiff,
> .line > span > span.idiff {
background-color: $line-added-dark;
}
}
......@@ -103,14 +69,6 @@ pre.code, .diff-line-num {
color: $black-transparent;
background-color: $match-line;
}
&.hll:not(.empty-cell) {
background-color: $line-select-yellow;
}
}
pre > .hll {
background-color: #f8eec7 !important;
}
span.highlight_word {
......
.commits-compare-switch {
@include btn-default;
@include btn-white;
background: image-url("switch_icon.png") no-repeat center center;
text-indent: -9999px;
float: left;
margin-right: 9px;
}
......@@ -61,6 +59,10 @@
font-size: 0;
}
.ci-status-link {
display: inline-block;
}
.btn-clipboard, .btn-transparent {
padding-left: 0;
padding-right: 0;
......
......@@ -164,7 +164,10 @@
line-height: 0;
img {
border: 1px solid #fff;
background: image-url('trans_bg.gif');
background-image: linear-gradient(45deg, #e5e5e5 25%, transparent 25%, transparent 75%, #e5e5e5 75%, #e5e5e5 100%),
linear-gradient(45deg, #e5e5e5 25%, transparent 25%, transparent 75%, #e5e5e5 75%, #e5e5e5 100%);
background-size: 10px 10px;
background-position: 0 0, 5px 5px;
max-width: 100%;
}
&.deleted {
......
......@@ -23,15 +23,9 @@
}
.group-row {
&.no-description {
.group-name {
line-height: 44px;
}
}
.stats {
float: right;
line-height: 44px;
line-height: $list-text-height;
color: $gl-gray;
span {
......
......@@ -99,3 +99,33 @@ form.edit-issue {
.issue-form .select2-container {
width: 250px !important;
}
.issues-footer {
padding-top: $gl-padding;
padding-bottom: 37px;
}
.issue-email-modal-btn {
padding: 0;
color: $gl-link-color;
background-color: transparent;
border: 0;
outline: 0;
&:hover {
text-decoration: underline;
}
}
.email-modal-input-group {
margin-bottom: 10px;
.form-control {
background-color: $white-light;
}
.btn {
background-color: $background-color;
border: 1px solid $border-gray-light;
}
}
......@@ -216,6 +216,11 @@
position: relative;
top: 3px;
}
&:hover,
&:focus {
text-decoration: none;
}
}
}
}
......
......@@ -18,6 +18,10 @@
.btn {
margin: 4px;
}
.table.builds {
min-width: 1200px;
}
}
.content-list {
......@@ -35,7 +39,7 @@
}
.table.builds {
min-width: 1200px;
min-width: 900px;
&.pipeline {
min-width: 650px;
......@@ -128,7 +132,7 @@
.icon-container {
display: inline-block;
text-align: right;
width: 20px;
width: 15px;
.fa {
position: relative;
......
......@@ -512,18 +512,12 @@ pre.light-well {
.project-row {
border-color: $table-border-color;
&.no-description {
.project {
line-height: 40px;
}
}
.project-full-name {
@include str-truncated;
}
.controls {
line-height: 40px;
line-height: $list-text-height;
a:hover {
text-decoration: none;
......@@ -661,14 +655,39 @@ pre.light-well {
}
}
.new_protected_branch {
label {
margin-top: 6px;
font-weight: normal;
}
}
.protected-branches-list {
a {
color: $gl-gray;
font-weight: 600;
&:hover {
color: $gl-link-color;
}
&.is-active {
font-weight: 600;
}
}
.settings-message {
margin: 0;
border-radius: 0 0 1px 1px;
padding: 20px 0;
border: none;
}
.table-bordered {
border-radius: 1px;
th:not(:last-child), td:not(:last-child) {
border-right: solid 1px transparent;
}
}
}
......
......@@ -58,6 +58,10 @@
.tree_commit {
max-width: 320px;
.str-truncated {
max-width: 100%;
}
}
.tree_time_ago {
......
class Admin::RequestsProfilesController < Admin::ApplicationController
def index
@profile_token = Gitlab::RequestProfiler.profile_token
@profiles = Gitlab::RequestProfiler::Profile.all.group_by(&:request_path)
end
def show
clean_name = Rack::Utils.clean_path_info(params[:name])
profile = Gitlab::RequestProfiler::Profile.find(clean_name)
if profile
render text: profile.content
else
redirect_to admin_requests_profiles_path, alert: 'Profile not found'
end
end
end
......@@ -243,42 +243,6 @@ class ApplicationController < ActionController::Base
end
end
def set_filters_params
set_default_sort
params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
@sort = params[:sort]
@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 get_issues_collection
set_filters_params
@issuable_finder = IssuesFinder.new(current_user, @filter_params)
@issuable_finder.execute
end
def get_merge_requests_collection
set_filters_params
@issuable_finder = MergeRequestsFinder.new(current_user, @filter_params)
@issuable_finder.execute
end
def import_sources_enabled?
!current_application_settings.import_sources.empty?
end
......@@ -363,24 +327,4 @@ class ApplicationController < ActionController::Base
def u2f_app_id
request.base_url
end
private
def set_default_sort
key = if is_a_listing_page_for?('issues') || is_a_listing_page_for?('merge_requests')
'issuable_sort'
end
cookies[key] = params[:sort] if key && params[:sort].present?
params[:sort] = cookies[key] if key
params[:sort] ||= 'id_desc'
end
def is_a_listing_page_for?(page_type)
controller_name, action_name = params.values_at(:controller, :action)
(controller_name == "projects/#{page_type}" && action_name == 'index') ||
(controller_name == 'groups' && action_name == page_type) ||
(controller_name == 'dashboard' && action_name == page_type)
end
end
......@@ -5,6 +5,7 @@ class AutocompleteController < ApplicationController
def users
@users ||= User.none
@users = @users.search(params[:search]) if params[:search].present?
@users = @users.where.not(id: params[:skip_users]) if params[:skip_users].present?
@users = @users.active
@users = @users.reorder(:name)
@users = @users.page(params[:page])
......
module DiffForPath
extend ActiveSupport::Concern
def render_diff_for_path(diffs, diff_refs, project)
diff_file = safe_diff_files(diffs, diff_refs: diff_refs, repository: project.repository).find do |diff|
def render_diff_for_path(diffs)
diff_file = diffs.diff_files.find do |diff|
diff.old_path == params[:old_path] && diff.new_path == params[:new_path]
end
......@@ -14,7 +14,7 @@ module DiffForPath
locals = {
diff_file: diff_file,
diff_commit: diff_commit,
diff_refs: diff_refs,
diff_refs: diffs.diff_refs,
blob: blob,
project: project
}
......
module IssuableCollections
extend ActiveSupport::Concern
include SortingHelper
included do
helper_method :issues_finder
helper_method :merge_requests_finder
end
private
def issues_collection
issues_finder.execute
end
def merge_requests_collection
merge_requests_finder.execute
end
def issues_finder
@issues_finder ||= issuable_finder_for(IssuesFinder)
end
def merge_requests_finder
@merge_requests_finder ||= issuable_finder_for(MergeRequestsFinder)
end
def issuable_finder_for(finder_class)
finder_class.new(current_user, filter_params)
end
def filter_params
set_sort_order_from_cookie
set_default_scope
set_default_state
@filter_params = params.dup
@filter_params[:sort] ||= default_sort_order
@sort = @filter_params[:sort]
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_default_scope
params[:scope] = 'all' if params[:scope].blank?
end
def set_default_state
params[:state] = 'opened' if params[:state].blank?
end
def set_sort_order_from_cookie
key = 'issuable_sort'
cookies[key] = params[:sort] if params[:sort].present?
params[:sort] = cookies[key]
end
def default_sort_order
case params[:state]
when 'opened', 'all' then sort_value_recently_created
when 'merged', 'closed' then sort_value_recently_updated
else sort_value_recently_created
end
end
end
module IssuesAction
extend ActiveSupport::Concern
include IssuableCollections
def issues
@issues = get_issues_collection.non_archived
@issues = @issues.page(params[:page])
@issues = @issues.preload(:author, :project)
@label = issues_finder.labels.first
@label = @issuable_finder.labels.first
@issues = issues_collection
.non_archived
.preload(:author, :project)
.page(params[:page])
respond_to do |format|
format.html
......
module MergeRequestsAction
extend ActiveSupport::Concern
include IssuableCollections
def merge_requests
@merge_requests = get_merge_requests_collection.non_archived
@merge_requests = @merge_requests.page(params[:page])
@merge_requests = @merge_requests.preload(:author, :target_project)
@label = merge_requests_finder.labels.first
@label = @issuable_finder.labels.first
@merge_requests = merge_requests_collection
.non_archived
.preload(:author, :target_project)
.page(params[:page])
end
end
class Explore::ApplicationController < ApplicationController
skip_before_action :authenticate_user!, :reject_blocked
skip_before_action :authenticate_user!, :reject_blocked!
layout 'explore'
end
class HelpController < ApplicationController
skip_before_action :authenticate_user!, :reject_blocked
skip_before_action :authenticate_user!, :reject_blocked!
layout 'help'
......
......@@ -82,8 +82,6 @@ class Import::BitbucketController < Import::BaseController
go_to_bitbucket_for_permissions
end
private
def access_params
{
bitbucket_access_token: session[:bitbucket_access_token],
......
......@@ -61,8 +61,6 @@ class Import::GitlabController < Import::BaseController
go_to_gitlab_for_permissions
end
private
def access_params
{ gitlab_access_token: session[:gitlab_access_token] }
end
......
......@@ -12,13 +12,14 @@ class Import::GitlabProjectsController < Import::BaseController
return redirect_back_or_default(options: { alert: "You need to upload a GitLab project export archive." })
end
imported_file = project_params[:file].path + "-import"
import_upload_path = Gitlab::ImportExport.import_upload_path(filename: project_params[:file].original_filename)
FileUtils.copy_entry(project_params[:file].path, imported_file)
FileUtils.mkdir_p(File.dirname(import_upload_path))
FileUtils.copy_entry(project_params[:file].path, import_upload_path)
@project = Gitlab::ImportExport::ProjectCreator.new(project_params[:namespace_id],
current_user,
File.expand_path(imported_file),
import_upload_path,
project_params[:path]).execute
if @project.saved?
......
......@@ -50,6 +50,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController
flash[:notice] = "Password was successfully updated. Please login with it"
redirect_to new_user_session_path
else
@user.reload
render 'edit'
end
end
......
......@@ -76,6 +76,8 @@ class Projects::BlobController < Projects::ApplicationController
end
def diff
apply_diff_view_cookie!
@form = UnfoldForm.new(params)
@lines = Gitlab::Highlight.highlight_lines(repository, @ref, @path)
@lines = @lines[@form.since - 1..@form.to - 1]
......
......@@ -6,8 +6,8 @@ class Projects::BranchesController < Projects::ApplicationController
before_action :authorize_push_code!, only: [:new, :create, :destroy]
def index
@sort = params[:sort] || 'name'
@branches = @repository.branches_sorted_by(@sort)
@sort = params[:sort].presence || 'name'
@branches = BranchesFinder.new(@repository, params).execute
@branches = Kaminari.paginate_array(@branches).page(params[:page])
@max_commits = @branches.reduce(0) do |memo, branch|
......
......@@ -28,7 +28,7 @@ class Projects::CommitController < Projects::ApplicationController
end
def diff_for_path
render_diff_for_path(@diffs, @commit.diff_refs, @project)
render_diff_for_path(@commit.diffs(diff_options))
end
def builds
......
......@@ -21,7 +21,7 @@ class Projects::CompareController < Projects::ApplicationController
def diff_for_path
return render_404 unless @compare
render_diff_for_path(@diffs, @diff_refs, @project)
render_diff_for_path(@compare.diffs(diff_options))
end
def create
......@@ -40,18 +40,12 @@ class Projects::CompareController < Projects::ApplicationController
@compare = CompareService.new.execute(@project, @head_ref, @project, @start_ref)
if @compare
@commits = Commit.decorate(@compare.commits, @project)
@start_commit = @project.commit(@start_ref)
@commit = @project.commit(@head_ref)
@base_commit = @project.merge_base_commit(@start_ref, @head_ref)
@commits = @compare.commits
@start_commit = @compare.start_commit
@commit = @compare.commit
@base_commit = @compare.base_commit
@diffs = @compare.diffs(diff_options)
@diff_refs = Gitlab::Diff::DiffRefs.new(
base_sha: @base_commit.try(:sha),
start_sha: @start_commit.try(:sha),
head_sha: @commit.try(:sha)
)
@diff_notes_disabled = true
@grouped_diff_discussions = {}
......
......@@ -12,8 +12,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
end
def new
redirect_to namespace_project_deploy_keys_path(@project.namespace,
@project)
redirect_to namespace_project_deploy_keys_path(@project.namespace, @project)
end
def create
......@@ -21,19 +20,16 @@ class Projects::DeployKeysController < Projects::ApplicationController
set_index_vars
if @key.valid? && @project.deploy_keys << @key
redirect_to namespace_project_deploy_keys_path(@project.namespace,
@project)
redirect_to namespace_project_deploy_keys_path(@project.namespace, @project)
else
render "index"
end
end
def enable
@key = accessible_keys.find(params[:id])
@project.deploy_keys << @key
Projects::EnableDeployKeyService.new(@project, current_user, params).execute
redirect_to namespace_project_deploy_keys_path(@project.namespace,
@project)
redirect_to namespace_project_deploy_keys_path(@project.namespace, @project)
end
def disable
......@@ -45,9 +41,9 @@ class Projects::DeployKeysController < Projects::ApplicationController
protected
def set_index_vars
@enabled_keys ||= @project.deploy_keys
@enabled_keys ||= @project.deploy_keys
@available_keys ||= accessible_keys - @enabled_keys
@available_keys ||= current_user.accessible_deploy_keys - @enabled_keys
@available_project_keys ||= current_user.project_deploy_keys - @enabled_keys
@available_public_keys ||= DeployKey.are_public - @enabled_keys
......@@ -56,10 +52,6 @@ class Projects::DeployKeysController < Projects::ApplicationController
@available_public_keys -= @available_project_keys
end
def accessible_keys
@accessible_keys ||= current_user.accessible_deploy_keys
end
def deploy_key_params
params.require(:deploy_key).permit(:key, :title)
end
......
......@@ -2,8 +2,8 @@ class Projects::EnvironmentsController < Projects::ApplicationController
layout 'project'
before_action :authorize_read_environment!
before_action :authorize_create_environment!, only: [:new, :create]
before_action :authorize_update_environment!, only: [:destroy]
before_action :environment, only: [:show, :destroy]
before_action :authorize_update_environment!, only: [:edit, :update, :destroy]
before_action :environment, only: [:show, :edit, :update, :destroy]
def index
@environments = project.environments
......@@ -17,13 +17,24 @@ class Projects::EnvironmentsController < Projects::ApplicationController
@environment = project.environments.new
end
def edit
end
def create
@environment = project.environments.create(create_params)
@environment = project.environments.create(environment_params)
if @environment.persisted?
redirect_to namespace_project_environment_path(project.namespace, project, @environment)
else
render 'new'
render :new
end
end
def update
if @environment.update(environment_params)
redirect_to namespace_project_environment_path(project.namespace, project, @environment)
else
render :edit
end
end
......@@ -39,8 +50,8 @@ class Projects::EnvironmentsController < Projects::ApplicationController
private
def create_params
params.require(:environment).permit(:name)
def environment_params
params.require(:environment).permit(:name, :external_url)
end
def environment
......
......@@ -20,9 +20,9 @@ class Projects::GitHttpController < Projects::ApplicationController
elsif receive_pack? && receive_pack_allowed?
render_ok
elsif http_blocked?
render_not_allowed
render_http_not_allowed
else
render_not_found
render_denied
end
end
......@@ -31,7 +31,7 @@ class Projects::GitHttpController < Projects::ApplicationController
if upload_pack? && upload_pack_allowed?
render_ok
else
render_not_found
render_denied
end
end
......@@ -40,7 +40,7 @@ class Projects::GitHttpController < Projects::ApplicationController
if receive_pack? && receive_pack_allowed?
render_ok
else
render_not_found
render_denied
end
end
......@@ -156,8 +156,17 @@ class Projects::GitHttpController < Projects::ApplicationController
render plain: 'Not Found', status: :not_found
end
def render_not_allowed
render plain: download_access.message, status: :forbidden
def render_http_not_allowed
render plain: access_check.message, status: :forbidden
end
def render_denied
if user && user.can?(:read_project, project)
render plain: 'Access denied', status: :forbidden
else
# Do not leak information about project existence
render_not_found
end
end
def ci?
......@@ -168,22 +177,20 @@ class Projects::GitHttpController < Projects::ApplicationController
return false unless Gitlab.config.gitlab_shell.upload_pack
if user
download_access.allowed?
access_check.allowed?
else
ci? || project.public?
end
end
def access
return @access if defined?(@access)
@access = Gitlab::GitAccess.new(user, project, 'http')
@access ||= Gitlab::GitAccess.new(user, project, 'http')
end
def download_access
return @download_access if defined?(@download_access)
@download_access = access.check('git-upload-pack')
def access_check
# Use the magic string '_any' to indicate we do not know what the
# changes are. This is also what gitlab-shell does.
@access_check ||= access.check(git_command, '_any')
end
def http_blocked?
......@@ -193,8 +200,6 @@ class Projects::GitHttpController < Projects::ApplicationController
def receive_pack_allowed?
return false unless Gitlab.config.gitlab_shell.receive_pack
# Skip user authorization on upload request.
# It will be done by the pre-receive hook in the repository.
user.present?
access_check.allowed?
end
end
class Projects::IssuesController < Projects::ApplicationController
include NotesHelper
include ToggleSubscriptionAction
include IssuableActions
include ToggleAwardEmoji
include IssuableCollections
before_action :redirect_to_external_issue_tracker, only: [:index, :new]
before_action :module_enabled
before_action :issue, only: [:edit, :update, :show, :referenced_merge_requests,
:related_branches, :can_create_branch]
......@@ -23,7 +26,7 @@ class Projects::IssuesController < Projects::ApplicationController
def index
terms = params['issue_search']
@issues = get_issues_collection
@issues = issues_collection
if terms.present?
if terms =~ /\A#(\d+)\z/
......@@ -70,6 +73,8 @@ class Projects::IssuesController < Projects::ApplicationController
@note = @project.notes.new(noteable: @issue)
@noteable = @issue
preload_max_access_for_authors(@notes, @project)
respond_to do |format|
format.html
format.json do
......@@ -79,7 +84,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def create
@issue = Issues::CreateService.new(project, current_user, issue_params).execute
@issue = Issues::CreateService.new(project, current_user, issue_params.merge(request: request)).execute
respond_to do |format|
format.html do
......@@ -89,7 +94,7 @@ class Projects::IssuesController < Projects::ApplicationController
render :new
end
end
format.js do |format|
format.js do
@link = @issue.attachment.url.to_js
end
end
......@@ -197,6 +202,18 @@ class Projects::IssuesController < Projects::ApplicationController
return render_404 unless @project.issues_enabled && @project.default_issues_tracker?
end
def redirect_to_external_issue_tracker
external = @project.external_issue_tracker
return unless external
if action_name == 'new'
redirect_to external.new_issue_path
else
redirect_to external.issues_url
end
end
# Since iids are implemented only in 6.1
# user may navigate to issue page using old global ids.
#
......
......@@ -3,7 +3,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
include DiffForPath
include DiffHelper
include IssuableActions
include NotesHelper
include ToggleAwardEmoji
include IssuableCollections
before_action :module_enabled
before_action :merge_request, only: [
......@@ -28,7 +30,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def index
terms = params['issue_search']
@merge_requests = get_merge_requests_collection
@merge_requests = merge_requests_collection
if terms.present?
if terms =~ /\A[#!](\d+)\z/
......@@ -83,7 +85,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
respond_to do |format|
format.html { define_discussion_vars }
format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } }
format.json do
@diffs = @merge_request.diffs(diff_options)
render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") }
end
end
end
......@@ -101,9 +107,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
define_commit_vars
diffs = @merge_request.diffs(diff_options)
render_diff_for_path(diffs, @merge_request.diff_refs, @merge_request.project)
render_diff_for_path(@merge_request.diffs(diff_options))
end
def commits
......@@ -151,7 +156,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@commits = @merge_request.compare_commits.reverse
@commit = @merge_request.diff_head_commit
@base_commit = @merge_request.diff_base_commit
@diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare
@diffs = @merge_request.diffs(diff_options) if @merge_request.compare
@diff_notes_disabled = true
@pipeline = @merge_request.pipeline
......@@ -376,6 +381,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
fresh.
discussions
preload_noteable_for_regular_notes(@discussions.flat_map(&:notes))
# This is not executed lazily
@notes = Banzai::NoteRenderer.render(
@discussions.flat_map(&:notes),
......@@ -385,6 +392,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@project_wiki,
@ref
)
preload_max_access_for_authors(@notes, @project)
end
def define_widget_vars
......@@ -404,7 +413,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
}
@use_legacy_diff_notes = !@merge_request.support_new_diff_notes?
@grouped_diff_discussions = @merge_request.notes.grouped_diff_discussions
@grouped_diff_discussions = @merge_request.notes.inc_author_project_award_emoji.grouped_diff_discussions
Banzai::NoteRenderer.render(
@grouped_diff_discussions.values.flat_map(&:notes),
......
......@@ -3,19 +3,24 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
before_action :require_non_empty_project
before_action :authorize_admin_project!
before_action :load_protected_branch, only: [:show, :update, :destroy]
before_action :load_protected_branches, only: [:index]
layout "project_settings"
def index
@protected_branches = @project.protected_branches.order(:name).page(params[:page])
@protected_branch = @project.protected_branches.new
gon.push({ open_branches: @project.open_branches.map { |br| { text: br.name, id: br.name, title: br.name } } })
load_protected_branches_gon_variables
end
def create
@project.protected_branches.create(protected_branch_params)
redirect_to namespace_project_protected_branches_path(@project.namespace,
@project)
@protected_branch = ProtectedBranches::CreateService.new(@project, current_user, protected_branch_params).execute
if @protected_branch.persisted?
redirect_to namespace_project_protected_branches_path(@project.namespace, @project)
else
load_protected_branches
load_protected_branches_gon_variables
render :index
end
end
def show
......@@ -23,7 +28,9 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
end
def update
if @protected_branch && @protected_branch.update_attributes(protected_branch_params)
@protected_branch = ProtectedBranches::UpdateService.new(@project, current_user, protected_branch_params).execute(@protected_branch)
if @protected_branch.valid?
respond_to do |format|
format.json { render json: @protected_branch, status: :ok }
end
......@@ -50,6 +57,18 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
end
def protected_branch_params
params.require(:protected_branch).permit(:name, :developers_can_push, :developers_can_merge)
params.require(:protected_branch).permit(:name,
merge_access_level_attributes: [:access_level],
push_access_level_attributes: [:access_level])
end
def load_protected_branches
@protected_branches = @project.protected_branches.order(:name).page(params[:page])
end
def load_protected_branches_gon_variables
gon.push({ open_branches: @project.open_branches.map { |br| { text: br.name, id: br.name, title: br.name } },
push_access_levels: ProtectedBranch::PushAccessLevel.human_access_levels.map { |id, text| { id: id, text: text } },
merge_access_levels: ProtectedBranch::MergeAccessLevel.human_access_levels.map { |id, text| { id: id, text: text } } })
end
end
......@@ -10,11 +10,12 @@ class Projects::TagsController < Projects::ApplicationController
@tags = @repository.tags_sorted_by(@sort)
@tags = Kaminari.paginate_array(@tags).page(params[:page])
@releases = project.releases.where(tag: @tags)
@releases = project.releases.where(tag: @tags.map(&:name))
end
def show
@tag = @repository.find_tag(params[:id])
@release = @project.releases.find_or_initialize_by(tag: @tag.name)
@commit = @repository.commit(@tag.target)
end
......
......@@ -97,7 +97,7 @@ class ProjectsController < Projects::ApplicationController
end
if @project.pending_delete?
flash[:alert] = "Project queued for delete."
flash[:alert] = "Project #{@project.name} queued for deletion."
end
respond_to do |format|
......
......@@ -33,7 +33,7 @@ class RegistrationsController < Devise::RegistrationsController
protected
def build_resource(hash=nil)
def build_resource(hash = nil)
super
end
......
class SearchController < ApplicationController
skip_before_action :authenticate_user!, :reject_blocked
skip_before_action :authenticate_user!, :reject_blocked!
include SearchHelper
......
......@@ -101,7 +101,7 @@ class SessionsController < Devise::SessionsController
# Prevent alert from popping up on the first page shown after authentication.
flash[:alert] = nil
redirect_to user_omniauth_authorize_path(provider.to_sym)
redirect_to omniauth_authorize_path(:user, provider)
end
def valid_otp_attempt?(user)
......
class BranchesFinder
def initialize(repository, params)
@repository = repository
@params = params
end
def execute
branches = @repository.branches_sorted_by(sort)
filter_by_name(branches)
end
private
attr_reader :repository, :params
def search
@params[:search].presence
end
def sort
@params[:sort].presence || 'name'
end
def filter_by_name(branches)
if search
branches.select { |branch| branch.name.include?(search) }
else
branches
end
end
end
......@@ -109,7 +109,7 @@ class IssuableFinder
scope.where(title: params[:milestone_title])
else
nil
Milestone.none
end
end
......
......@@ -163,9 +163,13 @@ module ApplicationHelper
# `html_class` argument is provided.
#
# Returns an HTML-safe String
def time_ago_with_tooltip(time, placement: 'top', html_class: 'time_ago', skip_js: false)
def time_ago_with_tooltip(time, placement: 'top', html_class: '', skip_js: false, short_format: false)
css_classes = short_format ? 'js-short-timeago' : 'js-timeago'
css_classes << " #{html_class}" unless html_class.blank?
css_classes << ' js-timeago-pending' unless skip_js
element = content_tag :time, time.to_s,
class: "#{html_class} js-timeago #{"js-timeago-pending" unless skip_js}",
class: css_classes,
datetime: time.to_time.getutc.iso8601,
title: time.to_time.in_time_zone.to_s(:medium),
data: { toggle: 'tooltip', placement: placement, container: 'body' }
......@@ -245,7 +249,6 @@ module ApplicationHelper
milestone_title: params[:milestone_title],
assignee_id: params[:assignee_id],
author_id: params[:author_id],
sort: params[:sort],
issue_search: params[:issue_search],
label_name: params[:label_name]
}
......
module AvatarsHelper
def author_avatar(commit_or_event, options = {})
user_avatar(options.merge({
user: commit_or_event.author,
......@@ -26,5 +25,4 @@ module AvatarsHelper
mail_to(options[:user_email], avatar)
end
end
end
......@@ -13,7 +13,7 @@ module BlobHelper
blob = project.repository.blob_at(ref, path) rescue nil
return unless blob && blob_text_viewable?(blob)
return unless blob
from_mr = options[:from_merge_request_id]
link_opts = {}
......
......@@ -9,6 +9,17 @@ module BranchesHelper
end
end
def filter_branches_path(options = {})
exist_opts = {
search: params[:search],
sort: params[:sort]
}
options = exist_opts.merge(options)
namespace_project_branches_path(@project.namespace, @project, @id, options)
end
def can_push_branch?(project, branch_name)
return false unless project.repository.branch_exists?(branch_name)
......
......@@ -206,10 +206,10 @@ module CommitsHelper
end
end
def view_file_btn(commit_sha, diff, project)
def view_file_btn(commit_sha, diff_new_path, project)
link_to(
namespace_project_blob_path(project.namespace, project,
tree_join(commit_sha, diff.new_path)),
tree_join(commit_sha, diff_new_path)),
class: 'btn view-file js-view-file btn-file-option'
) do
raw('View file @') + content_tag(:span, commit_sha[0..6],
......
......@@ -13,12 +13,11 @@ module DiffHelper
end
def diff_view
diff_views = %w(inline parallel)
if diff_views.include?(cookies[:diff_view])
cookies[:diff_view]
else
diff_views.first
@diff_view ||= begin
diff_views = %w(inline parallel)
diff_view = cookies[:diff_view]
diff_view = diff_views.first unless diff_views.include?(diff_view)
diff_view.to_sym
end
end
......@@ -30,19 +29,26 @@ module DiffHelper
options[:paths] = params.values_at(:old_path, :new_path)
end
Commit.max_diff_options.merge(options)
options
end
def safe_diff_files(diffs, diff_refs: nil, repository: nil)
diffs.decorate! { |diff| Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
end
def diff_match_line(old_pos, new_pos, text: '', view: :inline, bottom: false)
content = content_tag :td, text, class: "line_content match #{view == :inline ? '' : view}"
cls = ['diff-line-num', 'unfold', 'js-unfold']
cls << 'js-unfold-bottom' if bottom
def unfold_bottom_class(bottom)
bottom ? 'js-unfold js-unfold-bottom' : ''
end
html = ''
if old_pos
html << content_tag(:td, '...', class: cls + ['old_line'], data: { linenumber: old_pos })
html << content unless view == :inline
end
def unfold_class(unfold)
unfold ? 'unfold js-unfold' : ''
if new_pos
html << content_tag(:td, '...', class: cls + ['new_line'], data: { linenumber: new_pos })
html << content
end
html.html_safe
end
def diff_line_content(line, line_type = nil)
......@@ -71,11 +77,11 @@ module DiffHelper
end
def inline_diff_btn
diff_btn('Inline', 'inline', diff_view == 'inline')
diff_btn('Inline', 'inline', diff_view == :inline)
end
def parallel_diff_btn
diff_btn('Side-by-side', 'parallel', diff_view == 'parallel')
diff_btn('Side-by-side', 'parallel', diff_view == :parallel)
end
def submodule_link(blob, ref, repository = @repository)
......@@ -107,7 +113,8 @@ module DiffHelper
commit = commit_for_diff(diff_file)
{
blob_diff_path: namespace_project_blob_diff_path(project.namespace, project,
tree_join(commit.id, diff_file.file_path))
tree_join(commit.id, diff_file.file_path)),
view: diff_view
}
end
......@@ -144,8 +151,6 @@ module DiffHelper
toggle_whitespace_link(url, options)
end
private
def hide_whitespace?
params[:w] == '1'
end
......
module ExploreHelper
def filter_projects_path(options={})
def filter_projects_path(options = {})
exist_opts = {
sort: params[:sort],
scope: params[:scope],
......
......@@ -13,38 +13,6 @@ module IssuesHelper
OpenStruct.new(id: 0, title: 'None (backlog)', name: 'Unassigned')
end
def url_for_project_issues(project = @project, options = {})
return '' if project.nil?
url =
if options[:only_path]
project.issues_tracker.project_path
else
project.issues_tracker.project_url
end
# Ensure we return a valid URL to prevent possible XSS.
URI.parse(url).to_s
rescue URI::InvalidURIError
''
end
def url_for_new_issue(project = @project, options = {})
return '' if project.nil?
url =
if options[:only_path]
project.issues_tracker.new_issue_path
else
project.issues_tracker.new_issue_url
end
# Ensure we return a valid URL to prevent possible XSS.
URI.parse(url).to_s
rescue URI::InvalidURIError
''
end
def url_for_issue(issue_iid, project = @project, options = {})
return '' if project.nil?
......
......@@ -7,7 +7,7 @@ module NotesHelper
end
def note_editable?(note)
note.editable? && can?(current_user, :admin_note, note)
Ability.can_edit_note?(current_user, note)
end
def noteable_json(noteable)
......@@ -87,14 +87,17 @@ module NotesHelper
end
end
def note_max_access_for_user(note)
@max_access_by_user_id ||= Hash.new do |hash, key|
project = key[:project]
hash[key] = project.team.human_max_access(key[:user_id])
end
def preload_max_access_for_authors(notes, project)
user_ids = notes.map(&:author_id)
project.team.max_member_access_for_user_ids(user_ids)
end
full_key = { project: note.project, user_id: note.author_id }
@max_access_by_user_id[full_key]
def preload_noteable_for_regular_notes(notes)
ActiveRecord::Associations::Preloader.new.preload(notes.select { |note| !note.for_commit? }, :noteable)
end
def note_max_access_for_user(note)
note.project.team.human_max_access(note.author_id)
end
def discussion_diff_path(discussion)
......
......@@ -263,6 +263,10 @@ module ProjectsHelper
filename_path(project, :version)
end
def ci_configuration_path(project)
filename_path(project, :gitlab_ci_yml)
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)
......
......@@ -107,7 +107,7 @@ module SearchHelper
Sanitize.clean(str)
end
def search_filter_path(options={})
def search_filter_path(options = {})
exist_opts = {
search: params[:search],
project_id: params[:project_id],
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment