diff options
203 files changed, 1962 insertions, 1987 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b2ee157193..9a26bed3d29 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,9 +1,13 @@ -## Contributor license agreement +## Developer Certificate of Origin + License -By submitting code as an individual you agree to the -[individual contributor license agreement](doc/legal/individual_contributor_license_agreement.md). -By submitting code as an entity you agree to the -[corporate contributor license agreement](doc/legal/corporate_contributor_license_agreement.md). +By contributing to GitLab B.V., You accept and agree to the following terms and +conditions for Your present and future Contributions submitted to GitLab B.V. +Except for the license granted herein to GitLab B.V. and recipients of software +distributed by GitLab B.V., You reserve all right, title, and interest in and to +Your Contributions. All Contributions are subject to the following DCO + License +terms. + +[DCO + License](https://gitlab.com/gitlab-org/dco/blob/master/README.md) _This notice should stay as the first item in the CONTRIBUTING.md file._ diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index 944880fa15e..15a27998172 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -3.2.0 +3.3.0 diff --git a/Gemfile.lock b/Gemfile.lock index 4142977285e..8ccf18818a6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -291,7 +291,7 @@ GEM diff-lcs (~> 1.1) mime-types (>= 1.16) posix-spawn (~> 0.3) - gitlab-markup (1.6.2) + gitlab-markup (1.6.3) gitlab_omniauth-ldap (2.0.4) net-ldap (~> 0.16) omniauth (~> 1.3) diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js index 5d27518ac85..9ae5e270a4b 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js +++ b/app/assets/javascripts/boards/components/board_sidebar.js @@ -1,6 +1,5 @@ /* eslint-disable comma-dangle, space-before-function-paren, no-new */ /* global MilestoneSelect */ -/* global LabelsSelect */ /* global Sidebar */ import Vue from 'vue'; @@ -11,6 +10,7 @@ import Assignees from '../../sidebar/components/assignees/assignees'; import DueDateSelectors from '../../due_date_select'; import './sidebar/remove_issue'; import IssuableContext from '../../issuable_context'; +import LabelsSelect from '../../labels_select'; const Store = gl.issueBoards.BoardsStore; diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index b516fda84b9..5930868412b 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -3,7 +3,7 @@ import IssuableIndex from './issuable_index'; /* global Milestone */ import IssuableForm from './issuable_form'; -/* global LabelsSelect */ +import LabelsSelect from './labels_select'; /* global MilestoneSelect */ /* global NewBranchForm */ /* global NotificationsForm */ diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index e8d8fef8579..c4202f92443 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -1,6 +1,7 @@ /* eslint-disable func-names, no-underscore-dangle, space-before-function-paren, no-var, one-var, one-var-declaration-per-line, prefer-rest-params, max-len, vars-on-top, wrap-iife, no-unused-vars, quotes, no-shadow, no-cond-assign, prefer-arrow-callback, no-return-assign, no-else-return, camelcase, comma-dangle, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, prefer-template, no-param-reassign, no-loop-func, no-mixed-operators */ /* global fuzzaldrinPlus */ import _ from 'underscore'; +import fuzzaldrinPlus from 'fuzzaldrin-plus'; import { isObject } from './lib/utils/type_utility'; var GitLabDropdown, GitLabDropdownFilter, GitLabDropdownRemote, GitLabDropdownInput; diff --git a/app/assets/javascripts/init_issuable_sidebar.js b/app/assets/javascripts/init_issuable_sidebar.js index 6f476f96f72..1191e0b895e 100644 --- a/app/assets/javascripts/init_issuable_sidebar.js +++ b/app/assets/javascripts/init_issuable_sidebar.js @@ -1,6 +1,6 @@ /* eslint-disable no-new */ /* global MilestoneSelect */ -/* global LabelsSelect */ +import LabelsSelect from './labels_select'; import IssuableContext from './issuable_context'; /* global Sidebar */ diff --git a/app/assets/javascripts/init_legacy_filters.js b/app/assets/javascripts/init_legacy_filters.js index fcf424408f2..1b265721581 100644 --- a/app/assets/javascripts/init_legacy_filters.js +++ b/app/assets/javascripts/init_legacy_filters.js @@ -1,5 +1,5 @@ /* eslint-disable no-new */ -/* global LabelsSelect */ +import LabelsSelect from './labels_select'; /* global MilestoneSelect */ /* global SubscriptionSelect */ diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar.js index 4a15ec8b147..af6358953cf 100644 --- a/app/assets/javascripts/issuable_bulk_update_sidebar.js +++ b/app/assets/javascripts/issuable_bulk_update_sidebar.js @@ -1,5 +1,4 @@ /* eslint-disable class-methods-use-this, no-new */ -/* global LabelsSelect */ /* global MilestoneSelect */ /* global SubscriptionSelect */ @@ -7,7 +6,7 @@ import IssuableBulkUpdateActions from './issuable_bulk_update_actions'; import './milestone_select'; import issueStatusSelect from './issue_status_select'; import './subscription_select'; -import './labels_select'; +import LabelsSelect from './labels_select'; const HIDDEN_CLASS = 'hidden'; const DISABLED_CONTENT_CLASS = 'disabled-content'; diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index 84602cf9207..9b35efcb499 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -6,474 +6,470 @@ import IssuableBulkUpdateActions from './issuable_bulk_update_actions'; import DropdownUtils from './filtered_search/dropdown_utils'; import CreateLabelDropdown from './create_label'; -(function() { - this.LabelsSelect = (function() { - function LabelsSelect(els) { - var _this, $els; - _this = this; +export default class LabelsSelect { + constructor(els) { + var _this, $els; + _this = this; - $els = $(els); + $els = $(els); - if (!els) { - $els = $('.js-label-select'); - } + if (!els) { + $els = $('.js-label-select'); + } - $els.each(function(i, dropdown) { - var $block, $colorPreview, $dropdown, $form, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, defaultLabel, enableLabelCreateButton, issueURLSplit, issueUpdateURL, labelHTMLTemplate, labelNoneHTMLTemplate, labelUrl, namespacePath, projectPath, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected, $toggleText, fieldName, useId, propertyName, showMenuAbove, $container, $dropdownContainer; - $dropdown = $(dropdown); - $dropdownContainer = $dropdown.closest('.labels-filter'); - $toggleText = $dropdown.find('.dropdown-toggle-text'); - namespacePath = $dropdown.data('namespace-path'); - projectPath = $dropdown.data('project-path'); - labelUrl = $dropdown.data('labels'); - issueUpdateURL = $dropdown.data('issueUpdate'); - selectedLabel = $dropdown.data('selected'); - if ((selectedLabel != null) && !$dropdown.hasClass('js-multiselect')) { - selectedLabel = selectedLabel.split(','); - } - showNo = $dropdown.data('show-no'); - showAny = $dropdown.data('show-any'); - showMenuAbove = $dropdown.data('showMenuAbove'); - defaultLabel = $dropdown.data('default-label'); - abilityName = $dropdown.data('ability-name'); - $selectbox = $dropdown.closest('.selectbox'); - $block = $selectbox.closest('.block'); - $form = $dropdown.closest('form, .js-issuable-update'); - $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon span'); - $sidebarLabelTooltip = $block.find('.js-sidebar-labels-tooltip'); - $value = $block.find('.value'); - $loading = $block.find('.block-loading').fadeOut(); - fieldName = $dropdown.data('field-name'); - useId = $dropdown.is('.js-issuable-form-dropdown, .js-filter-bulk-update, .js-label-sidebar-dropdown'); - propertyName = useId ? 'id' : 'title'; - initialSelected = $selectbox - .find('input[name="' + $dropdown.data('field-name') + '"]') - .map(function () { - return this.value; - }).get(); - if (issueUpdateURL != null) { - issueURLSplit = issueUpdateURL.split('/'); - } - if (issueUpdateURL) { - labelHTMLTemplate = _.template('<% _.each(labels, function(label){ %> <a href="<%- ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name[]=<%- encodeURIComponent(label.title) %>"> <span class="label has-tooltip color-label" title="<%- label.description %>" style="background-color: <%- label.color %>; color: <%- label.text_color %>;"> <%- label.title %> </span> </a> <% }); %>'); - labelNoneHTMLTemplate = '<span class="no-value">None</span>'; - } + $els.each(function(i, dropdown) { + var $block, $colorPreview, $dropdown, $form, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, defaultLabel, enableLabelCreateButton, issueURLSplit, issueUpdateURL, labelHTMLTemplate, labelNoneHTMLTemplate, labelUrl, namespacePath, projectPath, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected, $toggleText, fieldName, useId, propertyName, showMenuAbove, $container, $dropdownContainer; + $dropdown = $(dropdown); + $dropdownContainer = $dropdown.closest('.labels-filter'); + $toggleText = $dropdown.find('.dropdown-toggle-text'); + namespacePath = $dropdown.data('namespace-path'); + projectPath = $dropdown.data('project-path'); + labelUrl = $dropdown.data('labels'); + issueUpdateURL = $dropdown.data('issueUpdate'); + selectedLabel = $dropdown.data('selected'); + if ((selectedLabel != null) && !$dropdown.hasClass('js-multiselect')) { + selectedLabel = selectedLabel.split(','); + } + showNo = $dropdown.data('show-no'); + showAny = $dropdown.data('show-any'); + showMenuAbove = $dropdown.data('showMenuAbove'); + defaultLabel = $dropdown.data('default-label'); + abilityName = $dropdown.data('ability-name'); + $selectbox = $dropdown.closest('.selectbox'); + $block = $selectbox.closest('.block'); + $form = $dropdown.closest('form, .js-issuable-update'); + $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon span'); + $sidebarLabelTooltip = $block.find('.js-sidebar-labels-tooltip'); + $value = $block.find('.value'); + $loading = $block.find('.block-loading').fadeOut(); + fieldName = $dropdown.data('field-name'); + useId = $dropdown.is('.js-issuable-form-dropdown, .js-filter-bulk-update, .js-label-sidebar-dropdown'); + propertyName = useId ? 'id' : 'title'; + initialSelected = $selectbox + .find('input[name="' + $dropdown.data('field-name') + '"]') + .map(function () { + return this.value; + }).get(); + if (issueUpdateURL != null) { + issueURLSplit = issueUpdateURL.split('/'); + } + if (issueUpdateURL) { + labelHTMLTemplate = _.template('<% _.each(labels, function(label){ %> <a href="<%- ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name[]=<%- encodeURIComponent(label.title) %>"> <span class="label has-tooltip color-label" title="<%- label.description %>" style="background-color: <%- label.color %>; color: <%- label.text_color %>;"> <%- label.title %> </span> </a> <% }); %>'); + labelNoneHTMLTemplate = '<span class="no-value">None</span>'; + } - $sidebarLabelTooltip.tooltip(); + $sidebarLabelTooltip.tooltip(); - if ($dropdown.closest('.dropdown').find('.dropdown-new-label').length) { - new CreateLabelDropdown($dropdown.closest('.dropdown').find('.dropdown-new-label'), namespacePath, projectPath); - } + if ($dropdown.closest('.dropdown').find('.dropdown-new-label').length) { + new CreateLabelDropdown($dropdown.closest('.dropdown').find('.dropdown-new-label'), namespacePath, projectPath); + } - saveLabelData = function() { - var data, selected; - selected = $dropdown.closest('.selectbox').find("input[name='" + fieldName + "']").map(function() { - return this.value; - }).get(); + saveLabelData = function() { + var data, selected; + selected = $dropdown.closest('.selectbox').find("input[name='" + fieldName + "']").map(function() { + return this.value; + }).get(); - if (_.isEqual(initialSelected, selected)) return; - initialSelected = selected; + if (_.isEqual(initialSelected, selected)) return; + initialSelected = selected; - data = {}; - data[abilityName] = {}; - data[abilityName].label_ids = selected; - if (!selected.length) { - data[abilityName].label_ids = ['']; + data = {}; + data[abilityName] = {}; + data[abilityName].label_ids = selected; + if (!selected.length) { + data[abilityName].label_ids = ['']; + } + $loading.removeClass('hidden').fadeIn(); + $dropdown.trigger('loading.gl.dropdown'); + return $.ajax({ + type: 'PUT', + url: issueUpdateURL, + dataType: 'JSON', + data: data + }).done(function(data) { + var labelCount, template, labelTooltipTitle, labelTitles; + $loading.fadeOut(); + $dropdown.trigger('loaded.gl.dropdown'); + $selectbox.hide(); + data.issueURLSplit = issueURLSplit; + labelCount = 0; + if (data.labels.length) { + template = labelHTMLTemplate(data); + labelCount = data.labels.length; } - $loading.removeClass('hidden').fadeIn(); - $dropdown.trigger('loading.gl.dropdown'); - return $.ajax({ - type: 'PUT', - url: issueUpdateURL, - dataType: 'JSON', - data: data - }).done(function(data) { - var labelCount, template, labelTooltipTitle, labelTitles; - $loading.fadeOut(); - $dropdown.trigger('loaded.gl.dropdown'); - $selectbox.hide(); - data.issueURLSplit = issueURLSplit; - labelCount = 0; - if (data.labels.length) { - template = labelHTMLTemplate(data); - labelCount = data.labels.length; - } - else { - template = labelNoneHTMLTemplate; - } - $value.removeAttr('style').html(template); - $sidebarCollapsedValue.text(labelCount); - - if (data.labels.length) { - labelTitles = data.labels.map(function(label) { - return label.title; - }); + else { + template = labelNoneHTMLTemplate; + } + $value.removeAttr('style').html(template); + $sidebarCollapsedValue.text(labelCount); - if (labelTitles.length > 5) { - labelTitles = labelTitles.slice(0, 5); - labelTitles.push('and ' + (data.labels.length - 5) + ' more'); - } + if (data.labels.length) { + labelTitles = data.labels.map(function(label) { + return label.title; + }); - labelTooltipTitle = labelTitles.join(', '); - } - else { - labelTooltipTitle = ''; - $sidebarLabelTooltip.tooltip('destroy'); + if (labelTitles.length > 5) { + labelTitles = labelTitles.slice(0, 5); + labelTitles.push('and ' + (data.labels.length - 5) + ' more'); } - $sidebarLabelTooltip - .attr('title', labelTooltipTitle) - .tooltip('fixTitle'); + labelTooltipTitle = labelTitles.join(', '); + } + else { + labelTooltipTitle = ''; + $sidebarLabelTooltip.tooltip('destroy'); + } - $('.has-tooltip', $value).tooltip({ - container: 'body' - }); + $sidebarLabelTooltip + .attr('title', labelTooltipTitle) + .tooltip('fixTitle'); + + $('.has-tooltip', $value).tooltip({ + container: 'body' }); - }; - $dropdown.glDropdown({ - showMenuAbove: showMenuAbove, - data: function(term, callback) { - return $.ajax({ - url: labelUrl - }).done(function(data) { - data = _.chain(data).groupBy(function(label) { - return label.title; - }).map(function(label) { - var color; - color = _.map(label, function(dup) { - return dup.color; + }); + }; + $dropdown.glDropdown({ + showMenuAbove: showMenuAbove, + data: function(term, callback) { + return $.ajax({ + url: labelUrl + }).done(function(data) { + data = _.chain(data).groupBy(function(label) { + return label.title; + }).map(function(label) { + var color; + color = _.map(label, function(dup) { + return dup.color; + }); + return { + id: label[0].id, + title: label[0].title, + color: color, + duplicate: color.length > 1 + }; + }).value(); + if ($dropdown.hasClass('js-extra-options')) { + var extraData = []; + if (showNo) { + extraData.unshift({ + id: 0, + title: 'No Label' }); - return { - id: label[0].id, - title: label[0].title, - color: color, - duplicate: color.length > 1 - }; - }).value(); - if ($dropdown.hasClass('js-extra-options')) { - var extraData = []; - if (showNo) { - extraData.unshift({ - id: 0, - title: 'No Label' - }); - } - if (showAny) { - extraData.unshift({ - isAny: true, - title: 'Any Label' - }); - } - if (extraData.length) { - extraData.push('divider'); - data = extraData.concat(data); - } - } - - callback(data); - if (showMenuAbove) { - $dropdown.data('glDropdown').positionMenuAbove(); - } - }); - }, - renderRow: function(label, instance) { - var $a, $li, color, colorEl, indeterminate, removesAll, selectedClass, spacing, i, marked, dropdownName, dropdownValue; - $li = $('<li>'); - $a = $('<a href="#">'); - selectedClass = []; - removesAll = label.id <= 0 || (label.id == null); - if ($dropdown.hasClass('js-filter-bulk-update')) { - indeterminate = $dropdown.data('indeterminate') || []; - marked = $dropdown.data('marked') || []; - - if (indeterminate.indexOf(label.id) !== -1) { - selectedClass.push('is-indeterminate'); } - - if (marked.indexOf(label.id) !== -1) { - // Remove is-indeterminate class if the item will be marked as active - i = selectedClass.indexOf('is-indeterminate'); - if (i !== -1) { - selectedClass.splice(i, 1); - } - selectedClass.push('is-active'); + if (showAny) { + extraData.unshift({ + isAny: true, + title: 'Any Label' + }); } - } else { - if (this.id(label)) { - dropdownName = $dropdown.data('fieldName'); - dropdownValue = this.id(label).toString().replace(/'/g, '\\\''); - - if ($form.find("input[type='hidden'][name='" + dropdownName + "'][value='" + dropdownValue + "']").length) { - selectedClass.push('is-active'); - } + if (extraData.length) { + extraData.push('divider'); + data = extraData.concat(data); } + } - if ($dropdown.hasClass('js-multiselect') && removesAll) { - selectedClass.push('dropdown-clear-active'); - } + callback(data); + if (showMenuAbove) { + $dropdown.data('glDropdown').positionMenuAbove(); } - if (label.duplicate) { - color = gl.DropdownUtils.duplicateLabelColor(label.color); + }); + }, + renderRow: function(label, instance) { + var $a, $li, color, colorEl, indeterminate, removesAll, selectedClass, spacing, i, marked, dropdownName, dropdownValue; + $li = $('<li>'); + $a = $('<a href="#">'); + selectedClass = []; + removesAll = label.id <= 0 || (label.id == null); + if ($dropdown.hasClass('js-filter-bulk-update')) { + indeterminate = $dropdown.data('indeterminate') || []; + marked = $dropdown.data('marked') || []; + + if (indeterminate.indexOf(label.id) !== -1) { + selectedClass.push('is-indeterminate'); } - else { - if (label.color != null) { - color = label.color[0]; + + if (marked.indexOf(label.id) !== -1) { + // Remove is-indeterminate class if the item will be marked as active + i = selectedClass.indexOf('is-indeterminate'); + if (i !== -1) { + selectedClass.splice(i, 1); } + selectedClass.push('is-active'); } - if (color) { - colorEl = "<span class='dropdown-label-box' style='background: " + color + "'></span>"; - } - else { - colorEl = ''; - } - // We need to identify which items are actually labels - if (label.id) { - selectedClass.push('label-item'); - $a.attr('data-label-id', label.id); - } - $a.addClass(selectedClass.join(' ')).html(colorEl + " " + label.title); - // Return generated html - return $li.html($a).prop('outerHTML'); - }, - search: { - fields: ['title'] - }, - selectable: true, - filterable: true, - selected: $dropdown.data('selected') || [], - toggleLabel: function(selected, el) { - var isSelected = el !== null ? el.hasClass('is-active') : false; - var title = selected.title; - var selectedLabels = this.selected; - - if (selected.id === 0) { - this.selected = []; - return 'No Label'; + } else { + if (this.id(label)) { + dropdownName = $dropdown.data('fieldName'); + dropdownValue = this.id(label).toString().replace(/'/g, '\\\''); + + if ($form.find("input[type='hidden'][name='" + dropdownName + "'][value='" + dropdownValue + "']").length) { + selectedClass.push('is-active'); + } } - else if (isSelected) { - this.selected.push(title); + + if ($dropdown.hasClass('js-multiselect') && removesAll) { + selectedClass.push('dropdown-clear-active'); } - else { - var index = this.selected.indexOf(title); - this.selected.splice(index, 1); + } + if (label.duplicate) { + color = gl.DropdownUtils.duplicateLabelColor(label.color); + } + else { + if (label.color != null) { + color = label.color[0]; } + } + if (color) { + colorEl = "<span class='dropdown-label-box' style='background: " + color + "'></span>"; + } + else { + colorEl = ''; + } + // We need to identify which items are actually labels + if (label.id) { + selectedClass.push('label-item'); + $a.attr('data-label-id', label.id); + } + $a.addClass(selectedClass.join(' ')).html(colorEl + " " + label.title); + // Return generated html + return $li.html($a).prop('outerHTML'); + }, + search: { + fields: ['title'] + }, + selectable: true, + filterable: true, + selected: $dropdown.data('selected') || [], + toggleLabel: function(selected, el) { + var isSelected = el !== null ? el.hasClass('is-active') : false; + var title = selected.title; + var selectedLabels = this.selected; + + if (selected.id === 0) { + this.selected = []; + return 'No Label'; + } + else if (isSelected) { + this.selected.push(title); + } + else { + var index = this.selected.indexOf(title); + this.selected.splice(index, 1); + } + + if (selectedLabels.length === 1) { + return selectedLabels; + } + else if (selectedLabels.length) { + return selectedLabels[0] + " +" + (selectedLabels.length - 1) + " more"; + } + else { + return defaultLabel; + } + }, + fieldName: $dropdown.data('field-name'), + id: function(label) { + if (label.id <= 0) return label.title; + + if ($dropdown.hasClass('js-issuable-form-dropdown')) { + return label.id; + } - if (selectedLabels.length === 1) { - return selectedLabels; + if ($dropdown.hasClass("js-filter-submit") && (label.isAny == null)) { + return label.title; + } + else { + return label.id; + } + }, + hidden: function() { + var isIssueIndex, isMRIndex, page, selectedLabels; + page = $('body').attr('data-page'); + isIssueIndex = page === 'projects:issues:index'; + isMRIndex = page === 'projects:merge_requests:index'; + $selectbox.hide(); + // display:block overrides the hide-collapse rule + $value.removeAttr('style'); + + if ($dropdown.hasClass('js-issuable-form-dropdown')) { + return; + } + + if ($('html').hasClass('issue-boards-page')) { + return; + } + if ($dropdown.hasClass('js-multiselect')) { + if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) { + selectedLabels = $dropdown.closest('form').find("input:hidden[name='" + ($dropdown.data('fieldName')) + "']"); + Issuable.filterResults($dropdown.closest('form')); } - else if (selectedLabels.length) { - return selectedLabels[0] + " +" + (selectedLabels.length - 1) + " more"; + else if ($dropdown.hasClass('js-filter-submit')) { + $dropdown.closest('form').submit(); } else { - return defaultLabel; + if (!$dropdown.hasClass('js-filter-bulk-update')) { + saveLabelData(); + } } - }, - fieldName: $dropdown.data('field-name'), - id: function(label) { - if (label.id <= 0) return label.title; + } + }, + multiSelect: $dropdown.hasClass('js-multiselect'), + vue: $dropdown.hasClass('js-issue-board-sidebar'), + clicked: function(options) { + const { $el, e, isMarking } = options; + const label = options.selectedObj; + + var isIssueIndex, isMRIndex, page, boardsModel; + var fadeOutLoader = () => { + $loading.fadeOut(); + }; - if ($dropdown.hasClass('js-issuable-form-dropdown')) { - return label.id; - } + page = $('body').attr('data-page'); + isIssueIndex = page === 'projects:issues:index'; + isMRIndex = page === 'projects:merge_requests:index'; - if ($dropdown.hasClass("js-filter-submit") && (label.isAny == null)) { - return label.title; - } - else { - return label.id; - } - }, - hidden: function() { - var isIssueIndex, isMRIndex, page, selectedLabels; - page = $('body').attr('data-page'); - isIssueIndex = page === 'projects:issues:index'; - isMRIndex = page === 'projects:merge_requests:index'; - $selectbox.hide(); - // display:block overrides the hide-collapse rule - $value.removeAttr('style'); - - if ($dropdown.hasClass('js-issuable-form-dropdown')) { - return; - } + if ($dropdown.parent().find('.is-active:not(.dropdown-clear-active)').length) { + $dropdown.parent() + .find('.dropdown-clear-active') + .removeClass('is-active'); + } - if ($('html').hasClass('issue-boards-page')) { - return; - } - if ($dropdown.hasClass('js-multiselect')) { - if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) { - selectedLabels = $dropdown.closest('form').find("input:hidden[name='" + ($dropdown.data('fieldName')) + "']"); - Issuable.filterResults($dropdown.closest('form')); - } - else if ($dropdown.hasClass('js-filter-submit')) { - $dropdown.closest('form').submit(); - } - else { - if (!$dropdown.hasClass('js-filter-bulk-update')) { - saveLabelData(); - } - } - } - }, - multiSelect: $dropdown.hasClass('js-multiselect'), - vue: $dropdown.hasClass('js-issue-board-sidebar'), - clicked: function(options) { - const { $el, e, isMarking } = options; - const label = options.selectedObj; - - var isIssueIndex, isMRIndex, page, boardsModel; - var fadeOutLoader = () => { - $loading.fadeOut(); - }; - - page = $('body').attr('data-page'); - isIssueIndex = page === 'projects:issues:index'; - isMRIndex = page === 'projects:merge_requests:index'; - - if ($dropdown.parent().find('.is-active:not(.dropdown-clear-active)').length) { - $dropdown.parent() - .find('.dropdown-clear-active') - .removeClass('is-active'); - } + if ($dropdown.hasClass('js-issuable-form-dropdown')) { + return; + } - if ($dropdown.hasClass('js-issuable-form-dropdown')) { - return; - } + if ($dropdown.hasClass('js-filter-bulk-update')) { + _this.enableBulkLabelDropdown(); + _this.setDropdownData($dropdown, isMarking, label.id); + return; + } - if ($dropdown.hasClass('js-filter-bulk-update')) { - _this.enableBulkLabelDropdown(); - _this.setDropdownData($dropdown, isMarking, label.id); - return; - } + if ($dropdown.closest('.add-issues-modal').length) { + boardsModel = gl.issueBoards.ModalStore.store.filter; + } - if ($dropdown.closest('.add-issues-modal').length) { - boardsModel = gl.issueBoards.ModalStore.store.filter; + if (boardsModel) { + if (label.isAny) { + boardsModel['label_name'] = []; + } else if ($el.hasClass('is-active')) { + boardsModel['label_name'].push(label.title); } - if (boardsModel) { - if (label.isAny) { - boardsModel['label_name'] = []; - } else if ($el.hasClass('is-active')) { - boardsModel['label_name'].push(label.title); - } - - e.preventDefault(); - return; + e.preventDefault(); + return; + } + else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) { + if (!$dropdown.hasClass('js-multiselect')) { + selectedLabel = label.title; + return Issuable.filterResults($dropdown.closest('form')); } - else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) { - if (!$dropdown.hasClass('js-multiselect')) { - selectedLabel = label.title; - return Issuable.filterResults($dropdown.closest('form')); - } + } + else if ($dropdown.hasClass('js-filter-submit')) { + return $dropdown.closest('form').submit(); + } + else if ($dropdown.hasClass('js-issue-board-sidebar')) { + if ($el.hasClass('is-active')) { + gl.issueBoards.BoardsStore.detail.issue.labels.push(new ListLabel({ + id: label.id, + title: label.title, + color: label.color[0], + textColor: '#fff' + })); } - else if ($dropdown.hasClass('js-filter-submit')) { - return $dropdown.closest('form').submit(); + else { + var labels = gl.issueBoards.BoardsStore.detail.issue.labels; + labels = labels.filter(function (selectedLabel) { + return selectedLabel.id !== label.id; + }); + gl.issueBoards.BoardsStore.detail.issue.labels = labels; } - else if ($dropdown.hasClass('js-issue-board-sidebar')) { - if ($el.hasClass('is-active')) { - gl.issueBoards.BoardsStore.detail.issue.labels.push(new ListLabel({ - id: label.id, - title: label.title, - color: label.color[0], - textColor: '#fff' - })); - } - else { - var labels = gl.issueBoards.BoardsStore.detail.issue.labels; - labels = labels.filter(function (selectedLabel) { - return selectedLabel.id !== label.id; - }); - gl.issueBoards.BoardsStore.detail.issue.labels = labels; - } - $loading.fadeIn(); + $loading.fadeIn(); + + gl.issueBoards.BoardsStore.detail.issue.update($dropdown.attr('data-issue-update')) + .then(fadeOutLoader) + .catch(fadeOutLoader); + } + else { + if ($dropdown.hasClass('js-multiselect')) { - gl.issueBoards.BoardsStore.detail.issue.update($dropdown.attr('data-issue-update')) - .then(fadeOutLoader) - .catch(fadeOutLoader); } else { - if ($dropdown.hasClass('js-multiselect')) { - - } - else { - return saveLabelData(); - } + return saveLabelData(); } - }, - }); - - // Set dropdown data - _this.setOriginalDropdownData($dropdownContainer, $dropdown); + } + }, }); - this.bindEvents(); - } - LabelsSelect.prototype.bindEvents = function() { - return $('body').on('change', '.selected_issue', this.onSelectCheckboxIssue); - }; - - LabelsSelect.prototype.onSelectCheckboxIssue = function() { - if ($('.selected_issue:checked').length) { - return; + // Set dropdown data + _this.setOriginalDropdownData($dropdownContainer, $dropdown); + }); + this.bindEvents(); + } + + bindEvents() { + return $('body').on('change', '.selected_issue', this.onSelectCheckboxIssue); + } + // eslint-disable-next-line class-methods-use-this + onSelectCheckboxIssue() { + if ($('.selected_issue:checked').length) { + return; + } + return $('.issues-bulk-update .labels-filter .dropdown-toggle-text').text('Label'); + } + // eslint-disable-next-line class-methods-use-this + enableBulkLabelDropdown() { + IssuableBulkUpdateActions.willUpdateLabels = true; + } + // eslint-disable-next-line class-methods-use-this + setDropdownData($dropdown, isMarking, value) { + var i, markedIds, unmarkedIds, indeterminateIds; + + markedIds = $dropdown.data('marked') || []; + unmarkedIds = $dropdown.data('unmarked') || []; + indeterminateIds = $dropdown.data('indeterminate') || []; + + if (isMarking) { + markedIds.push(value); + + i = indeterminateIds.indexOf(value); + if (i > -1) { + indeterminateIds.splice(i, 1); } - return $('.issues-bulk-update .labels-filter .dropdown-toggle-text').text('Label'); - }; - LabelsSelect.prototype.enableBulkLabelDropdown = function() { - IssuableBulkUpdateActions.willUpdateLabels = true; - }; - - LabelsSelect.prototype.setDropdownData = function($dropdown, isMarking, value) { - var i, markedIds, unmarkedIds, indeterminateIds; - - markedIds = $dropdown.data('marked') || []; - unmarkedIds = $dropdown.data('unmarked') || []; - indeterminateIds = $dropdown.data('indeterminate') || []; - - if (isMarking) { - markedIds.push(value); - - i = indeterminateIds.indexOf(value); - if (i > -1) { - indeterminateIds.splice(i, 1); - } - - i = unmarkedIds.indexOf(value); - if (i > -1) { - unmarkedIds.splice(i, 1); - } - } else { - // If marked item (not common) is unmarked - i = markedIds.indexOf(value); - if (i > -1) { - markedIds.splice(i, 1); - } - - // If an indeterminate item is being unmarked - if (IssuableBulkUpdateActions.getOriginalIndeterminateIds().indexOf(value) > -1) { - unmarkedIds.push(value); - } - - // If a marked item is being unmarked - // (a marked item could also be a label that is present in all selection) - if (IssuableBulkUpdateActions.getOriginalCommonIds().indexOf(value) > -1) { - unmarkedIds.push(value); - } + i = unmarkedIds.indexOf(value); + if (i > -1) { + unmarkedIds.splice(i, 1); + } + } else { + // If marked item (not common) is unmarked + i = markedIds.indexOf(value); + if (i > -1) { + markedIds.splice(i, 1); } - $dropdown.data('marked', markedIds); - $dropdown.data('unmarked', unmarkedIds); - $dropdown.data('indeterminate', indeterminateIds); - }; + // If an indeterminate item is being unmarked + if (IssuableBulkUpdateActions.getOriginalIndeterminateIds().indexOf(value) > -1) { + unmarkedIds.push(value); + } - LabelsSelect.prototype.setOriginalDropdownData = function($container, $dropdown) { - var labels = []; - $container.find('[name="label_name[]"]').map(function() { - return labels.push(this.value); - }); - $dropdown.data('marked', labels); - }; + // If a marked item is being unmarked + // (a marked item could also be a label that is present in all selection) + if (IssuableBulkUpdateActions.getOriginalCommonIds().indexOf(value) > -1) { + unmarkedIds.push(value); + } + } - return LabelsSelect; - })(); -}).call(window); + $dropdown.data('marked', markedIds); + $dropdown.data('unmarked', unmarkedIds); + $dropdown.data('indeterminate', indeterminateIds); + } + // eslint-disable-next-line class-methods-use-this + setOriginalDropdownData($container, $dropdown) { + const labels = []; + $container.find('[name="label_name[]"]').map(function() { + return labels.push(this.value); + }); + $dropdown.data('marked', labels); + } +} diff --git a/app/assets/javascripts/lazy_loader.js b/app/assets/javascripts/lazy_loader.js index 3d64b121fa7..dbbf1637a47 100644 --- a/app/assets/javascripts/lazy_loader.js +++ b/app/assets/javascripts/lazy_loader.js @@ -1,5 +1,3 @@ -/* eslint-disable one-export, one-var, one-var-declaration-per-line */ - import _ from 'underscore'; export const placeholderImage = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; @@ -21,7 +19,10 @@ export default class LazyLoader { } searchLazyImages() { this.lazyImages = [].slice.call(document.querySelectorAll('.lazy')); - this.checkElementsInView(); + + if (this.lazyImages.length) { + this.checkElementsInView(); + } } startContentObserver() { const contentNode = document.querySelector(this.observerNode) || document.querySelector('body'); @@ -45,15 +46,13 @@ export default class LazyLoader { checkElementsInView() { const scrollTop = pageYOffset; const visHeight = scrollTop + innerHeight + SCROLL_THRESHOLD; - let imgBoundRect, imgTop, imgBound; // Loading Images which are in the current viewport or close to them this.lazyImages = this.lazyImages.filter((selectedImage) => { if (selectedImage.getAttribute('data-src')) { - imgBoundRect = selectedImage.getBoundingClientRect(); - - imgTop = scrollTop + imgBoundRect.top; - imgBound = imgTop + imgBoundRect.height; + const imgBoundRect = selectedImage.getBoundingClientRect(); + const imgTop = scrollTop + imgBoundRect.top; + const imgBound = imgTop + imgBoundRect.height; if (scrollTop < imgBound && visHeight > imgTop) { LazyLoader.loadImage(selectedImage); diff --git a/app/assets/javascripts/logo.js b/app/assets/javascripts/logo.js index 729baa2e1a7..3688a57937e 100644 --- a/app/assets/javascripts/logo.js +++ b/app/assets/javascripts/logo.js @@ -1,7 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback */ - -(function() { - window.addEventListener('beforeunload', function() { +export default function initLogoAnimation() { + window.addEventListener('beforeunload', () => { $('.tanuki-logo').addClass('animate'); }); -}).call(window); +} diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index d743f20c615..9117f033c9f 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -12,7 +12,6 @@ import svg4everybody from 'svg4everybody'; // libraries with import side-effects import 'mousetrap'; import 'mousetrap/plugins/pause/mousetrap-pause'; -import 'vendor/fuzzaldrin-plus'; // expose common libraries as globals (TODO: remove these) window.jQuery = jQuery; @@ -56,11 +55,10 @@ import './gl_field_errors'; import './gl_form'; import initTodoToggle from './header'; import initImporterStatus from './importer_status'; -import './labels_select'; import './layout_nav'; import LazyLoader from './lazy_loader'; import './line_highlighter'; -import './logo'; +import initLogoAnimation from './logo'; import './merge_request'; import './merge_request_tabs'; import './milestone'; @@ -135,6 +133,7 @@ $(function () { initBreadcrumbs(); initImporterStatus(); initTodoToggle(); + initLogoAnimation(); // Set the default path for all cookies to GitLab's root directory Cookies.defaults.path = gon.relative_url_root || '/'; diff --git a/app/assets/javascripts/project_find_file.js b/app/assets/javascripts/project_find_file.js index 11f9754780d..19682b20a4a 100644 --- a/app/assets/javascripts/project_find_file.js +++ b/app/assets/javascripts/project_find_file.js @@ -1,5 +1,6 @@ /* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, consistent-return, one-var, one-var-declaration-per-line, no-cond-assign, max-len, object-shorthand, no-param-reassign, comma-dangle, prefer-template, no-unused-vars, no-return-assign */ -/* global fuzzaldrinPlus */ + +import fuzzaldrinPlus from 'fuzzaldrin-plus'; (function() { this.ProjectFindFile = (function() { diff --git a/app/assets/stylesheets/framework/animations.scss b/app/assets/stylesheets/framework/animations.scss index 81439c0d2fe..1b944831082 100644 --- a/app/assets/stylesheets/framework/animations.scss +++ b/app/assets/stylesheets/framework/animations.scss @@ -23,11 +23,16 @@ @include webkit-prefix(animation-duration, 2s); } - &.spin { + &.spin-cw { transform-origin: center; animation: spin 4s linear infinite; } + &.spin-ccw { + transform-origin: center; + animation: spin 4s linear infinite reverse; + } + &.flipOutX, &.flipOutY, &.bounceIn, diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index dbd990f84c1..8819a0c20f4 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -209,7 +209,6 @@ padding: 24px 0 0; .nav-links { - justify-content: center; width: 100%; float: none; @@ -217,6 +216,14 @@ float: none; } } + + li:first-child { + margin-left: auto; + } + + li:last-child { + margin-right: auto; + } } .group-info { diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss index 6cac37a4e28..5fb97b13470 100644 --- a/app/assets/stylesheets/pages/runners.scss +++ b/app/assets/stylesheets/pages/runners.scss @@ -50,3 +50,10 @@ font-size: 11px; } } + +@media (max-width: $screen-md-max) { + .runners-content { + width: 100%; + overflow: auto; + } +} diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index f59200d3b1f..dbc1c8bcc28 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -12,12 +12,7 @@ class Projects::GroupLinksController < Projects::ApplicationController if group return render_404 unless can?(current_user, :read_group, group) - - project.project_group_links.create( - group: group, - group_access: params[:link_group_access], - expires_at: params[:expires_at] - ) + Projects::GroupLinks::CreateService.new(project, current_user, group_link_create_params).execute(group) else flash[:alert] = 'Please select a group.' end @@ -32,7 +27,9 @@ class Projects::GroupLinksController < Projects::ApplicationController end def destroy - project.project_group_links.find(params[:id]).destroy + group_link = project.project_group_links.find(params[:id]) + + ::Projects::GroupLinks::DestroyService.new(project, current_user).execute(group_link) respond_to do |format| format.html do @@ -47,4 +44,8 @@ class Projects::GroupLinksController < Projects::ApplicationController def group_link_params params.require(:group_link).permit(:group_access, :expires_at) end + + def group_link_create_params + params.permit(:link_group_access, :expires_at) + end end diff --git a/app/services/projects/group_links/create_service.rb b/app/services/projects/group_links/create_service.rb new file mode 100644 index 00000000000..35624577024 --- /dev/null +++ b/app/services/projects/group_links/create_service.rb @@ -0,0 +1,15 @@ +module Projects + module GroupLinks + class CreateService < BaseService + def execute(group) + return false unless group + + project.project_group_links.create( + group: group, + group_access: params[:link_group_access], + expires_at: params[:expires_at] + ) + end + end + end +end diff --git a/app/services/projects/group_links/destroy_service.rb b/app/services/projects/group_links/destroy_service.rb new file mode 100644 index 00000000000..fbf31214c28 --- /dev/null +++ b/app/services/projects/group_links/destroy_service.rb @@ -0,0 +1,10 @@ +module Projects + module GroupLinks + class DestroyService < BaseService + def execute(group_link) + return false unless group_link + group_link.destroy + end + end + end +end diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml index 76f4a817744..4965dffab9d 100644 --- a/app/views/admin/runners/index.html.haml +++ b/app/views/admin/runners/index.html.haml @@ -52,22 +52,23 @@ %br - if @runners.any? - .table-holder - %table.table - %thead - %tr - %th Type - %th Runner token - %th Description - %th Version - %th Projects - %th Jobs - %th Tags - %th= link_to 'Last contact', admin_runners_path(params.slice(:search).merge(sort: 'contacted_asc')) - %th + .runners-content + .table-holder + %table.table + %thead + %tr + %th Type + %th Runner token + %th Description + %th Version + %th Projects + %th Jobs + %th Tags + %th Last contact + %th - - @runners.each do |runner| - = render "admin/runners/runner", runner: runner - = paginate @runners, theme: "gitlab" + - @runners.each do |runner| + = render "admin/runners/runner", runner: runner + = paginate @runners, theme: "gitlab" - else .nothing-here-block No runners found diff --git a/app/views/shared/icons/_icon_autodevops.svg b/app/views/shared/icons/_icon_autodevops.svg index dde84e14048..423ca6d760d 100644 --- a/app/views/shared/icons/_icon_autodevops.svg +++ b/app/views/shared/icons/_icon_autodevops.svg @@ -29,7 +29,7 @@ </g> <g fill-rule="nonzero" transform="rotate(15 -315.035 277.714)"> <path fill="#FFFFFF" d="M12.275,10.57 C13.986216,9.15630755 15.921048,8.03765363 18,7.26 L18,5.5 C18,2.463 20.47,0 23.493,0 L26.507,0 C27.9648848,0.000530018716 29.3628038,0.580386367 30.3930274,1.61192286 C31.4232511,2.64345935 32.0013267,4.04211574 32,5.5 L32,7.26 C34.098,8.043 36.03,9.17 37.725,10.57 L39.253,9.688 C41.8816141,8.17268496 45.2407537,9.07039379 46.763,11.695 L48.27,14.305 C48.9984289,15.5678669 49.1951495,17.0684426 48.8168566,18.4763972 C48.4385638,19.8843518 47.5162683,21.0842673 46.253,21.812 L44.728,22.693 C44.907,23.769 45,24.873 45,26 C45,27.127 44.907,28.231 44.728,29.307 L46.253,30.187 C48.8800379,31.705769 49.7822744,35.0642181 48.27,37.695 L46.763,40.305 C46.0335844,41.5673849 44.8323832,42.4881439 43.4238487,42.8645658 C42.0153143,43.2409877 40.5149245,43.0422119 39.253,42.312 L37.725,41.43 C36.013784,42.8436924 34.078952,43.9623464 32,44.74 L32,46.5 C32,49.537 29.53,52 26.507,52 L23.493,52 C22.0351152,51.99947 20.6371962,51.4196136 19.6069726,50.3880771 C18.5767489,49.3565406 17.9986733,47.9578843 18,46.5 L18,44.74 C15.921048,43.9623464 13.986216,42.8436924 12.275,41.43 L10.747,42.312 C8.11838594,43.827315 4.75924629,42.9296062 3.237,40.305 L1.73,37.695 C1.00157113,36.4321331 0.804850523,34.9315574 1.18314337,33.5236028 C1.56143621,32.1156482 2.48373172,30.9157327 3.747,30.188 L5.272,29.307 C5.09051204,28.2140265 4.9995366,27.107939 5,26 C5,24.873 5.093,23.769 5.272,22.693 L3.747,21.813 C1.11996213,20.294231 0.217725591,16.9357819 1.73,14.305 L3.237,11.695 C3.96641559,10.4326151 5.16761682,9.51185609 6.57615125,9.13543417 C7.98468568,8.75901226 9.48507553,8.95778814 10.747,9.688 L12.275,10.57 Z"/> - <path class="animated spin infinite" fill="#E1DBF1" d="M17.9996486,7.25963195 L18.0000013,5.49772675 C18.0034459,2.46713881 20.4561478,0.00952173148 23.493,0 L26.507,0 C29.542757,0 32,2.46161709 32,5.5 L32,7.25850184 C34.0799663,8.03664754 36.0149544,9.15559094 37.7260175,10.5694605 L39.2547869,9.68691874 C41.8812087,8.17416302 45.2363972,9.06948854 46.7630175,11.6949424 L48.270687,14.3061027 C48.9989901,15.569417 49.1952874,17.0704122 48.816349,18.4785295 C48.4374106,19.8866468 47.5143145,21.0864021 46.2530682,21.8120114 L44.7278655,22.6926677 C44.9091017,23.7802451 45,24.8850821 45,26 C45,27.1144218 44.9091826,28.218078 44.7278653,29.3073326 L46.2547984,30.1889888 C48.8778516,31.7070439 49.7801588,35.0599752 48.2700175,37.6950576 L46.7625317,40.3058986 C46.0327098,41.5684739 44.8309328,42.4891542 43.4219037,42.8651509 C42.0128746,43.2411475 40.512172,43.0416186 39.2533538,42.312255 L37.7244858,41.4299789 C36.013753,42.8435912 34.0794396,43.9622923 32.0003514,44.7403681 L31.9999987,46.5022733 C31.9965541,49.5328612 29.5438522,51.9904783 26.507,52 L23.493,52 C20.457243,52 18,49.5383829 18,46.5 L18,44.7414988 C15.9200337,43.9633525 13.9850456,42.8444091 12.2739825,41.4305395 L10.7452131,42.3130813 C8.11879127,43.825837 4.76360277,42.9305115 3.23698247,40.3050576 L1.72931303,37.6938973 C1.0010099,36.430583 0.804712603,34.9295878 1.18365098,33.5214705 C1.56258936,32.1133532 2.48568546,30.9135979 3.74693178,30.1879886 L5.27213454,29.3073323 C5.09089825,28.2197549 5,27.114918 5.00000019,26.0008761 C4.99951488,24.8930059 5.0904571,23.7869854 5.27213502,22.6926675 L3.74520157,21.8110112 C1.12214836,20.2929561 0.219841192,16.9400248 1.72998247,14.3049424 L3.23746831,11.6941014 C3.96729024,10.4315261 5.16906725,9.51084579 6.5780963,9.13484913 C7.98712536,8.75885247 9.48782803,8.95838137 10.7466462,9.687745 L12.2748018,10.56961 C14.0209791,9.13635584 15.9392199,8.03072455 17.9996486,7.25963195 Z M13.7518374,14.537862 C13.108069,15.069723 12.2016163,15.1456339 11.4783538,14.728255 L8.74433999,13.1505123 C8.40103903,12.9516035 7.99274958,12.8973186 7.60940137,12.9996143 C7.22605315,13.10191 6.89909107,13.3523954 6.70101753,13.6950576 L5.19724591,16.2994454 C4.78547321,17.0179634 5.03203388,17.9341714 5.74706822,18.3479886 L8.47306822,19.9219886 C9.19530115,20.3390079 9.58295216,21.1604138 9.44574883,21.983032 L9.21798321,23.3486236 C9.07251948,24.2246212 8.99961081,25.111131 9,26 C9,26.8953847 9.0728258,27.7804297 9.21774883,28.649968 L9.44574883,30.016968 C9.58295216,30.8395862 9.19530115,31.6609921 8.47306822,32.0780114 L5.74435077,33.6535776 C5.40046982,33.851417 5.14932721,34.1778291 5.04623114,34.5609292 C4.94313508,34.9440294 4.9965408,35.3523984 5.19401753,35.6949424 L6.69795587,38.2996585 C7.11427713,39.0156351 8.03110189,39.260288 8.7470791,38.8479035 L11.4770791,37.2719035 C12.200376,36.8543519 13.1069795,36.9302031 13.7508374,37.462138 L14.8210499,38.3463136 C16.1898549,39.4774943 17.737648,40.3725891 19.3990866,40.9941596 L20.6990866,41.4791596 C21.4813437,41.7710017 22,42.5180761 22,43.353 L22,46.5 C22,47.3308348 22.6679761,48 23.493,48 L26.5007228,48.0000099 C27.328845,47.9974107 27.99906,47.3258525 28,46.5 L28,43.353 C28,42.5185702 28.5180515,41.771829 29.2996486,41.4796319 L30.599003,40.9938734 C32.261836,40.3715765 33.8093225,39.4764853 35.1790197,38.3444304 L36.2490197,37.4614304 C36.8927697,36.9301861 37.798736,36.8545694 38.5216462,37.271745 L41.25566,38.8494877 C41.598961,39.0483965 42.0072504,39.1026814 42.3905986,39.0003857 C42.7739468,38.89809 43.1009089,38.6476046 43.2989825,38.3049424 L44.8027541,35.7005546 C45.2145268,34.9820366 44.9679661,34.0658286 44.2529318,33.6520114 L41.5269318,32.0780114 C40.8046988,31.6609921 40.4170478,30.8395862 40.5542512,30.016968 L40.7821577,28.6505288 C40.9272286,27.7792134 41,26.8950523 41,26 C41,25.1046153 40.9271742,24.2195703 40.7822512,23.350032 L40.5542512,21.983032 C40.4170478,21.1604138 40.8046988,20.3390079 41.5269318,19.9219886 L44.2556492,18.3464224 C44.5995302,18.148583 44.8506728,17.8221709 44.9537689,17.4390708 C45.0568649,17.0559706 45.0034592,16.6476016 44.8059825,16.3050576 L43.3020441,13.7003415 C42.8857229,12.9843649 41.9688981,12.739712 41.2529209,13.1520965 L38.5229209,14.7280965 C37.799624,15.1456481 36.8930205,15.0697969 36.2491626,14.537862 L35.1789501,13.6536864 C33.8101451,12.5225057 32.262352,11.6274109 30.6021792,11.0063122 L29.3021792,10.5223122 C28.5192618,10.230826 28,9.48341836 28,8.648 L28,5.5 C28,4.66916515 27.3320239,4 26.507,4 L23.4992772,3.99999015 C22.671155,4.00258933 22.00094,4.67414748 22,5.5 L22,8.647 C22,9.48142977 21.4819485,10.228171 20.7003514,10.5203681 L19.400997,11.0061266 C17.738164,11.6284235 16.1906775,12.5235147 14.822142,13.6546103 C14.8121128,13.6628994 14.4553446,13.9573166 13.7518374,14.537862 Z"/> + <path class="animated spin-cw infinite" fill="#E1DBF1" d="M17.9996486,7.25963195 L18.0000013,5.49772675 C18.0034459,2.46713881 20.4561478,0.00952173148 23.493,0 L26.507,0 C29.542757,0 32,2.46161709 32,5.5 L32,7.25850184 C34.0799663,8.03664754 36.0149544,9.15559094 37.7260175,10.5694605 L39.2547869,9.68691874 C41.8812087,8.17416302 45.2363972,9.06948854 46.7630175,11.6949424 L48.270687,14.3061027 C48.9989901,15.569417 49.1952874,17.0704122 48.816349,18.4785295 C48.4374106,19.8866468 47.5143145,21.0864021 46.2530682,21.8120114 L44.7278655,22.6926677 C44.9091017,23.7802451 45,24.8850821 45,26 C45,27.1144218 44.9091826,28.218078 44.7278653,29.3073326 L46.2547984,30.1889888 C48.8778516,31.7070439 49.7801588,35.0599752 48.2700175,37.6950576 L46.7625317,40.3058986 C46.0327098,41.5684739 44.8309328,42.4891542 43.4219037,42.8651509 C42.0128746,43.2411475 40.512172,43.0416186 39.2533538,42.312255 L37.7244858,41.4299789 C36.013753,42.8435912 34.0794396,43.9622923 32.0003514,44.7403681 L31.9999987,46.5022733 C31.9965541,49.5328612 29.5438522,51.9904783 26.507,52 L23.493,52 C20.457243,52 18,49.5383829 18,46.5 L18,44.7414988 C15.9200337,43.9633525 13.9850456,42.8444091 12.2739825,41.4305395 L10.7452131,42.3130813 C8.11879127,43.825837 4.76360277,42.9305115 3.23698247,40.3050576 L1.72931303,37.6938973 C1.0010099,36.430583 0.804712603,34.9295878 1.18365098,33.5214705 C1.56258936,32.1133532 2.48568546,30.9135979 3.74693178,30.1879886 L5.27213454,29.3073323 C5.09089825,28.2197549 5,27.114918 5.00000019,26.0008761 C4.99951488,24.8930059 5.0904571,23.7869854 5.27213502,22.6926675 L3.74520157,21.8110112 C1.12214836,20.2929561 0.219841192,16.9400248 1.72998247,14.3049424 L3.23746831,11.6941014 C3.96729024,10.4315261 5.16906725,9.51084579 6.5780963,9.13484913 C7.98712536,8.75885247 9.48782803,8.95838137 10.7466462,9.687745 L12.2748018,10.56961 C14.0209791,9.13635584 15.9392199,8.03072455 17.9996486,7.25963195 Z M13.7518374,14.537862 C13.108069,15.069723 12.2016163,15.1456339 11.4783538,14.728255 L8.74433999,13.1505123 C8.40103903,12.9516035 7.99274958,12.8973186 7.60940137,12.9996143 C7.22605315,13.10191 6.89909107,13.3523954 6.70101753,13.6950576 L5.19724591,16.2994454 C4.78547321,17.0179634 5.03203388,17.9341714 5.74706822,18.3479886 L8.47306822,19.9219886 C9.19530115,20.3390079 9.58295216,21.1604138 9.44574883,21.983032 L9.21798321,23.3486236 C9.07251948,24.2246212 8.99961081,25.111131 9,26 C9,26.8953847 9.0728258,27.7804297 9.21774883,28.649968 L9.44574883,30.016968 C9.58295216,30.8395862 9.19530115,31.6609921 8.47306822,32.0780114 L5.74435077,33.6535776 C5.40046982,33.851417 5.14932721,34.1778291 5.04623114,34.5609292 C4.94313508,34.9440294 4.9965408,35.3523984 5.19401753,35.6949424 L6.69795587,38.2996585 C7.11427713,39.0156351 8.03110189,39.260288 8.7470791,38.8479035 L11.4770791,37.2719035 C12.200376,36.8543519 13.1069795,36.9302031 13.7508374,37.462138 L14.8210499,38.3463136 C16.1898549,39.4774943 17.737648,40.3725891 19.3990866,40.9941596 L20.6990866,41.4791596 C21.4813437,41.7710017 22,42.5180761 22,43.353 L22,46.5 C22,47.3308348 22.6679761,48 23.493,48 L26.5007228,48.0000099 C27.328845,47.9974107 27.99906,47.3258525 28,46.5 L28,43.353 C28,42.5185702 28.5180515,41.771829 29.2996486,41.4796319 L30.599003,40.9938734 C32.261836,40.3715765 33.8093225,39.4764853 35.1790197,38.3444304 L36.2490197,37.4614304 C36.8927697,36.9301861 37.798736,36.8545694 38.5216462,37.271745 L41.25566,38.8494877 C41.598961,39.0483965 42.0072504,39.1026814 42.3905986,39.0003857 C42.7739468,38.89809 43.1009089,38.6476046 43.2989825,38.3049424 L44.8027541,35.7005546 C45.2145268,34.9820366 44.9679661,34.0658286 44.2529318,33.6520114 L41.5269318,32.0780114 C40.8046988,31.6609921 40.4170478,30.8395862 40.5542512,30.016968 L40.7821577,28.6505288 C40.9272286,27.7792134 41,26.8950523 41,26 C41,25.1046153 40.9271742,24.2195703 40.7822512,23.350032 L40.5542512,21.983032 C40.4170478,21.1604138 40.8046988,20.3390079 41.5269318,19.9219886 L44.2556492,18.3464224 C44.5995302,18.148583 44.8506728,17.8221709 44.9537689,17.4390708 C45.0568649,17.0559706 45.0034592,16.6476016 44.8059825,16.3050576 L43.3020441,13.7003415 C42.8857229,12.9843649 41.9688981,12.739712 41.2529209,13.1520965 L38.5229209,14.7280965 C37.799624,15.1456481 36.8930205,15.0697969 36.2491626,14.537862 L35.1789501,13.6536864 C33.8101451,12.5225057 32.262352,11.6274109 30.6021792,11.0063122 L29.3021792,10.5223122 C28.5192618,10.230826 28,9.48341836 28,8.648 L28,5.5 C28,4.66916515 27.3320239,4 26.507,4 L23.4992772,3.99999015 C22.671155,4.00258933 22.00094,4.67414748 22,5.5 L22,8.647 C22,9.48142977 21.4819485,10.228171 20.7003514,10.5203681 L19.400997,11.0061266 C17.738164,11.6284235 16.1906775,12.5235147 14.822142,13.6546103 C14.8121128,13.6628994 14.4553446,13.9573166 13.7518374,14.537862 Z"/> <g transform="rotate(15 -59.137 82.348)"> <circle cx="8" cy="8" r="8" fill="#FFFFFF" transform="translate(.035 6.008)"/> <path fill="#6B4FBB" d="M7.40192379,14.7679492 C2.98364579,14.7679492 -0.598076211,11.1862272 -0.598076211,6.76794919 C-0.598076211,2.34967119 2.98364579,-1.23205081 7.40192379,-1.23205081 C11.8202018,-1.23205081 15.4019238,2.34967119 15.4019238,6.76794919 C15.4019238,11.1862272 11.8202018,14.7679492 7.40192379,14.7679492 Z M7.40192379,10.7679492 C9.61106279,10.7679492 11.4019238,8.97708819 11.4019238,6.76794919 C11.4019238,4.55881019 9.61106279,2.76794919 7.40192379,2.76794919 C5.19278479,2.76794919 3.40192379,4.55881019 3.40192379,6.76794919 C3.40192379,8.97708819 5.19278479,10.7679492 7.40192379,10.7679492 Z"/> @@ -37,7 +37,7 @@ </g> <g fill-rule="nonzero" transform="rotate(15 -402.968 460.884)"> <path fill="#FFFFFF" d="M9.82,8.53730769 C11.1889728,7.39547918 12.7368384,6.49195101 14.4,5.86384615 L14.4,4.44230769 C14.4,1.98934615 16.376,0 18.7944,0 L21.2056,0 C22.3719078,0.00042809204 23.4902431,0.468773604 24.314422,1.30193769 C25.1386009,2.13510179 25.6010613,3.26478579 25.6,4.44230769 L25.6,5.86384615 C27.2784,6.49626923 28.824,7.40653846 30.18,8.53730769 L31.4024,7.82492308 C33.5052912,6.60101478 36.192603,7.32608729 37.4104,9.44596154 L38.616,11.5540385 C39.1987431,12.5740464 39.3561196,13.7860498 39.0534853,14.9232439 C38.750851,16.060438 38.0130146,17.0296006 37.0024,17.6173846 L35.7824,18.3289615 C35.9256,19.1980385 36,20.0897308 36,21 C36,21.9102692 35.9256,22.8019615 35.7824,23.6710385 L37.0024,24.3818077 C39.1040303,25.6085057 39.8258195,28.3210992 38.616,30.4459615 L37.4104,32.5540385 C36.8268675,33.573657 35.8659065,34.317347 34.739079,34.6213801 C33.6122515,34.9254132 32.4119396,34.7648634 31.4024,34.1750769 L30.18,33.4626923 C28.8110272,34.6045208 27.2631616,35.508049 25.6,36.1361538 L25.6,37.5576923 C25.6,40.0106538 23.624,42 21.2056,42 L18.7944,42 C17.6280922,41.9995719 16.5097569,41.5312264 15.685578,40.6980623 C14.8613991,39.8648982 14.3989387,38.7352142 14.4,37.5576923 L14.4,36.1361538 C12.7368384,35.508049 11.1889728,34.6045208 9.82,33.4626923 L8.5976,34.1750769 C6.49470875,35.3989852 3.80739703,34.6739127 2.5896,32.5540385 L1.384,30.4459615 C0.8012569,29.4259536 0.643880418,28.2139502 0.946514692,27.0767561 C1.24914897,25.939562 1.98698538,24.9703994 2.9976,24.3826154 L4.2176,23.6710385 C4.07240963,22.7882521 3.99962928,21.8948738 4,21 C4,20.0897308 4.0744,19.1980385 4.2176,18.3289615 L2.9976,17.6181923 C0.895969702,16.3914943 0.174180473,13.6789008 1.384,11.5540385 L2.5896,9.44596154 C3.17313247,8.42634297 4.13409345,7.682653 5.260921,7.37861991 C6.38774855,7.07458682 7.58806043,7.23513658 8.5976,7.82492308 L9.82,8.53730769 Z"/> - <path class="animated spin infinite" fill="#FEE1D3" d="M14.0000007,5.6038043 L14.0000013,4.44005609 C14.0029906,1.78475013 16.1390906,-0.376211234 18.7944,-0.384615385 L21.2056,-0.384615385 C23.8595941,-0.384615385 26,1.78021801 26,4.44230769 L26,5.60295806 C27.5208716,6.20655954 28.9434678,7.03621848 30.2204219,8.06411282 L31.1970056,7.49492104 C33.4941909,6.15907529 36.4301298,6.95005805 37.7609369,9.26076474 L38.9671983,11.3699991 C39.5988409,12.4761812 39.768854,13.7886936 39.4405746,15.0202941 C39.1116282,16.2543969 38.308799,17.3078735 37.2096539,17.946304 L36.2175721,18.5246428 C36.3390841,19.3401617 36.4,20.1667594 36.4,21 C36.4,21.8329668 36.339124,22.6588262 36.2175401,23.4753391 L37.2113882,24.0547082 C39.4944154,25.3886826 40.276605,28.3232105 38.9665369,30.6311583 L37.7604568,32.7400742 C37.1252608,33.8495148 36.0768547,34.6604208 34.8452776,34.9922248 C33.6111681,35.324711 32.2964469,35.1482289 31.195569,34.5042428 L30.2192355,33.9354047 C28.9426535,34.9630196 27.5206806,35.7924453 25.9999993,36.3961957 L25.9999987,37.5599439 C25.9970094,40.2152499 23.8609094,42.3762112 21.2056,42.3846154 L18.7944,42.3846154 C16.1404059,42.3846154 14,40.219782 14,37.5576923 L14,36.3970419 C12.4791284,35.7934405 11.0565322,34.9637815 9.77957815,33.9358872 L8.80299442,34.505079 C6.50580915,35.8409247 3.56987021,35.049942 2.23906313,32.7392353 L1.03280169,30.6300009 C0.401159146,29.5238188 0.231145999,28.2113064 0.559425405,26.9797059 C0.888371786,25.7456031 1.69120101,24.6921265 2.79034606,24.053696 L3.78242779,23.4753573 C3.66091587,22.6598457 3.60000002,21.8333228 3.60000019,21.0008678 C3.59964068,20.1722851 3.66061719,19.3449468 3.78254167,18.5247085 L2.78861183,17.9452918 C0.505584602,16.6113174 -0.276605002,13.6767895 1.03346313,11.3688417 L2.23954317,9.25992583 C2.87473915,8.15048519 3.92314533,7.33957919 5.15472238,7.00777521 C6.38883187,6.67528896 7.70355311,6.85177112 8.80443097,7.49575721 L9.78076186,8.06459377 C11.0573465,7.03698045 12.4793194,6.20755475 14.0000007,5.6038043 Z M11.2634746,12.0326234 C10.617233,12.5716613 9.7026973,12.6485026 8.97556903,12.2248582 L6.78774825,10.9501716 C6.60754053,10.8447551 6.39506809,10.8162338 6.19527576,10.8700606 C5.99295099,10.9245697 5.8183659,11.0596053 5.71133687,11.246543 L4.50892658,13.3490215 C4.28085652,13.7508163 4.41776119,14.2644394 4.80485394,14.4906191 L6.98565394,15.7619268 C7.70254629,16.1798426 8.08690703,16.9970357 7.95165511,17.8157512 L7.76948523,18.9184706 C7.65638664,19.6061109 7.59969735,20.3020342 7.6,21 C7.6,21.7031066 7.65662064,22.3978283 7.76925511,23.0801334 L7.95165511,24.1842488 C8.08690703,25.0029643 7.70254629,25.8201574 6.98565394,26.2380732 L4.80213007,27.5109659 C4.61772321,27.6180778 4.48116147,27.7972748 4.42448029,28.0099246 C4.36713215,28.2250767 4.39688141,28.454743 4.50573687,28.6453801 L5.70831165,30.7481858 C5.93243371,31.1373303 6.41410538,31.2670993 6.79049373,31.0482253 L8.97449373,29.7753023 C9.7016554,29.3514832 10.6163433,29.4282639 11.2626746,29.9673766 L12.1188867,30.6815536 C13.1796505,31.566598 14.3786867,32.2666727 15.6649769,32.7525215 L16.7049769,33.1442523 C17.4841581,33.4377419 18,34.1832625 18,35.0158846 L18,37.5576923 C18,38.02074 18.3597694,38.3846154 18.7944,38.3846154 L21.1992624,38.3846254 C21.6372484,38.3832375 21.9994819,38.0167881 22,37.5576923 L22,35.0158846 C22,34.18376 22.5152346,33.4385758 23.2937506,33.1447321 L24.3331012,32.7524389 C25.620867,32.2658727 26.8196661,31.5658006 27.8813806,30.679856 L28.7373806,29.9666637 C29.3836087,29.4282468 30.2976553,29.3517028 31.024431,29.7751418 L33.2122517,31.0498284 C33.3924595,31.1552449 33.6049319,31.1837662 33.8047242,31.1299394 C34.007049,31.0754303 34.1816341,30.9403947 34.2886631,30.753457 L35.4910734,28.6509785 C35.7191435,28.2491837 35.5822388,27.7355606 35.1951461,27.5093809 L33.0143461,26.2380732 C32.2974537,25.8201574 31.913093,25.0029643 32.0483449,24.1842488 L32.2306531,23.0806893 C32.3434217,22.3968737 32.4,21.7028459 32.4,21 C32.4,20.2968934 32.3433794,19.6021717 32.2307449,18.9198666 L32.0483449,17.8157512 C31.913093,16.9970357 32.2974537,16.1798426 33.0143461,15.7619268 L35.1978699,14.4890341 C35.3822768,14.3819222 35.5188385,14.2027252 35.5755197,13.9900754 C35.6328679,13.7749233 35.6031186,13.545257 35.4942631,13.3546199 L34.2916883,11.2518142 C34.0675663,10.8626697 33.5858946,10.7329007 33.2095063,10.9517747 L31.0255063,12.2246977 C30.2983446,12.6485168 29.3836567,12.5717361 28.7373254,12.0326234 L27.8811133,11.3184464 C26.8203495,10.433402 25.6213133,9.73332732 24.3362966,9.24795765 L23.2962966,8.85703457 C22.5164499,8.56389992 22,7.81804293 22,6.98492308 L22,4.44230769 C22,3.97925995 21.6402306,3.61538462 21.2056,3.61538462 L18.8007376,3.61537457 C18.3627516,3.61676247 18.0005181,3.98321188 18,4.44230769 L18,6.98411538 C18,7.81623999 17.4847654,8.56142419 16.7062494,8.85526793 L15.6668988,9.24756113 C14.379133,9.73412728 13.1803339,10.4341994 12.1197785,11.3191775 C12.1108094,11.3266617 11.8253748,11.564477 11.2634746,12.0326234 Z"/> + <path class="animated spin-ccw infinite" fill="#FEE1D3" d="M14.0000007,5.6038043 L14.0000013,4.44005609 C14.0029906,1.78475013 16.1390906,-0.376211234 18.7944,-0.384615385 L21.2056,-0.384615385 C23.8595941,-0.384615385 26,1.78021801 26,4.44230769 L26,5.60295806 C27.5208716,6.20655954 28.9434678,7.03621848 30.2204219,8.06411282 L31.1970056,7.49492104 C33.4941909,6.15907529 36.4301298,6.95005805 37.7609369,9.26076474 L38.9671983,11.3699991 C39.5988409,12.4761812 39.768854,13.7886936 39.4405746,15.0202941 C39.1116282,16.2543969 38.308799,17.3078735 37.2096539,17.946304 L36.2175721,18.5246428 C36.3390841,19.3401617 36.4,20.1667594 36.4,21 C36.4,21.8329668 36.339124,22.6588262 36.2175401,23.4753391 L37.2113882,24.0547082 C39.4944154,25.3886826 40.276605,28.3232105 38.9665369,30.6311583 L37.7604568,32.7400742 C37.1252608,33.8495148 36.0768547,34.6604208 34.8452776,34.9922248 C33.6111681,35.324711 32.2964469,35.1482289 31.195569,34.5042428 L30.2192355,33.9354047 C28.9426535,34.9630196 27.5206806,35.7924453 25.9999993,36.3961957 L25.9999987,37.5599439 C25.9970094,40.2152499 23.8609094,42.3762112 21.2056,42.3846154 L18.7944,42.3846154 C16.1404059,42.3846154 14,40.219782 14,37.5576923 L14,36.3970419 C12.4791284,35.7934405 11.0565322,34.9637815 9.77957815,33.9358872 L8.80299442,34.505079 C6.50580915,35.8409247 3.56987021,35.049942 2.23906313,32.7392353 L1.03280169,30.6300009 C0.401159146,29.5238188 0.231145999,28.2113064 0.559425405,26.9797059 C0.888371786,25.7456031 1.69120101,24.6921265 2.79034606,24.053696 L3.78242779,23.4753573 C3.66091587,22.6598457 3.60000002,21.8333228 3.60000019,21.0008678 C3.59964068,20.1722851 3.66061719,19.3449468 3.78254167,18.5247085 L2.78861183,17.9452918 C0.505584602,16.6113174 -0.276605002,13.6767895 1.03346313,11.3688417 L2.23954317,9.25992583 C2.87473915,8.15048519 3.92314533,7.33957919 5.15472238,7.00777521 C6.38883187,6.67528896 7.70355311,6.85177112 8.80443097,7.49575721 L9.78076186,8.06459377 C11.0573465,7.03698045 12.4793194,6.20755475 14.0000007,5.6038043 Z M11.2634746,12.0326234 C10.617233,12.5716613 9.7026973,12.6485026 8.97556903,12.2248582 L6.78774825,10.9501716 C6.60754053,10.8447551 6.39506809,10.8162338 6.19527576,10.8700606 C5.99295099,10.9245697 5.8183659,11.0596053 5.71133687,11.246543 L4.50892658,13.3490215 C4.28085652,13.7508163 4.41776119,14.2644394 4.80485394,14.4906191 L6.98565394,15.7619268 C7.70254629,16.1798426 8.08690703,16.9970357 7.95165511,17.8157512 L7.76948523,18.9184706 C7.65638664,19.6061109 7.59969735,20.3020342 7.6,21 C7.6,21.7031066 7.65662064,22.3978283 7.76925511,23.0801334 L7.95165511,24.1842488 C8.08690703,25.0029643 7.70254629,25.8201574 6.98565394,26.2380732 L4.80213007,27.5109659 C4.61772321,27.6180778 4.48116147,27.7972748 4.42448029,28.0099246 C4.36713215,28.2250767 4.39688141,28.454743 4.50573687,28.6453801 L5.70831165,30.7481858 C5.93243371,31.1373303 6.41410538,31.2670993 6.79049373,31.0482253 L8.97449373,29.7753023 C9.7016554,29.3514832 10.6163433,29.4282639 11.2626746,29.9673766 L12.1188867,30.6815536 C13.1796505,31.566598 14.3786867,32.2666727 15.6649769,32.7525215 L16.7049769,33.1442523 C17.4841581,33.4377419 18,34.1832625 18,35.0158846 L18,37.5576923 C18,38.02074 18.3597694,38.3846154 18.7944,38.3846154 L21.1992624,38.3846254 C21.6372484,38.3832375 21.9994819,38.0167881 22,37.5576923 L22,35.0158846 C22,34.18376 22.5152346,33.4385758 23.2937506,33.1447321 L24.3331012,32.7524389 C25.620867,32.2658727 26.8196661,31.5658006 27.8813806,30.679856 L28.7373806,29.9666637 C29.3836087,29.4282468 30.2976553,29.3517028 31.024431,29.7751418 L33.2122517,31.0498284 C33.3924595,31.1552449 33.6049319,31.1837662 33.8047242,31.1299394 C34.007049,31.0754303 34.1816341,30.9403947 34.2886631,30.753457 L35.4910734,28.6509785 C35.7191435,28.2491837 35.5822388,27.7355606 35.1951461,27.5093809 L33.0143461,26.2380732 C32.2974537,25.8201574 31.913093,25.0029643 32.0483449,24.1842488 L32.2306531,23.0806893 C32.3434217,22.3968737 32.4,21.7028459 32.4,21 C32.4,20.2968934 32.3433794,19.6021717 32.2307449,18.9198666 L32.0483449,17.8157512 C31.913093,16.9970357 32.2974537,16.1798426 33.0143461,15.7619268 L35.1978699,14.4890341 C35.3822768,14.3819222 35.5188385,14.2027252 35.5755197,13.9900754 C35.6328679,13.7749233 35.6031186,13.545257 35.4942631,13.3546199 L34.2916883,11.2518142 C34.0675663,10.8626697 33.5858946,10.7329007 33.2095063,10.9517747 L31.0255063,12.2246977 C30.2983446,12.6485168 29.3836567,12.5717361 28.7373254,12.0326234 L27.8811133,11.3184464 C26.8203495,10.433402 25.6213133,9.73332732 24.3362966,9.24795765 L23.2962966,8.85703457 C22.5164499,8.56389992 22,7.81804293 22,6.98492308 L22,4.44230769 C22,3.97925995 21.6402306,3.61538462 21.2056,3.61538462 L18.8007376,3.61537457 C18.3627516,3.61676247 18.0005181,3.98321188 18,4.44230769 L18,6.98411538 C18,7.81623999 17.4847654,8.56142419 16.7062494,8.85526793 L15.6668988,9.24756113 C14.379133,9.73412728 13.1803339,10.4341994 12.1197785,11.3191775 C12.1108094,11.3266617 11.8253748,11.564477 11.2634746,12.0326234 Z"/> <g transform="rotate(15 -47.892 66.043)"> <ellipse cx="6.4" cy="6.462" fill="#FFFFFF" rx="6.4" ry="6.462" transform="translate(.028 4.853)"/> <path fill="#FC6D26" d="M5.92153903,11.9125743 C2.3834711,11.9125743 -0.478460969,9.0231237 -0.478460969,5.4664205 C-0.478460969,1.9097173 2.3834711,-0.979733345 5.92153903,-0.979733345 C9.45960696,-0.979733345 12.321539,1.9097173 12.321539,5.4664205 C12.321539,9.0231237 9.45960696,11.9125743 5.92153903,11.9125743 Z M5.92153903,8.71257435 C7.6854047,8.71257435 9.12153903,7.26263103 9.12153903,5.4664205 C9.12153903,3.67020997 7.6854047,2.22026666 5.92153903,2.22026666 C4.15767337,2.22026666 2.72153903,3.67020997 2.72153903,5.4664205 C2.72153903,7.26263103 4.15767337,8.71257435 5.92153903,8.71257435 Z"/> diff --git a/app/workers/update_merge_requests_worker.rb b/app/workers/update_merge_requests_worker.rb index 89ae17cef37..150788ca611 100644 --- a/app/workers/update_merge_requests_worker.rb +++ b/app/workers/update_merge_requests_worker.rb @@ -2,6 +2,10 @@ class UpdateMergeRequestsWorker include Sidekiq::Worker include DedicatedSidekiqQueue + def metrics_tags + @metrics_tags || {} + end + def perform(project_id, user_id, oldrev, newrev, ref) project = Project.find_by(id: project_id) return unless project @@ -9,6 +13,11 @@ class UpdateMergeRequestsWorker user = User.find_by(id: user_id) return unless user + @metrics_tags = { + project_id: project_id, + user_id: user_id + } + MergeRequests::RefreshService.new(project, user).execute(oldrev, newrev, ref) end end diff --git a/changelogs/unreleased/35914-merge-request-update-worker-is-slow.yml b/changelogs/unreleased/35914-merge-request-update-worker-is-slow.yml new file mode 100644 index 00000000000..34bb76195af --- /dev/null +++ b/changelogs/unreleased/35914-merge-request-update-worker-is-slow.yml @@ -0,0 +1,5 @@ +--- +title: Add metric tagging for sidekiq workers +merge_request: 15111 +author: +type: added diff --git a/changelogs/unreleased/backport-workhorse-show-all-refs.yml b/changelogs/unreleased/backport-workhorse-show-all-refs.yml new file mode 100644 index 00000000000..36dd2115152 --- /dev/null +++ b/changelogs/unreleased/backport-workhorse-show-all-refs.yml @@ -0,0 +1,5 @@ +--- +title: Support show-all-refs for git over HTTP +merge_request: 14834 +author: +type: added diff --git a/changelogs/unreleased/feature-plantuml-restructured-text-captions.yml b/changelogs/unreleased/feature-plantuml-restructured-text-captions.yml new file mode 100644 index 00000000000..3d8d0f4fcd1 --- /dev/null +++ b/changelogs/unreleased/feature-plantuml-restructured-text-captions.yml @@ -0,0 +1,5 @@ +--- +title: 'Support uml:: and captions in reStructuredText' +merge_request: 15120 +author: Markus Koller +type: changed diff --git a/changelogs/unreleased/fix-user-tab-activity-mobile.yml b/changelogs/unreleased/fix-user-tab-activity-mobile.yml new file mode 100644 index 00000000000..a7e4fcb4355 --- /dev/null +++ b/changelogs/unreleased/fix-user-tab-activity-mobile.yml @@ -0,0 +1,5 @@ +--- +title: Fixed user profile activity tab being off-screen on mobile +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/go-get-ssh.yml b/changelogs/unreleased/go-get-ssh.yml new file mode 100644 index 00000000000..e485a94c6db --- /dev/null +++ b/changelogs/unreleased/go-get-ssh.yml @@ -0,0 +1,5 @@ +--- +title: Returns a ssh url for go-get=1 +merge_request: 14990 +author: gvieira37 +type: fixed diff --git a/changelogs/unreleased/jivl-mobile-friendly-table-runners.yml b/changelogs/unreleased/jivl-mobile-friendly-table-runners.yml new file mode 100644 index 00000000000..3448b003ee0 --- /dev/null +++ b/changelogs/unreleased/jivl-mobile-friendly-table-runners.yml @@ -0,0 +1,5 @@ +--- +title: Mobile-friendly table on Admin Runners +merge_request: +author: Takuya Noguchi +type: fixed diff --git a/changelogs/unreleased/refactor-group_links_controller.yml b/changelogs/unreleased/refactor-group_links_controller.yml new file mode 100644 index 00000000000..af3d22c34cb --- /dev/null +++ b/changelogs/unreleased/refactor-group_links_controller.yml @@ -0,0 +1,5 @@ +--- +title: Refactor GroupLinksController +merge_request: +author: 15121 +type: other diff --git a/changelogs/unreleased/sh-disable-unicorn-sampling-sidekiq.yml b/changelogs/unreleased/sh-disable-unicorn-sampling-sidekiq.yml new file mode 100644 index 00000000000..c4ed017dacd --- /dev/null +++ b/changelogs/unreleased/sh-disable-unicorn-sampling-sidekiq.yml @@ -0,0 +1,5 @@ +--- +title: Disable Unicorn sampling in Sidekiq since there are no Unicorn sockets to monitor +merge_request: +author: +type: performance diff --git a/config/initializers/8_metrics.rb b/config/initializers/8_metrics.rb index e1a59d8c152..2d8704622b6 100644 --- a/config/initializers/8_metrics.rb +++ b/config/initializers/8_metrics.rb @@ -123,7 +123,9 @@ def instrument_classes(instrumentation) end # rubocop:enable Metrics/AbcSize -Gitlab::Metrics::UnicornSampler.initialize_instance(Settings.monitoring.unicorn_sampler_interval).start +unless Sidekiq.server? + Gitlab::Metrics::UnicornSampler.initialize_instance(Settings.monitoring.unicorn_sampler_interval).start +end Gitlab::Application.configure do |config| # 0 should be Sentry to catch errors in this middleware diff --git a/doc/README.md b/doc/README.md index 5eabc126b95..7c33a708dc7 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,5 +1,6 @@ --- toc: false +comments: false --- # GitLab Documentation diff --git a/doc/administration/auth/README.md b/doc/administration/auth/README.md index 13bd501e397..ee9b9a9466a 100644 --- a/doc/administration/auth/README.md +++ b/doc/administration/auth/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Authentication and Authorization GitLab integrates with the following external authentication and authorization diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md index 652ca9cf454..93c3642a1f1 100644 --- a/doc/administration/integration/plantuml.md +++ b/doc/administration/integration/plantuml.md @@ -56,29 +56,34 @@ that, login with an Admin account and do following: With PlantUML integration enabled and configured, we can start adding diagrams to our AsciiDoc snippets, wikis and repos using delimited blocks: -``` -[plantuml, format="png", id="myDiagram", width="200px"] --- -Bob->Alice : hello -Alice -> Bob : Go Away --- -``` +- **Markdown** + + ```plantuml + Bob -> Alice : hello + Alice -> Bob : Go Away + ``` -And in Markdown using fenced code blocks: +- **AsciiDoc** - ```plantuml - Bob -> Alice : hello + ``` + [plantuml, format="png", id="myDiagram", width="200px"] + -- + Bob->Alice : hello Alice -> Bob : Go Away + -- ``` -And in reStructuredText using a directive: +- **reStructuredText** -``` -.. plantuml:: + ``` + .. plantuml:: + :caption: Caption with **bold** and *italic* - Bob -> Alice: hello - Alice -> Bob: Go Away -``` + Bob -> Alice: hello + Alice -> Bob: Go Away + ``` + + You can also use the `uml::` directive for compatibility with [sphinxcontrib-plantuml](https://pypi.python.org/pypi/sphinxcontrib-plantuml), but please note that we currently only support the `caption` option. The above blocks will be converted to an HTML img tag with source pointing to the PlantUML instance. If the PlantUML server is correctly configured, this should diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md index 0cb2648cc1e..bc9b6253f1a 100644 --- a/doc/administration/repository_storage_types.md +++ b/doc/administration/repository_storage_types.md @@ -76,7 +76,7 @@ To migrate your existing projects to the new storage type, check the specific [r We are incrementally moving every storable object in GitLab to the Hashed Storage pattern. You can check the current coverage status below. -Not that things stored in S3 compatible endpoint, will not have the downsides mentioned earlier, if they are not +Note that things stored in an S3 compatible endpoint will not have the downsides mentioned earlier, if they are not prefixed with `#{namespace}/#{project_name}`, which is true for CI Cache and LFS Objects. | Storable Object | Legacy Storage | Hashed Storage | S3 Compatible | GitLab Version | diff --git a/doc/ci/README.md b/doc/ci/README.md index ec0ddfbea75..12404eddbe2 100644 --- a/doc/ci/README.md +++ b/doc/ci/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab Continuous Integration (GitLab CI) ![Pipeline graph](img/cicd_pipeline_infograph.png) diff --git a/doc/ci/docker/README.md b/doc/ci/docker/README.md index 99669a9272a..b0e01d74f7e 100644 --- a/doc/ci/docker/README.md +++ b/doc/ci/docker/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Docker integration - [Using Docker Images](using_docker_images.md) diff --git a/doc/ci/enable_or_disable_ci.md b/doc/ci/enable_or_disable_ci.md index b8f9988e3ef..7aa7de97c43 100644 --- a/doc/ci/enable_or_disable_ci.md +++ b/doc/ci/enable_or_disable_ci.md @@ -1,4 +1,4 @@ -## Enable or disable GitLab CI/CD +# How to enable or disable GitLab CI/CD To effectively use GitLab CI/CD, you need a valid [`.gitlab-ci.yml`](yaml/README.md) file present at the root directory of your project and a @@ -21,7 +21,7 @@ individually under each project's settings, or site-wide by modifying the settings in `gitlab.yml` and `gitlab.rb` for source and Omnibus installations respectively. -### Per-project user setting +## Per-project user setting The setting to enable or disable GitLab CI/CD can be found under your project's **Settings > General > Permissions**. Choose one of "Disabled", "Only team members" @@ -29,7 +29,7 @@ or "Everyone with access" and hit **Save changes** for the settings to take effe ![Sharing & Permissions settings](../user/project/settings/img/sharing_and_permissions_settings.png) -### Site-wide admin setting +## Site-wide admin setting You can disable GitLab CI/CD site-wide, by modifying the settings in `gitlab.yml` and `gitlab.rb` for source and Omnibus installations respectively. diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md index f094546c3bd..d05b4db953a 100644 --- a/doc/ci/examples/README.md +++ b/doc/ci/examples/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab CI Examples A collection of `.gitlab-ci.yml` files is maintained at the [GitLab CI Yml project][gitlab-ci-templates]. diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md index b9f0485290e..bed379b0254 100644 --- a/doc/ci/examples/deployment/composer-npm-deploy.md +++ b/doc/ci/examples/deployment/composer-npm-deploy.md @@ -1,4 +1,4 @@ -## Running Composer and NPM scripts with deployment via SCP +# Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD This guide covers the building dependencies of a PHP project while compiling assets via an NPM script. @@ -39,13 +39,13 @@ In this particular case, the `npm deploy` script is a Gulp script that does the All these operations will put all files into a `build` folder, which is ready to be deployed to a live server. -### How to transfer files to a live server? +## How to transfer files to a live server You have multiple options: rsync, scp, sftp and so on. For now, we will use scp. To make this work, you need to add a GitLab Secret Variable (accessible on _gitlab.example/your-project-name/variables_). That variable will be called `STAGING_PRIVATE_KEY` and it's the **private** ssh key of your server. -#### Security tip +### Security tip Create a user that has access **only** to the folder that needs to be updated! @@ -69,7 +69,7 @@ In order, this means that: And this is basically all you need in the `before_script` section. -## How to deploy things? +## How to deploy things As we stated above, we need to deploy the `build` folder from the docker image to our server. To do so, we create a new job: @@ -88,7 +88,7 @@ stage_deploy: - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old" ``` -### What's going on here? +Here's the breakdown: 1. `only:dev` means that this build will run only when something is pushed to the `dev` branch. You can remove this block completely and have everything be ran on every push (but probably this is something you don't want) 2. `ssh-add ...` we will add that private key you added on the web UI to the docker container @@ -99,7 +99,7 @@ stage_deploy: What's the deal with the artifacts? We just tell GitLab CI to keep the `build` directory (later on, you can download that as needed). -#### Why we do it this way? +### Why we do it this way If you're using this only for stage server, you could do this in two steps: @@ -112,7 +112,7 @@ The problem is that there will be a small period of time when you won't have the So we use so many steps because we want to make sure that at any given time we have a functional app in place. -## Where to go next? +## Where to go next Since this was a WordPress project, I gave real life code snippets. Some ideas you can pursuit: diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md index 73aebaf6d7f..0f7ed055e79 100644 --- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md +++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md @@ -1,10 +1,13 @@ -## Test and Deploy a python application +# Test and Deploy a python application with GitLab CI/CD + This example will guide you how to run tests in your Python application and deploy it automatically as Heroku application. -You can checkout the example [source](https://gitlab.com/ayufan/python-getting-started) and check [CI status](https://gitlab.com/ayufan/python-getting-started/builds?scope=all). +You can checkout the [example source](https://gitlab.com/ayufan/python-getting-started). + +## Configure project -### Configure project This is what the `.gitlab-ci.yml` file looks like for this project: + ```yaml test: script: @@ -41,21 +44,25 @@ This project has three jobs: 2. `staging` - used to automatically deploy staging environment every push to `master` branch 3. `production` - used to automatically deploy production environmnet for every created tag -### Store API keys +## Store API keys + You'll need to create two variables in `Project > Variables`: 1. `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app, 2. `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app. Find your Heroku API key in [Manage Account](https://dashboard.heroku.com/account). -### Create Heroku application +## Create Heroku application + For each of your environments, you'll need to create a new Heroku application. You can do this through the [Dashboard](https://dashboard.heroku.com/). -### Create runner +## Create Runner + First install [Docker Engine](https://docs.docker.com/installation/). -To build this project you also need to have [GitLab Runner](https://about.gitlab.com/gitlab-ci/#gitlab-runner). +To build this project you also need to have [GitLab Runner](https://docs.gitlab.com/runner). You can use public runners available on `gitlab.com`, but you can register your own: + ``` gitlab-ci-multi-runner register \ --non-interactive \ diff --git a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md index 6fa64a67e82..10fd2616fab 100644 --- a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md +++ b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md @@ -1,10 +1,13 @@ -## Test and Deploy a ruby application +# Test and Deploy a ruby application with GitLab CI/CD + This example will guide you how to run tests in your Ruby on Rails application and deploy it automatically as Heroku application. You can checkout the example [source](https://gitlab.com/ayufan/ruby-getting-started) and check [CI status](https://gitlab.com/ayufan/ruby-getting-started/builds?scope=all). -### Configure project +## Configure the project + This is what the `.gitlab-ci.yml` file looks like for this project: + ```yaml test: script: @@ -36,23 +39,28 @@ This project has three jobs: 2. `staging` - used to automatically deploy staging environment every push to `master` branch 3. `production` - used to automatically deploy production environment for every created tag -### Store API keys -You'll need to create two variables in `Project > Variables`: +## Store API keys + +You'll need to create two variables in your project's **Settings > CI/CD > Variables**: + 1. `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app, 2. `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app. Find your Heroku API key in [Manage Account](https://dashboard.heroku.com/account). -### Create Heroku application +## Create Heroku application + For each of your environments, you'll need to create a new Heroku application. You can do this through the [Dashboard](https://dashboard.heroku.com/). -### Create runner +## Create Runner + First install [Docker Engine](https://docs.docker.com/installation/). To build this project you also need to have [GitLab Runner](https://about.gitlab.com/gitlab-ci/#gitlab-runner). You can use public runners available on `gitlab.com`, but you can register your own: + ``` -gitlab-ci-multi-runner register \ +gitlab-runner register \ --non-interactive \ --url "https://gitlab.com/" \ --registration-token "PROJECT_REGISTRATION_TOKEN" \ @@ -62,6 +70,6 @@ gitlab-ci-multi-runner register \ --docker-postgres latest ``` -With the command above, you create a runner that uses [ruby:2.2](https://hub.docker.com/r/_/ruby/) image and uses [postgres](https://hub.docker.com/r/_/postgres/) database. +With the command above, you create a Runner that uses [ruby:2.2](https://hub.docker.com/r/_/ruby/) image and uses [postgres](https://hub.docker.com/r/_/postgres/) database. To access PostgreSQL database you need to connect to `host: postgres` as user `postgres` without password. diff --git a/doc/ci/examples/test-clojure-application.md b/doc/ci/examples/test-clojure-application.md index 56b746ce025..3b1026d174f 100644 --- a/doc/ci/examples/test-clojure-application.md +++ b/doc/ci/examples/test-clojure-application.md @@ -1,10 +1,10 @@ -## Test a Clojure application +# Test a Clojure application with GitLab CI/CD This example will guide you how to run tests in your Clojure application. You can checkout the example [source](https://gitlab.com/dzaporozhets/clojure-web-application) and check [CI status](https://gitlab.com/dzaporozhets/clojure-web-application/builds?scope=all). -### Configure project +## Configure the project This is what the `.gitlab-ci.yml` file looks like for this project: @@ -23,13 +23,13 @@ before_script: - lein deps - lein migratus migrate -test: - script: +test: + script: - lein test ``` -In before script we install JRE and [Leiningen](http://leiningen.org/). -Sample project uses [migratus](https://github.com/yogthos/migratus) library to manage database migrations. +In before script we install JRE and [Leiningen](http://leiningen.org/). +Sample project uses [migratus](https://github.com/yogthos/migratus) library to manage database migrations. So we added database migration as last step of `before_script` section You can use public runners available on `gitlab.com` for testing your application with such configuration. diff --git a/doc/ci/examples/test-phoenix-application.md b/doc/ci/examples/test-phoenix-application.md index 150698ca04b..f6c81b076bc 100644 --- a/doc/ci/examples/test-phoenix-application.md +++ b/doc/ci/examples/test-phoenix-application.md @@ -1,9 +1,9 @@ -## Test a Phoenix application +# Test a Phoenix application with GitLab CI/CD This example demonstrates the integration of Gitlab CI with Phoenix, Elixir and Postgres. -### Add `.gitlab-ci.yml` file to project +## Add `.gitlab-ci.yml` to project The following `.gitlab-ci.yml` should be added in the root of your repository to trigger CI: @@ -36,7 +36,7 @@ run your migrations. Finally, the test `script` will run your tests. -### Update the Config Settings +## Update the Config Settings In `config/test.exs`, update the database hostname: @@ -45,12 +45,12 @@ config :my_app, MyApp.Repo, hostname: if(System.get_env("CI"), do: "postgres", else: "localhost"), ``` -### Add the Migrations Folder +## Add the Migrations Folder If you do not have any migrations yet, you will need to create an empty `.gitkeep` file in `priv/repo/migrations`. -### Sources +## Sources - https://medium.com/@nahtnam/using-phoenix-on-gitlab-ci-5a51eec81142 - https://davejlong.com/ci-with-phoenix-and-gitlab/ diff --git a/doc/ci/permissions/README.md b/doc/ci/permissions/README.md index 42eb59f84c8..80d8e46f29c 100644 --- a/doc/ci/permissions/README.md +++ b/doc/ci/permissions/README.md @@ -1,3 +1 @@ -# Users Permissions - This document was moved to [user/permissions.md](../../user/permissions.md#gitlab-ci). diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md index 2d56b2540ef..f621bf07251 100644 --- a/doc/ci/quick_start/README.md +++ b/doc/ci/quick_start/README.md @@ -1,4 +1,4 @@ -# Getting started with GitLab CI +# Getting started with GitLab CI/CD >**Note:** Starting from version 8.0, GitLab [Continuous Integration][ci] (CI) is fully integrated into GitLab itself and is [enabled] by default on all diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md index 8b51d112a2c..df66810a838 100644 --- a/doc/ci/runners/README.md +++ b/doc/ci/runners/README.md @@ -1,4 +1,4 @@ -# Runners +# Configuring GitLab Runners In GitLab CI, Runners run the code defined in [`.gitlab-ci.yml`](../yaml/README.md). They are isolated (virtual) machines that pick up jobs through the coordinator diff --git a/doc/ci/services/README.md b/doc/ci/services/README.md index 4b79461d55c..d94b472b768 100644 --- a/doc/ci/services/README.md +++ b/doc/ci/services/README.md @@ -1,4 +1,8 @@ -## GitLab CI Services +--- +comments: false +--- + +# GitLab CI Services GitLab CI uses the `services` keyword to define what docker containers should be linked with your base image. Below is a list of examples you may use. diff --git a/doc/ci/services/docker-services.md b/doc/ci/services/docker-services.md index df36ebaf7d4..787c5e462e4 100644 --- a/doc/ci/services/docker-services.md +++ b/doc/ci/services/docker-services.md @@ -1,5 +1,9 @@ -## GitLab CI Services +--- +comments: false +--- -+ [Using MySQL](mysql.md) -+ [Using PostgreSQL](postgres.md) -+ [Using Redis](redis.md) +# GitLab CI Services + +- [Using MySQL](mysql.md) +- [Using PostgreSQL](postgres.md) +- [Using Redis](redis.md) diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index 73568757aaa..535ed351366 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -1,4 +1,4 @@ -# Variables +# GitLab CI/CD Variables When receiving a job from GitLab CI, the [Runner] prepares the build environment. It starts by setting a list of **predefined variables** (environment variables) @@ -43,7 +43,7 @@ future GitLab releases.** | **CI_COMMIT_TAG** | 9.0 | 0.5 | The commit tag name. Present only when building tags. | | **CI_CONFIG_PATH** | 9.4 | 0.5 | The path to CI config file. Defaults to `.gitlab-ci.yml` | | **CI_DEBUG_TRACE** | all | 1.7 | Whether [debug tracing](#debug-tracing) is enabled | -| **CI_DISPOSABLE_ENVIRONMENT** | all | 10.1 | Mark that job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). If the environment is disposable, it is set to true, otherwise it is not defined at all. | +| **CI_DISPOSABLE_ENVIRONMENT** | all | 10.1 | Marks that the job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). If the environment is disposable, it is set to true, otherwise it is not defined at all. | | **CI_ENVIRONMENT_NAME** | 8.15 | all | The name of the environment for this job | | **CI_ENVIRONMENT_SLUG** | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, etc. | | **CI_ENVIRONMENT_URL** | 9.3 | all | The URL of the environment for this job | @@ -74,7 +74,7 @@ future GitLab releases.** | **CI_SERVER_NAME** | all | all | The name of CI server that is used to coordinate jobs | | **CI_SERVER_REVISION** | all | all | GitLab revision that is used to schedule jobs | | **CI_SERVER_VERSION** | all | all | GitLab version that is used to schedule jobs | -| **CI_SHARED_ENVIRONMENT** | all | 10.1 | Mark that job is executed in a shared environment (something that is persisted across CI invocations like `shell` or `ssh` executor). If the environment is shared, it is set to true, otherwise it is not defined at all. | +| **CI_SHARED_ENVIRONMENT** | all | 10.1 | Marks that the job is executed in a shared environment (something that is persisted across CI invocations like `shell` or `ssh` executor). If the environment is shared, it is set to true, otherwise it is not defined at all. | | **ARTIFACT_DOWNLOAD_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to download artifacts running a job | | **GET_SOURCES_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to fetch sources running a job | | **GITLAB_CI** | all | all | Mark that job is executed in GitLab CI environment | diff --git a/doc/development/README.md b/doc/development/README.md index 36096842344..0cafc112b6b 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab development guides ## Get started! diff --git a/doc/development/testing_guide/testing_rake_tasks.md b/doc/development/testing_guide/testing_rake_tasks.md index 5bf185dd7b5..60163f1a230 100644 --- a/doc/development/testing_guide/testing_rake_tasks.md +++ b/doc/development/testing_guide/testing_rake_tasks.md @@ -1,4 +1,4 @@ -## Testing Rake tasks +# Testing Rake tasks To make testing Rake tasks a little easier, there is a helper that can be included in lieu of the standard Spec helper. Instead of `require 'spec_helper'`, use diff --git a/doc/development/ux_guide/users.md b/doc/development/ux_guide/users.md index cbd7c17de41..fce882a45f1 100644 --- a/doc/development/ux_guide/users.md +++ b/doc/development/ux_guide/users.md @@ -1,4 +1,5 @@ -## UX Personas +# UX Personas + * [Nazim Ramesh](#nazim-ramesh) - Small to medium size organisations using GitLab CE * [James Mackey](#james-mackey) @@ -7,16 +8,16 @@ * [Karolina Plaskaty](#karolina-plaskaty) - Using GitLab.com for personal/hobby projects - Would like to use GitLab at work - - Working for a medium to large size organisation + - Working for a medium to large size organisation -<hr> +--- -### Nazim Ramesh +## Nazim Ramesh - Small to medium size organisations using GitLab CE <img src="img/nazim-ramesh.png" width="300px"> -#### Demographics +### Demographics - **Age**<br>32 years old - **Location**<br>Germany @@ -26,7 +27,7 @@ - **Frequently used programming languages**<br>JavaScript, SQL, PHP - **Hobbies / interests**<br>Functional programming, open source, gaming, web development and web security. -#### Motivations +### Motivations Nazim works for a software development company which currently hires around 80 people. When Nazim first joined the company, the engineering team were using Subversion (SVN) as their primary form of source control. However, Nazim felt SVN was not flexible enough to work with many feature branches and noticed that developers with less experience of source control struggled with the central-repository nature of SVN. Armed with a wishlist of features, Nazim began comparing source control tools. A search for “self-hosted Git server repository management” returned GitLab. In his own words, Nazim explains why he wanted the engineering team to start using GitLab: > @@ -39,48 +40,48 @@ In his role as a full-stack web developer, Nazim could recommend products that h “The biggest challenge...why should we change anything at all from the status quo? We needed to switch from SVN to Git. They knew they needed to learn Git and a Git workflow...using Git was scary to my colleagues...they thought it was more complex than SVN to use.” > -Undeterred, Nazim decided to migrate a couple of projects across to GitLab. +Undeterred, Nazim decided to migrate a couple of projects across to GitLab. > “Old SVN users couldn’t see the benefits of Git at first. It took a month or two to convince them.” > -Slowly, by showing his colleagues how easy it was to use Git, the majority of the team’s projects were migrated to GitLab. +Slowly, by showing his colleagues how easy it was to use Git, the majority of the team’s projects were migrated to GitLab. -The engineering team have been using GitLab CE for around 2 years now. Nazim credits himself as being entirely responsible for his company’s decision to move to GitLab. +The engineering team have been using GitLab CE for around 2 years now. Nazim credits himself as being entirely responsible for his company’s decision to move to GitLab. -#### Frustrations -##### Adoption to GitLab has been slow +### Frustrations +#### Adoption to GitLab has been slow Not only has the engineering team had to get to grips with Git, they’ve also had to adapt to using GitLab. Due to lack of training and existing skills in other tools, the full feature set of GitLab CE is not being utilised. Nazim sold GitLab to his manager as an ‘all in one’ tool which would replace multiple tools used within the company, thus saving costs. Nazim hasn’t had the time to integrate the legacy tools to GitLab and he’s struggling to convince his peers to change their habits. -##### Missing Features +#### Missing Features Nazim’s company want GitLab to be able to do everything. There isn’t a large budget for software, so they’re selective about what tools are implemented. It needs to add real value to the company. In order for GitLab to be widely adopted and to meet the requirements of different roles within the company, it needs a host of features. When an individual within Nazim’s company wants to know if GitLab has a specific feature or does a particular thing, Nazim is the person to ask. He becomes the point of contact to investigate, build or sometimes just raise the feature request. Nazim gets frustrated when GitLab isn’t able to do what he or his colleagues need it to do. -##### Regressions and bugs +#### Regressions and bugs Nazim often has to calm down his colleagues, when a release contains regressions or new bugs. As he puts it “every new version adds something awesome, but breaks something”. He feels that “old issues for "minor" annoyances get quickly buried in the mass of open issues and linger for a very long time. More generally, I have the feeling that GitLab focus on adding new functionalities, but overlook a bunch of annoying minor regressions or introduced bugs.” Due to limited resource and expertise within the team, not only is it difficult to remain up-to-date with the frequent release cycle, it’s also counterproductive to fix workflows every month. -##### Uses too much RAM and CPU +#### Uses too much RAM and CPU > “Memory usages mean that if we host it from a cloud based host like AWS, we spend almost as much on the instance as what we would pay GitHub” > -##### UI/UX +#### UI/UX GitLab’s interface initially attracted Nazim when he was comparing version control software. He thought it would help his less technical colleagues to adapt to using Git and perhaps, GitLab could be rolled out to other areas of the business, beyond engineering. However, using GitLab’s interface daily has left him frustrated at the lack of personalisation / control over his user experience. He’s also regularly lost in a maze of navigation. Whilst he acknowledges that GitLab listens to its users and that the interface is improving, he becomes annoyed when the changes are too progressive. “Too frequent UI changes. Most of them tend to turn out great after a few cycles of fixes, but the frequency is still far too high for me to feel comfortable to always stay on the current release.” -#### Goals +### Goals * To convince his colleagues to fully adopt GitLab CE, thus improving workflow and collaboration. * To use a feature rich version control platform that covers all stages of the development lifecycle, in order to reduce dependencies on other tools. * To use an intuitive and stable product, so he can spend more time on his core job responsibilities and less time bug-fixing, guiding colleagues, etc. -<hr> +--- -### James Mackey +## James Mackey - Medium to large size organisations using CE or EE - Small organisations using EE <img src="img/james-mackey.png" width="300px"> -#### Demographics +### Demographics - **Age**<br>36 years old - **Location**<br>US @@ -90,7 +91,7 @@ GitLab’s interface initially attracted Nazim when he was comparing version con - **Frequently used programming languages**<br>JavaScript, SQL, Node.js, Java, PHP, Python - **Hobbies / interests**<br>DevOps, open source, web development, science, automation and electronics. -#### Motivations +### Motivations James works for a research company which currently hires around 800 staff. He began using GitLab.com back in 2013 for his own open source, hobby projects and loved “the simplicity of installation, administration and use”. After using GitLab for over a year, he began to wonder about using it at work. James explains: > @@ -99,7 +100,7 @@ James works for a research company which currently hires around 800 staff. He be James and his colleagues also reviewed competitor products including GitHub Enterprise, but they found it “less innovative and with considerable costs...GitLab had the features we wanted at a much lower cost per head than GitHub”. -The company James works for provides employees with a discretionary budget to spend how they want on software, so James and his team decided to upgrade to EE. +The company James works for provides employees with a discretionary budget to spend how they want on software, so James and his team decided to upgrade to EE. James feels partially responsible for his organisation’s decision to start using GitLab. @@ -107,33 +108,33 @@ James feels partially responsible for his organisation’s decision to start usi “It's still up to the teams themselves [to decide] which tools to use. We just had a great experience moving our daily development to GitLab, so other teams have followed the path or are thinking about switching.” > -#### Frustrations -##### Third Party Integration +### Frustrations +#### Third Party Integration Some of GitLab EE’s features are too basic, in particular, issues boards which do not have the level of reporting that James and his team need. Subsequently, they still need to use GitLab EE in conjunction with other tools, such as JIRA. Whilst James feels it isn’t essential for GitLab to meet all his needs (his company are happy for him to use, and pay for, multiple tools), he sometimes isn’t sure what is/isn’t possible with plugins and what level of custom development he and his team will need to do. -##### UX/UI +#### UX/UI James and his team use CI quite heavily for several projects. Whilst they’ve welcomed improvements to the builds and pipelines interface, they still have some difficulty following build process on the different tabs under Pipelines. Some confusion has arisen from not knowing where to find different pieces of information or how to get to the next stages logs from the current stage’s log output screen. They feel more intuitive linking and flow may alleviate the problem. Generally, they feel GitLab’s navigation needs to reviewed and optimised. -##### Permissions +#### Permissions > “There is no granular control over user or group permissions. The permissions for a project are too tightly coupled to the permissions for Gitlab CI/build pipelines.” > -#### Goals +### Goals * To be able to integrate third party tools easily with GitLab EE and to create custom integrations and patches where needed. * To use GitLab EE primarily for code hosting, merge requests, continuous integration and issue management. James and his team want to be able to understand and use these particular features easily. * To able to share one instance of GitLab EE with multiple teams across the business. Advanced user management, the ability to separate permissions on different parts of the source code, etc are important to James. -<hr> +--- -### Karolina Plaskaty +## Karolina Plaskaty - Using GitLab.com for personal/hobby projects - Would like to use GitLab at work -- Working for a medium to large size organisation +- Working for a medium to large size organisation <img src="img/karolina-plaskaty.png" width="300px"> -#### Demographics +### Demographics - **Age**<br>26 years old - **Location**<br>UK @@ -143,22 +144,22 @@ James and his team use CI quite heavily for several projects. Whilst they’ve w - **Frequently used programming languages**<br>JavaScript and SQL - **Hobbies / interests**<br>Web development, mobile development, UX, open source, gaming and travel. -#### Motivations +### Motivations Karolina has been using GitLab.com for around a year. She roughly spends 8 hours every week programming, of that, 2 hours is spent contributing to open source projects. Karolina contributes to open source projects to gain programming experience and to give back to the community. She likes GitLab.com for its free private repositories and range of features which provide her with everything she needs for her personal projects. Karolina is also a massive fan of GitLab’s values and the fact that it isn’t a “behemoth of a company”. She explains that “displaying every single thing (doc, culture, assumptions, development...) in the open gives me greater confidence to choose Gitlab personally and to recommend it at work.” She’s also an avid reader of GitLab’s blog. Karolina works for a software development company which currently hires around 500 people. Karolina would love to use GitLab at work but the company has used GitHub Enterprise for a number of years. She describes management at her company as “old fashioned” and explains that it’s “less of a technical issue and more of a cultural issue” to convince upper management to move to GitLab. Karolina is also relatively new to the company so she’s apprehensive about pushing too hard to change version control platforms. -#### Frustrations -##### Unable to use GitLab at work +### Frustrations +#### Unable to use GitLab at work Karolina wants to use GitLab at work but isn’t sure how to approach the subject with management. In her current role, she doesn’t feel that she has the authority to request GitLab. -##### Performance +#### Performance GitLab.com is frequently slow and unavailable. Karolina has also heard that GitLab is a “memory hog” which has deterred her from running GitLab on her own machine for just hobby / personal projects. -##### UX/UI +#### UX/UI Karolina has an interest in UX and therefore has strong opinions about how GitLab should look and feel. She feels the interface is cluttered, “it has too many links/buttons” and the navigation “feels a bit weird sometimes. I get lost if I don’t pay attention.” As Karolina also enjoys contributing to open-source projects, it’s important to her that GitLab is well designed for public repositories, she doesn’t feel that GitLab currently achieves this. -#### Goals +### Goals * To develop her programming experience and to learn from other developers. * To contribute to both her own and other open source projects. -* To use a fast and intuitive version control platform.
\ No newline at end of file +* To use a fast and intuitive version control platform. diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md index 3d893ba53dd..4e15f7cfd49 100644 --- a/doc/gitlab-basics/README.md +++ b/doc/gitlab-basics/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab basics Step-by-step guides on the basics of working with Git and GitLab. diff --git a/doc/install/README.md b/doc/install/README.md index 656f8720361..540cb0d3f38 100644 --- a/doc/install/README.md +++ b/doc/install/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Installation GitLab can be installed via various ways. Check the [installation methods][methods] diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md index 713d11b75e4..2f5d4142d04 100644 --- a/doc/install/relative_url.md +++ b/doc/install/relative_url.md @@ -1,11 +1,11 @@ -## Install GitLab under a relative URL +# Install GitLab under a relative URL -_**Note:** +NOTE: **Note:** This document describes how to run GitLab under a relative URL for installations from source. If you are using an Omnibus package, [the steps are different][omnibus-rel]. Use this guide along with the [installation guide](installation.md) if you are installing GitLab for the -first time._ +first time. --- @@ -33,7 +33,7 @@ serve GitLab under a relative URL is: After all the changes you need to recompile the assets and [restart GitLab]. -### Relative URL requirements +## Relative URL requirements If you configure GitLab with a relative URL, the assets (JavaScript, CSS, fonts, images, etc.) will need to be recompiled, which is a task which consumes a lot @@ -43,11 +43,11 @@ least 2GB of RAM available on your system, while we recommend 4GB RAM, and 4 or See the [requirements](requirements.md) document for more information. -### Enable relative URL in GitLab +## Enable relative URL in GitLab -_**Note:** +NOTE: **Note:** Do not make any changes to your web server configuration file regarding -relative URL. The relative URL support is implemented by GitLab Workhorse._ +relative URL. The relative URL support is implemented by GitLab Workhorse. --- @@ -115,7 +115,7 @@ Make sure to follow all steps below: 1. [Restart GitLab][] for the changes to take effect. -### Disable relative URL in GitLab +## Disable relative URL in GitLab To disable the relative URL: diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 3d7becd18fc..7d9bbca4168 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -121,7 +121,7 @@ Existing users using GitLab with MySQL/MariaDB are advised to ### PostgreSQL Requirements -As of GitLab 10.0, PostgreSQL 9.6 or newer is required, and earlier versions are +As of GitLab 10.0, PostgreSQL 9.6 or newer (but less than 10) is required, and earlier versions are not supported. We highly recommend users to use PostgreSQL 9.6 as this is the PostgreSQL version used for development and testing. diff --git a/doc/integration/README.md b/doc/integration/README.md index 09d96bdd338..54e78bdef54 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab Integration GitLab integrates with multiple third-party services to allow external issue diff --git a/doc/intro/README.md b/doc/intro/README.md index 7485912d1a2..d9acc5bdeac 100644 --- a/doc/intro/README.md +++ b/doc/intro/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Get started with GitLab ## Organize diff --git a/doc/legal/README.md b/doc/legal/README.md index 56d72ae3859..6413f1d645f 100644 --- a/doc/legal/README.md +++ b/doc/legal/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Legal - [Corporate contributor license agreement](corporate_contributor_license_agreement.md) diff --git a/doc/legal/corporate_contributor_license_agreement.md b/doc/legal/corporate_contributor_license_agreement.md index 7f08188bd65..ebb24ba0a7f 100644 --- a/doc/legal/corporate_contributor_license_agreement.md +++ b/doc/legal/corporate_contributor_license_agreement.md @@ -1,29 +1,2 @@ -# Corporate contributor license agreement - -You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions. - -1. Definitions. - - "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab B.V.. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - "Contribution" shall mean the code, documentation or other original works of authorship, including any modifications or additions to an existing work, that is submitted by You to GitLab B.V. for inclusion in, or documentation of, any of the products owned or managed by GitLab B.V. (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab B.V. or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab B.V. for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." - -2. Grant of Copyright License. - -Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. - -3. Grant of Patent License. - -Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. - -4. You represent that You are legally entitled to grant the above license. You represent further that each of Your employees is authorized to submit Contributions on Your behalf, but excluding employees that are designated in writing by You as "Not authorized to submit Contributions on behalf of [name of Your corporation here]." Such designations of exclusion for unauthorized employees are to be submitted via email to legal@gitlab.com. - -5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). - -6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. - -7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". - -8. It is Your responsibility to notify GitLab.com when any change is required to the list of designated employees excluded from submitting Contributions on Your behalf per Section 4. Such notification should be sent via email to legal@gitlab.com. - -This text is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. +This document has been replaced by a Developer Certificate of Origin and License, +as described in [Contributing.md](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md).
\ No newline at end of file diff --git a/doc/legal/individual_contributor_license_agreement.md b/doc/legal/individual_contributor_license_agreement.md index 59803aea080..ebb24ba0a7f 100644 --- a/doc/legal/individual_contributor_license_agreement.md +++ b/doc/legal/individual_contributor_license_agreement.md @@ -1,25 +1,2 @@ -# Individual contributor license agreement - -You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions. - -1. Definitions. - - "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab B.V.. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GitLab B.V. for inclusion in, or documentation of, any of the products owned or managed by GitLab B.V. (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab B.V. or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab B.V. for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." - -2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. - -3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. - -4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to GitLab B.V., or that your employer has executed a separate Corporate CLA with GitLab B.V.. - -5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. - -6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. - -7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [insert_name_here]". - -8. You agree to notify GitLab B.V. of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. - -This text is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. +This document has been replaced by a Developer Certificate of Origin and License, +as described in [Contributing.md](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md).
\ No newline at end of file diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md index 2e7782736ff..9347a834510 100644 --- a/doc/migrate_ci_to_ce/README.md +++ b/doc/migrate_ci_to_ce/README.md @@ -372,8 +372,10 @@ CREATE TABLE ``` To fix that you need to apply this SQL statement before doing final backup: -``` -# Omnibus + +```sql +## Omnibus GitLab + gitlab-ci-rails dbconsole <<EOF -- ALTER TABLES - DROP DEFAULTS ALTER TABLE ONLY ci_application_settings ALTER COLUMN id DROP DEFAULT; @@ -427,7 +429,8 @@ ALTER TABLE ONLY ci_variables ALTER COLUMN id SET DEFAULT nextval('ci_variables_ ALTER TABLE ONLY ci_web_hooks ALTER COLUMN id SET DEFAULT nextval('ci_web_hooks_id_seq'::regclass); EOF -# Source +## Source installations + cd /home/gitlab_ci/gitlab-ci sudo -u gitlab_ci -H bundle exec rails dbconsole production <<EOF ... COPY SQL STATEMENTS FROM ABOVE ... diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md index 2b81ebc9c59..2f916f5dea7 100644 --- a/doc/raketasks/README.md +++ b/doc/raketasks/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Rake tasks - [Backup restore](backup_restore.md) diff --git a/doc/security/README.md b/doc/security/README.md index 0fea6be8b55..d397ff104ab 100644 --- a/doc/security/README.md +++ b/doc/security/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Security - [Password length limits](password_length_limits.md) diff --git a/doc/ssh/README.md b/doc/ssh/README.md index 793de9d777c..33a2d7a88a7 100644 --- a/doc/ssh/README.md +++ b/doc/ssh/README.md @@ -1,4 +1,4 @@ -# SSH +# GitLab and SSH keys Git is a distributed version control system, which means you can work locally but you can also share or "push" your changes to other servers. @@ -114,7 +114,7 @@ custom name continue onto the next step. If you manually copied your public SSH key make sure you copied the entire key starting with `ssh-rsa` and ending with your email. - + 1. Optionally you can test your setup by running `ssh -T git@example.com` (replacing `example.com` with your GitLab domain) and verifying that you receive a `Welcome to GitLab` message. @@ -172,7 +172,7 @@ dummy user account. If you are a project master or owner, you can add a deploy key in the project settings under the section 'Repository'. Specify a title for the new deploy key and paste a public SSH key. After this, the machine that uses -the corresponding private SSH key has read-only or read-write (if enabled) +the corresponding private SSH key has read-only or read-write (if enabled) access to the project. You can't add the same deploy key twice using the form. @@ -232,7 +232,7 @@ something is wrong with your SSH setup. - Ensure that you generated your SSH key pair correctly and added the public SSH key to your GitLab profile -- Try manually registering your private SSH key using `ssh-agent` as documented +- Try manually registering your private SSH key using `ssh-agent` as documented earlier in this document - Try to debug the connection by running `ssh -Tv git@example.com` (replacing `example.com` with your GitLab domain) diff --git a/doc/university/README.md b/doc/university/README.md index 170582bcd0c..c96b9f38890 100644 --- a/doc/university/README.md +++ b/doc/university/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab University GitLab University is the best place to learn about **Version Control with Git and GitLab**. diff --git a/doc/university/bookclub/booklist.md b/doc/university/bookclub/booklist.md index c4229832e9f..26c3851276b 100644 --- a/doc/university/bookclub/booklist.md +++ b/doc/university/bookclub/booklist.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Books List of books and resources, that may be worth reading. diff --git a/doc/university/bookclub/index.md b/doc/university/bookclub/index.md index 022a61f4429..63238685b2b 100644 --- a/doc/university/bookclub/index.md +++ b/doc/university/bookclub/index.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # The GitLab Book Club The Book Club is a casual meet-up to read and discuss books we like. diff --git a/doc/university/glossary/README.md b/doc/university/glossary/README.md index 9544de41b9a..02c0233d75a 100644 --- a/doc/university/glossary/README.md +++ b/doc/university/glossary/README.md @@ -1,4 +1,8 @@ -## What is the Glossary +--- +comments: false +--- + +# What is the Glossary This contains a simplified list and definitions of some of the terms that you will encounter in your day to day activities when working with GitLab. Please add any terms that you discover that you think would be useful for others. diff --git a/doc/university/high-availability/aws/README.md b/doc/university/high-availability/aws/README.md index 6b8f3cd3d1d..54625996dff 100644 --- a/doc/university/high-availability/aws/README.md +++ b/doc/university/high-availability/aws/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # High Availability on AWS diff --git a/doc/university/process/README.md b/doc/university/process/README.md index 04f2d52514f..fdf6224f7f6 100644 --- a/doc/university/process/README.md +++ b/doc/university/process/README.md @@ -1,8 +1,12 @@ --- +comments: false +--- + +--- title: University | Process --- -## Suggesting improvements +# Suggesting improvements If you would like to teach a class or participate or help in any way please submit a merge request and assign it to [Job](https://gitlab.com/u/JobV). diff --git a/doc/university/support/README.md b/doc/university/support/README.md index 567dadb3b47..25d5fe351ca 100644 --- a/doc/university/support/README.md +++ b/doc/university/support/README.md @@ -1,5 +1,9 @@ +--- +comments: false +--- -## Support Boot Camp + +# Support Boot Camp **Goal:** Prepare new Service Engineers at GitLab diff --git a/doc/university/training/end-user/README.md b/doc/university/training/end-user/README.md index 03c62a81b10..a882bf0eb48 100644 --- a/doc/university/training/end-user/README.md +++ b/doc/university/training/end-user/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Training diff --git a/doc/university/training/gitlab_flow.md b/doc/university/training/gitlab_flow.md index a7db1f2e069..02a6ad48a38 100644 --- a/doc/university/training/gitlab_flow.md +++ b/doc/university/training/gitlab_flow.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab Flow - A simplified branching strategy diff --git a/doc/university/training/index.md b/doc/university/training/index.md index 03179ff5a77..14f096b130f 100644 --- a/doc/university/training/index.md +++ b/doc/university/training/index.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab Training Material All GitLab training material is stored in markdown format. Slides are diff --git a/doc/university/training/topics/additional_resources.md b/doc/university/training/topics/additional_resources.md index 3ed601625cf..d01634df744 100644 --- a/doc/university/training/topics/additional_resources.md +++ b/doc/university/training/topics/additional_resources.md @@ -1,4 +1,8 @@ -## Additional Resources +--- +comments: false +--- + +# Additional Resources 1. GitLab Documentation [http://docs.gitlab.com](http://docs.gitlab.com/) 2. GUI Clients [http://git-scm.com/downloads/guis](http://git-scm.com/downloads/guis) diff --git a/doc/university/training/topics/agile_git.md b/doc/university/training/topics/agile_git.md index e6e4fea9b51..251af99bed7 100644 --- a/doc/university/training/topics/agile_git.md +++ b/doc/university/training/topics/agile_git.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Agile and Git ---------- diff --git a/doc/university/training/topics/bisect.md b/doc/university/training/topics/bisect.md index a60c4365e0c..2d5ab107fe6 100644 --- a/doc/university/training/topics/bisect.md +++ b/doc/university/training/topics/bisect.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Bisect ---------- diff --git a/doc/university/training/topics/cherry_picking.md b/doc/university/training/topics/cherry_picking.md index af7a70a2818..df23024b6ee 100644 --- a/doc/university/training/topics/cherry_picking.md +++ b/doc/university/training/topics/cherry_picking.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Cherry Pick ---------- diff --git a/doc/university/training/topics/env_setup.md b/doc/university/training/topics/env_setup.md index 8149379b36f..b7bec83ed8a 100644 --- a/doc/university/training/topics/env_setup.md +++ b/doc/university/training/topics/env_setup.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Configure your environment ---------- diff --git a/doc/university/training/topics/explore_gitlab.md b/doc/university/training/topics/explore_gitlab.md index b65457728c0..84a1879cd92 100644 --- a/doc/university/training/topics/explore_gitlab.md +++ b/doc/university/training/topics/explore_gitlab.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Explore GitLab projects ---------- diff --git a/doc/university/training/topics/feature_branching.md b/doc/university/training/topics/feature_branching.md index 4b34406ea75..0df5f26dbea 100644 --- a/doc/university/training/topics/feature_branching.md +++ b/doc/university/training/topics/feature_branching.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Feature branching ---------- diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md index ec7bb2631aa..153b45fb4da 100644 --- a/doc/university/training/topics/getting_started.md +++ b/doc/university/training/topics/getting_started.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Getting Started ---------- diff --git a/doc/university/training/topics/git_add.md b/doc/university/training/topics/git_add.md index 9ffb4b9c859..651366e0d49 100644 --- a/doc/university/training/topics/git_add.md +++ b/doc/university/training/topics/git_add.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Git Add ---------- diff --git a/doc/university/training/topics/git_intro.md b/doc/university/training/topics/git_intro.md index ca1ff29d93b..7e502d6dad4 100644 --- a/doc/university/training/topics/git_intro.md +++ b/doc/university/training/topics/git_intro.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Git introduction ---------- diff --git a/doc/university/training/topics/git_log.md b/doc/university/training/topics/git_log.md index 32ebceff491..21d81840ea7 100644 --- a/doc/university/training/topics/git_log.md +++ b/doc/university/training/topics/git_log.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Git Log ---------- diff --git a/doc/university/training/topics/gitlab_flow.md b/doc/university/training/topics/gitlab_flow.md index 8e5d3baf959..b8049b5c80e 100644 --- a/doc/university/training/topics/gitlab_flow.md +++ b/doc/university/training/topics/gitlab_flow.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab Flow ---------- diff --git a/doc/university/training/topics/merge_conflicts.md b/doc/university/training/topics/merge_conflicts.md index 77807b3e7ef..9a1ce550868 100644 --- a/doc/university/training/topics/merge_conflicts.md +++ b/doc/university/training/topics/merge_conflicts.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Merge conflicts ---------- diff --git a/doc/university/training/topics/merge_requests.md b/doc/university/training/topics/merge_requests.md index 5b446f02f63..4e8c9de85a1 100644 --- a/doc/university/training/topics/merge_requests.md +++ b/doc/university/training/topics/merge_requests.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Merge requests ---------- diff --git a/doc/university/training/topics/rollback_commits.md b/doc/university/training/topics/rollback_commits.md index cf647284604..0db1d93d1dc 100644 --- a/doc/university/training/topics/rollback_commits.md +++ b/doc/university/training/topics/rollback_commits.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Rollback Commits ---------- diff --git a/doc/university/training/topics/stash.md b/doc/university/training/topics/stash.md index c1bdda32645..5b27ac12f77 100644 --- a/doc/university/training/topics/stash.md +++ b/doc/university/training/topics/stash.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Git Stash ---------- diff --git a/doc/university/training/topics/subtree.md b/doc/university/training/topics/subtree.md index 5d869af64c1..b5a892dc17b 100644 --- a/doc/university/training/topics/subtree.md +++ b/doc/university/training/topics/subtree.md @@ -1,8 +1,8 @@ -## Subtree +--- +comments: false +--- ----------- - -## Subtree +# Subtree * Used when there are nested repositories. * Not recommended when the amount of dependencies is too large diff --git a/doc/university/training/topics/tags.md b/doc/university/training/topics/tags.md index e9607b5a875..ab48d52d3c3 100644 --- a/doc/university/training/topics/tags.md +++ b/doc/university/training/topics/tags.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Tags ---------- diff --git a/doc/university/training/topics/unstage.md b/doc/university/training/topics/unstage.md index 17dbb64b9e6..fc72949ade9 100644 --- a/doc/university/training/topics/unstage.md +++ b/doc/university/training/topics/unstage.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Unstage ---------- diff --git a/doc/university/training/user_training.md b/doc/university/training/user_training.md index 9e38df26b6a..90e1d2ba5e8 100644 --- a/doc/university/training/user_training.md +++ b/doc/university/training/user_training.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab Git Workshop --- diff --git a/doc/update/10.0-to-10.1.md b/doc/update/10.0-to-10.1.md index dc14c779026..af815d26a74 100644 --- a/doc/update/10.0-to-10.1.md +++ b/doc/update/10.0-to-10.1.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 10.0 to 10.1 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/2.6-to-3.0.md b/doc/update/2.6-to-3.0.md index 97cd277b424..8f18bd93cea 100644 --- a/doc/update/2.6-to-3.0.md +++ b/doc/update/2.6-to-3.0.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 2.6 to 3.0 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/2.6-to-3.0.md) for the most up to date instructions.* diff --git a/doc/update/2.9-to-3.0.md b/doc/update/2.9-to-3.0.md index a890aa885d5..6a3c2387683 100644 --- a/doc/update/2.9-to-3.0.md +++ b/doc/update/2.9-to-3.0.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 2.9 to 3.0 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/2.9-to-3.0.md) for the most up to date instructions.* diff --git a/doc/update/3.0-to-3.1.md b/doc/update/3.0-to-3.1.md index e32508745a2..1f25b8265c9 100644 --- a/doc/update/3.0-to-3.1.md +++ b/doc/update/3.0-to-3.1.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 3.0 to 3.1 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/3.0-to-3.1.md) for the most up to date instructions.* diff --git a/doc/update/3.1-to-4.0.md b/doc/update/3.1-to-4.0.md index b370464390e..1a53ddeb4bd 100644 --- a/doc/update/3.1-to-4.0.md +++ b/doc/update/3.1-to-4.0.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 3.1 to 4.0 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/3.1-to-4.0.md) for the most up to date instructions.* diff --git a/doc/update/4.0-to-4.1.md b/doc/update/4.0-to-4.1.md index 7124424bb60..40a133e796e 100644 --- a/doc/update/4.0-to-4.1.md +++ b/doc/update/4.0-to-4.1.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 4.0 to 4.1 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/4.0-to-4.1.md) for the most up to date instructions.* diff --git a/doc/update/4.1-to-4.2.md b/doc/update/4.1-to-4.2.md index 8ed5b333a2e..1fd6c58bda7 100644 --- a/doc/update/4.1-to-4.2.md +++ b/doc/update/4.1-to-4.2.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 4.1 to 4.2 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/4.1-to-4.2.md) for the most up to date instructions.* diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md index 1ec39218ba8..311664b2bc1 100644 --- a/doc/update/4.2-to-5.0.md +++ b/doc/update/4.2-to-5.0.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 4.2 to 5.0 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/4.2-to-5.0.md) for the most up to date instructions.* diff --git a/doc/update/5.0-to-5.1.md b/doc/update/5.0-to-5.1.md index 9c9950fb2c6..7067ea4c40c 100644 --- a/doc/update/5.0-to-5.1.md +++ b/doc/update/5.0-to-5.1.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 5.0 to 5.1 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.0-to-5.1.md) for the most up to date instructions.* diff --git a/doc/update/5.1-to-5.2.md b/doc/update/5.1-to-5.2.md index 2aab47d2d7c..4faf5fa549e 100644 --- a/doc/update/5.1-to-5.2.md +++ b/doc/update/5.1-to-5.2.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 5.1 to 5.2 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.1-to-5.2.md) for the most up to date instructions.* diff --git a/doc/update/5.1-to-5.4.md b/doc/update/5.1-to-5.4.md index e80f1b89c63..212343bac3f 100644 --- a/doc/update/5.1-to-5.4.md +++ b/doc/update/5.1-to-5.4.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 5.1 to 5.4 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.1-to-5.4.md) for the most up to date instructions.* diff --git a/doc/update/5.1-to-6.0.md b/doc/update/5.1-to-6.0.md index 1ee175383da..865d38e0ca4 100644 --- a/doc/update/5.1-to-6.0.md +++ b/doc/update/5.1-to-6.0.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 5.1 to 6.0 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.1-to-6.0.md) for the most up to date instructions.* diff --git a/doc/update/5.2-to-5.3.md b/doc/update/5.2-to-5.3.md index 2ae50510f63..ed4f3ebdd53 100644 --- a/doc/update/5.2-to-5.3.md +++ b/doc/update/5.2-to-5.3.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 5.2 to 5.3 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.2-to-5.3.md) for the most up to date instructions.* diff --git a/doc/update/5.3-to-5.4.md b/doc/update/5.3-to-5.4.md index 842e3bb6791..7277250eb32 100644 --- a/doc/update/5.3-to-5.4.md +++ b/doc/update/5.3-to-5.4.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 5.3 to 5.4 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.3-to-5.4.md) for the most up to date instructions.* diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md index 44715984f0c..dacdf05cc9c 100644 --- a/doc/update/5.4-to-6.0.md +++ b/doc/update/5.4-to-6.0.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 5.4 to 6.0 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.4-to-6.0.md) for the most up to date instructions.* diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md index 0c672abeb05..a3c52a1cfb4 100644 --- a/doc/update/6.0-to-6.1.md +++ b/doc/update/6.0-to-6.1.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.0 to 6.1 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.0-to-6.1.md) for the most up to date instructions.* diff --git a/doc/update/6.1-to-6.2.md b/doc/update/6.1-to-6.2.md index d3760cf0619..36a395bf01e 100644 --- a/doc/update/6.1-to-6.2.md +++ b/doc/update/6.1-to-6.2.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.1 to 6.2 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.1-to-6.2.md) for the most up to date instructions.* diff --git a/doc/update/6.2-to-6.3.md b/doc/update/6.2-to-6.3.md index 91105de2e29..02e87a08b8f 100644 --- a/doc/update/6.2-to-6.3.md +++ b/doc/update/6.2-to-6.3.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.2 to 6.3 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.2-to-6.3.md) for the most up to date instructions.* diff --git a/doc/update/6.3-to-6.4.md b/doc/update/6.3-to-6.4.md index 20b58ed8b25..285ed06bdad 100644 --- a/doc/update/6.3-to-6.4.md +++ b/doc/update/6.3-to-6.4.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.3 to 6.4 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.3-to-6.4.md) for the most up to date instructions.* diff --git a/doc/update/6.4-to-6.5.md b/doc/update/6.4-to-6.5.md index 5ee0f040b5d..e07c98a5ad4 100644 --- a/doc/update/6.4-to-6.5.md +++ b/doc/update/6.4-to-6.5.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.4 to 6.5 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.4-to-6.5.md) for the most up to date instructions.* diff --git a/doc/update/6.5-to-6.6.md b/doc/update/6.5-to-6.6.md index fa3712f83ad..3f79b19644e 100644 --- a/doc/update/6.5-to-6.6.md +++ b/doc/update/6.5-to-6.6.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.5 to 6.6 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.5-to-6.6.md) for the most up to date instructions.* diff --git a/doc/update/6.6-to-6.7.md b/doc/update/6.6-to-6.7.md index 9c85ed091c5..a0542d20d49 100644 --- a/doc/update/6.6-to-6.7.md +++ b/doc/update/6.6-to-6.7.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.6 to 6.7 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.6-to-6.7.md) for the most up to date instructions.* diff --git a/doc/update/6.7-to-6.8.md b/doc/update/6.7-to-6.8.md index 687c1265d9b..acf004577f1 100644 --- a/doc/update/6.7-to-6.8.md +++ b/doc/update/6.7-to-6.8.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.7 to 6.8 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.7-to-6.8.md) for the most up to date instructions.* diff --git a/doc/update/6.8-to-6.9.md b/doc/update/6.8-to-6.9.md index 0205b0c896a..3d7b1e5346b 100644 --- a/doc/update/6.8-to-6.9.md +++ b/doc/update/6.8-to-6.9.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.8 to 6.9 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.8-to-6.9.md) for the most up to date instructions.* diff --git a/doc/update/6.9-to-7.0.md b/doc/update/6.9-to-7.0.md index 4b6e3989893..27063948028 100644 --- a/doc/update/6.9-to-7.0.md +++ b/doc/update/6.9-to-7.0.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.9 to 7.0 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.9-to-7.0.md) for the most up to date instructions.* diff --git a/doc/update/6.x-or-7.x-to-7.14.md b/doc/update/6.x-or-7.x-to-7.14.md index 1e39fe47ef9..41d0e78b7d8 100644 --- a/doc/update/6.x-or-7.x-to-7.14.md +++ b/doc/update/6.x-or-7.x-to-7.14.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 6.x or 7.x to 7.14 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.x-or-7.x-to-7.14.md) for the most up to date instructions.* diff --git a/doc/update/7.0-to-7.1.md b/doc/update/7.0-to-7.1.md index 2e9457aa142..308e8aeb985 100644 --- a/doc/update/7.0-to-7.1.md +++ b/doc/update/7.0-to-7.1.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.0 to 7.1 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.0-to-7.1.md) for the most up to date instructions.* diff --git a/doc/update/7.1-to-7.2.md b/doc/update/7.1-to-7.2.md index e5045b5570f..07f92ac3af6 100644 --- a/doc/update/7.1-to-7.2.md +++ b/doc/update/7.1-to-7.2.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.1 to 7.2 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.1-to-7.2.md) for the most up to date instructions.* diff --git a/doc/update/7.10-to-7.11.md b/doc/update/7.10-to-7.11.md index 89213ba7178..39eeefc0e32 100644 --- a/doc/update/7.10-to-7.11.md +++ b/doc/update/7.10-to-7.11.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.10 to 7.11 ### 0. Stop server diff --git a/doc/update/7.11-to-7.12.md b/doc/update/7.11-to-7.12.md index 3865186918c..530066e5fdb 100644 --- a/doc/update/7.11-to-7.12.md +++ b/doc/update/7.11-to-7.12.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.11 to 7.12 ### 0. Double-check your Git version diff --git a/doc/update/7.12-to-7.13.md b/doc/update/7.12-to-7.13.md index 4c8d8f1f741..8f413a2079a 100644 --- a/doc/update/7.12-to-7.13.md +++ b/doc/update/7.12-to-7.13.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.12 to 7.13 ### 0. Double-check your Git version diff --git a/doc/update/7.13-to-7.14.md b/doc/update/7.13-to-7.14.md index 934898da5a1..a8980662855 100644 --- a/doc/update/7.13-to-7.14.md +++ b/doc/update/7.13-to-7.14.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.13 to 7.14 ### 0. Double-check your Git version diff --git a/doc/update/7.14-to-8.0.md b/doc/update/7.14-to-8.0.md index 25fa6d93f06..513afccff50 100644 --- a/doc/update/7.14-to-8.0.md +++ b/doc/update/7.14-to-8.0.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.14 to 8.0 ### 0. Double-check your Git version diff --git a/doc/update/7.2-to-7.3.md b/doc/update/7.2-to-7.3.md index d3391ddd225..a16f9de54e4 100644 --- a/doc/update/7.2-to-7.3.md +++ b/doc/update/7.2-to-7.3.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.2 to 7.3 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.2-to-7.3.md) for the most up to date instructions.* diff --git a/doc/update/7.3-to-7.4.md b/doc/update/7.3-to-7.4.md index 6d632dc3c8e..734c655f1d1 100644 --- a/doc/update/7.3-to-7.4.md +++ b/doc/update/7.3-to-7.4.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.3 to 7.4 *Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.3-to-7.4.md) for the most up to date instructions.* diff --git a/doc/update/7.4-to-7.5.md b/doc/update/7.4-to-7.5.md index ec50706d421..7a3a49ff948 100644 --- a/doc/update/7.4-to-7.5.md +++ b/doc/update/7.4-to-7.5.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.4 to 7.5 ### 0. Stop server diff --git a/doc/update/7.5-to-7.6.md b/doc/update/7.5-to-7.6.md index 331f5de080e..f0dfb177b79 100644 --- a/doc/update/7.5-to-7.6.md +++ b/doc/update/7.5-to-7.6.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.5 to 7.6 ### 0. Stop server diff --git a/doc/update/7.6-to-7.7.md b/doc/update/7.6-to-7.7.md index 918b10fbd95..85de6b0c546 100644 --- a/doc/update/7.6-to-7.7.md +++ b/doc/update/7.6-to-7.7.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.6 to 7.7 ### 0. Stop server diff --git a/doc/update/7.7-to-7.8.md b/doc/update/7.7-to-7.8.md index 84e0464a824..7cee5f79a13 100644 --- a/doc/update/7.7-to-7.8.md +++ b/doc/update/7.7-to-7.8.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.7 to 7.8 ### 0. Stop server diff --git a/doc/update/7.8-to-7.9.md b/doc/update/7.8-to-7.9.md index b0dc2ba1dbb..5a8b689dbc1 100644 --- a/doc/update/7.8-to-7.9.md +++ b/doc/update/7.8-to-7.9.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.8 to 7.9 ### 0. Stop server diff --git a/doc/update/7.9-to-7.10.md b/doc/update/7.9-to-7.10.md index 8f7f84b41ba..99df51dbb99 100644 --- a/doc/update/7.9-to-7.10.md +++ b/doc/update/7.9-to-7.10.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 7.9 to 7.10 ### 0. Stop server diff --git a/doc/update/8.0-to-8.1.md b/doc/update/8.0-to-8.1.md index 6ee0c0656ee..f612606af68 100644 --- a/doc/update/8.0-to-8.1.md +++ b/doc/update/8.0-to-8.1.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.0 to 8.1 **NOTE:** GitLab 8.0 introduced several significant changes related to diff --git a/doc/update/8.1-to-8.2.md b/doc/update/8.1-to-8.2.md index 4c9ff5c5c0a..2d0b19abd74 100644 --- a/doc/update/8.1-to-8.2.md +++ b/doc/update/8.1-to-8.2.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.1 to 8.2 **NOTE:** GitLab 8.0 introduced several significant changes related to diff --git a/doc/update/8.10-to-8.11.md b/doc/update/8.10-to-8.11.md index e538983e603..df3e34f5cc6 100644 --- a/doc/update/8.10-to-8.11.md +++ b/doc/update/8.10-to-8.11.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.10 to 8.11 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.11-to-8.12.md b/doc/update/8.11-to-8.12.md index 604166beb56..9d6a1f42375 100644 --- a/doc/update/8.11-to-8.12.md +++ b/doc/update/8.11-to-8.12.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.11 to 8.12 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.12-to-8.13.md b/doc/update/8.12-to-8.13.md index d83965131f5..6225dee9802 100644 --- a/doc/update/8.12-to-8.13.md +++ b/doc/update/8.12-to-8.13.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.12 to 8.13 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.13-to-8.14.md b/doc/update/8.13-to-8.14.md index aaadcec8ac0..d2508e3f980 100644 --- a/doc/update/8.13-to-8.14.md +++ b/doc/update/8.13-to-8.14.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.13 to 8.14 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.14-to-8.15.md b/doc/update/8.14-to-8.15.md index a68fe3bb605..daf8d0f2ca6 100644 --- a/doc/update/8.14-to-8.15.md +++ b/doc/update/8.14-to-8.15.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.14 to 8.15 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.15-to-8.16.md b/doc/update/8.15-to-8.16.md index 9f8f0f714d4..3668142edd2 100644 --- a/doc/update/8.15-to-8.16.md +++ b/doc/update/8.15-to-8.16.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.15 to 8.16 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.16-to-8.17.md b/doc/update/8.16-to-8.17.md index 74ffe0bc846..ee2e31c2aec 100644 --- a/doc/update/8.16-to-8.17.md +++ b/doc/update/8.16-to-8.17.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.16 to 8.17 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.17-to-9.0.md b/doc/update/8.17-to-9.0.md index baab217b6b7..2e0c26a9092 100644 --- a/doc/update/8.17-to-9.0.md +++ b/doc/update/8.17-to-9.0.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.17 to 9.0 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.2-to-8.3.md b/doc/update/8.2-to-8.3.md index 4b3c5bf6d64..3a0d647cbfe 100644 --- a/doc/update/8.2-to-8.3.md +++ b/doc/update/8.2-to-8.3.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.2 to 8.3 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.3-to-8.4.md b/doc/update/8.3-to-8.4.md index 8b89455ca87..f5162dd5ff5 100644 --- a/doc/update/8.3-to-8.4.md +++ b/doc/update/8.3-to-8.4.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.3 to 8.4 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.4-to-8.5.md b/doc/update/8.4-to-8.5.md index 0eedfaee2db..9e2f98add8d 100644 --- a/doc/update/8.4-to-8.5.md +++ b/doc/update/8.4-to-8.5.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.4 to 8.5 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.5-to-8.6.md b/doc/update/8.5-to-8.6.md index 851056161bb..55d8178c407 100644 --- a/doc/update/8.5-to-8.6.md +++ b/doc/update/8.5-to-8.6.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.5 to 8.6 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.6-to-8.7.md b/doc/update/8.6-to-8.7.md index 34c727260aa..49db6f2967c 100644 --- a/doc/update/8.6-to-8.7.md +++ b/doc/update/8.6-to-8.7.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.6 to 8.7 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.7-to-8.8.md b/doc/update/8.7-to-8.8.md index 6feeb1919de..ee7ec6f7614 100644 --- a/doc/update/8.7-to-8.8.md +++ b/doc/update/8.7-to-8.8.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.7 to 8.8 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.8-to-8.9.md b/doc/update/8.8-to-8.9.md index 61cdf8854d4..7508443c30a 100644 --- a/doc/update/8.8-to-8.9.md +++ b/doc/update/8.8-to-8.9.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.8 to 8.9 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/8.9-to-8.10.md b/doc/update/8.9-to-8.10.md index 42132f690d8..915e7db819a 100644 --- a/doc/update/8.9-to-8.10.md +++ b/doc/update/8.9-to-8.10.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 8.9 to 8.10 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/9.0-to-9.1.md b/doc/update/9.0-to-9.1.md index 6f1870a1366..f60bd92e236 100644 --- a/doc/update/9.0-to-9.1.md +++ b/doc/update/9.0-to-9.1.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 9.0 to 9.1 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/9.1-to-9.2.md b/doc/update/9.1-to-9.2.md index ce72b313031..2fff6544797 100644 --- a/doc/update/9.1-to-9.2.md +++ b/doc/update/9.1-to-9.2.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 9.1 to 9.2 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/9.2-to-9.3.md b/doc/update/9.2-to-9.3.md index 779ced0cf75..1b36cf53f4c 100644 --- a/doc/update/9.2-to-9.3.md +++ b/doc/update/9.2-to-9.3.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 9.2 to 9.3 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/9.3-to-9.4.md b/doc/update/9.3-to-9.4.md index 78d8a6c7de5..210b6eb607d 100644 --- a/doc/update/9.3-to-9.4.md +++ b/doc/update/9.3-to-9.4.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 9.3 to 9.4 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/9.4-to-9.5.md b/doc/update/9.4-to-9.5.md index a7255142ef5..1bfc1167c36 100644 --- a/doc/update/9.4-to-9.5.md +++ b/doc/update/9.4-to-9.5.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 9.4 to 9.5 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/9.5-to-10.0.md b/doc/update/9.5-to-10.0.md index 8581e6511f2..8d1cf0f737b 100644 --- a/doc/update/9.5-to-10.0.md +++ b/doc/update/9.5-to-10.0.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # From 9.5 to 10.0 Make sure you view this update guide from the tag (version) of GitLab you would diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md index b2679d1ff22..e1857ce99c6 100644 --- a/doc/update/patch_versions.md +++ b/doc/update/patch_versions.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Universal update guide for patch versions ## Select Version to Install diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md index eb7f14a96d5..746d6bf93e7 100644 --- a/doc/update/upgrader.md +++ b/doc/update/upgrader.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # GitLab Upgrader (deprecated) *DEPRECATED* We recommend to [switch to the Omnibus package and repository server](https://about.gitlab.com/update/) instead of using this script. diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md index df75e25e12b..5896f8f72a0 100644 --- a/doc/user/project/integrations/webhooks.md +++ b/doc/user/project/integrations/webhooks.md @@ -1140,6 +1140,18 @@ From this page, you can repeat delivery with the same data by clicking `Resend R >**Note:** If URL or secret token of the webhook were updated, data will be delivered to the new address. +### Receiving duplicate or multiple web hook requests triggered by one event + +When GitLab sends a webhook it expects a response in 10 seconds (set default value). If it does not receive one, it'll retry the webhook. +If the endpoint doesn't send its HTTP response within those 10 seconds, GitLab may decide the hook failed and retry it. + +If you are receiving multiple requests, you can try increasing the default value to wait for the HTTP response after sending the webhook +by uncommenting or adding the following setting to your `/etc/gitlab/gitlab.rb`: + +``` +gitlab_rails['webhook_timeout'] = 10 +``` + ## Example webhook receiver If you want to see GitLab's webhooks in action for testing purposes you can use diff --git a/doc/workflow/README.md b/doc/workflow/README.md index 6b2aba47f54..272f7807ac0 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -1,3 +1,7 @@ +--- +comments: false +--- + # Workflow - [Automatic issue closing](../user/project/issues/automatic_issue_closing.md) diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md index 9d466ae1971..23b67310d25 100644 --- a/doc/workflow/gitlab_flow.md +++ b/doc/workflow/gitlab_flow.md @@ -1,6 +1,6 @@ ![GitLab Flow](gitlab_flow.png) -## Introduction +# Introduction to GitLab Flow Version management with git makes branching and merging much easier than older versioning systems such as SVN. This allows a wide variety of branching strategies and workflows. diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb index c4c60d1dfee..0ea534a5fd0 100644 --- a/lib/gitlab/ee_compat_check.rb +++ b/lib/gitlab/ee_compat_check.rb @@ -2,8 +2,8 @@ module Gitlab # Checks if a set of migrations requires downtime or not. class EeCompatCheck - DEFAULT_CE_REPO = 'https://gitlab.com/gitlab-org/gitlab-ce.git'.freeze - EE_REPO = 'https://gitlab.com/gitlab-org/gitlab-ee.git'.freeze + DEFAULT_CE_PROJECT_URL = 'https://gitlab.com/gitlab-org/gitlab-ce'.freeze + EE_REPO_URL = 'https://gitlab.com/gitlab-org/gitlab-ee.git'.freeze CHECK_DIR = Rails.root.join('ee_compat_check') IGNORED_FILES_REGEX = /(VERSION|CHANGELOG\.md:\d+)/.freeze PLEASE_READ_THIS_BANNER = %Q{ @@ -17,14 +17,16 @@ module Gitlab ============================================================\n }.freeze - attr_reader :ee_repo_dir, :patches_dir, :ce_repo, :ce_branch, :ee_branch_found - attr_reader :failed_files + attr_reader :ee_repo_dir, :patches_dir, :ce_project_url, :ce_repo_url, :ce_branch, :ee_branch_found + attr_reader :job_id, :failed_files - def initialize(branch:, ce_repo: DEFAULT_CE_REPO) + def initialize(branch:, ce_project_url: DEFAULT_CE_PROJECT_URL, job_id: nil) @ee_repo_dir = CHECK_DIR.join('ee-repo') @patches_dir = CHECK_DIR.join('patches') @ce_branch = branch - @ce_repo = ce_repo + @ce_project_url = ce_project_url + @ce_repo_url = "#{ce_project_url}.git" + @job_id = job_id end def check @@ -59,8 +61,8 @@ module Gitlab step("#{ee_repo_dir} already exists") else step( - "Cloning #{EE_REPO} into #{ee_repo_dir}", - %W[git clone --branch master --single-branch --depth=200 #{EE_REPO} #{ee_repo_dir}] + "Cloning #{EE_REPO_URL} into #{ee_repo_dir}", + %W[git clone --branch master --single-branch --depth=200 #{EE_REPO_URL} #{ee_repo_dir}] ) end end @@ -132,7 +134,7 @@ module Gitlab def check_patch(patch_path) step("Checking out master", %w[git checkout master]) step("Resetting to latest master", %w[git reset --hard origin/master]) - step("Fetching CE/#{ce_branch}", %W[git fetch #{ce_repo} #{ce_branch}]) + step("Fetching CE/#{ce_branch}", %W[git fetch #{ce_repo_url} #{ce_branch}]) step( "Checking if #{patch_path} applies cleanly to EE/master", # Don't use --check here because it can result in a 0-exit status even @@ -237,7 +239,7 @@ module Gitlab end def patch_url - "https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/#{ENV['CI_JOB_ID']}/artifacts/raw/ee_compat_check/patches/#{ce_patch_name}" + "#{ce_project_url}/-/jobs/#{job_id}/artifacts/raw/ee_compat_check/patches/#{ce_patch_name}" end def step(desc, cmd = nil) @@ -304,7 +306,7 @@ module Gitlab # In the EE repo $ git fetch origin $ git checkout -b #{ee_branch_prefix} origin/master - $ git fetch #{ce_repo} #{ce_branch} + $ git fetch #{ce_repo_url} #{ce_branch} $ git cherry-pick SHA # Repeat for all the commits you want to pick You can squash the `#{ce_branch}` commits into a single "Port of #{ce_branch} to EE" commit. diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb index a4336facee5..cc6c7609ec7 100644 --- a/lib/gitlab/git/blob.rb +++ b/lib/gitlab/git/blob.rb @@ -12,6 +12,12 @@ module Gitlab # blob data should use load_all_data!. MAX_DATA_DISPLAY_SIZE = 10.megabytes + # These limits are used as a heuristic to ignore files which can't be LFS + # pointers. The format of these is described in + # https://github.com/git-lfs/git-lfs/blob/master/docs/spec.md#the-pointer + LFS_POINTER_MIN_SIZE = 120.bytes + LFS_POINTER_MAX_SIZE = 200.bytes + attr_accessor :name, :path, :size, :data, :mode, :id, :commit_id, :loaded_size, :binary class << self @@ -30,16 +36,7 @@ module Gitlab if is_enabled Gitlab::GitalyClient::BlobService.new(repository).get_blob(oid: sha, limit: MAX_DATA_DISPLAY_SIZE) else - blob = repository.lookup(sha) - - next unless blob.is_a?(Rugged::Blob) - - new( - id: blob.oid, - size: blob.size, - data: blob.content(MAX_DATA_DISPLAY_SIZE), - binary: blob.binary? - ) + rugged_raw(repository, sha, limit: MAX_DATA_DISPLAY_SIZE) end end end @@ -59,10 +56,25 @@ module Gitlab end end + # Find LFS blobs given an array of sha ids + # Returns array of Gitlab::Git::Blob + # Does not guarantee blob data will be set + def batch_lfs_pointers(repository, blob_ids) + blob_ids.lazy + .select { |sha| possible_lfs_blob?(repository, sha) } + .map { |sha| rugged_raw(repository, sha, limit: LFS_POINTER_MAX_SIZE) } + .select(&:lfs_pointer?) + .force + end + def binary?(data) EncodingHelper.detect_libgit2_binary?(data) end + def size_could_be_lfs?(size) + size.between?(LFS_POINTER_MIN_SIZE, LFS_POINTER_MAX_SIZE) + end + private # Recursive search of blob id by path @@ -167,6 +179,29 @@ module Gitlab end end end + + def rugged_raw(repository, sha, limit:) + blob = repository.lookup(sha) + + return unless blob.is_a?(Rugged::Blob) + + new( + id: blob.oid, + size: blob.size, + data: blob.content(limit), + binary: blob.binary? + ) + end + + # Efficient lookup to determine if object size + # and type make it a possible LFS blob without loading + # blob content into memory with repository.lookup(sha) + def possible_lfs_blob?(repository, sha) + object_header = repository.rugged.read_header(sha) + + object_header[:type] == :blob && + size_could_be_lfs?(object_header[:len]) + end end def initialize(options) @@ -226,7 +261,7 @@ module Gitlab # size # see https://github.com/github/git-lfs/blob/v1.1.0/docs/spec.md#the-pointer def lfs_pointer? - has_lfs_version_key? && lfs_oid.present? && lfs_size.present? + self.class.size_could_be_lfs?(size) && has_lfs_version_key? && lfs_oid.present? && lfs_size.present? end def lfs_oid diff --git a/lib/gitlab/git/lfs_changes.rb b/lib/gitlab/git/lfs_changes.rb new file mode 100644 index 00000000000..2749e2e69e2 --- /dev/null +++ b/lib/gitlab/git/lfs_changes.rb @@ -0,0 +1,36 @@ +module Gitlab + module Git + class LfsChanges + def initialize(repository, newrev) + @repository = repository + @newrev = newrev + end + + def new_pointers(object_limit: nil, not_in: nil) + @new_pointers ||= begin + object_ids = new_objects(not_in: not_in) + object_ids = object_ids.take(object_limit) if object_limit + + Gitlab::Git::Blob.batch_lfs_pointers(@repository, object_ids) + end + end + + def all_pointers + object_ids = rev_list.all_objects(require_path: true) + + Gitlab::Git::Blob.batch_lfs_pointers(@repository, object_ids) + end + + private + + def new_objects(not_in:) + rev_list.new_objects(require_path: true, lazy: true, not_in: not_in) + end + + def rev_list + ::Gitlab::Git::RevList.new(path_to_repo: @repository.path_to_repo, + newrev: @newrev) + end + end + end +end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index fc8af38d4d9..a9e4e1130c3 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -290,6 +290,14 @@ module Gitlab end end + def batch_existence(object_ids, existing: true) + filter_method = existing ? :select : :reject + + object_ids.public_send(filter_method) do |oid| # rubocop:disable GitlabSecurity/PublicSend + rugged.exists?(oid) + end + end + # Returns an Array of branch and tag names def ref_names branch_names + tag_names diff --git a/lib/gitlab/git/rev_list.rb b/lib/gitlab/git/rev_list.rb index 60b2a4ec411..e0c884aceaa 100644 --- a/lib/gitlab/git/rev_list.rb +++ b/lib/gitlab/git/rev_list.rb @@ -13,11 +13,31 @@ module Gitlab @path_to_repo = path_to_repo end - # This method returns an array of new references + # This method returns an array of new commit references def new_refs execute([*base_args, newrev, '--not', '--all']) end + # Finds newly added objects + # Returns an array of shas + # + # Can skip objects which do not have a path using required_path: true + # This skips commit objects and root trees, which might not be needed when + # looking for blobs + # + # Can return a lazy enumerator to limit work done on megabytes of data + def new_objects(require_path: nil, lazy: false, not_in: nil) + object_output = execute([*base_args, newrev, *not_in_refs(not_in), '--objects']) + + objects_from_output(object_output, require_path: require_path, lazy: lazy) + end + + def all_objects(require_path: nil) + object_output = execute([*base_args, '--all', '--objects']) + + objects_from_output(object_output, require_path: require_path, lazy: true) + end + # This methods returns an array of missed references # # Should become obsolete after https://gitlab.com/gitlab-org/gitaly/issues/348. @@ -27,6 +47,13 @@ module Gitlab private + def not_in_refs(references) + return ['--not', '--all'] unless references + return [] if references.empty? + + references.prepend('--not') + end + def execute(args) output, status = popen(args, nil, Gitlab::Git::Env.to_env_hash) @@ -44,6 +71,22 @@ module Gitlab 'rev-list' ] end + + def objects_from_output(object_output, require_path: nil, lazy: nil) + objects = object_output.lazy.map do |output_line| + sha, path = output_line.split(' ', 2) + + next if require_path && path.blank? + + sha + end.reject(&:nil?) + + if lazy + objects + else + objects.force + end + end end end end diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb index 549d22adde5..45362ac438b 100644 --- a/lib/gitlab/git/wiki.rb +++ b/lib/gitlab/git/wiki.rb @@ -68,11 +68,13 @@ module Gitlab end def file(name, version) - version ||= self.class.default_ref - gollum_file = gollum_wiki.file(name, version) - return unless gollum_file - - Gitlab::Git::WikiFile.new(gollum_file) + @repository.gitaly_migrate(:wiki_find_file) do |is_enabled| + if is_enabled + gitaly_find_file(name, version) + else + gollum_find_file(name, version) + end + end end def page_versions(page_path) @@ -156,6 +158,14 @@ module Gitlab new_page(gollum_page) end + def gollum_find_file(name, version) + version ||= self.class.default_ref + gollum_file = gollum_wiki.file(name, version) + return unless gollum_file + + Gitlab::Git::WikiFile.new(gollum_file) + end + def gitaly_write_page(name, format, content, commit_details) gitaly_wiki_client.write_page(name, format, content, commit_details) end @@ -170,6 +180,13 @@ module Gitlab Gitlab::Git::WikiPage.new(wiki_page, version) end + + def gitaly_find_file(name, version) + wiki_file = gitaly_wiki_client.find_file(name, version) + return unless wiki_file + + Gitlab::Git::WikiFile.new(wiki_file) + end end end end diff --git a/lib/gitlab/gitaly_client/wiki_file.rb b/lib/gitlab/gitaly_client/wiki_file.rb new file mode 100644 index 00000000000..a2e415864e6 --- /dev/null +++ b/lib/gitlab/gitaly_client/wiki_file.rb @@ -0,0 +1,17 @@ +module Gitlab + module GitalyClient + class WikiFile + FIELDS = %i(name mime_type path raw_data).freeze + + attr_accessor(*FIELDS) + + def initialize(params) + params = params.with_indifferent_access + + FIELDS.each do |field| + instance_variable_set("@#{field}", params[field]) + end + end + end + end +end diff --git a/lib/gitlab/gitaly_client/wiki_service.rb b/lib/gitlab/gitaly_client/wiki_service.rb index 5d7930f5ff9..15f0f30d303 100644 --- a/lib/gitlab/gitaly_client/wiki_service.rb +++ b/lib/gitlab/gitaly_client/wiki_service.rb @@ -80,6 +80,32 @@ module Gitlab [wiki_page, version] end + def find_file(name, revision) + request = Gitaly::WikiFindFileRequest.new( + repository: @gitaly_repo, + name: GitalyClient.encode(name), + revision: GitalyClient.encode(revision) + ) + + response = GitalyClient.call(@repository.storage, :wiki_service, :wiki_find_file, request) + wiki_file = nil + + response.each do |message| + next unless message.name.present? + + if wiki_file + wiki_file.raw_data << message.raw_data + else + wiki_file = GitalyClient::WikiFile.new(message.to_h) + # All gRPC strings in a response are frozen, so we get + # an unfrozen version here so appending in the else clause below doesn't blow up. + wiki_file.raw_data = wiki_file.raw_data.dup + end + end + + wiki_file + end + private def gitaly_commit_details(commit_details) diff --git a/lib/gitlab/metrics/sidekiq_middleware.rb b/lib/gitlab/metrics/sidekiq_middleware.rb index f9dd8e41912..b983a40611f 100644 --- a/lib/gitlab/metrics/sidekiq_middleware.rb +++ b/lib/gitlab/metrics/sidekiq_middleware.rb @@ -11,6 +11,8 @@ module Gitlab # Old gitlad-shell messages don't provide enqueued_at/created_at attributes trans.set(:sidekiq_queue_duration, Time.now.to_f - (message['enqueued_at'] || message['created_at'] || 0)) trans.run { yield } + + worker.metrics_tags.each { |tag, value| trans.add_tag(tag, value) } if worker.respond_to?(:metrics_tags) rescue Exception => error # rubocop: disable Lint/RescueException trans.add_event(:sidekiq_exception) diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb index f42168c720e..cfc6b2a2029 100644 --- a/lib/gitlab/middleware/go.rb +++ b/lib/gitlab/middleware/go.rb @@ -4,6 +4,7 @@ module Gitlab module Middleware class Go include ActionView::Helpers::TagHelper + include Gitlab::CurrentSettings PROJECT_PATH_REGEX = %r{\A(#{Gitlab::PathRegex.full_namespace_route_regex}/#{Gitlab::PathRegex.project_route_regex})/}.freeze @@ -37,10 +38,20 @@ module Gitlab end def go_body(path) - project_url = URI.join(Gitlab.config.gitlab.url, path) + config = Gitlab.config + project_url = URI.join(config.gitlab.url, path) import_prefix = strip_url(project_url.to_s) - meta_tag = tag :meta, name: 'go-import', content: "#{import_prefix} git #{project_url}.git" + repository_url = case current_application_settings.enabled_git_access_protocol + when 'ssh' + shell = config.gitlab_shell + port = ":#{shell.ssh_port}" unless shell.ssh_port == 22 + "ssh://#{shell.ssh_user}@#{shell.ssh_host}#{port}/#{path}.git" + when 'http', nil + "#{project_url}.git" + end + + meta_tag = tag :meta, name: 'go-import', content: "#{import_prefix} git #{repository_url}" head_tag = content_tag :head, meta_tag content_tag :html, head_tag end diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index 58d5b0da1c4..e1219df1b25 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -16,14 +16,15 @@ module Gitlab SECRET_LENGTH = 32 class << self - def git_http_ok(repository, is_wiki, user, action) + def git_http_ok(repository, is_wiki, user, action, show_all_refs: false) project = repository.project repo_path = repository.path_to_repo params = { GL_ID: Gitlab::GlId.gl_id(user), GL_REPOSITORY: Gitlab::GlRepository.gl_repository(project, is_wiki), GL_USERNAME: user&.username, - RepoPath: repo_path + RepoPath: repo_path, + ShowAllRefs: show_all_refs } server = { address: Gitlab::GitalyClient.address(project.repository_storage), diff --git a/lib/tasks/gitlab/dev.rake b/lib/tasks/gitlab/dev.rake index 930b4bc13e2..ba221e44e5d 100644 --- a/lib/tasks/gitlab/dev.rake +++ b/lib/tasks/gitlab/dev.rake @@ -5,10 +5,9 @@ namespace :gitlab do opts = if ENV['CI'] { - # We don't use CI_REPOSITORY_URL since it includes `gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@` - # which is confusing in the steps suggested in the job's output. - ce_repo: "#{ENV['CI_PROJECT_URL']}.git", - branch: ENV['CI_COMMIT_REF_NAME'] + ce_project_url: ENV['CI_PROJECT_URL'], + branch: ENV['CI_COMMIT_REF_NAME'], + job_id: ENV['CI_JOB_ID'] } else unless args[:branch] diff --git a/package.json b/package.json index 376c47ba796..0a1f5c8d081 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "eslint-plugin-html": "^2.0.1", "exports-loader": "^0.6.4", "file-loader": "^0.11.1", + "fuzzaldrin-plus": "^0.5.0", "imports-loader": "^0.7.1", "jed": "^1.1.1", "jquery": "^2.2.1", @@ -8,6 +8,7 @@ module QA autoload :Release, 'qa/runtime/release' autoload :User, 'qa/runtime/user' autoload :Namespace, 'qa/runtime/namespace' + autoload :Scenario, 'qa/runtime/scenario' end ## @@ -80,6 +81,11 @@ module QA module Admin autoload :Menu, 'qa/page/admin/menu' end + + module Mattermost + autoload :Main, 'qa/page/mattermost/main' + autoload :Login, 'qa/page/mattermost/login' + end end ## diff --git a/qa/qa/page/mattermost/login.rb b/qa/qa/page/mattermost/login.rb new file mode 100644 index 00000000000..2001dc5b230 --- /dev/null +++ b/qa/qa/page/mattermost/login.rb @@ -0,0 +1,19 @@ +module QA + module Page + module Mattermost + class Login < Page::Base + def initialize + visit(Runtime::Scenario.mattermost + '/login') + end + + def sign_in_using_oauth + click_link class: 'btn btn-custom-login gitlab' + + if page.has_content?('Authorize GitLab Mattermost to use your account?') + click_button 'Authorize' + end + end + end + end + end +end diff --git a/qa/qa/page/mattermost/main.rb b/qa/qa/page/mattermost/main.rb new file mode 100644 index 00000000000..e636d7676f4 --- /dev/null +++ b/qa/qa/page/mattermost/main.rb @@ -0,0 +1,11 @@ +module QA + module Page + module Mattermost + class Main < Page::Base + def initialize + visit(Runtime::Scenario.mattermost) + end + end + end + end +end diff --git a/qa/qa/runtime/scenario.rb b/qa/qa/runtime/scenario.rb new file mode 100644 index 00000000000..0c5e9787e17 --- /dev/null +++ b/qa/qa/runtime/scenario.rb @@ -0,0 +1,8 @@ +module QA + module Runtime + module Scenario + extend self + attr_accessor :mattermost + end + end +end diff --git a/qa/qa/scenario/test/integration/mattermost.rb b/qa/qa/scenario/test/integration/mattermost.rb index 4732f2b635b..9a84e5c8fd8 100644 --- a/qa/qa/scenario/test/integration/mattermost.rb +++ b/qa/qa/scenario/test/integration/mattermost.rb @@ -8,6 +8,11 @@ module QA # class Mattermost < Scenario::Entrypoint tags :core, :mattermost + + def perform(address, mattermost, *files) + Runtime::Scenario.mattermost = mattermost + super(address, files) + end end end end diff --git a/qa/qa/specs/features/mattermost/login_spec.rb b/qa/qa/specs/features/mattermost/login_spec.rb new file mode 100644 index 00000000000..a89a6a3d1cf --- /dev/null +++ b/qa/qa/specs/features/mattermost/login_spec.rb @@ -0,0 +1,12 @@ +module QA + feature 'logging in to Mattermost', :mattermost do + scenario 'can use gitlab oauth' do + Page::Main::Entry.act { sign_in_using_credentials } + Page::Mattermost::Login.act { sign_in_using_oauth } + + Page::Mattermost::Main.perform do |page| + expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/) + end + end + end +end diff --git a/qa/spec/scenario/entrypoint_spec.rb b/qa/spec/scenario/entrypoint_spec.rb new file mode 100644 index 00000000000..3fd068b641c --- /dev/null +++ b/qa/spec/scenario/entrypoint_spec.rb @@ -0,0 +1,46 @@ +describe QA::Scenario::Entrypoint do + subject do + Class.new(QA::Scenario::Entrypoint) do + tags :rspec + end + end + + context '#perform' do + let(:config) { spy('Specs::Config') } + let(:release) { spy('Runtime::Release') } + let(:runner) { spy('Specs::Runner') } + + before do + allow(config).to receive(:perform) { |&block| block.call config } + allow(runner).to receive(:perform) { |&block| block.call runner } + + stub_const('QA::Specs::Config', config) + stub_const('QA::Runtime::Release', release) + stub_const('QA::Specs::Runner', runner) + end + + it 'should set address' do + subject.perform("hello") + + expect(config).to have_received(:address=).with("hello") + end + + context 'no paths' do + it 'should call runner with default arguments' do + subject.perform("test") + + expect(runner).to have_received(:rspec) + .with(hash_including(files: 'qa/specs/features')) + end + end + + context 'specifying paths' do + it 'should call runner with paths' do + subject.perform('test', 'path1', 'path2') + + expect(runner).to have_received(:rspec) + .with(hash_including(files: %w(path1 path2))) + end + end + end +end diff --git a/spec/features/projects/wiki/user_views_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_page_spec.rb index 470391dc66b..89f6901eb01 100644 --- a/spec/features/projects/wiki/user_views_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_views_wiki_page_spec.rb @@ -81,10 +81,15 @@ describe 'User views a wiki page' do end it 'shows a file stored in a page' do - file = Gollum::File.new(project.wiki) - - allow_any_instance_of(Gollum::Wiki).to receive(:file).with('image.jpg', 'master').and_return(file) - allow_any_instance_of(Gollum::File).to receive(:mime_type).and_return('image/jpeg') + gollum_file_double = double('Gollum::File', + mime_type: 'image/jpeg', + name: 'images/image.jpg', + path: 'images/image.jpg', + raw_data: '') + wiki_file = Gitlab::Git::WikiFile.new(gollum_file_double) + + allow(wiki_file).to receive(:mime_type).and_return('image/jpeg') + allow_any_instance_of(ProjectWiki).to receive(:find_file).with('image.jpg', nil).and_return(wiki_file) expect(page).to have_xpath('//img[@data-src="image.jpg"]') expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/image.jpg") diff --git a/spec/javascripts/labels_issue_sidebar_spec.js b/spec/javascripts/labels_issue_sidebar_spec.js index 4e66304e0ad..a197b35f6fb 100644 --- a/spec/javascripts/labels_issue_sidebar_spec.js +++ b/spec/javascripts/labels_issue_sidebar_spec.js @@ -1,13 +1,12 @@ /* eslint-disable no-new */ import IssuableContext from '~/issuable_context'; -/* global LabelsSelect */ +import LabelsSelect from '~/labels_select'; import '~/gl_dropdown'; import 'select2'; import '~/api'; import '~/create_label'; import '~/users_select'; -import '~/labels_select'; (() => { let saveLabelCount = 0; diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js index cf811af3d6c..5e55a5d2686 100644 --- a/spec/javascripts/search_autocomplete_spec.js +++ b/spec/javascripts/search_autocomplete_spec.js @@ -3,7 +3,6 @@ import '~/gl_dropdown'; import '~/search_autocomplete'; import '~/lib/utils/common_utils'; -import 'vendor/fuzzaldrin-plus'; (function() { var assertLinks, dashboardIssuesPath, dashboardMRsPath, groupIssuesPath, groupMRsPath, groupName, mockDashboardOptions, mockGroupOptions, mockProjectOptions, projectIssuesPath, projectMRsPath, projectName, userId, widget; diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb index 412a0093d97..c04a9688503 100644 --- a/spec/lib/gitlab/git/blob_spec.rb +++ b/spec/lib/gitlab/git/blob_spec.rb @@ -143,6 +143,16 @@ describe Gitlab::Git::Blob, seed_helper: true do expect(blob.loaded_size).to eq(blob_size) end end + + context 'when sha references a tree' do + it 'returns nil' do + tree = Gitlab::Git::Commit.find(repository, 'master').tree + + blob = Gitlab::Git::Blob.raw(repository, tree.oid) + + expect(blob).to be_nil + end + end end describe '.raw' do @@ -226,6 +236,51 @@ describe Gitlab::Git::Blob, seed_helper: true do end end + describe '.batch_lfs_pointers' do + let(:tree_object) { Gitlab::Git::Commit.find(repository, 'master').tree } + + let(:non_lfs_blob) do + Gitlab::Git::Blob.find( + repository, + 'master', + 'README.md' + ) + end + + let(:lfs_blob) do + Gitlab::Git::Blob.find( + repository, + '33bcff41c232a11727ac6d660bd4b0c2ba86d63d', + 'files/lfs/image.jpg' + ) + end + + it 'returns a list of Gitlab::Git::Blob' do + blobs = described_class.batch_lfs_pointers(repository, [lfs_blob.id]) + + expect(blobs.count).to eq(1) + expect(blobs).to all( be_a(Gitlab::Git::Blob) ) + end + + it 'silently ignores tree objects' do + blobs = described_class.batch_lfs_pointers(repository, [tree_object.oid]) + + expect(blobs).to eq([]) + end + + it 'silently ignores non lfs objects' do + blobs = described_class.batch_lfs_pointers(repository, [non_lfs_blob.id]) + + expect(blobs).to eq([]) + end + + it 'avoids loading large blobs into memory' do + expect(repository).not_to receive(:lookup) + + described_class.batch_lfs_pointers(repository, [non_lfs_blob.id]) + end + end + describe 'encoding' do context 'file with russian text' do let(:blob) { Gitlab::Git::Blob.find(repository, SeedRepo::Commit::ID, "encoding/russian.rb") } diff --git a/spec/lib/gitlab/git/lfs_changes_spec.rb b/spec/lib/gitlab/git/lfs_changes_spec.rb new file mode 100644 index 00000000000..c2d2c6e1bc8 --- /dev/null +++ b/spec/lib/gitlab/git/lfs_changes_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +describe Gitlab::Git::LfsChanges do + let(:project) { create(:project, :repository) } + let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' } + let(:blob_object_id) { '0c304a93cb8430108629bbbcaa27db3343299bc0' } + + subject { described_class.new(project.repository, newrev) } + + describe 'new_pointers' do + before do + allow_any_instance_of(Gitlab::Git::RevList).to receive(:new_objects).and_return([blob_object_id]) + end + + it 'uses rev-list to find new objects' do + rev_list = double + allow(Gitlab::Git::RevList).to receive(:new).and_return(rev_list) + + expect(rev_list).to receive(:new_objects).and_return([]) + + subject.new_pointers + end + + it 'filters new objects to find lfs pointers' do + expect(Gitlab::Git::Blob).to receive(:batch_lfs_pointers).with(project.repository, [blob_object_id]) + + subject.new_pointers(object_limit: 1) + end + + it 'limits new_objects using object_limit' do + expect(Gitlab::Git::Blob).to receive(:batch_lfs_pointers).with(project.repository, []) + + subject.new_pointers(object_limit: 0) + end + end + + describe 'all_pointers' do + it 'uses rev-list to find all objects' do + rev_list = double + allow(Gitlab::Git::RevList).to receive(:new).and_return(rev_list) + allow(rev_list).to receive(:all_objects).and_return([blob_object_id]) + + expect(Gitlab::Git::Blob).to receive(:batch_lfs_pointers).with(project.repository, [blob_object_id]) + + subject.all_pointers + end + end +end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index b161d25b96c..0fa88d17f5d 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1336,6 +1336,24 @@ describe Gitlab::Git::Repository, seed_helper: true do end end + describe '#batch_existence' do + let(:refs) { ['deadbeef', SeedRepo::RubyBlob::ID, '909e6157199'] } + + it 'returns existing refs back' do + result = repository.batch_existence(refs) + + expect(result).to eq([SeedRepo::RubyBlob::ID]) + end + + context 'existing: true' do + it 'inverts meaning and returns non-existing refs' do + result = repository.batch_existence(refs, existing: false) + + expect(result).to eq(%w(deadbeef 909e6157199)) + end + end + end + describe '#local_branches' do before(:all) do @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') diff --git a/spec/lib/gitlab/git/rev_list_spec.rb b/spec/lib/gitlab/git/rev_list_spec.rb index c0eac98d718..643a4b2d03e 100644 --- a/spec/lib/gitlab/git/rev_list_spec.rb +++ b/spec/lib/gitlab/git/rev_list_spec.rb @@ -2,53 +2,82 @@ require 'spec_helper' describe Gitlab::Git::RevList do let(:project) { create(:project, :repository) } + let(:rev_list) { described_class.new(newrev: 'newrev', path_to_repo: project.repository.path_to_repo) } before do - expect(Gitlab::Git::Env).to receive(:all).and_return({ + allow(Gitlab::Git::Env).to receive(:all).and_return({ GIT_OBJECT_DIRECTORY: 'foo', GIT_ALTERNATE_OBJECT_DIRECTORIES: 'bar' }) end - context "#new_refs" do - let(:rev_list) { described_class.new(newrev: 'newrev', path_to_repo: project.repository.path_to_repo) } + def stub_popen_rev_list(*additional_args, output:) + expect(rev_list).to receive(:popen).with([ + Gitlab.config.git.bin_path, + "--git-dir=#{project.repository.path_to_repo}", + 'rev-list', + *additional_args + ], + nil, + { + 'GIT_OBJECT_DIRECTORY' => 'foo', + 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => 'bar' + }).and_return([output, 0]) + end + context "#new_refs" do it 'calls out to `popen`' do - expect(rev_list).to receive(:popen).with([ - Gitlab.config.git.bin_path, - "--git-dir=#{project.repository.path_to_repo}", - 'rev-list', - 'newrev', - '--not', - '--all' - ], - nil, - { - 'GIT_OBJECT_DIRECTORY' => 'foo', - 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => 'bar' - }).and_return(["sha1\nsha2", 0]) + stub_popen_rev_list('newrev', '--not', '--all', output: "sha1\nsha2") expect(rev_list.new_refs).to eq(%w[sha1 sha2]) end end + context '#new_objects' do + it 'fetches list of newly pushed objects using rev-list' do + stub_popen_rev_list('newrev', '--not', '--all', '--objects', output: "sha1\nsha2") + + expect(rev_list.new_objects).to eq(%w[sha1 sha2]) + end + + it 'can skip pathless objects' do + stub_popen_rev_list('newrev', '--not', '--all', '--objects', output: "sha1\nsha2 path/to/file") + + expect(rev_list.new_objects(require_path: true)).to eq(%w[sha2]) + end + + it 'can return a lazy enumerator' do + stub_popen_rev_list('newrev', '--not', '--all', '--objects', output: "sha1\nsha2") + + expect(rev_list.new_objects(lazy: true)).to be_a Enumerator::Lazy + end + + it 'can accept list of references to exclude' do + stub_popen_rev_list('newrev', '--not', 'master', '--objects', output: "sha1\nsha2") + + expect(rev_list.new_objects(not_in: ['master'])).to eq(%w[sha1 sha2]) + end + + it 'handles empty list of references to exclude as listing all known objects' do + stub_popen_rev_list('newrev', '--objects', output: "sha1\nsha2") + + expect(rev_list.new_objects(not_in: [])).to eq(%w[sha1 sha2]) + end + end + + context '#all_objects' do + it 'fetches list of all pushed objects using rev-list' do + stub_popen_rev_list('--all', '--objects', output: "sha1\nsha2") + + expect(rev_list.all_objects.force).to eq(%w[sha1 sha2]) + end + end + context "#missed_ref" do let(:rev_list) { described_class.new(oldrev: 'oldrev', newrev: 'newrev', path_to_repo: project.repository.path_to_repo) } it 'calls out to `popen`' do - expect(rev_list).to receive(:popen).with([ - Gitlab.config.git.bin_path, - "--git-dir=#{project.repository.path_to_repo}", - 'rev-list', - '--max-count=1', - 'oldrev', - '^newrev' - ], - nil, - { - 'GIT_OBJECT_DIRECTORY' => 'foo', - 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => 'bar' - }).and_return(["sha1\nsha2", 0]) + stub_popen_rev_list('--max-count=1', 'oldrev', '^newrev', output: "sha1\nsha2") expect(rev_list.missed_ref).to eq(%w[sha1 sha2]) end diff --git a/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb b/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb index b576d7173f5..0803ce42fac 100644 --- a/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb +++ b/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb @@ -4,35 +4,30 @@ describe Gitlab::Metrics::SidekiqMiddleware do let(:middleware) { described_class.new } let(:message) { { 'args' => ['test'], 'enqueued_at' => Time.new(2016, 6, 23, 6, 59).to_f } } - describe '#call' do - it 'tracks the transaction' do - worker = double(:worker, class: double(:class, name: 'TestWorker')) + def run(worker, message) + expect(Gitlab::Metrics::Transaction).to receive(:new) + .with('TestWorker#perform') + .and_call_original + + expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:set) + .with(:sidekiq_queue_duration, instance_of(Float)) - expect(Gitlab::Metrics::Transaction).to receive(:new) - .with('TestWorker#perform') - .and_call_original + expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:finish) - expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:set) - .with(:sidekiq_queue_duration, instance_of(Float)) + middleware.call(worker, message, :test) { nil } + end - expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:finish) + describe '#call' do + it 'tracks the transaction' do + worker = double(:worker, class: double(:class, name: 'TestWorker')) - middleware.call(worker, message, :test) { nil } + run(worker, message) end it 'tracks the transaction (for messages without `enqueued_at`)' do worker = double(:worker, class: double(:class, name: 'TestWorker')) - expect(Gitlab::Metrics::Transaction).to receive(:new) - .with('TestWorker#perform') - .and_call_original - - expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:set) - .with(:sidekiq_queue_duration, instance_of(Float)) - - expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:finish) - - middleware.call(worker, {}, :test) { nil } + run(worker, {}) end it 'tracks any raised exceptions' do @@ -50,5 +45,18 @@ describe Gitlab::Metrics::SidekiqMiddleware do expect { middleware.call(worker, message, :test) } .to raise_error(RuntimeError) end + + it 'tags the metrics accordingly' do + tags = { one: 1, two: 2 } + worker = double(:worker, class: double(:class, name: 'TestWorker')) + allow(worker).to receive(:metrics_tags).and_return(tags) + + tags.each do |tag, value| + expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:add_tag) + .with(tag, value) + end + + run(worker, message) + end end end diff --git a/spec/lib/gitlab/middleware/go_spec.rb b/spec/lib/gitlab/middleware/go_spec.rb index cab662819ac..67121937398 100644 --- a/spec/lib/gitlab/middleware/go_spec.rb +++ b/spec/lib/gitlab/middleware/go_spec.rb @@ -17,89 +17,115 @@ describe Gitlab::Middleware::Go do describe 'when go-get=1' do let(:current_user) { nil } - context 'with simple 2-segment project path' do - let!(:project) { create(:project, :private) } + shared_examples 'go-get=1' do |enabled_protocol:| + context 'with simple 2-segment project path' do + let!(:project) { create(:project, :private) } - context 'with subpackages' do - let(:path) { "#{project.full_path}/subpackage" } + context 'with subpackages' do + let(:path) { "#{project.full_path}/subpackage" } - it 'returns the full project path' do - expect_response_with_path(go, project.full_path) - end - end - - context 'without subpackages' do - let(:path) { project.full_path } - - it 'returns the full project path' do - expect_response_with_path(go, project.full_path) + it 'returns the full project path' do + expect_response_with_path(go, enabled_protocol, project.full_path) + end end - end - end - context 'with a nested project path' do - let(:group) { create(:group, :nested) } - let!(:project) { create(:project, :public, namespace: group) } + context 'without subpackages' do + let(:path) { project.full_path } - shared_examples 'a nested project' do - context 'when the project is public' do it 'returns the full project path' do - expect_response_with_path(go, project.full_path) + expect_response_with_path(go, enabled_protocol, project.full_path) end end + end - context 'when the project is private' do - before do - project.update_attribute(:visibility_level, Project::PRIVATE) - end + context 'with a nested project path' do + let(:group) { create(:group, :nested) } + let!(:project) { create(:project, :public, namespace: group) } - context 'with access to the project' do - let(:current_user) { project.creator } + shared_examples 'a nested project' do + context 'when the project is public' do + it 'returns the full project path' do + expect_response_with_path(go, enabled_protocol, project.full_path) + end + end + context 'when the project is private' do before do - project.team.add_master(current_user) + project.update_attribute(:visibility_level, Project::PRIVATE) end - it 'returns the full project path' do - expect_response_with_path(go, project.full_path) + context 'with access to the project' do + let(:current_user) { project.creator } + + before do + project.team.add_master(current_user) + end + + it 'returns the full project path' do + expect_response_with_path(go, enabled_protocol, project.full_path) + end end - end - context 'without access to the project' do - it 'returns the 2-segment group path' do - expect_response_with_path(go, group.full_path) + context 'without access to the project' do + it 'returns the 2-segment group path' do + expect_response_with_path(go, enabled_protocol, group.full_path) + end end end end - end - context 'with subpackages' do - let(:path) { "#{project.full_path}/subpackage" } + context 'with subpackages' do + let(:path) { "#{project.full_path}/subpackage" } - it_behaves_like 'a nested project' - end + it_behaves_like 'a nested project' + end + + context 'with a subpackage that is not a valid project path' do + let(:path) { "#{project.full_path}/---subpackage" } - context 'with a subpackage that is not a valid project path' do - let(:path) { "#{project.full_path}/---subpackage" } + it_behaves_like 'a nested project' + end + + context 'without subpackages' do + let(:path) { project.full_path } - it_behaves_like 'a nested project' + it_behaves_like 'a nested project' + end end - context 'without subpackages' do - let(:path) { project.full_path } + context 'with a bogus path' do + let(:path) { "http:;url=http://www.example.com'http-equiv='refresh'x='?go-get=1" } + + it 'skips go-import generation' do + expect(app).to receive(:call).and_return('no-go') - it_behaves_like 'a nested project' + go + end + end + end + + context 'with SSH disabled' do + before do + stub_application_setting(enabled_git_access_protocol: 'http') end + + include_examples 'go-get=1', enabled_protocol: :http end - context 'with a bogus path' do - let(:path) { "http:;url=http://www.example.com'http-equiv='refresh'x='?go-get=1" } + context 'with HTTP disabled' do + before do + stub_application_setting(enabled_git_access_protocol: 'ssh') + end - it 'skips go-import generation' do - expect(app).to receive(:call).and_return('no-go') + include_examples 'go-get=1', enabled_protocol: :ssh + end - go + context 'with nothing disabled' do + before do + stub_application_setting(enabled_git_access_protocol: nil) end + + include_examples 'go-get=1', enabled_protocol: nil end end @@ -113,10 +139,16 @@ describe Gitlab::Middleware::Go do middleware.call(env) end - def expect_response_with_path(response, path) + def expect_response_with_path(response, protocol, path) + repository_url = case protocol + when :ssh + "ssh://git@#{Gitlab.config.gitlab.host}/#{path}.git" + when :http, nil + "http://#{Gitlab.config.gitlab.host}/#{path}.git" + end expect(response[0]).to eq(200) expect(response[1]['Content-Type']).to eq('text/html') - expected_body = %{<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git http://#{Gitlab.config.gitlab.host}/#{path}.git" /></head></html>} + expected_body = %{<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git #{repository_url}" /></head></html>} expect(response[2].body).to eq([expected_body]) end end diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb index 80bf7986ee0..249c77dc636 100644 --- a/spec/lib/gitlab/workhorse_spec.rb +++ b/spec/lib/gitlab/workhorse_spec.rb @@ -268,7 +268,8 @@ describe Gitlab::Workhorse do GL_ID: "user-#{user.id}", GL_USERNAME: user.username, GL_REPOSITORY: "project-#{project.id}", - RepoPath: repo_path + RepoPath: repo_path, + ShowAllRefs: false } end @@ -282,7 +283,8 @@ describe Gitlab::Workhorse do GL_ID: "user-#{user.id}", GL_USERNAME: user.username, GL_REPOSITORY: "wiki-#{project.id}", - RepoPath: repo_path + RepoPath: repo_path, + ShowAllRefs: false } end @@ -324,6 +326,12 @@ describe Gitlab::Workhorse do expect(subject).to include(gitaly_params) end + + context 'show_all_refs enabled' do + subject { described_class.git_http_ok(repository, false, user, action, show_all_refs: true) } + + it { is_expected.to include(ShowAllRefs: true) } + end end context "when git_receive_pack action is passed" do @@ -336,6 +344,12 @@ describe Gitlab::Workhorse do let(:action) { 'info_refs' } it { expect(subject).to include(gitaly_params) } + + context 'show_all_refs enabled' do + subject { described_class.git_http_ok(repository, false, user, action, show_all_refs: true) } + + it { is_expected.to include(ShowAllRefs: true) } + end end context 'when action passed is not supported by Gitaly' do diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index 52a2b4b2850..3d46434fc27 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -156,36 +156,35 @@ describe ProjectWiki do end describe '#find_file' do - before do - file = Gollum::File.new(subject.wiki) - allow_any_instance_of(Gollum::Wiki) - .to receive(:file).with('image.jpg', 'master') - .and_return(file) - allow_any_instance_of(Gollum::File) - .to receive(:mime_type) - .and_return('image/jpeg') - allow_any_instance_of(Gollum::Wiki) - .to receive(:file).with('non-existant', 'master') - .and_return(nil) - end + shared_examples 'finding a wiki file' do + before do + file = File.open(Rails.root.join('spec', 'fixtures', 'dk.png')) + subject.wiki # Make sure the wiki repo exists - after do - allow_any_instance_of(Gollum::Wiki).to receive(:file).and_call_original - allow_any_instance_of(Gollum::File).to receive(:mime_type).and_call_original - end + BareRepoOperations.new(subject.repository.path_to_repo).commit_file(file, 'image.png') + end - it 'returns the latest version of the file if it exists' do - file = subject.find_file('image.jpg') - expect(file.mime_type).to eq('image/jpeg') + it 'returns the latest version of the file if it exists' do + file = subject.find_file('image.png') + expect(file.mime_type).to eq('image/png') + end + + it 'returns nil if the page does not exist' do + expect(subject.find_file('non-existant')).to eq(nil) + end + + it 'returns a Gitlab::Git::WikiFile instance' do + file = subject.find_file('image.png') + expect(file).to be_a Gitlab::Git::WikiFile + end end - it 'returns nil if the page does not exist' do - expect(subject.find_file('non-existant')).to eq(nil) + context 'when Gitaly wiki_find_file is enabled' do + it_behaves_like 'finding a wiki file' end - it 'returns a Gitlab::Git::WikiFile instance' do - file = subject.find_file('image.jpg') - expect(file).to be_a Gitlab::Git::WikiFile + context 'when Gitaly wiki_find_file is disabled', :skip_gitaly_mock do + it_behaves_like 'finding a wiki file' end end diff --git a/spec/services/projects/group_links/create_service_spec.rb b/spec/services/projects/group_links/create_service_spec.rb new file mode 100644 index 00000000000..ffb270d277e --- /dev/null +++ b/spec/services/projects/group_links/create_service_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe Projects::GroupLinks::CreateService, '#execute' do + let(:user) { create :user } + let(:group) { create :group } + let(:project) { create :project } + let(:opts) do + { + link_group_access: '30', + expires_at: nil + } + end + let(:subject) { described_class.new(project, user, opts) } + + it 'adds group to project' do + expect { subject.execute(group) }.to change { project.project_group_links.count }.from(0).to(1) + end + + it 'returns false if group is blank' do + expect { subject.execute(nil) }.not_to change { project.project_group_links.count } + end +end diff --git a/spec/services/projects/group_links/destroy_service_spec.rb b/spec/services/projects/group_links/destroy_service_spec.rb new file mode 100644 index 00000000000..336ee01ae50 --- /dev/null +++ b/spec/services/projects/group_links/destroy_service_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe Projects::GroupLinks::DestroyService, '#execute' do + let(:group_link) { create :project_group_link } + let(:project) { group_link.project } + let(:user) { create :user } + let(:subject) { described_class.new(project, user) } + + it 'removes group from project' do + expect { subject.execute(group_link) }.to change { project.project_group_links.count }.from(1).to(0) + end + + it 'returns false if group_link is blank' do + expect { subject.execute(nil) }.not_to change { project.project_group_links.count } + end +end diff --git a/spec/support/bare_repo_operations.rb b/spec/support/bare_repo_operations.rb new file mode 100644 index 00000000000..38d11992dc2 --- /dev/null +++ b/spec/support/bare_repo_operations.rb @@ -0,0 +1,60 @@ +require 'zlib' + +class BareRepoOperations + # The ID of empty tree. + # See http://stackoverflow.com/a/40884093/1856239 and https://github.com/git/git/blob/3ad8b5bf26362ac67c9020bf8c30eee54a84f56d/cache.h#L1011-L1012 + EMPTY_TREE_ID = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'.freeze + + include Gitlab::Popen + + def initialize(path_to_repo) + @path_to_repo = path_to_repo + end + + # Based on https://stackoverflow.com/a/25556917/1856239 + def commit_file(file, dst_path, branch = 'master') + head_id = execute(['show', '--format=format:%H', '--no-patch', branch], allow_failure: true)[0] || EMPTY_TREE_ID + + execute(['read-tree', '--empty']) + execute(['read-tree', head_id]) + + blob_id = execute(['hash-object', '--stdin', '-w']) do |stdin| + stdin.write(file.read) + end + + execute(['update-index', '--add', '--cacheinfo', '100644', blob_id[0], dst_path]) + + tree_id = execute(['write-tree']) + + commit_tree_args = ['commit-tree', tree_id[0], '-m', "Add #{dst_path}"] + commit_tree_args += ['-p', head_id] unless head_id == EMPTY_TREE_ID + commit_id = execute(commit_tree_args) + + execute(['update-ref', "refs/heads/#{branch}", commit_id[0]]) + end + + private + + def execute(args, allow_failure: false) + output, status = popen(base_args + args, nil) do |stdin| + yield stdin if block_given? + end + + unless status.zero? + if allow_failure + return [] + else + raise "Got a non-zero exit code while calling out `#{args.join(' ')}`: #{output}" + end + end + + output.split("\n") + end + + def base_args + [ + Gitlab.config.git.bin_path, + "--git-dir=#{@path_to_repo}" + ] + end +end diff --git a/vendor/assets/javascripts/fuzzaldrin-plus.js b/vendor/assets/javascripts/fuzzaldrin-plus.js deleted file mode 100644 index 1985e3f8f6c..00000000000 --- a/vendor/assets/javascripts/fuzzaldrin-plus.js +++ /dev/null @@ -1,1161 +0,0 @@ -/*! - * fuzzaldrin-plus.js - 0.3.1 - * https://github.com/jeancroy/fuzzaldrin-plus - * - * Copyright 2016 - Jean Christophe Roy - * Released under the MIT license - * https://github.com/jeancroy/fuzzaldrin-plus/raw/master/LICENSE.md - */ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ -fuzzaldrinPlus = require('fuzzaldrin-plus'); - -},{"fuzzaldrin-plus":3}],2:[function(require,module,exports){ -(function() { - var PathSeparator, legacy_scorer, pluckCandidates, scorer, sortCandidates; - - scorer = require('./scorer'); - - legacy_scorer = require('./legacy'); - - pluckCandidates = function(a) { - return a.candidate; - }; - - sortCandidates = function(a, b) { - return b.score - a.score; - }; - - PathSeparator = require('path').sep; - - module.exports = function(candidates, query, _arg) { - var allowErrors, bAllowErrors, bKey, candidate, coreQuery, key, legacy, maxInners, maxResults, prepQuery, queryHasSlashes, score, scoredCandidates, spotLeft, string, _i, _j, _len, _len1, _ref; - _ref = _arg != null ? _arg : {}, key = _ref.key, maxResults = _ref.maxResults, maxInners = _ref.maxInners, allowErrors = _ref.allowErrors, legacy = _ref.legacy; - scoredCandidates = []; - spotLeft = (maxInners != null) && maxInners > 0 ? maxInners : candidates.length; - bAllowErrors = !!allowErrors; - bKey = key != null; - prepQuery = scorer.prepQuery(query); - if (!legacy) { - for (_i = 0, _len = candidates.length; _i < _len; _i++) { - candidate = candidates[_i]; - string = bKey ? candidate[key] : candidate; - if (!string) { - continue; - } - score = scorer.score(string, query, prepQuery, bAllowErrors); - if (score > 0) { - scoredCandidates.push({ - candidate: candidate, - score: score - }); - if (!--spotLeft) { - break; - } - } - } - } else { - queryHasSlashes = prepQuery.depth > 0; - coreQuery = prepQuery.core; - for (_j = 0, _len1 = candidates.length; _j < _len1; _j++) { - candidate = candidates[_j]; - string = key != null ? candidate[key] : candidate; - if (!string) { - continue; - } - score = legacy_scorer.score(string, coreQuery, queryHasSlashes); - if (!queryHasSlashes) { - score = legacy_scorer.basenameScore(string, coreQuery, score); - } - if (score > 0) { - scoredCandidates.push({ - candidate: candidate, - score: score - }); - } - } - } - scoredCandidates.sort(sortCandidates); - candidates = scoredCandidates.map(pluckCandidates); - if (maxResults != null) { - candidates = candidates.slice(0, maxResults); - } - return candidates; - }; - -}).call(this); - -},{"./legacy":4,"./scorer":6,"path":7}],3:[function(require,module,exports){ -(function() { - var PathSeparator, filter, legacy_scorer, matcher, prepQueryCache, scorer; - - scorer = require('./scorer'); - - legacy_scorer = require('./legacy'); - - filter = require('./filter'); - - matcher = require('./matcher'); - - PathSeparator = require('path').sep; - - prepQueryCache = null; - - module.exports = { - filter: function(candidates, query, options) { - if (!((query != null ? query.length : void 0) && (candidates != null ? candidates.length : void 0))) { - return []; - } - return filter(candidates, query, options); - }, - prepQuery: function(query) { - return scorer.prepQuery(query); - }, - score: function(string, query, prepQuery, _arg) { - var allowErrors, coreQuery, legacy, queryHasSlashes, score, _ref; - _ref = _arg != null ? _arg : {}, allowErrors = _ref.allowErrors, legacy = _ref.legacy; - if (!((string != null ? string.length : void 0) && (query != null ? query.length : void 0))) { - return 0; - } - if (prepQuery == null) { - prepQuery = prepQueryCache && prepQueryCache.query === query ? prepQueryCache : (prepQueryCache = scorer.prepQuery(query)); - } - if (!legacy) { - score = scorer.score(string, query, prepQuery, !!allowErrors); - } else { - queryHasSlashes = prepQuery.depth > 0; - coreQuery = prepQuery.core; - score = legacy_scorer.score(string, coreQuery, queryHasSlashes); - if (!queryHasSlashes) { - score = legacy_scorer.basenameScore(string, coreQuery, score); - } - } - return score; - }, - match: function(string, query, prepQuery, _arg) { - var allowErrors, baseMatches, matches, query_lw, string_lw, _i, _ref, _results; - allowErrors = (_arg != null ? _arg : {}).allowErrors; - if (!string) { - return []; - } - if (!query) { - return []; - } - if (string === query) { - return (function() { - _results = []; - for (var _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); } - return _results; - }).apply(this); - } - if (prepQuery == null) { - prepQuery = prepQueryCache && prepQueryCache.query === query ? prepQueryCache : (prepQueryCache = scorer.prepQuery(query)); - } - if (!(allowErrors || scorer.isMatch(string, prepQuery.core_lw, prepQuery.core_up))) { - return []; - } - string_lw = string.toLowerCase(); - query_lw = prepQuery.query_lw; - matches = matcher.match(string, string_lw, prepQuery); - if (matches.length === 0) { - return matches; - } - if (string.indexOf(PathSeparator) > -1) { - baseMatches = matcher.basenameMatch(string, string_lw, prepQuery); - matches = matcher.mergeMatches(matches, baseMatches); - } - return matches; - } - }; - -}).call(this); - -},{"./filter":2,"./legacy":4,"./matcher":5,"./scorer":6,"path":7}],4:[function(require,module,exports){ -(function() { - var PathSeparator, queryIsLastPathSegment; - - PathSeparator = require('path').sep; - - exports.basenameScore = function(string, query, score) { - var base, depth, index, lastCharacter, segmentCount, slashCount; - index = string.length - 1; - while (string[index] === PathSeparator) { - index--; - } - slashCount = 0; - lastCharacter = index; - base = null; - while (index >= 0) { - if (string[index] === PathSeparator) { - slashCount++; - if (base == null) { - base = string.substring(index + 1, lastCharacter + 1); - } - } else if (index === 0) { - if (lastCharacter < string.length - 1) { - if (base == null) { - base = string.substring(0, lastCharacter + 1); - } - } else { - if (base == null) { - base = string; - } - } - } - index--; - } - if (base === string) { - score *= 2; - } else if (base) { - score += exports.score(base, query); - } - segmentCount = slashCount + 1; - depth = Math.max(1, 10 - segmentCount); - score *= depth * 0.01; - return score; - }; - - exports.score = function(string, query) { - var character, characterScore, indexInQuery, indexInString, lowerCaseIndex, minIndex, queryLength, queryScore, stringLength, totalCharacterScore, upperCaseIndex, _ref; - if (string === query) { - return 1; - } - if (queryIsLastPathSegment(string, query)) { - return 1; - } - totalCharacterScore = 0; - queryLength = query.length; - stringLength = string.length; - indexInQuery = 0; - indexInString = 0; - while (indexInQuery < queryLength) { - character = query[indexInQuery++]; - lowerCaseIndex = string.indexOf(character.toLowerCase()); - upperCaseIndex = string.indexOf(character.toUpperCase()); - minIndex = Math.min(lowerCaseIndex, upperCaseIndex); - if (minIndex === -1) { - minIndex = Math.max(lowerCaseIndex, upperCaseIndex); - } - indexInString = minIndex; - if (indexInString === -1) { - return 0; - } - characterScore = 0.1; - if (string[indexInString] === character) { - characterScore += 0.1; - } - if (indexInString === 0 || string[indexInString - 1] === PathSeparator) { - characterScore += 0.8; - } else if ((_ref = string[indexInString - 1]) === '-' || _ref === '_' || _ref === ' ') { - characterScore += 0.7; - } - string = string.substring(indexInString + 1, stringLength); - totalCharacterScore += characterScore; - } - queryScore = totalCharacterScore / queryLength; - return ((queryScore * (queryLength / stringLength)) + queryScore) / 2; - }; - - queryIsLastPathSegment = function(string, query) { - if (string[string.length - query.length - 1] === PathSeparator) { - return string.lastIndexOf(query) === string.length - query.length; - } - }; - - exports.match = function(string, query, stringOffset) { - var character, indexInQuery, indexInString, lowerCaseIndex, matches, minIndex, queryLength, stringLength, upperCaseIndex, _i, _ref, _results; - if (stringOffset == null) { - stringOffset = 0; - } - if (string === query) { - return (function() { - _results = []; - for (var _i = stringOffset, _ref = stringOffset + string.length; stringOffset <= _ref ? _i < _ref : _i > _ref; stringOffset <= _ref ? _i++ : _i--){ _results.push(_i); } - return _results; - }).apply(this); - } - queryLength = query.length; - stringLength = string.length; - indexInQuery = 0; - indexInString = 0; - matches = []; - while (indexInQuery < queryLength) { - character = query[indexInQuery++]; - lowerCaseIndex = string.indexOf(character.toLowerCase()); - upperCaseIndex = string.indexOf(character.toUpperCase()); - minIndex = Math.min(lowerCaseIndex, upperCaseIndex); - if (minIndex === -1) { - minIndex = Math.max(lowerCaseIndex, upperCaseIndex); - } - indexInString = minIndex; - if (indexInString === -1) { - return []; - } - matches.push(stringOffset + indexInString); - stringOffset += indexInString + 1; - string = string.substring(indexInString + 1, stringLength); - } - return matches; - }; - -}).call(this); - -},{"path":7}],5:[function(require,module,exports){ -(function() { - var PathSeparator, scorer; - - PathSeparator = require('path').sep; - - scorer = require('./scorer'); - - exports.basenameMatch = function(subject, subject_lw, prepQuery) { - var basePos, depth, end; - end = subject.length - 1; - while (subject[end] === PathSeparator) { - end--; - } - basePos = subject.lastIndexOf(PathSeparator, end); - if (basePos === -1) { - return []; - } - depth = prepQuery.depth; - while (depth-- > 0) { - basePos = subject.lastIndexOf(PathSeparator, basePos - 1); - if (basePos === -1) { - return []; - } - } - basePos++; - end++; - return exports.match(subject.slice(basePos, end), subject_lw.slice(basePos, end), prepQuery, basePos); - }; - - exports.mergeMatches = function(a, b) { - var ai, bj, i, j, m, n, out; - m = a.length; - n = b.length; - if (n === 0) { - return a.slice(); - } - if (m === 0) { - return b.slice(); - } - i = -1; - j = 0; - bj = b[j]; - out = []; - while (++i < m) { - ai = a[i]; - while (bj <= ai && ++j < n) { - if (bj < ai) { - out.push(bj); - } - bj = b[j]; - } - out.push(ai); - } - while (j < n) { - out.push(b[j++]); - } - return out; - }; - - exports.match = function(subject, subject_lw, prepQuery, offset) { - var DIAGONAL, LEFT, STOP, UP, acro_score, align, backtrack, csc_diag, csc_row, csc_score, i, j, m, matches, move, n, pos, query, query_lw, score, score_diag, score_row, score_up, si_lw, start, trace; - if (offset == null) { - offset = 0; - } - query = prepQuery.query; - query_lw = prepQuery.query_lw; - m = subject.length; - n = query.length; - acro_score = scorer.scoreAcronyms(subject, subject_lw, query, query_lw).score; - score_row = new Array(n); - csc_row = new Array(n); - STOP = 0; - UP = 1; - LEFT = 2; - DIAGONAL = 3; - trace = new Array(m * n); - pos = -1; - j = -1; - while (++j < n) { - score_row[j] = 0; - csc_row[j] = 0; - } - i = -1; - while (++i < m) { - score = 0; - score_up = 0; - csc_diag = 0; - si_lw = subject_lw[i]; - j = -1; - while (++j < n) { - csc_score = 0; - align = 0; - score_diag = score_up; - if (query_lw[j] === si_lw) { - start = scorer.isWordStart(i, subject, subject_lw); - csc_score = csc_diag > 0 ? csc_diag : scorer.scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start); - align = score_diag + scorer.scoreCharacter(i, j, start, acro_score, csc_score); - } - score_up = score_row[j]; - csc_diag = csc_row[j]; - if (score > score_up) { - move = LEFT; - } else { - score = score_up; - move = UP; - } - if (align > score) { - score = align; - move = DIAGONAL; - } else { - csc_score = 0; - } - score_row[j] = score; - csc_row[j] = csc_score; - trace[++pos] = score > 0 ? move : STOP; - } - } - i = m - 1; - j = n - 1; - pos = i * n + j; - backtrack = true; - matches = []; - while (backtrack && i >= 0 && j >= 0) { - switch (trace[pos]) { - case UP: - i--; - pos -= n; - break; - case LEFT: - j--; - pos--; - break; - case DIAGONAL: - matches.push(i + offset); - j--; - i--; - pos -= n + 1; - break; - default: - backtrack = false; - } - } - matches.reverse(); - return matches; - }; - -}).call(this); - -},{"./scorer":6,"path":7}],6:[function(require,module,exports){ -(function() { - var AcronymResult, PathSeparator, Query, basenameScore, coreChars, countDir, doScore, emptyAcronymResult, file_coeff, isMatch, isSeparator, isWordEnd, isWordStart, miss_coeff, opt_char_re, pos_bonus, scoreAcronyms, scoreCharacter, scoreConsecutives, scoreExact, scoreExactMatch, scorePattern, scorePosition, scoreSize, tau_depth, tau_size, truncatedUpperCase, wm; - - PathSeparator = require('path').sep; - - wm = 150; - - pos_bonus = 20; - - tau_depth = 13; - - tau_size = 85; - - file_coeff = 1.2; - - miss_coeff = 0.75; - - opt_char_re = /[ _\-:\/\\]/g; - - exports.coreChars = coreChars = function(query) { - return query.replace(opt_char_re, ''); - }; - - exports.score = function(string, query, prepQuery, allowErrors) { - var score, string_lw; - if (prepQuery == null) { - prepQuery = new Query(query); - } - if (allowErrors == null) { - allowErrors = false; - } - if (!(allowErrors || isMatch(string, prepQuery.core_lw, prepQuery.core_up))) { - return 0; - } - string_lw = string.toLowerCase(); - score = doScore(string, string_lw, prepQuery); - return Math.ceil(basenameScore(string, string_lw, prepQuery, score)); - }; - - Query = (function() { - function Query(query) { - if (!(query != null ? query.length : void 0)) { - return null; - } - this.query = query; - this.query_lw = query.toLowerCase(); - this.core = coreChars(query); - this.core_lw = this.core.toLowerCase(); - this.core_up = truncatedUpperCase(this.core); - this.depth = countDir(query, query.length); - } - - return Query; - - })(); - - exports.prepQuery = function(query) { - return new Query(query); - }; - - exports.isMatch = isMatch = function(subject, query_lw, query_up) { - var i, j, m, n, qj_lw, qj_up, si; - m = subject.length; - n = query_lw.length; - if (!m || n > m) { - return false; - } - i = -1; - j = -1; - while (++j < n) { - qj_lw = query_lw[j]; - qj_up = query_up[j]; - while (++i < m) { - si = subject[i]; - if (si === qj_lw || si === qj_up) { - break; - } - } - if (i === m) { - return false; - } - } - return true; - }; - - doScore = function(subject, subject_lw, prepQuery) { - var acro, acro_score, align, csc_diag, csc_row, csc_score, i, j, m, miss_budget, miss_left, mm, n, pos, query, query_lw, record_miss, score, score_diag, score_row, score_up, si_lw, start, sz; - query = prepQuery.query; - query_lw = prepQuery.query_lw; - m = subject.length; - n = query.length; - acro = scoreAcronyms(subject, subject_lw, query, query_lw); - acro_score = acro.score; - if (acro.count === n) { - return scoreExact(n, m, acro_score, acro.pos); - } - pos = subject_lw.indexOf(query_lw); - if (pos > -1) { - return scoreExactMatch(subject, subject_lw, query, query_lw, pos, n, m); - } - score_row = new Array(n); - csc_row = new Array(n); - sz = scoreSize(n, m); - miss_budget = Math.ceil(miss_coeff * n) + 5; - miss_left = miss_budget; - j = -1; - while (++j < n) { - score_row[j] = 0; - csc_row[j] = 0; - } - i = subject_lw.indexOf(query_lw[0]); - if (i > -1) { - i--; - } - mm = subject_lw.lastIndexOf(query_lw[n - 1], m); - if (mm > i) { - m = mm + 1; - } - while (++i < m) { - score = 0; - score_diag = 0; - csc_diag = 0; - si_lw = subject_lw[i]; - record_miss = true; - j = -1; - while (++j < n) { - score_up = score_row[j]; - if (score_up > score) { - score = score_up; - } - csc_score = 0; - if (query_lw[j] === si_lw) { - start = isWordStart(i, subject, subject_lw); - csc_score = csc_diag > 0 ? csc_diag : scoreConsecutives(subject, subject_lw, query, query_lw, i, j, start); - align = score_diag + scoreCharacter(i, j, start, acro_score, csc_score); - if (align > score) { - score = align; - miss_left = miss_budget; - } else { - if (record_miss && --miss_left <= 0) { - return score_row[n - 1] * sz; - } - record_miss = false; - } - } - score_diag = score_up; - csc_diag = csc_row[j]; - csc_row[j] = csc_score; - score_row[j] = score; - } - } - return score * sz; - }; - - exports.isWordStart = isWordStart = function(pos, subject, subject_lw) { - var curr_s, prev_s; - if (pos === 0) { - return true; - } - curr_s = subject[pos]; - prev_s = subject[pos - 1]; - return isSeparator(curr_s) || isSeparator(prev_s) || (curr_s !== subject_lw[pos] && prev_s === subject_lw[pos - 1]); - }; - - exports.isWordEnd = isWordEnd = function(pos, subject, subject_lw, len) { - var curr_s, next_s; - if (pos === len - 1) { - return true; - } - curr_s = subject[pos]; - next_s = subject[pos + 1]; - return isSeparator(curr_s) || isSeparator(next_s) || (curr_s === subject_lw[pos] && next_s !== subject_lw[pos + 1]); - }; - - isSeparator = function(c) { - return c === ' ' || c === '.' || c === '-' || c === '_' || c === '/' || c === '\\'; - }; - - scorePosition = function(pos) { - var sc; - if (pos < pos_bonus) { - sc = pos_bonus - pos; - return 100 + sc * sc; - } else { - return Math.max(100 + pos_bonus - pos, 0); - } - }; - - scoreSize = function(n, m) { - return tau_size / (tau_size + Math.abs(m - n)); - }; - - scoreExact = function(n, m, quality, pos) { - return 2 * n * (wm * quality + scorePosition(pos)) * scoreSize(n, m); - }; - - exports.scorePattern = scorePattern = function(count, len, sameCase, start, end) { - var bonus, sz; - sz = count; - bonus = 6; - if (sameCase === count) { - bonus += 2; - } - if (start) { - bonus += 3; - } - if (end) { - bonus += 1; - } - if (count === len) { - if (start) { - if (sameCase === len) { - sz += 2; - } else { - sz += 1; - } - } - if (end) { - bonus += 1; - } - } - return sameCase + sz * (sz + bonus); - }; - - exports.scoreCharacter = scoreCharacter = function(i, j, start, acro_score, csc_score) { - var posBonus; - posBonus = scorePosition(i); - if (start) { - return posBonus + wm * ((acro_score > csc_score ? acro_score : csc_score) + 10); - } - return posBonus + wm * csc_score; - }; - - exports.scoreConsecutives = scoreConsecutives = function(subject, subject_lw, query, query_lw, i, j, start) { - var k, m, mi, n, nj, sameCase, startPos, sz; - m = subject.length; - n = query.length; - mi = m - i; - nj = n - j; - k = mi < nj ? mi : nj; - startPos = i; - sameCase = 0; - sz = 0; - if (query[j] === subject[i]) { - sameCase++; - } - while (++sz < k && query_lw[++j] === subject_lw[++i]) { - if (query[j] === subject[i]) { - sameCase++; - } - } - if (sz === 1) { - return 1 + 2 * sameCase; - } - return scorePattern(sz, n, sameCase, start, isWordEnd(i, subject, subject_lw, m)); - }; - - exports.scoreExactMatch = scoreExactMatch = function(subject, subject_lw, query, query_lw, pos, n, m) { - var end, i, pos2, sameCase, start; - start = isWordStart(pos, subject, subject_lw); - if (!start) { - pos2 = subject_lw.indexOf(query_lw, pos + 1); - if (pos2 > -1) { - start = isWordStart(pos2, subject, subject_lw); - if (start) { - pos = pos2; - } - } - } - i = -1; - sameCase = 0; - while (++i < n) { - if (query[pos + i] === subject[i]) { - sameCase++; - } - } - end = isWordEnd(pos + n - 1, subject, subject_lw, m); - return scoreExact(n, m, scorePattern(n, n, sameCase, start, end), pos); - }; - - AcronymResult = (function() { - function AcronymResult(score, pos, count) { - this.score = score; - this.pos = pos; - this.count = count; - } - - return AcronymResult; - - })(); - - emptyAcronymResult = new AcronymResult(0, 0.1, 0); - - exports.scoreAcronyms = scoreAcronyms = function(subject, subject_lw, query, query_lw) { - var count, i, j, m, n, pos, qj_lw, sameCase, score; - m = subject.length; - n = query.length; - if (!(m > 1 && n > 1)) { - return emptyAcronymResult; - } - count = 0; - pos = 0; - sameCase = 0; - i = -1; - j = -1; - while (++j < n) { - qj_lw = query_lw[j]; - while (++i < m) { - if (qj_lw === subject_lw[i] && isWordStart(i, subject, subject_lw)) { - if (query[j] === subject[i]) { - sameCase++; - } - pos += i; - count++; - break; - } - } - if (i === m) { - break; - } - } - if (count < 2) { - return emptyAcronymResult; - } - score = scorePattern(count, n, sameCase, true, false); - return new AcronymResult(score, pos / count, count); - }; - - basenameScore = function(subject, subject_lw, prepQuery, fullPathScore) { - var alpha, basePathScore, basePos, depth, end; - if (fullPathScore === 0) { - return 0; - } - end = subject.length - 1; - while (subject[end] === PathSeparator) { - end--; - } - basePos = subject.lastIndexOf(PathSeparator, end); - if (basePos === -1) { - return fullPathScore; - } - depth = prepQuery.depth; - while (depth-- > 0) { - basePos = subject.lastIndexOf(PathSeparator, basePos - 1); - if (basePos === -1) { - return fullPathScore; - } - } - basePos++; - end++; - basePathScore = doScore(subject.slice(basePos, end), subject_lw.slice(basePos, end), prepQuery); - alpha = 0.5 * tau_depth / (tau_depth + countDir(subject, end + 1)); - return alpha * basePathScore + (1 - alpha) * fullPathScore * scoreSize(0, file_coeff * (end - basePos)); - }; - - exports.countDir = countDir = function(path, end) { - var count, i; - if (end < 1) { - return 0; - } - count = 0; - i = -1; - while (++i < end && path[i] === PathSeparator) { - continue; - } - while (++i < end) { - if (path[i] === PathSeparator) { - count++; - while (++i < end && path[i] === PathSeparator) { - continue; - } - } - } - return count; - }; - - truncatedUpperCase = function(str) { - var char, upper, _i, _len; - upper = ""; - for (_i = 0, _len = str.length; _i < _len; _i++) { - char = str[_i]; - upper += char.toUpperCase()[0]; - } - return upper; - }; - -}).call(this); - -},{"path":7}],7:[function(require,module,exports){ -(function (process){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// resolves . and .. elements in a path array with directory names there -// must be no slashes, empty elements, or device names (c:\) in the array -// (so also no leading and trailing slashes - it does not distinguish -// relative and absolute paths) -function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; -} - -// Split a filename into [root, dir, basename, ext], unix version -// 'root' is just a slash, or nothing. -var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; -var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); -}; - -// path.resolve([from ...], to) -// posix version -exports.resolve = function() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : process.cwd(); - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; -}; - -// path.normalize(path) -// posix version -exports.normalize = function(path) { - var isAbsolute = exports.isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isAbsolute).join('/'); - - if (!path && !isAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isAbsolute ? '/' : '') + path; -}; - -// posix version -exports.isAbsolute = function(path) { - return path.charAt(0) === '/'; -}; - -// posix version -exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); -}; - - -// path.relative(from, to) -// posix version -exports.relative = function(from, to) { - from = exports.resolve(from).substr(1); - to = exports.resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); -}; - -exports.sep = '/'; -exports.delimiter = ':'; - -exports.dirname = function(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; -}; - - -exports.basename = function(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; -}; - - -exports.extname = function(path) { - return splitPath(path)[3]; -}; - -function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; -} - -// String.prototype.substr - negative index don't work in IE8 -var substr = 'ab'.substr(-1) === 'b' - ? function (str, start, len) { return str.substr(start, len) } - : function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } -; - -}).call(this,require('_process')) -},{"_process":8}],8:[function(require,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = setTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - clearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - setTimeout(drainQueue, 0); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}]},{},[1]); diff --git a/yarn.lock b/yarn.lock index 1d4538b0b94..818878fe36c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2675,6 +2675,10 @@ function-bind@^1.1.1, function-bind@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" +fuzzaldrin-plus@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/fuzzaldrin-plus/-/fuzzaldrin-plus-0.5.0.tgz#ef5f26f0c2fc7e9e9a16ea149a802d6cb4804b1e" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" |