Commit 57917b1d authored by Valery Sizov's avatar Valery Sizov

Merge branch 'ce_upstream' into 'master'

CE upstream



See merge request !629
parents 41aa6fe0 792da3ca
...@@ -254,6 +254,9 @@ coverage: ...@@ -254,6 +254,9 @@ coverage:
notify:slack: notify:slack:
stage: post-test stage: post-test
variables:
USE_DB: "false"
USE_BUNDLE_INSTALL: "false"
script: 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>" - ./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 when: on_failure
......
...@@ -153,11 +153,11 @@ Style/EmptyLinesAroundBlockBody: ...@@ -153,11 +153,11 @@ Style/EmptyLinesAroundBlockBody:
# Keeps track of empty lines around class bodies. # Keeps track of empty lines around class bodies.
Style/EmptyLinesAroundClassBody: Style/EmptyLinesAroundClassBody:
Enabled: false Enabled: true
# Keeps track of empty lines around module bodies. # Keeps track of empty lines around module bodies.
Style/EmptyLinesAroundModuleBody: Style/EmptyLinesAroundModuleBody:
Enabled: false Enabled: true
# Keeps track of empty lines around method bodies. # Keeps track of empty lines around method bodies.
Style/EmptyLinesAroundMethodBody: Style/EmptyLinesAroundMethodBody:
...@@ -373,6 +373,10 @@ Style/SpaceAfterNot: ...@@ -373,6 +373,10 @@ Style/SpaceAfterNot:
Style/SpaceAfterSemicolon: Style/SpaceAfterSemicolon:
Enabled: true Enabled: true
# Use space around equals in parameter default
Style/SpaceAroundEqualsInParameterDefault:
Enabled: true
# Use a space around keywords if appropriate. # Use a space around keywords if appropriate.
Style/SpaceAroundKeyword: Style/SpaceAroundKeyword:
Enabled: true Enabled: true
......
...@@ -339,13 +339,6 @@ Style/SingleLineBlockParams: ...@@ -339,13 +339,6 @@ Style/SingleLineBlockParams:
Style/SingleLineMethods: Style/SingleLineMethods:
Enabled: false Enabled: false
# Offense count: 14
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: space, no_space
Style/SpaceAroundEqualsInParameterDefault:
Enabled: false
# Offense count: 119 # Offense count: 119
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles. # Configuration parameters: EnforcedStyle, SupportedStyles.
......
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.11.0 (unreleased) v 8.11.0 (unreleased)
- Fix don't pass a local variable called `i` to a partial. !20510 (herminiotorres)
- Fix rename `add_users_into_project` and `projects_ids`. !20512 (herminiotorres)
- Fix the title of the toggle dropdown button. !5515 (herminiotorres) - Fix the title of the toggle dropdown button. !5515 (herminiotorres)
- Improve diff performance by eliminating redundant checks for text blobs - Improve diff performance by eliminating redundant checks for text blobs
- Convert switch icon into icon font (ClemMakesApps) - Convert switch icon into icon font (ClemMakesApps)
- Remove magic comments (`# encoding: UTF-8`) from Ruby files. !5456 (winniehell) - Remove magic comments (`# encoding: UTF-8`) from Ruby files. !5456 (winniehell)
- Add support for relative links starting with ./ or / to RelativeLinkFilter (winniehell) - Add support for relative links starting with ./ or / to RelativeLinkFilter (winniehell)
- Ignore URLs starting with // in Markdown links !5677 (winniehell)
- Fix CI status icon link underline (ClemMakesApps) - Fix CI status icon link underline (ClemMakesApps)
- The Repository class is now instrumented - The Repository class is now instrumented
- Cache the commit author in RequestStore to avoid extra lookups in PostReceive - Cache the commit author in RequestStore to avoid extra lookups in PostReceive
...@@ -15,14 +18,21 @@ v 8.11.0 (unreleased) ...@@ -15,14 +18,21 @@ v 8.11.0 (unreleased)
- Add support for using RequestStore within Sidekiq tasks via SIDEKIQ_REQUEST_STORE env variable - Add support for using RequestStore within Sidekiq tasks via SIDEKIQ_REQUEST_STORE env variable
- Optimize maximum user access level lookup in loading of notes - Optimize maximum user access level lookup in loading of notes
- Add "No one can push" as an option for protected branches. !5081 - Add "No one can push" as an option for protected branches. !5081
- Improve performance of AutolinkFilter#text_parse by using XPath
- Environments have an url to link to - Environments have an url to link to
- Update `timeago` plugin to use multiple string/locale settings
- Remove unused images (ClemMakesApps)
- Limit git rev-list output count to one in forced push check - Limit git rev-list output count to one in forced push check
- Clean up unused routes (Josef Strzibny) - Clean up unused routes (Josef Strzibny)
- Fix issue on empty project to allow developers to only push to protected branches if given permission
- Add green outline to New Branch button. !5447 (winniehell) - Add green outline to New Branch button. !5447 (winniehell)
- Optimize generating of cache keys for issues and notes
- Improve performance of syntax highlighting Markdown code blocks
- Update to gitlab_git 10.4.1 and take advantage of preserved Ref objects - Update to gitlab_git 10.4.1 and take advantage of preserved Ref objects
- Remove delay when hitting "Reply..." button on page with a lot of discussions - Remove delay when hitting "Reply..." button on page with a lot of discussions
- Retrieve rendered HTML from cache in one request - Retrieve rendered HTML from cache in one request
- Fix renaming repository when name contains invalid chararacters under project settings - Fix renaming repository when name contains invalid chararacters under project settings
- Fix devise deprecation warnings.
- Optimize checking if a user has read access to a list of issues !5370 - Optimize checking if a user has read access to a list of issues !5370
- Nokogiri's various parsing methods are now instrumented - Nokogiri's various parsing methods are now instrumented
- Add simple identifier to public SSH keys (muteor) - Add simple identifier to public SSH keys (muteor)
...@@ -31,14 +41,18 @@ v 8.11.0 (unreleased) ...@@ -31,14 +41,18 @@ v 8.11.0 (unreleased)
- Include old revision in merge request update hooks (Ben Boeckel) - Include old revision in merge request update hooks (Ben Boeckel)
- Add build event color in HipChat messages (David Eisner) - Add build event color in HipChat messages (David Eisner)
- Make fork counter always clickable. !5463 (winniehell) - Make fork counter always clickable. !5463 (winniehell)
- Document that webhook secret token is sent in X-Gitlab-Token HTTP header !5664 (lycoperdon)
- Gitlab::Highlight is now instrumented
- All created issues, API or WebUI, can be submitted to Akismet for spam check !5333 - All created issues, API or WebUI, can be submitted to Akismet for spam check !5333
- The overhead of instrumented method calls has been reduced - The overhead of instrumented method calls has been reduced
- Remove `search_id` of labels dropdown filter to fix 'Missleading URI for labels in Merge Requests and Issues view'. !5368 (Scott Le) - Remove `search_id` of labels dropdown filter to fix 'Missleading URI for labels in Merge Requests and Issues view'. !5368 (Scott Le)
- Load project invited groups and members eagerly in `ProjectTeam#fetch_members` - Load project invited groups and members eagerly in `ProjectTeam#fetch_members`
- Bump gitlab_git to speedup DiffCollection iterations - Bump gitlab_git to speedup DiffCollection iterations
- Rewrite description of a blocked user in admin settings. (Elias Werberich)
- Make branches sortable without push permission !5462 (winniehell) - Make branches sortable without push permission !5462 (winniehell)
- Check for Ci::Build artifacts at database level on pipeline partial - Check for Ci::Build artifacts at database level on pipeline partial
- Convert image diff background image to CSS (ClemMakesApps) - Convert image diff background image to CSS (ClemMakesApps)
- Remove unnecessary index_projects_on_builds_enabled index from the projects table
- Make "New issue" button in Issue page less obtrusive !5457 (winniehell) - Make "New issue" button in Issue page less obtrusive !5457 (winniehell)
- Gitlab::Metrics.current_transaction needs to be public for RailsQueueDuration - Gitlab::Metrics.current_transaction needs to be public for RailsQueueDuration
- Fix search for notes which belongs to deleted objects - Fix search for notes which belongs to deleted objects
...@@ -52,12 +66,25 @@ v 8.11.0 (unreleased) ...@@ -52,12 +66,25 @@ v 8.11.0 (unreleased)
- Add commit stats in commit api. !5517 (dixpac) - Add commit stats in commit api. !5517 (dixpac)
- Add CI configuration button on project page - Add CI configuration button on project page
- Make error pages responsive (Takuya Noguchi) - Make error pages responsive (Takuya Noguchi)
- Fix skip_repo parameter being ignored when destroying a namespace
- Change requests_profiles resource constraint to catch virtually any file - Change requests_profiles resource constraint to catch virtually any file
- Bump gitlab_git to lazy load compare commits
- Reduce number of queries made for merge_requests/:id/diffs - Reduce number of queries made for merge_requests/:id/diffs
- Sensible state specific default sort order for issues and merge requests !5453 (tomb0y) - Sensible state specific default sort order for issues and merge requests !5453 (tomb0y)
- Fix RequestProfiler::Middleware error when code is reloaded in development - Fix RequestProfiler::Middleware error when code is reloaded in development
- Catch what warden might throw when profiling requests to re-throw it - Catch what warden might throw when profiling requests to re-throw it
- Add description to new_issue email and new_merge_request_email in text/plain content type. !5663 (dixpac)
- Speed up and reduce memory usage of Commit#repo_changes, Repository#expire_avatar_cache and IrkerWorker - Speed up and reduce memory usage of Commit#repo_changes, Repository#expire_avatar_cache and IrkerWorker
- Add unfold links for Side-by-Side view. !5415 (Tim Masliuchenko)
- Adds support for pending invitation project members importing projects
v 8.10.5 (unreleased)
v 8.10.4
- Don't close referenced upstream issues from a forked project.
- Fixes issue with dropdowns `enter` key not working correctly. !5544
- Fix Import/Export project import not working in HA mode. !5618
- Fix Import/Export error checking versions. !5638
v 8.10.3 v 8.10.3
- Fix Import/Export issue importing milestones and labels not associated properly. !5426 - Fix Import/Export issue importing milestones and labels not associated properly. !5426
...@@ -149,6 +176,9 @@ v 8.10.0 ...@@ -149,6 +176,9 @@ v 8.10.0
- Fix check for New Branch button on Issue page. !4630 (winniehell) - Fix check for New Branch button on Issue page. !4630 (winniehell)
- Fix GFM autocomplete not working on wiki pages - Fix GFM autocomplete not working on wiki pages
- Fixed enter key not triggering click on first row when searching in a dropdown - Fixed enter key not triggering click on first row when searching in a dropdown
- Updated dropdowns in issuable form to use new GitLab dropdown style
- Make images fit to the size of the viewport !4810
- Fix check for New Branch button on Issue page !4630 (winniehell)
- Fix MR-auto-close text added to description. !4836 - Fix MR-auto-close text added to description. !4836
- Support U2F devices in Firefox. !5177 - Support U2F devices in Firefox. !5177
- Fix issue, preventing users w/o push access to sort tags. !5105 (redetection) - Fix issue, preventing users w/o push access to sort tags. !5105 (redetection)
......
...@@ -336,6 +336,10 @@ request is as follows: ...@@ -336,6 +336,10 @@ request is as follows:
1. If your code creates new files on disk please read the 1. If your code creates new files on disk please read the
[shared files guidelines](doc/development/shared_files.md). [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. 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 **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 the 7th day of the month. This is the best time to submit an MR and get
...@@ -462,7 +466,8 @@ merge request: ...@@ -462,7 +466,8 @@ merge request:
- string literal quoting style **Option A**: single quoted by default - string literal quoting style **Option A**: single quoted by default
1. [Rails](https://github.com/bbatsov/rails-style-guide) 1. [Rails](https://github.com/bbatsov/rails-style-guide)
1. [Testing](doc/development/testing.md) 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. [SCSS styleguide][scss-styleguide]
1. [Shell commands](doc/development/shell_commands.md) created by GitLab 1. [Shell commands](doc/development/shell_commands.md) created by GitLab
contributors to enhance security contributors to enhance security
......
...@@ -57,7 +57,7 @@ gem 'browser', '~> 2.2' ...@@ -57,7 +57,7 @@ gem 'browser', '~> 2.2'
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem 'gitlab_git', '~> 10.4.3' gem 'gitlab_git', '~> 10.4.5'
# LDAP Auth # LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes # GitLab fork with several improvements to original library. For full list of changes
...@@ -337,7 +337,7 @@ group :production do ...@@ -337,7 +337,7 @@ group :production do
gem 'gitlab_meta', '7.0' gem 'gitlab_meta', '7.0'
end end
gem 'newrelic_rpm', '~> 3.14' gem 'newrelic_rpm', '~> 3.16'
gem 'octokit', '~> 4.3.0' gem 'octokit', '~> 4.3.0'
......
...@@ -300,7 +300,7 @@ GEM ...@@ -300,7 +300,7 @@ GEM
mime-types (>= 1.16, < 3) mime-types (>= 1.16, < 3)
posix-spawn (~> 0.3) posix-spawn (~> 0.3)
gitlab-license (1.0.0) gitlab-license (1.0.0)
gitlab_git (10.4.3) gitlab_git (10.4.5)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.7.3) charlock_holmes (~> 0.7.3)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
...@@ -428,7 +428,7 @@ GEM ...@@ -428,7 +428,7 @@ GEM
nested_form (0.3.2) nested_form (0.3.2)
net-ldap (0.12.1) net-ldap (0.12.1)
net-ssh (3.0.1) net-ssh (3.0.1)
newrelic_rpm (3.14.1.311) newrelic_rpm (3.16.0.318)
nokogiri (1.6.8) nokogiri (1.6.8)
mini_portile2 (~> 2.1.0) mini_portile2 (~> 2.1.0)
pkg-config (~> 1.1.7) pkg-config (~> 1.1.7)
...@@ -901,7 +901,7 @@ DEPENDENCIES ...@@ -901,7 +901,7 @@ DEPENDENCIES
gitlab-elasticsearch-git (~> 0.0.15) gitlab-elasticsearch-git (~> 0.0.15)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-license (~> 1.0) gitlab-license (~> 1.0)
gitlab_git (~> 10.4.3) gitlab_git (~> 10.4.5)
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1) gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.2) gollum-lib (~> 4.2)
...@@ -935,7 +935,7 @@ DEPENDENCIES ...@@ -935,7 +935,7 @@ DEPENDENCIES
nested_form (~> 0.3.2) nested_form (~> 0.3.2)
net-ldap net-ldap
net-ssh (~> 3.0.1) net-ssh (~> 3.0.1)
newrelic_rpm (~> 3.14) newrelic_rpm (~> 3.16)
nokogiri (~> 1.6.7, >= 1.6.7.2) nokogiri (~> 1.6.7, >= 1.6.7.2)
oauth2 (~> 1.2.0) oauth2 (~> 1.2.0)
octokit (~> 4.3.0) octokit (~> 4.3.0)
......
...@@ -293,7 +293,7 @@ ...@@ -293,7 +293,7 @@
$('.page-with-sidebar').toggleClass('page-sidebar-collapsed page-sidebar-expanded').removeClass('page-sidebar-pinned'); $('.page-with-sidebar').toggleClass('page-sidebar-collapsed page-sidebar-expanded').removeClass('page-sidebar-pinned');
$('.navbar-fixed-top').removeClass('header-pinned-nav'); $('.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; var $page, $pinBtn, $tooltip, $topNav, doPinNav, tooltipText;
e.preventDefault(); e.preventDefault();
$pinBtn = $(e.currentTarget); $pinBtn = $(e.currentTarget);
...@@ -321,6 +321,8 @@ ...@@ -321,6 +321,8 @@
$tooltip.find('.tooltip-inner').text(tooltipText); $tooltip.find('.tooltip-inner').text(tooltipText);
return $pinBtn.attr('title', tooltipText).tooltip('fixTitle'); return $pinBtn.attr('title', tooltipText).tooltip('fixTitle');
}); });
});
// Custom time ago
gl.utils.shortTimeAgo($('.js-short-timeago'));
});
}).call(this); }).call(this);
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
$(document).off('click', '.js-unfold'); $(document).off('click', '.js-unfold');
$(document).on('click', '.js-unfold', (function(_this) { $(document).on('click', '.js-unfold', (function(_this) {
return function(event) { 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); target = $(event.target);
unfoldBottom = target.hasClass('js-unfold-bottom'); unfoldBottom = target.hasClass('js-unfold-bottom');
unfold = true; unfold = true;
...@@ -31,14 +31,16 @@ ...@@ -31,14 +31,16 @@
unfold = false; unfold = false;
} }
} }
link = target.parents('.diff-file').attr('data-blob-diff-path'); file = target.parents('.diff-file');
link = file.data('blob-diff-path');
params = { params = {
since: since, since: since,
to: to, to: to,
bottom: unfoldBottom, bottom: unfoldBottom,
offset: offset, offset: offset,
unfold: unfold, unfold: unfold,
indent: 1 indent: 1,
view: file.data('view')
}; };
return $.get(link, params, function(response) { return $.get(link, params, function(response) {
return target.parent().replaceWith(response); return target.parent().replaceWith(response);
...@@ -48,26 +50,13 @@ ...@@ -48,26 +50,13 @@
} }
Diff.prototype.lineNumbers = function(line) { Diff.prototype.lineNumbers = function(line) {
var i, l, len, line_number, line_numbers, lines, results;
if (!line.children().length) { if (!line.children().length) {
return [0, 0]; return [0, 0];
} }
lines = line.children().slice(0, 2);
line_numbers = (function() { return line.find('.diff-line-num').map(function() {
var i, len, results; return parseInt($(this).data('linenumber'));
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 Diff; return Diff;
......
...@@ -180,8 +180,8 @@ ...@@ -180,8 +180,8 @@
new AdminEmailSelect(); new AdminEmailSelect();
break; break;
case 'projects:protected_branches:index': case 'projects:protected_branches:index':
new ProtectedBranchesAccessSelect($(".new_protected_branch"), false, true); new gl.ProtectedBranchCreate();
new ProtectedBranchesAccessSelect($(".protected-branches-list"), true, false); new gl.ProtectedBranchEditList();
break; break;
} }
switch (path.first()) { switch (path.first()) {
......
...@@ -28,38 +28,43 @@ ...@@ -28,38 +28,43 @@
}; };
})(this)); })(this));
timeout = ""; timeout = "";
this.input.on("keyup", (function(_this) { this.input
return function(e) { .on('keydown', function (e) {
var keyCode = e.which;
if (keyCode === 13) {
e.preventDefault()
}
})
.on('keyup', function(e) {
var keyCode; var keyCode;
keyCode = e.which; keyCode = e.which;
if (ARROW_KEY_CODES.indexOf(keyCode) >= 0) { if (ARROW_KEY_CODES.indexOf(keyCode) >= 0) {
return; return;
} }
if (_this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) { if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.addClass(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); $inputContainer.removeClass(HAS_VALUE_CLASS);
} }
if (keyCode === 13) { if (keyCode === 13) {
return false; return false;
} }
if (_this.options.remote) { if (this.options.remote) {
clearTimeout(timeout); clearTimeout(timeout);
return timeout = setTimeout(function() { return timeout = setTimeout(function() {
var blur_field; var blurField = this.shouldBlur(keyCode);
blur_field = _this.shouldBlur(keyCode); if (blurField && this.filterInputBlur) {
if (blur_field && _this.filterInputBlur) { this.input.blur();
_this.input.blur(); }
} return this.options.query(this.input.val(), function(data) {
return _this.options.query(_this.input.val(), function(data) { return this.options.callback(data);
return _this.options.callback(data); }.bind(this));
}); }.bind(this), 250);
}, 250);
} else { } else {
return _this.filter(_this.input.val()); return this.filter(this.input.val());
} }
}; }.bind(this));
})(this));
} }
GitLabDropdownFilter.prototype.shouldBlur = function(keyCode) { GitLabDropdownFilter.prototype.shouldBlur = function(keyCode) {
...@@ -382,6 +387,7 @@ ...@@ -382,6 +387,7 @@
GitLabDropdown.prototype.opened = function() { GitLabDropdown.prototype.opened = function() {
var contentHtml; var contentHtml;
currentIndex = -1;
this.addArrowKeyEvent(); this.addArrowKeyEvent();
if (this.options.setIndeterminateIds) { if (this.options.setIndeterminateIds) {
this.options.setIndeterminateIds.call(this); this.options.setIndeterminateIds.call(this);
...@@ -601,7 +607,7 @@ ...@@ -601,7 +607,7 @@
return this.dropdown.before($input); return this.dropdown.before($input);
}; };
GitLabDropdown.prototype.selectRowAtIndex = function(e, index) { GitLabDropdown.prototype.selectRowAtIndex = function(index) {
var $el, selector; var $el, selector;
selector = ".dropdown-content li:not(.divider,.dropdown-header,.separator):eq(" + index + ") a"; selector = ".dropdown-content li:not(.divider,.dropdown-header,.separator):eq(" + index + ") a";
if (this.dropdown.find(".dropdown-toggle-page").length) { if (this.dropdown.find(".dropdown-toggle-page").length) {
...@@ -609,8 +615,6 @@ ...@@ -609,8 +615,6 @@
} }
$el = $(selector, this.dropdown); $el = $(selector, this.dropdown);
if ($el.length) { if ($el.length) {
e.preventDefault();
e.stopImmediatePropagation();
return $el.first().trigger('click'); return $el.first().trigger('click');
} }
}; };
...@@ -619,7 +623,7 @@ ...@@ -619,7 +623,7 @@
var $input, ARROW_KEY_CODES, selector; var $input, ARROW_KEY_CODES, selector;
ARROW_KEY_CODES = [38, 40]; ARROW_KEY_CODES = [38, 40];
$input = this.dropdown.find(".dropdown-input-field"); $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) { if (this.dropdown.find(".dropdown-toggle-page").length) {
selector = ".dropdown-page-one " + selector; selector = ".dropdown-page-one " + selector;
} }
...@@ -647,7 +651,7 @@ ...@@ -647,7 +651,7 @@
return false; return false;
} }
if (currentKeyCode === 13 && currentIndex !== -1) { if (currentKeyCode === 13 && currentIndex !== -1) {
return _this.selectRowAtIndex(e, currentIndex); return _this.selectRowAtIndex($('.is-focused', _this.dropdown).closest('li').index() - 1);
} }
}; };
})(this)); })(this));
......
...@@ -8,13 +8,16 @@ ...@@ -8,13 +8,16 @@
base.utils = {}; base.utils = {};
} }
w.gl.utils.days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; w.gl.utils.days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
w.gl.utils.formatDate = function(datetime) { w.gl.utils.formatDate = function(datetime) {
return dateFormat(datetime, 'mmm d, yyyy h:MMtt Z'); return dateFormat(datetime, 'mmm d, yyyy h:MMtt Z');
}; };
w.gl.utils.getDayName = function(date) { w.gl.utils.getDayName = function(date) {
return this.days[date.getDay()]; return this.days[date.getDay()];
}; };
return w.gl.utils.localTimeAgo = function($timeagoEls, setTimeago) {
w.gl.utils.localTimeAgo = function($timeagoEls, setTimeago) {
if (setTimeago == null) { if (setTimeago == null) {
setTimeago = true; setTimeago = true;
} }
...@@ -31,6 +34,39 @@ ...@@ -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); })(window);
}).call(this); }).call(this);
...@@ -89,8 +89,14 @@ ...@@ -89,8 +89,14 @@
toggleLabel: function(obj, $el) { toggleLabel: function(obj, $el) {
return $el.text().trim(); return $el.text().trim();
}, },
clicked: function(e) { clicked: function(selected, $el, e) {
return $dropdown.closest('form').submit(); 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);
class ProtectedBranchesAccessSelect {
constructor(container, saveOnSelect, selectDefault) {
this.container = container;
this.saveOnSelect = saveOnSelect;
this.container.find(".allowed-to-merge").each((i, element) => {
var fieldName = $(element).data('field-name');
var dropdown = $(element).glDropdown({
data: gon.merge_access_levels,
selectable: true,
fieldName: fieldName,
clicked: _.chain(this.onSelect).partial(element).bind(this).value()
});
if (selectDefault) {
dropdown.data('glDropdown').selectRowAtIndex(document.createEvent("Event"), 0);
}
});
this.container.find(".allowed-to-push").each((i, element) => {
var fieldName = $(element).data('field-name');
var dropdown = $(element).glDropdown({
data: gon.push_access_levels,
selectable: true,
fieldName: fieldName,
clicked: _.chain(this.onSelect).partial(element).bind(this).value()
});
if (selectDefault) {
dropdown.data('glDropdown').selectRowAtIndex(document.createEvent("Event"), 0);
}
});
}
onSelect(dropdown, selected, element, e) {
$(dropdown).find('.dropdown-toggle-text').text(selected.text);
if (this.saveOnSelect) {
return $.ajax({
type: "POST",
url: $(dropdown).data('url'),
dataType: "json",
data: {
_method: 'PATCH',
id: $(dropdown).data('id'),
protected_branch: {
["" + ($(dropdown).data('type')) + "_attributes"]: {
"access_level": selected.id
}
}
},
success: function() {
var row;
row = $(e.target);
return row.closest('tr').effect('highlight');
},
error: function() {
return new Flash("Failed to update branch!", "alert");
}
});
}
}
}
...@@ -72,6 +72,14 @@ ...@@ -72,6 +72,14 @@
&.large { &.large {
width: 200px; width: 200px;
} }
&.wide {
width: 100%;
+ .dropdown-select {
width: 100%;
}
}
} }
.dropdown-menu, .dropdown-menu,
......
...@@ -114,6 +114,12 @@ ul.content-list { ...@@ -114,6 +114,12 @@ ul.content-list {
font-size: $list-font-size; font-size: $list-font-size;
color: $list-text-color; color: $list-text-color;
&.no-description {
.title {
line-height: $list-text-height;
}
}
.title { .title {
font-weight: 600; font-weight: 600;
} }
...@@ -134,12 +140,11 @@ ul.content-list { ...@@ -134,12 +140,11 @@ ul.content-list {
} }
.controls { .controls {
padding-top: 1px;
float: right; float: right;
> .control-text { > .control-text {
margin-right: $gl-padding-top; margin-right: $gl-padding-top;
line-height: 40px; line-height: $list-text-height;
&:last-child { &:last-child {
margin-right: 0; margin-right: 0;
...@@ -150,7 +155,7 @@ ul.content-list { ...@@ -150,7 +155,7 @@ ul.content-list {
> .btn-group { > .btn-group {
margin-right: $gl-padding-top; margin-right: $gl-padding-top;
display: inline-block; display: inline-block;
margin-top: 4px; margin-top: 3px;
margin-bottom: 4px; margin-bottom: 4px;
&:last-child { &:last-child {
......
...@@ -23,4 +23,9 @@ ...@@ -23,4 +23,9 @@
margin-top: $gl-padding; margin-top: $gl-padding;
} }
} }
.panel-title {
font-size: inherit;
line-height: inherit;
}
} }
...@@ -43,6 +43,7 @@ $gl-header-color: $gl-title-color; ...@@ -43,6 +43,7 @@ $gl-header-color: $gl-title-color;
$list-font-size: $gl-font-size; $list-font-size: $gl-font-size;
$list-title-color: $gl-title-color; $list-title-color: $gl-title-color;
$list-text-color: $gl-text-color; $list-text-color: $gl-text-color;
$list-text-height: 42px;
/* /*
* Markdown * Markdown
......
...@@ -28,15 +28,9 @@ ...@@ -28,15 +28,9 @@
} }
.group-row { .group-row {
&.no-description {
.group-name {
line-height: 44px;
}
}
.stats { .stats {
float: right; float: right;
line-height: 44px; line-height: $list-text-height;
color: $gl-gray; color: $gl-gray;
span { span {
......
...@@ -512,18 +512,12 @@ pre.light-well { ...@@ -512,18 +512,12 @@ pre.light-well {
.project-row { .project-row {
border-color: $table-border-color; border-color: $table-border-color;
&.no-description {
.project {
line-height: 40px;
}
}
.project-full-name { .project-full-name {
@include str-truncated; @include str-truncated;
} }
.controls { .controls {
line-height: 40px; line-height: $list-text-height;
a:hover { a:hover {
text-decoration: none; text-decoration: none;
...@@ -662,13 +656,9 @@ pre.light-well { ...@@ -662,13 +656,9 @@ pre.light-well {
} }
.new_protected_branch { .new_protected_branch {
.dropdown {
display: inline;
margin-left: 15px;
}
label { label {
min-width: 120px; margin-top: 6px;
font-weight: normal;
} }
} }
...@@ -684,6 +674,21 @@ pre.light-well { ...@@ -684,6 +674,21 @@ pre.light-well {
font-weight: 600; 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;
}
}
} }
.disabled-item { .disabled-item {
......
...@@ -12,13 +12,14 @@ class Import::GitlabProjectsController < Import::BaseController ...@@ -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." }) return redirect_back_or_default(options: { alert: "You need to upload a GitLab project export archive." })
end 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], @project = Gitlab::ImportExport::ProjectCreator.new(project_params[:namespace_id],
current_user, current_user,
File.expand_path(imported_file), import_upload_path,
project_params[:path]).execute project_params[:path]).execute
if @project.saved? if @project.saved?
......
...@@ -76,6 +76,8 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -76,6 +76,8 @@ class Projects::BlobController < Projects::ApplicationController
end end
def diff def diff
apply_diff_view_cookie!
@form = UnfoldForm.new(params) @form = UnfoldForm.new(params)
@lines = Gitlab::Highlight.highlight_lines(repository, @ref, @path) @lines = Gitlab::Highlight.highlight_lines(repository, @ref, @path)
@lines = @lines[@form.since - 1..@form.to - 1] @lines = @lines[@form.since - 1..@form.to - 1]
......
...@@ -33,7 +33,7 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -33,7 +33,7 @@ class RegistrationsController < Devise::RegistrationsController
protected protected
def build_resource(hash=nil) def build_resource(hash = nil)
super super
end end
......
...@@ -124,7 +124,7 @@ class SessionsController < Devise::SessionsController ...@@ -124,7 +124,7 @@ class SessionsController < Devise::SessionsController
# Prevent alert from popping up on the first page shown after authentication. # Prevent alert from popping up on the first page shown after authentication.
flash[:alert] = nil flash[:alert] = nil
redirect_to user_omniauth_authorize_path(provider.to_sym) redirect_to omniauth_authorize_path(:user, provider)
end end
def valid_otp_attempt?(user) def valid_otp_attempt?(user)
......
...@@ -166,9 +166,13 @@ module ApplicationHelper ...@@ -166,9 +166,13 @@ module ApplicationHelper
# `html_class` argument is provided. # `html_class` argument is provided.
# #
# Returns an HTML-safe String # 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, 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, datetime: time.to_time.getutc.iso8601,
title: time.to_time.in_time_zone.to_s(:medium), title: time.to_time.in_time_zone.to_s(:medium),
data: { toggle: 'tooltip', placement: placement, container: 'body' } data: { toggle: 'tooltip', placement: placement, container: 'body' }
......
module AvatarsHelper module AvatarsHelper
def author_avatar(commit_or_event, options = {}) def author_avatar(commit_or_event, options = {})
user_avatar(options.merge({ user_avatar(options.merge({
user: commit_or_event.author, user: commit_or_event.author,
...@@ -26,5 +25,4 @@ module AvatarsHelper ...@@ -26,5 +25,4 @@ module AvatarsHelper
mail_to(options[:user_email], avatar) mail_to(options[:user_email], avatar)
end end
end end
end end
...@@ -13,12 +13,11 @@ module DiffHelper ...@@ -13,12 +13,11 @@ module DiffHelper
end end
def diff_view def diff_view
@diff_view ||= begin
diff_views = %w(inline parallel) diff_views = %w(inline parallel)
diff_view = cookies[:diff_view]
if diff_views.include?(cookies[:diff_view]) diff_view = diff_views.first unless diff_views.include?(diff_view)
cookies[:diff_view] diff_view.to_sym
else
diff_views.first
end end
end end
...@@ -33,12 +32,23 @@ module DiffHelper ...@@ -33,12 +32,23 @@ module DiffHelper
options options
end end
def unfold_bottom_class(bottom) def diff_match_line(old_pos, new_pos, text: '', view: :inline, bottom: false)
bottom ? 'js-unfold js-unfold-bottom' : '' 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
html = ''
if old_pos
html << content_tag(:td, '...', class: cls + ['old_line'], data: { linenumber: old_pos })
html << content unless view == :inline
end
if new_pos
html << content_tag(:td, '...', class: cls + ['new_line'], data: { linenumber: new_pos })
html << content
end end
def unfold_class(unfold) html.html_safe
unfold ? 'unfold js-unfold' : ''
end end
def diff_line_content(line, line_type = nil) def diff_line_content(line, line_type = nil)
...@@ -67,11 +77,11 @@ module DiffHelper ...@@ -67,11 +77,11 @@ module DiffHelper
end end
def inline_diff_btn def inline_diff_btn
diff_btn('Inline', 'inline', diff_view == 'inline') diff_btn('Inline', 'inline', diff_view == :inline)
end end
def parallel_diff_btn def parallel_diff_btn
diff_btn('Side-by-side', 'parallel', diff_view == 'parallel') diff_btn('Side-by-side', 'parallel', diff_view == :parallel)
end end
def submodule_link(blob, ref, repository = @repository) def submodule_link(blob, ref, repository = @repository)
...@@ -103,7 +113,8 @@ module DiffHelper ...@@ -103,7 +113,8 @@ module DiffHelper
commit = commit_for_diff(diff_file) commit = commit_for_diff(diff_file)
{ {
blob_diff_path: namespace_project_blob_diff_path(project.namespace, project, 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 end
......
module ExploreHelper module ExploreHelper
def filter_projects_path(options={}) def filter_projects_path(options = {})
exist_opts = { exist_opts = {
sort: params[:sort], sort: params[:sort],
scope: params[:scope], scope: params[:scope],
......
...@@ -107,7 +107,7 @@ module SearchHelper ...@@ -107,7 +107,7 @@ module SearchHelper
Sanitize.clean(str) Sanitize.clean(str)
end end
def search_filter_path(options={}) def search_filter_path(options = {})
exist_opts = { exist_opts = {
search: params[:search], search: params[:search],
project_id: params[:project_id], project_id: params[:project_id],
......
module FasterCacheKeys
# A faster version of Rails' "cache_key" method.
#
# Rails' default "cache_key" method uses all kind of complex logic to figure
# out the cache key. In many cases this complexity and overhead may not be
# needed.
#
# This method does not do any timestamp parsing as this process is quite
# expensive and not needed when generating cache keys. This method also relies
# on the table name instead of the cache namespace name as the latter uses
# complex logic to generate the exact same value (as when using the table
# name) in 99% of the cases.
def cache_key
"#{self.class.table_name}/#{id}-#{read_attribute_before_type_cast(:updated_at)}"
end
end
...@@ -8,6 +8,7 @@ class Issue < ActiveRecord::Base ...@@ -8,6 +8,7 @@ class Issue < ActiveRecord::Base
include Taskable include Taskable
include Spammable include Spammable
include Elastic::IssuesSearch include Elastic::IssuesSearch
include FasterCacheKeys
WEIGHT_RANGE = 1..9 WEIGHT_RANGE = 1..9
WEIGHT_ALL = 'Everything' WEIGHT_ALL = 'Everything'
......
...@@ -21,19 +21,19 @@ class ProjectMember < Member ...@@ -21,19 +21,19 @@ class ProjectMember < Member
# or symbol like :master representing role # or symbol like :master representing role
# #
# Ex. # Ex.
# add_users_into_projects( # add_users_to_projects(
# project_ids, # project_ids,
# user_ids, # user_ids,
# ProjectMember::MASTER # ProjectMember::MASTER
# ) # )
# #
# add_users_into_projects( # add_users_to_projects(
# project_ids, # project_ids,
# user_ids, # user_ids,
# :master # :master
# ) # )
# #
def add_users_into_projects(project_ids, user_ids, access, current_user = nil) def add_users_to_projects(project_ids, user_ids, access, current_user = nil)
access_level = if roles_hash.has_key?(access) access_level = if roles_hash.has_key?(access)
roles_hash[access] roles_hash[access]
elsif roles_hash.values.include?(access.to_i) elsif roles_hash.values.include?(access.to_i)
......
...@@ -36,7 +36,7 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -36,7 +36,7 @@ class MergeRequestDiff < ActiveRecord::Base
real_size.presence || raw_diffs.size real_size.presence || raw_diffs.size
end end
def raw_diffs(options={}) def raw_diffs(options = {})
if options[:ignore_whitespace_change] if options[:ignore_whitespace_change]
@raw_diffs_no_whitespace ||= begin @raw_diffs_no_whitespace ||= begin
compare = Gitlab::Git::Compare.new( compare = Gitlab::Git::Compare.new(
......
...@@ -6,6 +6,7 @@ class Note < ActiveRecord::Base ...@@ -6,6 +6,7 @@ class Note < ActiveRecord::Base
include Elastic::NotesSearch include Elastic::NotesSearch
include Awardable include Awardable
include Importable include Importable
include FasterCacheKeys
# Attribute containing rendered and redacted Markdown as generated by # Attribute containing rendered and redacted Markdown as generated by
# Banzai::ObjectRenderer. # Banzai::ObjectRenderer.
......
...@@ -408,11 +408,6 @@ class Project < ActiveRecord::Base ...@@ -408,11 +408,6 @@ class Project < ActiveRecord::Base
joins(join_body).reorder('join_note_counts.amount DESC') joins(join_body).reorder('join_note_counts.amount DESC')
end end
# Deletes gitlab project export files older than 24 hours
def remove_gitlab_exports!
Gitlab::Popen.popen(%W(find #{Gitlab::ImportExport.storage_path} -not -path #{Gitlab::ImportExport.storage_path} -mmin +1440 -delete))
end
end end
def repository_storage_path def repository_storage_path
...@@ -976,10 +971,16 @@ class Project < ActiveRecord::Base ...@@ -976,10 +971,16 @@ class Project < ActiveRecord::Base
# Check if current branch name is marked as protected in the system # Check if current branch name is marked as protected in the system
def protected_branch?(branch_name) def protected_branch?(branch_name)
return true if empty_repo? && default_branch_protected?
@protected_branches ||= self.protected_branches.to_a @protected_branches ||= self.protected_branches.to_a
ProtectedBranch.matching(branch_name, protected_branches: @protected_branches).present? ProtectedBranch.matching(branch_name, protected_branches: @protected_branches).present?
end end
def user_can_push_to_empty_repo?(user)
!default_branch_protected? || team.max_member_access(user.id) > Gitlab::Access::DEVELOPER
end
def forked? def forked?
!(forked_project_link.nil? || forked_project_link.forked_from_project.nil?) !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
end end
...@@ -1492,6 +1493,11 @@ class Project < ActiveRecord::Base ...@@ -1492,6 +1493,11 @@ class Project < ActiveRecord::Base
private private
def default_branch_protected?
current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_FULL ||
current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_MERGE
end
def authorized_for_user_by_group?(user, min_access_level) def authorized_for_user_by_group?(user, min_access_level)
member = user.group_members.find_by(source_id: group) member = user.group_members.find_by(source_id: group)
......
...@@ -34,9 +34,10 @@ class ProjectTeam ...@@ -34,9 +34,10 @@ class ProjectTeam
end end
def add_users(users, access, current_user = nil) def add_users(users, access, current_user = nil)
return false if group_member_lock return false if group_member_lock
ProjectMember.add_users_into_projects( ProjectMember.add_users_to_projects(
[project.id], [project.id],
users, users,
access, access,
......
...@@ -666,7 +666,7 @@ class Repository ...@@ -666,7 +666,7 @@ class Repository
commit(sha) commit(sha)
end end
def next_branch(name, opts={}) def next_branch(name, opts = {})
branch_ids = self.branch_names.map do |n| branch_ids = self.branch_names.map do |n|
next 1 if n == name next 1 if n == name
result = n.match(/\A#{name}-([0-9]+)\z/) result = n.match(/\A#{name}-([0-9]+)\z/)
......
module Geo module Geo
class NotifyNodesService < BaseNotify class NotifyNodesService < BaseNotify
def initialize def initialize
@wiki_queue = Gitlab::Geo::UpdateQueue.new('updated_wikis') @wiki_queue = Gitlab::Geo::UpdateQueue.new('updated_wikis')
end end
......
class ImportExportCleanUpService
LAST_MODIFIED_TIME_IN_MINUTES = 1440
attr_reader :mmin, :path
def initialize(mmin = LAST_MODIFIED_TIME_IN_MINUTES)
@mmin = mmin
@path = Gitlab::ImportExport.storage_path
end
def execute
Gitlab::Metrics.measure(:import_export_clean_up) do
return unless File.directory?(path)
clean_up_export_files
end
end
private
def clean_up_export_files
Gitlab::Popen.popen(%W(find #{path} -not -path #{path} -mmin +#{mmin} -delete))
end
end
...@@ -2,7 +2,7 @@ module Oauth2 ...@@ -2,7 +2,7 @@ module Oauth2
class LogoutTokenValidationService < ::BaseService class LogoutTokenValidationService < ::BaseService
attr_reader :status attr_reader :status
def initialize(user, params={}) def initialize(user, params = {})
@params = params @params = params
@current_user = user @current_user = user
end end
......
...@@ -123,6 +123,5 @@ module Projects ...@@ -123,6 +123,5 @@ module Projects
tags << name if local_tags[name].nil? tags << name if local_tags[name].nil?
end end
end end
end end
end end
class RepositoryArchiveCleanUpService class RepositoryArchiveCleanUpService
LAST_MODIFIED_TIME_IN_MINUTES = 120 LAST_MODIFIED_TIME_IN_MINUTES = 120
attr_reader :mmin, :path
def initialize(mmin = LAST_MODIFIED_TIME_IN_MINUTES) def initialize(mmin = LAST_MODIFIED_TIME_IN_MINUTES)
@mmin = mmin @mmin = mmin
@path = Gitlab.config.gitlab.repository_downloads_path @path = Gitlab.config.gitlab.repository_downloads_path
...@@ -17,8 +19,6 @@ class RepositoryArchiveCleanUpService ...@@ -17,8 +19,6 @@ class RepositoryArchiveCleanUpService
private private
attr_reader :mmin, :path
def clean_up_old_archives def clean_up_old_archives
run(%W(find #{path} -not -path #{path} -type f \( -name \*.tar -o -name \*.bz2 -o -name \*.tar.gz -o -name \*.zip \) -maxdepth 2 -mmin +#{mmin} -delete)) run(%W(find #{path} -not -path #{path} -type f \( -name \*.tar -o -name \*.bz2 -o -name \*.tar.gz -o -name \*.zip \) -maxdepth 2 -mmin +#{mmin} -delete))
end end
......
...@@ -140,12 +140,10 @@ ...@@ -140,12 +140,10 @@
.panel-heading .panel-heading
This user is blocked This user is blocked
.panel-body .panel-body
%p Blocking user has the following effects: %p A blocked user cannot:
%ul %ul
%li User will not be able to login %li Log in
%li User will not be able to access git repositories %li Access Git repositories
%li Personal projects will be left
%li Owned groups will be left
%br %br
= link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' } = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' }
- else - else
......
= form_tag(user_omniauth_authorize_path("crowd"), id: 'new_crowd_user' ) do = form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user' ) do
= text_field_tag :username, nil, {class: "form-control top", placeholder: "Username", autofocus: "autofocus"} = text_field_tag :username, nil, {class: "form-control top", placeholder: "Username", autofocus: "autofocus"}
= password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"} = password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"}
- if devise_mapping.rememberable? - if devise_mapping.rememberable?
......
...@@ -5,4 +5,4 @@ ...@@ -5,4 +5,4 @@
- providers.each do |provider| - providers.each do |provider|
%span.light %span.light
- has_icon = provider_has_icon?(provider) - has_icon = provider_has_icon?(provider)
= link_to provider_image_tag(provider), user_omniauth_authorize_path(provider), method: :post, class: (has_icon ? 'oauth-image-link' : 'btn'), "data-no-turbolink" => "true" = link_to provider_image_tag(provider), omniauth_authorize_path(:user, provider), method: :post, class: (has_icon ? 'oauth-image-link' : 'btn'), "data-no-turbolink" => "true"
...@@ -3,3 +3,5 @@ New Issue was created. ...@@ -3,3 +3,5 @@ New Issue was created.
Issue <%= @issue.iid %>: <%= url_for(namespace_project_issue_url(@issue.project.namespace, @issue.project, @issue)) %> Issue <%= @issue.iid %>: <%= url_for(namespace_project_issue_url(@issue.project.namespace, @issue.project, @issue)) %>
Author: <%= @issue.author_name %> Author: <%= @issue.author_name %>
Assignee: <%= @issue.assignee_name %> Assignee: <%= @issue.assignee_name %>
<%= @issue.description %>
...@@ -9,3 +9,5 @@ Assignee: <%= @merge_request.assignee_name %> ...@@ -9,3 +9,5 @@ Assignee: <%= @merge_request.assignee_name %>
Approvers: <%= render_items_list(@merge_request.approvers_left.map(&:name)) %> Approvers: <%= render_items_list(@merge_request.approvers_left.map(&:name)) %>
<% end %> <% end %>
<%= @merge_request.description %>
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'provider-btn' do = link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'provider-btn' do
Disconnect Disconnect
- else - else
= link_to user_omniauth_authorize_path(provider), method: :post, class: 'provider-btn not-active', "data-no-turbolink" => "true" do = link_to omniauth_authorize_path(:user, provider), method: :post, class: 'provider-btn not-active', "data-no-turbolink" => "true" do
Connect Connect
%hr %hr
- if current_user.can_change_username? - if current_user.can_change_username?
......
- if @lines.present? - if @lines.present?
- line_class = diff_view == :inline ? '' : diff_view
- if @form.unfold? && @form.since != 1 && !@form.bottom? - if @form.unfold? && @form.since != 1 && !@form.bottom?
%tr.line_holder %tr.line_holder{ class: line_class }
= render "projects/diffs/match_line", { line: @match_line, = diff_match_line @form.since, @form.since, text: @match_line, view: diff_view
line_old: @form.since, line_new: @form.since, bottom: false, new_file: false }
- @lines.each_with_index do |line, index| - @lines.each_with_index do |line, index|
- line_new = index + @form.since - line_new = index + @form.since
- line_old = line_new - @form.offset - line_old = line_new - @form.offset
%tr.line_holder{ id: line_old } - line_content = capture do
%td.line_content.noteable_line{ class: line_class }==#{' ' * @form.indent}#{line}
%tr.line_holder{ id: line_old, class: line_class }
- case diff_view
- when :inline
%td.old_line.diff-line-num{ data: { linenumber: line_old } } %td.old_line.diff-line-num{ data: { linenumber: line_old } }
%a{href: "##{line_old}", data: { linenumber: line_old }}
%td.new_line.diff-line-num{ data: { linenumber: line_new } }
%a{href: "##{line_new}", data: { linenumber: line_new }}
= line_content
- when :parallel
%td.old_line.diff-line-num{data: { linenumber: line_old }}
= link_to raw(line_old), "##{line_old}" = link_to raw(line_old), "##{line_old}"
%td.new_line.diff-line-num{ data: { linenumber: line_old } } = line_content
= link_to raw(line_new) , "##{line_old}" %td.new_line.diff-line-num{data: { linenumber: line_new }}
%td.line_content.noteable_line==#{' ' * @form.indent}#{line} = link_to raw(line_new), "##{line_new}"
= line_content
- if @form.unfold? && @form.bottom? && @form.to < @blob.loc - if @form.unfold? && @form.bottom? && @form.to < @blob.loc
%tr.line_holder{ id: @form.to } %tr.line_holder{ id: @form.to, class: line_class }
= render "projects/diffs/match_line", { line: @match_line, = diff_match_line @form.to, @form.to, text: @match_line, view: diff_view, bottom: true
line_old: @form.to, line_new: @form.to, bottom: true, new_file: false }
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
- if pipeline.finished_at - if pipeline.finished_at
%p.finished-at %p.finished-at
= icon("calendar") = icon("calendar")
#{time_ago_with_tooltip(pipeline.finished_at)} #{time_ago_with_tooltip(pipeline.finished_at, short_format: true, skip_js: true)}
%td.pipeline-actions %td.pipeline-actions
.controls.hidden-xs.pull-right .controls.hidden-xs.pull-right
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
.nothing-here-block.diff-collapsed{data: { diff_for_path: url } } .nothing-here-block.diff-collapsed{data: { diff_for_path: url } }
This diff is collapsed. Click to expand it. This diff is collapsed. Click to expand it.
- elsif diff_file.diff_lines.length > 0 - elsif diff_file.diff_lines.length > 0
- if diff_view == 'parallel' - if diff_view == :parallel
= render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob
- else - else
= render "projects/diffs/text_file", diff_file: diff_file = render "projects/diffs/text_file", diff_file: diff_file
......
- show_whitespace_toggle = local_assigns.fetch(:show_whitespace_toggle, true) - show_whitespace_toggle = local_assigns.fetch(:show_whitespace_toggle, true)
- diff_files = diffs.diff_files - diff_files = diffs.diff_files
- if diff_view == 'parallel' - if diff_view == :parallel
- fluid_layout true - fluid_layout true
.content-block.oneline-block.files-changed .content-block.oneline-block.files-changed
...@@ -29,5 +29,5 @@ ...@@ -29,5 +29,5 @@
- next unless blob - next unless blob
- blob.load_all_data!(diffs.project.repository) unless blob.only_display_raw? - blob.load_all_data!(diffs.project.repository) unless blob.only_display_raw?
= render 'projects/diffs/file', i: index, project: diffs.project, = render 'projects/diffs/file', index: index, project: diffs.project,
diff_file: diff_file, diff_commit: diff_commit, blob: blob diff_file: diff_file, diff_commit: diff_commit, blob: blob
.diff-file.file-holder{id: "diff-#{i}", data: diff_file_html_data(project, diff_file)} .diff-file.file-holder{id: "diff-#{index}", data: diff_file_html_data(project, diff_file)}
.file-title{id: "file-path-#{hexdigest(diff_file.file_path)}"} .file-title{id: "file-path-#{hexdigest(diff_file.file_path)}"}
= render "projects/diffs/file_header", diff_file: diff_file, blob: blob, diff_commit: diff_commit, project: project, url: "#diff-#{i}" = render "projects/diffs/file_header", diff_file: diff_file, blob: blob, diff_commit: diff_commit, project: project, url: "#diff-#{index}"
- unless diff_file.submodule? - unless diff_file.submodule?
.file-actions.hidden-xs .file-actions.hidden-xs
......
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
%tr.line_holder{ plain ? { class: type} : { class: type, id: line_code } } %tr.line_holder{ plain ? { class: type} : { class: type, id: line_code } }
- case type - case type
- when 'match' - when 'match'
= render "projects/diffs/match_line", { line: line.text, = diff_match_line line.old_pos, line.new_pos, text: line.text
line_old: line.old_pos, line_new: line.new_pos, bottom: false, new_file: diff_file.new_file }
- when 'nonewline' - when 'nonewline'
%td.old_line.diff-line-num %td.old_line.diff-line-num
%td.new_line.diff-line-num %td.new_line.diff-line-num
......
%td.old_line.diff-line-num{data: {linenumber: line_old},
class: [unfold_bottom_class(bottom), unfold_class(!new_file)]}
\...
%td.new_line.diff-line-num{data: {linenumber: line_new},
class: [unfold_bottom_class(bottom), unfold_class(!new_file)]}
\...
%td.line_content.match= line
/ Side-by-side diff view / Side-by-side diff view
%div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight{ data: diff_view_data } %div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight{ data: diff_view_data }
%table %table
- last_line = 0
- diff_file.parallel_diff_lines.each do |line| - diff_file.parallel_diff_lines.each do |line|
- left = line[:left] - left = line[:left]
- right = line[:right] - right = line[:right]
- last_line = right.new_pos if right
%tr.line_holder.parallel %tr.line_holder.parallel
- if left - if left
- if left.meta? - if left.meta?
%td.old_line.diff-line-num.empty-cell = diff_match_line left.old_pos, nil, text: left.text, view: :parallel
%td.line_content.parallel.match= left.text
- else - else
- left_line_code = diff_file.line_code(left) - left_line_code = diff_file.line_code(left)
- left_position = diff_file.position(left) - left_position = diff_file.position(left)
...@@ -21,8 +22,7 @@ ...@@ -21,8 +22,7 @@
- if right - if right
- if right.meta? - if right.meta?
%td.old_line.diff-line-num.empty-cell = diff_match_line nil, right.new_pos, text: left.text, view: :parallel
%td.line_content.parallel.match= left.text
- else - else
- right_line_code = diff_file.line_code(right) - right_line_code = diff_file.line_code(right)
- right_position = diff_file.position(right) - right_position = diff_file.position(right)
...@@ -37,3 +37,5 @@ ...@@ -37,3 +37,5 @@
- discussion_left, discussion_right = parallel_diff_discussions(left, right, diff_file) - discussion_left, discussion_right = parallel_diff_discussions(left, right, diff_file)
- if discussion_left || discussion_right - if discussion_left || discussion_right
= render "discussions/parallel_diff_discussion", discussion_left: discussion_left, discussion_right: discussion_right = render "discussions/parallel_diff_discussion", discussion_left: discussion_left, discussion_right: discussion_right
- if !diff_file.new_file && last_line > 0
= diff_match_line last_line, last_line, bottom: true, view: :parallel
...@@ -15,6 +15,5 @@ ...@@ -15,6 +15,5 @@
- if discussion - if discussion
= render "discussions/diff_discussion", discussion: discussion = render "discussions/diff_discussion", discussion: discussion
- if last_line > 0 - if !diff_file.new_file && last_line > 0
= render "projects/diffs/match_line", { line: "", = diff_match_line last_line, last_line, bottom: true
line_old: last_line, line_new: last_line, bottom: true, new_file: diff_file.new_file }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
- page_description @merge_request.description - page_description @merge_request.description
- page_card_attributes @merge_request.card_attributes - page_card_attributes @merge_request.card_attributes
- if diff_view == 'parallel' - if diff_view == :parallel
- fluid_layout true - fluid_layout true
.merge-request{'data-url' => merge_request_path(@merge_request)} .merge-request{'data-url' => merge_request_path(@merge_request)}
......
%h5.prepend-top-0 .panel.panel-default.protected-branches-list
Already Protected (#{@protected_branches.size}) - if @protected_branches.empty?
- if @protected_branches.empty? .panel-heading
%h3.panel-title
Protected branch (#{@protected_branches.size})
%p.settings-message.text-center %p.settings-message.text-center
No branches are protected, protect a branch with the form above. There are currently no protected branches, protect a branch with the form above.
- else - else
- can_admin_project = can?(current_user, :admin_project, @project) - can_admin_project = can?(current_user, :admin_project, @project)
%table.table.protected-branches-list %table.table.table-bordered
%colgroup %colgroup
%col{ width: "20%" }
%col{ width: "30%" }
%col{ width: "25%" } %col{ width: "25%" }
%col{ width: "30%" }
%col{ width: "25%" } %col{ width: "25%" }
%col{ width: "20%" }
%thead %thead
%tr %tr
%th Branch %th Protected branch (#{@protected_branches.size})
%th Last commit %th Last commit
%th Allowed to merge %th Allowed to merge
%th Allowed to push %th Allowed to push
......
= form_for [@project.namespace.becomes(Namespace), @project, @protected_branch] do |f|
.panel.panel-default
.panel-heading
%h3.panel-title
Protect a branch
.panel-body
.form-horizontal
.form-group
= f.label :name, class: 'col-md-2 text-right' do
Branch:
.col-md-10
= render partial: "dropdown", locals: { f: f }
.help-block
= link_to 'Wildcards', help_page_path('user/project/protected_branches', anchor: 'wildcard-protected-branches')
such as
%code *-stable
or
%code production/*
are supported
.form-group
%label.col-md-2.text-right{ for: 'merge_access_level_attributes' }
Allowed to merge:
.col-md-10
= dropdown_tag('Select',
options: { toggle_class: 'js-allowed-to-merge wide',
data: { field_name: 'protected_branch[merge_access_level_attributes][access_level]', input_id: 'merge_access_level_attributes' }})
.form-group
%label.col-md-2.text-right{ for: 'push_access_level_attributes' }
Allowed to push:
.col-md-10
= dropdown_tag('Select',
options: { toggle_class: 'js-allowed-to-push wide',
data: { field_name: 'protected_branch[push_access_level_attributes][access_level]', input_id: 'push_access_level_attributes' }})
.panel-footer
= f.submit 'Protect', class: 'btn-create btn', disabled: true
= f.hidden_field(:name) = f.hidden_field(:name)
= dropdown_tag("Protected Branch", = dropdown_tag('Select branch or create wildcard',
options: { title: "Pick protected branch", toggle_class: 'js-protected-branch-select js-filter-submit', options: { toggle_class: 'js-protected-branch-select js-filter-submit wide',
filter: true, dropdown_class: "dropdown-menu-selectable", placeholder: "Search protected branches", filter: true, dropdown_class: "dropdown-menu-selectable", placeholder: "Search protected branches",
footer_content: true, footer_content: true,
data: { show_no: true, show_any: true, show_upcoming: true, data: { show_no: true, show_any: true, show_upcoming: true,
selected: params[:protected_branch_name], selected: params[:protected_branch_name],
project_id: @project.try(:id) } }) do project_id: @project.try(:id) } }) do
%ul.dropdown-footer-list.hidden.protected-branch-select-footer-list %ul.dropdown-footer-list
%li %li
= link_to '#', title: "New Protected Branch", class: "create-new-protected-branch" do = link_to '#', title: "New Protected Branch", class: "create-new-protected-branch" do
Create new Create wildcard
%code
:javascript
new ProtectedBranchSelect();
- url = namespace_project_protected_branch_path(@project.namespace, @project, protected_branch) %tr.js-protected-branch-edit-form{ data: { url: namespace_project_protected_branch_path(@project.namespace, @project, protected_branch), branch_id: protected_branch.id } }
%tr
%td %td
= protected_branch.name = protected_branch.name
- if @project.root_ref?(protected_branch.name) - if @project.root_ref?(protected_branch.name)
...@@ -16,14 +15,14 @@ ...@@ -16,14 +15,14 @@
(branch was removed from repository) (branch was removed from repository)
%td %td
= hidden_field_tag "allowed_to_merge_#{protected_branch.id}", protected_branch.merge_access_level.access_level = hidden_field_tag "allowed_to_merge_#{protected_branch.id}", protected_branch.merge_access_level.access_level
= dropdown_tag(protected_branch.merge_access_level.humanize, = dropdown_tag( (protected_branch.merge_access_level.humanize || 'Select') ,
options: { title: "Allowed to merge", toggle_class: 'allowed-to-merge', dropdown_class: 'dropdown-menu-selectable merge', options: { toggle_class: 'js-allowed-to-merge', dropdown_class: 'dropdown-menu-selectable js-allowed-to-merge-container',
data: { field_name: "allowed_to_merge_#{protected_branch.id}", url: url, id: protected_branch.id, type: "merge_access_level" }}) data: { field_name: "allowed_to_merge_#{protected_branch.id}" }})
%td %td
= hidden_field_tag "allowed_to_push_#{protected_branch.id}", protected_branch.push_access_level.access_level = hidden_field_tag "allowed_to_push_#{protected_branch.id}", protected_branch.push_access_level.access_level
= dropdown_tag(protected_branch.push_access_level.humanize, = dropdown_tag( (protected_branch.push_access_level.humanize || 'Select') ,
options: { title: "Allowed to push", toggle_class: 'allowed-to-push', dropdown_class: 'dropdown-menu-selectable push', options: { toggle_class: 'js-allowed-to-push', dropdown_class: 'dropdown-menu-selectable js-allowed-to-push-container',
data: { field_name: "allowed_to_push_#{protected_branch.id}", url: url, id: protected_branch.id, type: "push_access_level" }}) data: { field_name: "allowed_to_push_#{protected_branch.id}" }})
- if can_admin_project - if can_admin_project
%td %td
= link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm pull-right" = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: 'btn btn-warning'
...@@ -14,41 +14,7 @@ ...@@ -14,41 +14,7 @@
%li prevent <strong>anyone</strong> from deleting the branch %li prevent <strong>anyone</strong> from deleting the branch
%p.append-bottom-0 Read more about #{link_to "protected branches", help_page_path("user/project/protected_branches"), class: "underlined-link"} and #{link_to "project permissions", help_page_path("user/permissions"), class: "underlined-link"}. %p.append-bottom-0 Read more about #{link_to "protected branches", help_page_path("user/project/protected_branches"), class: "underlined-link"} and #{link_to "project permissions", help_page_path("user/permissions"), class: "underlined-link"}.
.col-lg-9 .col-lg-9
%h5.prepend-top-0
Protect a branch
- if can? current_user, :admin_project, @project - if can? current_user, :admin_project, @project
= form_for [@project.namespace.becomes(Namespace), @project, @protected_branch] do |f| = render 'create_protected_branch'
= form_errors(@protected_branch)
.form-group
= f.label :name, "Branch", class: "label-light"
= render partial: "dropdown", locals: { f: f }
%p.help-block
= link_to "Wildcards", help_page_path('user/project/protected_branches', anchor: "wildcard-protected-branches")
such as
%code *-stable
or
%code production/*
are supported.
.form-group
= hidden_field_tag 'protected_branch[merge_access_level_attributes][access_level]'
= label_tag "Allowed to merge: ", nil, class: "label-light append-bottom-0"
= dropdown_tag("<Make a selection>",
options: { title: "Allowed to merge", toggle_class: 'allowed-to-merge',
dropdown_class: 'dropdown-menu-selectable',
data: { field_name: "protected_branch[merge_access_level_attributes][access_level]" }})
.form-group
= hidden_field_tag 'protected_branch[push_access_level_attributes][access_level]'
= label_tag "Allowed to push: ", nil, class: "label-light append-bottom-0"
= dropdown_tag("<Make a selection>",
options: { title: "Allowed to push", toggle_class: 'allowed-to-push',
dropdown_class: 'dropdown-menu-selectable',
data: { field_name: "protected_branch[push_access_level_attributes][access_level]" }})
= f.submit "Protect", class: "btn-create btn protect-branch-btn", disabled: true
%hr
= render "branches_list" = render "branches_list"
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
= f.label :token, "Secret Token", class: 'label-light' = f.label :token, "Secret Token", class: 'label-light'
= f.text_field :token, class: "form-control", placeholder: '' = f.text_field :token, class: "form-control", placeholder: ''
%p.help-block %p.help-block
Use this token to validate received payloads Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header.
.form-group .form-group
= f.label :url, "Trigger", class: 'label-light' = f.label :url, "Trigger", class: 'label-light'
%ul.list-unstyled %ul.list-unstyled
......
...@@ -22,5 +22,4 @@ module GeoDynamicBackoff ...@@ -22,5 +22,4 @@ module GeoDynamicBackoff
count = count - 30 # we must start counting after 30 count = count - 30 # we must start counting after 30
(count**4) + 15 + (rand(30) * (count + 1)) (count**4) + 15 + (rand(30) * (count + 1))
end end
end end
class GitlabRemoveProjectExportWorker class ImportExportProjectCleanupWorker
include Sidekiq::Worker include Sidekiq::Worker
sidekiq_options queue: :default sidekiq_options queue: :default
def perform def perform
Project.remove_gitlab_exports! ImportExportCleanUpService.new.execute
end end
end end
...@@ -11,6 +11,10 @@ class PostReceive ...@@ -11,6 +11,10 @@ class PostReceive
log("Check gitlab.yml config for correct repositories.storages values. No repository storage path matches \"#{repo_path}\"") log("Check gitlab.yml config for correct repositories.storages values. No repository storage path matches \"#{repo_path}\"")
end end
changes = Base64.decode64(changes) unless changes.include?(' ')
# Use Sidekiq.logger so arguments can be correlated with execution
# time and thread ID's.
Sidekiq.logger.info "changes: #{changes.inspect}" if ENV['SIDEKIQ_LOG_ARGUMENTS']
post_received = Gitlab::GitPostReceive.new(repo_path, identifier, changes) post_received = Gitlab::GitPostReceive.new(repo_path, identifier, changes)
if post_received.project.nil? if post_received.project.nil?
......
...@@ -12,6 +12,6 @@ class ProjectDestroyWorker ...@@ -12,6 +12,6 @@ class ProjectDestroyWorker
user = User.find(user_id) user = User.find(user_id)
::Projects::DestroyService.new(project, user, params).execute ::Projects::DestroyService.new(project, user, params.symbolize_keys).execute
end end
end end
...@@ -374,12 +374,12 @@ Settings.cron_jobs['ldap_group_sync_worker']['job_class'] = 'LdapGroupSyncWorker ...@@ -374,12 +374,12 @@ Settings.cron_jobs['ldap_group_sync_worker']['job_class'] = 'LdapGroupSyncWorker
Settings.cron_jobs['geo_bulk_notify_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['geo_bulk_notify_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['geo_bulk_notify_worker']['cron'] ||= '*/10 * * * * *' Settings.cron_jobs['geo_bulk_notify_worker']['cron'] ||= '*/10 * * * * *'
Settings.cron_jobs['geo_bulk_notify_worker']['job_class'] ||= 'GeoBulkNotifyWorker' Settings.cron_jobs['geo_bulk_notify_worker']['job_class'] ||= 'GeoBulkNotifyWorker'
Settings.cron_jobs['gitlab_remove_project_export_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['gitlab_remove_project_export_worker']['cron'] ||= '0 * * * *'
Settings.cron_jobs['gitlab_remove_project_export_worker']['job_class'] = 'GitlabRemoveProjectExportWorker'
Settings.cron_jobs['gitlab_usage_ping_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['gitlab_usage_ping_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['gitlab_usage_ping_worker']['cron'] ||= Settings.send(:cron_random_weekly_time) Settings.cron_jobs['gitlab_usage_ping_worker']['cron'] ||= Settings.send(:cron_random_weekly_time)
Settings.cron_jobs['gitlab_usage_ping_worker']['job_class'] = 'GitlabUsagePingWorker' Settings.cron_jobs['gitlab_usage_ping_worker']['job_class'] = 'GitlabUsagePingWorker'
Settings.cron_jobs['import_export_project_cleanup_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['import_export_project_cleanup_worker']['cron'] ||= '0 * * * *'
Settings.cron_jobs['import_export_project_cleanup_worker']['job_class'] = 'ImportExportProjectCleanupWorker'
Settings.cron_jobs['requests_profiles_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['requests_profiles_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['requests_profiles_worker']['cron'] ||= '0 0 * * *' Settings.cron_jobs['requests_profiles_worker']['cron'] ||= '0 0 * * *'
Settings.cron_jobs['requests_profiles_worker']['job_class'] = 'RequestsProfilesWorker' Settings.cron_jobs['requests_profiles_worker']['job_class'] = 'RequestsProfilesWorker'
......
...@@ -145,6 +145,9 @@ if Gitlab::Metrics.enabled? ...@@ -145,6 +145,9 @@ if Gitlab::Metrics.enabled?
config.instrument_methods(Rinku) config.instrument_methods(Rinku)
config.instrument_instance_methods(Repository) config.instrument_instance_methods(Repository)
config.instrument_methods(Gitlab::Highlight)
config.instrument_instance_methods(Gitlab::Highlight)
end end
GC::Profiler.enable GC::Profiler.enable
......
...@@ -8,26 +8,26 @@ class Gitlab::Seeder::Builds ...@@ -8,26 +8,26 @@ class Gitlab::Seeder::Builds
def seed! def seed!
pipelines.each do |pipeline| pipelines.each do |pipeline|
begin begin
build_create!(pipeline, name: 'build:linux', stage: 'build') build_create!(pipeline, name: 'build:linux', stage: 'build', status_event: :success)
build_create!(pipeline, name: 'build:osx', stage: 'build') build_create!(pipeline, name: 'build:osx', stage: 'build', status_event: :success)
build_create!(pipeline, name: 'slack post build', stage: 'notify_build') build_create!(pipeline, name: 'slack post build', stage: 'notify_build', status_event: :success)
build_create!(pipeline, name: 'rspec:linux', stage: 'test') build_create!(pipeline, name: 'rspec:linux', stage: 'test', status_event: :success)
build_create!(pipeline, name: 'rspec:windows', stage: 'test') build_create!(pipeline, name: 'rspec:windows', stage: 'test', status_event: :success)
build_create!(pipeline, name: 'rspec:windows', stage: 'test') build_create!(pipeline, name: 'rspec:windows', stage: 'test', status_event: :success)
build_create!(pipeline, name: 'rspec:osx', stage: 'test') build_create!(pipeline, name: 'rspec:osx', stage: 'test', status_event: :success)
build_create!(pipeline, name: 'spinach:linux', stage: 'test') build_create!(pipeline, name: 'spinach:linux', stage: 'test', status: :pending)
build_create!(pipeline, name: 'spinach:osx', stage: 'test') build_create!(pipeline, name: 'spinach:osx', stage: 'test', status_event: :cancel)
build_create!(pipeline, name: 'cucumber:linux', stage: 'test') build_create!(pipeline, name: 'cucumber:linux', stage: 'test', status_event: :run)
build_create!(pipeline, name: 'cucumber:osx', stage: 'test') build_create!(pipeline, name: 'cucumber:osx', stage: 'test', status_event: :drop)
build_create!(pipeline, name: 'slack post test', stage: 'notify_test') build_create!(pipeline, name: 'slack post test', stage: 'notify_test', status_event: :success)
build_create!(pipeline, name: 'staging', stage: 'deploy', environment: 'staging') build_create!(pipeline, name: 'staging', stage: 'deploy', environment: 'staging', status_event: :success)
build_create!(pipeline, name: 'production', stage: 'deploy', environment: 'production', when: 'manual') build_create!(pipeline, name: 'production', stage: 'deploy', environment: 'production', when: 'manual', status: :success)
commit_status_create!(pipeline, name: 'jenkins') commit_status_create!(pipeline, name: 'jenkins', status: :success)
print '.' print '.'
rescue ActiveRecord::RecordInvalid rescue ActiveRecord::RecordInvalid
...@@ -48,7 +48,7 @@ class Gitlab::Seeder::Builds ...@@ -48,7 +48,7 @@ class Gitlab::Seeder::Builds
def build_create!(pipeline, opts = {}) def build_create!(pipeline, opts = {})
attributes = build_attributes_for(pipeline, opts) attributes = build_attributes_for(pipeline, opts)
build = Ci::Build.new(attributes) build = Ci::Build.create!(attributes)
if opts[:name].start_with?('build') if opts[:name].start_with?('build')
artifacts_cache_file(artifacts_archive_path) do |file| artifacts_cache_file(artifacts_archive_path) do |file|
...@@ -60,9 +60,6 @@ class Gitlab::Seeder::Builds ...@@ -60,9 +60,6 @@ class Gitlab::Seeder::Builds
end end
end end
build.save!
build.update(status: build_status)
if %w(running success failed).include?(build.status) if %w(running success failed).include?(build.status)
# We need to set build trace after saving a build (id required) # We need to set build trace after saving a build (id required)
build.trace = FFaker::Lorem.paragraphs(6).join("\n\n") build.trace = FFaker::Lorem.paragraphs(6).join("\n\n")
...@@ -71,12 +68,12 @@ class Gitlab::Seeder::Builds ...@@ -71,12 +68,12 @@ class Gitlab::Seeder::Builds
def commit_status_create!(pipeline, opts = {}) def commit_status_create!(pipeline, opts = {})
attributes = commit_status_attributes_for(pipeline, opts) attributes = commit_status_attributes_for(pipeline, opts)
GenericCommitStatus.create(attributes) GenericCommitStatus.create!(attributes)
end end
def commit_status_attributes_for(pipeline, opts) def commit_status_attributes_for(pipeline, opts)
{ name: 'test build', stage: 'test', stage_idx: stage_index(opts[:stage]), { name: 'test build', stage: 'test', stage_idx: stage_index(opts[:stage]),
ref: 'master', user: build_user, project: @project, pipeline: pipeline, ref: 'master', tag: false, user: build_user, project: @project, pipeline: pipeline,
created_at: Time.now, updated_at: Time.now created_at: Time.now, updated_at: Time.now
}.merge(opts) }.merge(opts)
end end
......
...@@ -14,7 +14,7 @@ class MoveFromDevelopersCanMergeToProtectedBranchesMergeAccess < ActiveRecord::M ...@@ -14,7 +14,7 @@ class MoveFromDevelopersCanMergeToProtectedBranchesMergeAccess < ActiveRecord::M
def up def up
execute <<-HEREDOC execute <<-HEREDOC
INSERT into protected_branch_merge_access_levels (protected_branch_id, access_level, created_at, updated_at) INSERT into protected_branch_merge_access_levels (protected_branch_id, access_level, created_at, updated_at)
SELECT id, (CASE WHEN developers_can_merge THEN 1 ELSE 0 END), now(), now() SELECT id, (CASE WHEN developers_can_merge THEN 30 ELSE 40 END), now(), now()
FROM protected_branches FROM protected_branches
HEREDOC HEREDOC
end end
...@@ -23,7 +23,7 @@ class MoveFromDevelopersCanMergeToProtectedBranchesMergeAccess < ActiveRecord::M ...@@ -23,7 +23,7 @@ class MoveFromDevelopersCanMergeToProtectedBranchesMergeAccess < ActiveRecord::M
execute <<-HEREDOC execute <<-HEREDOC
UPDATE protected_branches SET developers_can_merge = TRUE UPDATE protected_branches SET developers_can_merge = TRUE
WHERE id IN (SELECT protected_branch_id FROM protected_branch_merge_access_levels WHERE id IN (SELECT protected_branch_id FROM protected_branch_merge_access_levels
WHERE access_level = 1); WHERE access_level = 30);
HEREDOC HEREDOC
end end
end end
...@@ -14,7 +14,7 @@ class MoveFromDevelopersCanPushToProtectedBranchesPushAccess < ActiveRecord::Mig ...@@ -14,7 +14,7 @@ class MoveFromDevelopersCanPushToProtectedBranchesPushAccess < ActiveRecord::Mig
def up def up
execute <<-HEREDOC execute <<-HEREDOC
INSERT into protected_branch_push_access_levels (protected_branch_id, access_level, created_at, updated_at) INSERT into protected_branch_push_access_levels (protected_branch_id, access_level, created_at, updated_at)
SELECT id, (CASE WHEN developers_can_push THEN 1 ELSE 0 END), now(), now() SELECT id, (CASE WHEN developers_can_push THEN 30 ELSE 40 END), now(), now()
FROM protected_branches FROM protected_branches
HEREDOC HEREDOC
end end
...@@ -23,7 +23,7 @@ class MoveFromDevelopersCanPushToProtectedBranchesPushAccess < ActiveRecord::Mig ...@@ -23,7 +23,7 @@ class MoveFromDevelopersCanPushToProtectedBranchesPushAccess < ActiveRecord::Mig
execute <<-HEREDOC execute <<-HEREDOC
UPDATE protected_branches SET developers_can_push = TRUE UPDATE protected_branches SET developers_can_push = TRUE
WHERE id IN (SELECT protected_branch_id FROM protected_branch_push_access_levels WHERE id IN (SELECT protected_branch_id FROM protected_branch_push_access_levels
WHERE access_level = 1); WHERE access_level = 30);
HEREDOC HEREDOC
end end
end end
...@@ -14,6 +14,6 @@ class RemoveDevelopersCanPushFromProtectedBranches < ActiveRecord::Migration ...@@ -14,6 +14,6 @@ class RemoveDevelopersCanPushFromProtectedBranches < ActiveRecord::Migration
end end
def down def down
add_column_with_default(:protected_branches, :developers_can_push, :boolean, default: false, null: false) add_column_with_default(:protected_branches, :developers_can_push, :boolean, default: false, allow_null: false)
end end
end end
...@@ -14,6 +14,6 @@ class RemoveDevelopersCanMergeFromProtectedBranches < ActiveRecord::Migration ...@@ -14,6 +14,6 @@ class RemoveDevelopersCanMergeFromProtectedBranches < ActiveRecord::Migration
end end
def down def down
add_column_with_default(:protected_branches, :developers_can_merge, :boolean, default: false, null: false) add_column_with_default(:protected_branches, :developers_can_merge, :boolean, default: false, allow_null: false)
end end
end end
class RemoveBuildsEnableIndexOnProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
remove_index :projects, column: :builds_enabled if index_exists?(:projects, :builds_enabled)
end
end
# rubocop:disable all
# 20141121133009_add_timestamps_to_members.rb was meant to ensure that all
# rows in the members table had created_at and updated_at set, following an
# error in a previous migration. This failed to set all rows in at least one
# case: https://gitlab.com/gitlab-org/gitlab-ce/issues/20568
#
# Why this happened is lost in the mists of time, so repeat the SQL query
# without speculation, just in case more than one person was affected.
class AddTimestampsToMembersAgain < ActiveRecord::Migration
DOWNTIME = false
def up
execute "UPDATE members SET created_at = NOW() WHERE created_at IS NULL"
execute "UPDATE members SET updated_at = NOW() WHERE updated_at IS NULL"
end
def down
# no change
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160726093600) do ActiveRecord::Schema.define(version: 20160804150737) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -969,7 +969,6 @@ ActiveRecord::Schema.define(version: 20160726093600) do ...@@ -969,7 +969,6 @@ ActiveRecord::Schema.define(version: 20160726093600) do
end end
add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree
add_index "projects", ["builds_enabled"], name: "index_projects_on_builds_enabled", using: :btree
add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree
add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree
add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
......
...@@ -68,7 +68,5 @@ ...@@ -68,7 +68,5 @@
## Contributor documentation ## Contributor documentation
- [Documentation styleguide](development/doc_styleguide.md) Use this styleguide if you are - [Development](development/README.md) All styleguides and explanations how to contribute.
contributing to documentation.
- [Development](development/README.md) Explains the architecture and the guidelines for shell commands.
- [Legal](legal/README.md) Contributor license agreements. - [Legal](legal/README.md) Contributor license agreements.
# GitLab Container Registry Administration # GitLab Container Registry Administration
> **Note:** > [Introduced][ce-4040] in GitLab 8.8.
This feature was [introduced][ce-4040] in GitLab 8.8.
With the Docker Container Registry integrated into GitLab, every project can With the Docker Container Registry integrated into GitLab, every project can
have its own space to store its Docker images. have its own space to store its Docker images.
......
...@@ -44,8 +44,7 @@ as appropriate. ...@@ -44,8 +44,7 @@ as appropriate.
## Custom error messages ## Custom error messages
>**Note:** > [Introduced][5073] in GitLab 8.10.
This feature was [introduced][5073] in GitLab 8.10.
If the commit is declined or an error occurs during the Git hook check, If the commit is declined or an error occurs during the Git hook check,
the STDERR or STDOUT message of the hook will be present in GitLab's UI. the STDERR or STDOUT message of the hook will be present in GitLab's UI.
......
# Housekeeping # Housekeeping
_**Note:** This feature was [introduced][ce-2371] in GitLab 8.4_ > [Introduced][ce-2371] in GitLab 8.4.
--- ---
......
# Project import/export # Project import/export
>**Note:** >**Note:**
- This feature was [introduced][ce-3050] in GitLab 8.9 >
- Importing will not be possible if the import instance version is lower > - [Introduced][ce-3050] in GitLab 8.9.
than that of the exporter. > - Importing will not be possible if the import instance version is lower
- For existing installations, the project import option has to be enabled in > than that of the exporter.
application settings (`/admin/application_settings`) under 'Import sources'. > - For existing installations, the project import option has to be enabled in
- The exports are stored in a temporary [shared directory][tmp] and are deleted > application settings (`/admin/application_settings`) under 'Import sources'.
every 24 hours by a specific worker. > - The exports are stored in a temporary [shared directory][tmp] and are deleted
> every 24 hours by a specific worker.
The GitLab Import/Export version can be checked by using: The GitLab Import/Export version can be checked by using:
......
# Repository checks # Repository checks
>**Note:** > [Introduced][ce-3232] in GitLab 8.7. It is OFF by default because it still
This feature was [introduced][ce-3232] in GitLab 8.7. It is OFF by causes too many false alarms.
default because it still causes too many false alarms.
Git has a built-in mechanism, [git fsck][git-fsck], to verify the Git has a built-in mechanism, [git fsck][git-fsck], to verify the
integrity of all data committed to a repository. GitLab administrators integrity of all data committed to a repository. GitLab administrators
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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