summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/experimental_flags.js3
-rw-r--r--app/assets/javascripts/main.js1
-rw-r--r--app/assets/javascripts/shortcuts.js2
-rw-r--r--app/assets/javascripts/users/activity_calendar.js227
-rw-r--r--app/assets/javascripts/users/calendar.js231
-rw-r--r--app/assets/javascripts/users/index.js7
-rw-r--r--app/assets/javascripts/users/user.js (renamed from app/assets/javascripts/user.js)13
-rw-r--r--app/assets/javascripts/users/user_tabs.js (renamed from app/assets/javascripts/user_tabs.js)0
-rw-r--r--app/assets/javascripts/users/users_bundle.js1
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss3
-rw-r--r--app/assets/stylesheets/pages/builds.scss4
-rw-r--r--app/controllers/admin/application_settings_controller.rb2
-rw-r--r--app/controllers/application_controller.rb2
-rw-r--r--app/controllers/passwords_controller.rb12
-rw-r--r--app/controllers/profiles/passwords_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/creations_controller.rb2
-rw-r--r--app/controllers/projects/triggers_controller.rb3
-rw-r--r--app/controllers/sessions_controller.rb2
-rw-r--r--app/helpers/application_settings_helper.rb2
-rw-r--r--app/helpers/button_helper.rb4
-rw-r--r--app/helpers/projects_helper.rb12
-rw-r--r--app/models/application_setting.rb2
-rw-r--r--app/models/concerns/sortable.rb23
-rw-r--r--app/models/merge_request.rb37
-rw-r--r--app/models/project.rb6
-rw-r--r--app/models/repository.rb2
-rw-r--r--app/models/user.rb12
-rw-r--r--app/services/git_operation_service.rb1
-rw-r--r--app/services/merge_requests/create_service.rb3
-rw-r--r--app/views/admin/application_settings/_form.html.haml6
-rw-r--r--app/views/devise/sessions/new.html.haml6
-rw-r--r--app/views/devise/shared/_signin_box.html.haml4
-rw-r--r--app/views/devise/shared/_tabs_ldap.html.haml4
-rw-r--r--app/views/devise/shared/_tabs_normal.html.haml2
-rw-r--r--app/views/layouts/_broadcast.html.haml2
-rw-r--r--app/views/layouts/application.html.haml2
-rw-r--r--app/views/layouts/header/_default.html.haml5
-rw-r--r--app/views/layouts/header/_new.html.haml5
-rw-r--r--app/views/layouts/nav/_profile.html.haml2
-rw-r--r--app/views/projects/jobs/_sidebar.html.haml8
-rw-r--r--app/views/projects/protected_branches/_branches_list.html.haml30
-rw-r--r--app/views/projects/protected_branches/_create_protected_branch.html.haml53
-rw-r--r--app/views/projects/protected_branches/_index.html.haml26
-rw-r--r--app/views/projects/protected_branches/_protected_branch.html.haml22
-rw-r--r--app/views/projects/protected_branches/shared/_branches_list.html.haml28
-rw-r--r--app/views/projects/protected_branches/shared/_create_protected_branch.html.haml33
-rw-r--r--app/views/projects/protected_branches/shared/_dropdown.html.haml (renamed from app/views/projects/protected_branches/_dropdown.html.haml)0
-rw-r--r--app/views/projects/protected_branches/shared/_index.html.haml24
-rw-r--r--app/views/projects/protected_branches/shared/_matching_branch.html.haml (renamed from app/views/projects/protected_branches/_matching_branch.html.haml)0
-rw-r--r--app/views/projects/protected_branches/shared/_protected_branch.html.haml24
-rw-r--r--app/views/projects/protected_branches/show.html.haml2
-rw-r--r--app/views/projects/protected_tags/_create_protected_tag.html.haml38
-rw-r--r--app/views/projects/protected_tags/_index.html.haml26
-rw-r--r--app/views/projects/protected_tags/_protected_tag.html.haml22
-rw-r--r--app/views/projects/protected_tags/_tags_list.html.haml32
-rw-r--r--app/views/projects/protected_tags/shared/_create_protected_tag.html.haml29
-rw-r--r--app/views/projects/protected_tags/shared/_dropdown.html.haml (renamed from app/views/projects/protected_tags/_dropdown.html.haml)0
-rw-r--r--app/views/projects/protected_tags/shared/_index.html.haml24
-rw-r--r--app/views/projects/protected_tags/shared/_matching_tag.html.haml (renamed from app/views/projects/protected_tags/_matching_tag.html.haml)0
-rw-r--r--app/views/projects/protected_tags/shared/_protected_tag.html.haml22
-rw-r--r--app/views/projects/protected_tags/shared/_tags_list.html.haml30
-rw-r--r--app/views/projects/protected_tags/show.html.haml2
-rw-r--r--app/views/projects/settings/repository/show.html.haml4
-rw-r--r--app/views/shared/_personal_access_tokens_table.html.haml19
-rw-r--r--changelogs/unreleased/19629-remove-inactive-tokens-list.yml4
-rw-r--r--changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml4
-rw-r--r--changelogs/unreleased/35035-sidebar-job-spaces.yml4
-rw-r--r--changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml4
-rw-r--r--changelogs/unreleased/dm-drop-default-scope-on-sortable-finders.yml4
-rw-r--r--changelogs/unreleased/fixes-for-internal-auth-disabled.yml4
-rw-r--r--config/initializers/1_settings.rb2
-rw-r--r--config/initializers/8_metrics.rb4
-rw-r--r--config/webpack.config.js2
-rw-r--r--db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb15
-rw-r--r--db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb15
-rw-r--r--db/schema.rb2
-rw-r--r--doc/api/settings.md6
-rw-r--r--doc/development/fe_guide/droplab/plugins/input_setter.md2
-rw-r--r--doc/development/rake_tasks.md50
-rw-r--r--lib/api/entities.rb3
-rw-r--r--lib/api/internal.rb2
-rw-r--r--lib/api/settings.rb9
-rw-r--r--lib/api/v3/entities.rb3
-rw-r--r--lib/api/v3/settings.rb14
-rw-r--r--lib/gitlab/auth.rb6
-rw-r--r--lib/gitlab/git/commit.rb2
-rw-r--r--lib/gitlab/git/repository.rb164
-rw-r--r--lib/gitlab/git_ref_validator.rb2
-rw-r--r--lib/gitlab/shell.rb13
-rw-r--r--locale/pt_BR/gitlab.po970
-rw-r--r--spec/controllers/application_controller_spec.rb9
-rw-r--r--spec/controllers/passwords_controller_spec.rb29
-rw-r--r--spec/factories/ci/triggers.rb7
-rw-r--r--spec/features/admin/admin_users_impersonation_tokens_spec.rb12
-rw-r--r--spec/features/merge_requests/conflicts_spec.rb5
-rw-r--r--spec/features/profiles/password_spec.rb80
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb12
-rw-r--r--spec/features/projects/diffs/diff_show_spec.rb4
-rw-r--r--spec/features/projects/no_password_spec.rb2
-rw-r--r--spec/helpers/button_helper_spec.rb2
-rw-r--r--spec/helpers/projects_helper_spec.rb4
-rw-r--r--spec/lib/gitlab/auth_spec.rb12
-rw-r--r--spec/lib/gitlab/fake_application_settings_spec.rb10
-rw-r--r--spec/lib/gitlab/git/diff_spec.rb4
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb16
-rw-r--r--spec/models/concerns/sortable_spec.rb21
-rw-r--r--spec/models/project_services/gitlab_issue_tracker_service_spec.rb27
-rw-r--r--spec/models/user_spec.rb22
-rw-r--r--spec/requests/api/internal_spec.rb11
-rw-r--r--spec/requests/api/settings_spec.rb6
-rw-r--r--spec/requests/api/v3/settings_spec.rb6
-rw-r--r--spec/requests/git_http_spec.rb2
-rw-r--r--spec/requests/jwt_controller_spec.rb2
-rw-r--r--spec/spec_helper.rb3
-rw-r--r--spec/support/stub_feature_flags.rb8
118 files changed, 1975 insertions, 816 deletions
diff --git a/Gemfile b/Gemfile
index 0eeb5807d04..8d71ac74308 100644
--- a/Gemfile
+++ b/Gemfile
@@ -12,7 +12,7 @@ gem 'sprockets', '~> 3.7.0'
gem 'default_value_for', '~> 3.0.0'
# Supported DBs
-gem 'mysql2', '~> 0.3.16', group: :mysql
+gem 'mysql2', '~> 0.4.5', group: :mysql
gem 'pg', '~> 0.18.2', group: :postgres
gem 'rugged', '~> 0.25.1.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index c27c06e9c34..41ef1e9d456 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -470,7 +470,7 @@ GEM
tool (~> 0.2)
mustermann-grape (0.4.0)
mustermann (= 0.4.0)
- mysql2 (0.3.20)
+ mysql2 (0.4.5)
net-ldap (0.12.1)
netrc (0.11.0)
nokogiri (1.6.8.1)
@@ -1011,7 +1011,7 @@ DEPENDENCIES
method_source (~> 0.8)
minitest (~> 5.7.0)
mousetrap-rails (~> 1.4.6)
- mysql2 (~> 0.3.16)
+ mysql2 (~> 0.4.5)
nokogiri (~> 1.6.7, >= 1.6.7.2)
oauth2 (~> 1.4)
octokit (~> 4.6.2)
diff --git a/app/assets/javascripts/experimental_flags.js b/app/assets/javascripts/experimental_flags.js
index dbd3843cef7..6ee65ca72f9 100644
--- a/app/assets/javascripts/experimental_flags.js
+++ b/app/assets/javascripts/experimental_flags.js
@@ -7,5 +7,8 @@ export default () => {
Cookies.set(el.name, el.value, {
expires: 365 * 10,
});
+
+ document.body.scrollTop = 0;
+ window.location.reload();
});
};
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 892b3fab1c6..26c67fb721c 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -149,7 +149,6 @@ import './star';
import './subscription';
import './subscription_select';
import './syntax_highlight';
-import './user';
// eslint-disable-next-line global-require, import/no-commonjs
if (process.env.NODE_ENV !== 'production') require('./test_utils/');
diff --git a/app/assets/javascripts/shortcuts.js b/app/assets/javascripts/shortcuts.js
index 49d980212d6..e3daa8cf949 100644
--- a/app/assets/javascripts/shortcuts.js
+++ b/app/assets/javascripts/shortcuts.js
@@ -1,6 +1,5 @@
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, prefer-arrow-callback, consistent-return, object-shorthand, no-unused-vars, one-var, one-var-declaration-per-line, no-else-return, comma-dangle, max-len */
/* global Mousetrap */
-/* global findFileURL */
import Cookies from 'js-cookie';
import findAndFollowLink from './shortcuts_dashboard_navigation';
@@ -20,6 +19,7 @@ import findAndFollowLink from './shortcuts_dashboard_navigation';
const $globalDropdownMenu = $('.global-dropdown-menu');
const $globalDropdownToggle = $('.global-dropdown-toggle');
+ const findFileURL = document.body.dataset.findFile;
$('.global-dropdown').on('hide.bs.dropdown', () => {
$globalDropdownMenu.removeClass('shortcuts');
diff --git a/app/assets/javascripts/users/activity_calendar.js b/app/assets/javascripts/users/activity_calendar.js
new file mode 100644
index 00000000000..b7f50cfd083
--- /dev/null
+++ b/app/assets/javascripts/users/activity_calendar.js
@@ -0,0 +1,227 @@
+/* eslint-disable func-names, space-before-function-paren, no-var, wrap-iife, camelcase, vars-on-top, object-shorthand, comma-dangle, eqeqeq, no-mixed-operators, no-return-assign, newline-per-chained-call, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, prefer-template, quotes, no-unused-vars, no-else-return, max-len, class-methods-use-this */
+
+import d3 from 'd3';
+
+export default class ActivityCalendar {
+ constructor(timestamps, calendar_activities_path) {
+ this.calendar_activities_path = calendar_activities_path;
+ this.clickDay = this.clickDay.bind(this);
+ this.currentSelectedDate = '';
+ this.daySpace = 1;
+ this.daySize = 15;
+ this.daySizeWithSpace = this.daySize + (this.daySpace * 2);
+ this.monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+ this.months = [];
+ // Loop through the timestamps to create a group of objects
+ // The group of objects will be grouped based on the day of the week they are
+ this.timestampsTmp = [];
+ var group = 0;
+
+ var today = new Date();
+ today.setHours(0, 0, 0, 0, 0);
+
+ var oneYearAgo = new Date(today);
+ oneYearAgo.setFullYear(today.getFullYear() - 1);
+
+ var days = gl.utils.getDayDifference(oneYearAgo, today);
+
+ for (var i = 0; i <= days; i += 1) {
+ var date = new Date(oneYearAgo);
+ date.setDate(date.getDate() + i);
+
+ var day = date.getDay();
+ var count = timestamps[date.format('yyyy-mm-dd')];
+
+ // Create a new group array if this is the first day of the week
+ // or if is first object
+ if ((day === 0 && i !== 0) || i === 0) {
+ this.timestampsTmp.push([]);
+ group += 1;
+ }
+
+ var innerArray = this.timestampsTmp[group - 1];
+ // Push to the inner array the values that will be used to render map
+ innerArray.push({
+ count: count || 0,
+ date: date,
+ day: day
+ });
+ }
+
+ // Init color functions
+ this.colorKey = this.initColorKey();
+ this.color = this.initColor();
+ // Init the svg element
+ this.renderSvg(group);
+ this.renderDays();
+ this.renderMonths();
+ this.renderDayTitles();
+ this.renderKey();
+ this.initTooltips();
+ }
+
+ // Add extra padding for the last month label if it is also the last column
+ getExtraWidthPadding(group) {
+ var extraWidthPadding = 0;
+ var lastColMonth = this.timestampsTmp[group - 1][0].date.getMonth();
+ var secondLastColMonth = this.timestampsTmp[group - 2][0].date.getMonth();
+
+ if (lastColMonth != secondLastColMonth) {
+ extraWidthPadding = 3;
+ }
+
+ return extraWidthPadding;
+ }
+
+ renderSvg(group) {
+ var width = (group + 1) * this.daySizeWithSpace + this.getExtraWidthPadding(group);
+ return this.svg = d3.select('.js-contrib-calendar').append('svg').attr('width', width).attr('height', 167).attr('class', 'contrib-calendar');
+ }
+
+ renderDays() {
+ return this.svg.selectAll('g').data(this.timestampsTmp).enter().append('g').attr('transform', (function(_this) {
+ return function(group, i) {
+ _.each(group, function(stamp, a) {
+ var lastMonth, lastMonthX, month, x;
+ if (a === 0 && stamp.day === 0) {
+ month = stamp.date.getMonth();
+ x = (_this.daySizeWithSpace * i + 1) + _this.daySizeWithSpace;
+ lastMonth = _.last(_this.months);
+ if (lastMonth != null) {
+ lastMonthX = lastMonth.x;
+ }
+ if (lastMonth == null) {
+ return _this.months.push({
+ month: month,
+ x: x
+ });
+ } else if (month !== lastMonth.month && x - _this.daySizeWithSpace !== lastMonthX) {
+ return _this.months.push({
+ month: month,
+ x: x
+ });
+ }
+ }
+ });
+ return "translate(" + ((_this.daySizeWithSpace * i + 1) + _this.daySizeWithSpace) + ", 18)";
+ };
+ })(this)).selectAll('rect').data(function(stamp) {
+ return stamp;
+ }).enter().append('rect').attr('x', '0').attr('y', (function(_this) {
+ return function(stamp, i) {
+ return _this.daySizeWithSpace * stamp.day;
+ };
+ })(this)).attr('width', this.daySize).attr('height', this.daySize).attr('title', (function(_this) {
+ return function(stamp) {
+ var contribText, date, dateText;
+ date = new Date(stamp.date);
+ contribText = 'No contributions';
+ if (stamp.count > 0) {
+ contribText = stamp.count + " contribution" + (stamp.count > 1 ? 's' : '');
+ }
+ dateText = date.format('mmm d, yyyy');
+ return contribText + "<br />" + (gl.utils.getDayName(date)) + " " + dateText;
+ };
+ })(this)).attr('class', 'user-contrib-cell js-tooltip').attr('fill', (function(_this) {
+ return function(stamp) {
+ if (stamp.count !== 0) {
+ return _this.color(Math.min(stamp.count, 40));
+ } else {
+ return '#ededed';
+ }
+ };
+ })(this)).attr('data-container', 'body').on('click', this.clickDay);
+ }
+
+ renderDayTitles() {
+ var days;
+ days = [
+ {
+ text: 'M',
+ y: 29 + (this.daySizeWithSpace * 1)
+ }, {
+ text: 'W',
+ y: 29 + (this.daySizeWithSpace * 3)
+ }, {
+ text: 'F',
+ y: 29 + (this.daySizeWithSpace * 5)
+ }
+ ];
+ return this.svg.append('g').selectAll('text').data(days).enter().append('text').attr('text-anchor', 'middle').attr('x', 8).attr('y', function(day) {
+ return day.y;
+ }).text(function(day) {
+ return day.text;
+ }).attr('class', 'user-contrib-text');
+ }
+
+ renderMonths() {
+ return this.svg.append('g').attr('direction', 'ltr').selectAll('text').data(this.months).enter().append('text').attr('x', function(date) {
+ return date.x;
+ }).attr('y', 10).attr('class', 'user-contrib-text').text((function(_this) {
+ return function(date) {
+ return _this.monthNames[date.month];
+ };
+ })(this));
+ }
+
+ renderKey() {
+ const keyValues = ['no contributions', '1-9 contributions', '10-19 contributions', '20-29 contributions', '30+ contributions'];
+ const keyColors = ['#ededed', this.colorKey(0), this.colorKey(1), this.colorKey(2), this.colorKey(3)];
+
+ this.svg.append('g')
+ .attr('transform', `translate(18, ${this.daySizeWithSpace * 8 + 16})`)
+ .selectAll('rect')
+ .data(keyColors)
+ .enter()
+ .append('rect')
+ .attr('width', this.daySize)
+ .attr('height', this.daySize)
+ .attr('x', (color, i) => this.daySizeWithSpace * i)
+ .attr('y', 0)
+ .attr('fill', color => color)
+ .attr('class', 'js-tooltip')
+ .attr('title', (color, i) => keyValues[i])
+ .attr('data-container', 'body');
+ }
+
+ initColor() {
+ var colorRange;
+ colorRange = ['#ededed', this.colorKey(0), this.colorKey(1), this.colorKey(2), this.colorKey(3)];
+ return d3.scale.threshold().domain([0, 10, 20, 30]).range(colorRange);
+ }
+
+ initColorKey() {
+ return d3.scale.linear().range(['#acd5f2', '#254e77']).domain([0, 3]);
+ }
+
+ clickDay(stamp) {
+ var formatted_date;
+ if (this.currentSelectedDate !== stamp.date) {
+ this.currentSelectedDate = stamp.date;
+ formatted_date = this.currentSelectedDate.getFullYear() + "-" + (this.currentSelectedDate.getMonth() + 1) + "-" + this.currentSelectedDate.getDate();
+ return $.ajax({
+ url: this.calendar_activities_path,
+ data: {
+ date: formatted_date
+ },
+ cache: false,
+ dataType: 'html',
+ beforeSend: function() {
+ return $('.user-calendar-activities').html('<div class="text-center"><i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i></div>');
+ },
+ success: function(data) {
+ return $('.user-calendar-activities').html(data);
+ }
+ });
+ } else {
+ this.currentSelectedDate = '';
+ return $('.user-calendar-activities').html('');
+ }
+ }
+
+ initTooltips() {
+ return $('.js-contrib-calendar .js-tooltip').tooltip({
+ html: true
+ });
+ }
+}
diff --git a/app/assets/javascripts/users/calendar.js b/app/assets/javascripts/users/calendar.js
deleted file mode 100644
index b11f691e424..00000000000
--- a/app/assets/javascripts/users/calendar.js
+++ /dev/null
@@ -1,231 +0,0 @@
-/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, camelcase, vars-on-top, object-shorthand, comma-dangle, eqeqeq, no-mixed-operators, no-return-assign, newline-per-chained-call, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, prefer-template, quotes, no-unused-vars, no-else-return, max-len */
-
-import d3 from 'd3';
-
-(function() {
- this.Calendar = (function() {
- function Calendar(timestamps, calendar_activities_path) {
- this.calendar_activities_path = calendar_activities_path;
- this.clickDay = this.clickDay.bind(this);
- this.currentSelectedDate = '';
- this.daySpace = 1;
- this.daySize = 15;
- this.daySizeWithSpace = this.daySize + (this.daySpace * 2);
- this.monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
- this.months = [];
- // Loop through the timestamps to create a group of objects
- // The group of objects will be grouped based on the day of the week they are
- this.timestampsTmp = [];
- var group = 0;
-
- var today = new Date();
- today.setHours(0, 0, 0, 0, 0);
-
- var oneYearAgo = new Date(today);
- oneYearAgo.setFullYear(today.getFullYear() - 1);
-
- var days = gl.utils.getDayDifference(oneYearAgo, today);
-
- for (var i = 0; i <= days; i += 1) {
- var date = new Date(oneYearAgo);
- date.setDate(date.getDate() + i);
-
- var day = date.getDay();
- var count = timestamps[date.format('yyyy-mm-dd')];
-
- // Create a new group array if this is the first day of the week
- // or if is first object
- if ((day === 0 && i !== 0) || i === 0) {
- this.timestampsTmp.push([]);
- group += 1;
- }
-
- var innerArray = this.timestampsTmp[group - 1];
- // Push to the inner array the values that will be used to render map
- innerArray.push({
- count: count || 0,
- date: date,
- day: day
- });
- }
-
- // Init color functions
- this.colorKey = this.initColorKey();
- this.color = this.initColor();
- // Init the svg element
- this.renderSvg(group);
- this.renderDays();
- this.renderMonths();
- this.renderDayTitles();
- this.renderKey();
- this.initTooltips();
- }
-
- // Add extra padding for the last month label if it is also the last column
- Calendar.prototype.getExtraWidthPadding = function(group) {
- var extraWidthPadding = 0;
- var lastColMonth = this.timestampsTmp[group - 1][0].date.getMonth();
- var secondLastColMonth = this.timestampsTmp[group - 2][0].date.getMonth();
-
- if (lastColMonth != secondLastColMonth) {
- extraWidthPadding = 3;
- }
-
- return extraWidthPadding;
- };
-
- Calendar.prototype.renderSvg = function(group) {
- var width = (group + 1) * this.daySizeWithSpace + this.getExtraWidthPadding(group);
- return this.svg = d3.select('.js-contrib-calendar').append('svg').attr('width', width).attr('height', 167).attr('class', 'contrib-calendar');
- };
-
- Calendar.prototype.renderDays = function() {
- return this.svg.selectAll('g').data(this.timestampsTmp).enter().append('g').attr('transform', (function(_this) {
- return function(group, i) {
- _.each(group, function(stamp, a) {
- var lastMonth, lastMonthX, month, x;
- if (a === 0 && stamp.day === 0) {
- month = stamp.date.getMonth();
- x = (_this.daySizeWithSpace * i + 1) + _this.daySizeWithSpace;
- lastMonth = _.last(_this.months);
- if (lastMonth != null) {
- lastMonthX = lastMonth.x;
- }
- if (lastMonth == null) {
- return _this.months.push({
- month: month,
- x: x
- });
- } else if (month !== lastMonth.month && x - _this.daySizeWithSpace !== lastMonthX) {
- return _this.months.push({
- month: month,
- x: x
- });
- }
- }
- });
- return "translate(" + ((_this.daySizeWithSpace * i + 1) + _this.daySizeWithSpace) + ", 18)";
- };
- })(this)).selectAll('rect').data(function(stamp) {
- return stamp;
- }).enter().append('rect').attr('x', '0').attr('y', (function(_this) {
- return function(stamp, i) {
- return _this.daySizeWithSpace * stamp.day;
- };
- })(this)).attr('width', this.daySize).attr('height', this.daySize).attr('title', (function(_this) {
- return function(stamp) {
- var contribText, date, dateText;
- date = new Date(stamp.date);
- contribText = 'No contributions';
- if (stamp.count > 0) {
- contribText = stamp.count + " contribution" + (stamp.count > 1 ? 's' : '');
- }
- dateText = date.format('mmm d, yyyy');
- return contribText + "<br />" + (gl.utils.getDayName(date)) + " " + dateText;
- };
- })(this)).attr('class', 'user-contrib-cell js-tooltip').attr('fill', (function(_this) {
- return function(stamp) {
- if (stamp.count !== 0) {
- return _this.color(Math.min(stamp.count, 40));
- } else {
- return '#ededed';
- }
- };
- })(this)).attr('data-container', 'body').on('click', this.clickDay);
- };
-
- Calendar.prototype.renderDayTitles = function() {
- var days;
- days = [
- {
- text: 'M',
- y: 29 + (this.daySizeWithSpace * 1)
- }, {
- text: 'W',
- y: 29 + (this.daySizeWithSpace * 3)
- }, {
- text: 'F',
- y: 29 + (this.daySizeWithSpace * 5)
- }
- ];
- return this.svg.append('g').selectAll('text').data(days).enter().append('text').attr('text-anchor', 'middle').attr('x', 8).attr('y', function(day) {
- return day.y;
- }).text(function(day) {
- return day.text;
- }).attr('class', 'user-contrib-text');
- };
-
- Calendar.prototype.renderMonths = function() {
- return this.svg.append('g').attr('direction', 'ltr').selectAll('text').data(this.months).enter().append('text').attr('x', function(date) {
- return date.x;
- }).attr('y', 10).attr('class', 'user-contrib-text').text((function(_this) {
- return function(date) {
- return _this.monthNames[date.month];
- };
- })(this));
- };
-
- Calendar.prototype.renderKey = function() {
- const keyValues = ['no contributions', '1-9 contributions', '10-19 contributions', '20-29 contributions', '30+ contributions'];
- const keyColors = ['#ededed', this.colorKey(0), this.colorKey(1), this.colorKey(2), this.colorKey(3)];
-
- this.svg.append('g')
- .attr('transform', `translate(18, ${this.daySizeWithSpace * 8 + 16})`)
- .selectAll('rect')
- .data(keyColors)
- .enter()
- .append('rect')
- .attr('width', this.daySize)
- .attr('height', this.daySize)
- .attr('x', (color, i) => this.daySizeWithSpace * i)
- .attr('y', 0)
- .attr('fill', color => color)
- .attr('class', 'js-tooltip')
- .attr('title', (color, i) => keyValues[i])
- .attr('data-container', 'body');
- };
-
- Calendar.prototype.initColor = function() {
- var colorRange;
- colorRange = ['#ededed', this.colorKey(0), this.colorKey(1), this.colorKey(2), this.colorKey(3)];
- return d3.scale.threshold().domain([0, 10, 20, 30]).range(colorRange);
- };
-
- Calendar.prototype.initColorKey = function() {
- return d3.scale.linear().range(['#acd5f2', '#254e77']).domain([0, 3]);
- };
-
- Calendar.prototype.clickDay = function(stamp) {
- var formatted_date;
- if (this.currentSelectedDate !== stamp.date) {
- this.currentSelectedDate = stamp.date;
- formatted_date = this.currentSelectedDate.getFullYear() + "-" + (this.currentSelectedDate.getMonth() + 1) + "-" + this.currentSelectedDate.getDate();
- return $.ajax({
- url: this.calendar_activities_path,
- data: {
- date: formatted_date
- },
- cache: false,
- dataType: 'html',
- beforeSend: function() {
- return $('.user-calendar-activities').html('<div class="text-center"><i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i></div>');
- },
- success: function(data) {
- return $('.user-calendar-activities').html(data);
- }
- });
- } else {
- this.currentSelectedDate = '';
- return $('.user-calendar-activities').html('');
- }
- };
-
- Calendar.prototype.initTooltips = function() {
- return $('.js-contrib-calendar .js-tooltip').tooltip({
- html: true
- });
- };
-
- return Calendar;
- })();
-}).call(window);
diff --git a/app/assets/javascripts/users/index.js b/app/assets/javascripts/users/index.js
new file mode 100644
index 00000000000..ecd8e09161e
--- /dev/null
+++ b/app/assets/javascripts/users/index.js
@@ -0,0 +1,7 @@
+import ActivityCalendar from './activity_calendar';
+import User from './user';
+
+// use legacy exports until embedded javascript is refactored
+window.Calendar = ActivityCalendar;
+window.gl = window.gl || {};
+window.gl.User = User;
diff --git a/app/assets/javascripts/user.js b/app/assets/javascripts/users/user.js
index 9ef94ac7616..0b0a3e1afb4 100644
--- a/app/assets/javascripts/user.js
+++ b/app/assets/javascripts/users/user.js
@@ -1,9 +1,9 @@
-/* eslint-disable class-methods-use-this, comma-dangle, arrow-parens, no-param-reassign */
+/* eslint-disable class-methods-use-this */
import Cookies from 'js-cookie';
import UserTabs from './user_tabs';
-class User {
+export default class User {
constructor({ action }) {
this.action = action;
this.placeProfileAvatarsToTop();
@@ -13,25 +13,22 @@ class User {
placeProfileAvatarsToTop() {
$('.profile-groups-avatars').tooltip({
- placement: 'top'
+ placement: 'top',
});
}
initTabs() {
return new UserTabs({
parentEl: '.user-profile',
- action: this.action
+ action: this.action,
});
}
hideProjectLimitMessage() {
- $('.hide-project-limit-message').on('click', e => {
+ $('.hide-project-limit-message').on('click', (e) => {
e.preventDefault();
Cookies.set('hide_project_limit_message', 'false');
$(this).parents('.project-limit-message').remove();
});
}
}
-
-window.gl = window.gl || {};
-window.gl.User = User;
diff --git a/app/assets/javascripts/user_tabs.js b/app/assets/javascripts/users/user_tabs.js
index f8e23c8624d..f8e23c8624d 100644
--- a/app/assets/javascripts/user_tabs.js
+++ b/app/assets/javascripts/users/user_tabs.js
diff --git a/app/assets/javascripts/users/users_bundle.js b/app/assets/javascripts/users/users_bundle.js
deleted file mode 100644
index a38ce4eb25e..00000000000
--- a/app/assets/javascripts/users/users_bundle.js
+++ /dev/null
@@ -1 +0,0 @@
-import './calendar';
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 8eacb7d950d..f89f2f30443 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -187,11 +187,12 @@
@include set-invisible;
display: block;
position: absolute;
- width: 100%;
+ width: auto;
top: 100%;
left: 0;
z-index: 9;
min-width: 240px;
+ max-width: 500px;
margin-top: 2px;
margin-bottom: 0;
font-size: 14px;
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index 0393820dee6..b6fc628c02b 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -244,6 +244,10 @@
}
}
+ .block-last {
+ padding: 16px 0;
+ }
+
.trigger-build-variable {
color: $code-color;
}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 1cc060e4de8..c1bc4c0d675 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -113,6 +113,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:html_emails_enabled,
:koding_enabled,
:koding_url,
+ :password_authentication_enabled,
:plantuml_enabled,
:plantuml_url,
:max_artifacts_size,
@@ -135,7 +136,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:require_two_factor_authentication,
:session_expire_delay,
:sign_in_text,
- :signin_enabled,
:signup_enabled,
:sentry_dsn,
:sentry_enabled,
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index db7edbd619b..43462b13903 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -170,7 +170,7 @@ class ApplicationController < ActionController::Base
end
def check_password_expiration
- if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user?
+ if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && current_user.allow_password_authentication?
return redirect_to new_profile_password_path
end
end
diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb
index a8575e037e4..aa8cf630032 100644
--- a/app/controllers/passwords_controller.rb
+++ b/app/controllers/passwords_controller.rb
@@ -1,6 +1,8 @@
class PasswordsController < Devise::PasswordsController
+ include Gitlab::CurrentSettings
+
before_action :resource_from_email, only: [:create]
- before_action :prevent_ldap_reset, only: [:create]
+ before_action :check_password_authentication_available, only: [:create]
before_action :throttle_reset, only: [:create]
def edit
@@ -25,7 +27,7 @@ class PasswordsController < Devise::PasswordsController
def update
super do |resource|
- if resource.valid? && resource.require_password?
+ if resource.valid? && resource.require_password_creation?
resource.update_attribute(:password_automatically_set, false)
end
end
@@ -38,11 +40,11 @@ class PasswordsController < Devise::PasswordsController
self.resource = resource_class.find_by_email(email)
end
- def prevent_ldap_reset
- return unless resource && resource.ldap_user?
+ def check_password_authentication_available
+ return if current_application_settings.password_authentication_enabled? && (resource.nil? || resource.allow_password_authentication?)
redirect_to after_sending_reset_password_instructions_path_for(resource_name),
- alert: "Cannot reset password for LDAP user."
+ alert: "Password authentication is unavailable."
end
def throttle_reset
diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb
index 10145bae0d3..c423761ab24 100644
--- a/app/controllers/profiles/passwords_controller.rb
+++ b/app/controllers/profiles/passwords_controller.rb
@@ -77,7 +77,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController
end
def authorize_change_password!
- return render_404 if @user.ldap_user?
+ render_404 unless @user.allow_password_authentication?
end
def user_params
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index c9e636fb65e..13f03e7e63e 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -227,7 +227,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issue
return @issue if defined?(@issue)
# The Sortable default scope causes performance issues when used with find_by
- @noteable = @issue ||= @project.issues.find_by!(iid: params[:id])
+ @noteable = @issue ||= @project.issues.where(iid: params[:id]).reorder(nil).take!
return render_404 unless can?(current_user, :read_issue, @issue)
diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb
index da058da795e..f35d53896ba 100644
--- a/app/controllers/projects/merge_requests/creations_controller.rb
+++ b/app/controllers/projects/merge_requests/creations_controller.rb
@@ -107,7 +107,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
@target_project = @merge_request.target_project
@source_project = @merge_request.source_project
- @commits = @merge_request.compare_commits.reverse
+ @commits = @merge_request.commits
@commit = @merge_request.diff_head_commit
@note_counts = Note.where(commit_id: @commits.map(&:id))
diff --git a/app/controllers/projects/triggers_controller.rb b/app/controllers/projects/triggers_controller.rb
index a5b17fa65ea..e04145dd0b3 100644
--- a/app/controllers/projects/triggers_controller.rb
+++ b/app/controllers/projects/triggers_controller.rb
@@ -69,8 +69,7 @@ class Projects::TriggersController < Projects::ApplicationController
def trigger_params
params.require(:trigger).permit(
- :description,
- trigger_schedule_attributes: [:id, :active, :cron, :cron_timezone, :ref]
+ :description
)
end
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index f39441a281e..e0e72170d1e 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -58,7 +58,7 @@ class SessionsController < Devise::SessionsController
user = User.admins.last
- return unless user && user.require_password?
+ return unless user && user.require_password_creation?
Users::UpdateService.new(user).execute do |user|
@token = user.generate_reset_token
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 45b10f61f33..29b88c60dab 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -1,7 +1,7 @@
module ApplicationSettingsHelper
delegate :gravatar_enabled?,
:signup_enabled?,
- :signin_enabled?,
+ :password_authentication_enabled?,
:akismet_enabled?,
:koding_enabled?,
to: :current_application_settings
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index ba84dbe4a7a..bf9ad95b7c2 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -50,12 +50,12 @@ module ButtonHelper
def http_clone_button(project, placement = 'right', append_link: true)
klass = 'http-selector'
- klass << ' has-tooltip' if current_user.try(:require_password?) || current_user.try(:require_personal_access_token?)
+ klass << ' has-tooltip' if current_user.try(:require_password_creation?) || current_user.try(:require_personal_access_token_creation_for_git_auth?)
protocol = gitlab_config.protocol.upcase
tooltip_title =
- if current_user.try(:require_password?)
+ if current_user.try(:require_password_creation?)
_("Set a password on your account to pull or push via %{protocol}.") % { protocol: protocol }
else
_("Create a personal access token on your account to pull or push via %{protocol}.") % { protocol: protocol }
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 25969adb649..26d11f9ab46 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -214,11 +214,11 @@ module ProjectsHelper
def show_no_password_message?
cookies[:hide_no_password_message].blank? && !current_user.hide_no_password &&
- ( current_user.require_password? || current_user.require_personal_access_token? )
+ ( current_user.require_password_creation? || current_user.require_personal_access_token_creation_for_git_auth? )
end
def link_to_set_password
- if current_user.require_password?
+ if current_user.require_password_creation?
link_to s_('SetPasswordToCloneLink|set a password'), edit_profile_password_path
else
link_to s_('CreateTokenToCloneLink|create a personal access token'), profile_personal_access_tokens_path
@@ -518,4 +518,12 @@ module ProjectsHelper
current_application_settings.restricted_visibility_levels || []
end
+
+ def find_file_path
+ return unless @project && !@project.empty_repo?
+
+ ref = @ref || @project.repository.root_ref
+
+ project_find_file_path(@project, ref)
+ end
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 98e3906a932..898ce45f60e 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -237,6 +237,7 @@ class ApplicationSetting < ActiveRecord::Base
koding_url: nil,
max_artifacts_size: Settings.artifacts['max_size'],
max_attachment_size: Settings.gitlab['max_attachment_size'],
+ password_authentication_enabled: Settings.gitlab['password_authentication_enabled'],
performance_bar_allowed_group_id: nil,
plantuml_enabled: false,
plantuml_url: nil,
@@ -251,7 +252,6 @@ class ApplicationSetting < ActiveRecord::Base
shared_runners_text: nil,
sidekiq_throttling_enabled: false,
sign_in_text: nil,
- signin_enabled: Settings.gitlab['signin_enabled'],
signup_enabled: Settings.gitlab['signup_enabled'],
terminal_max_session_time: 0,
two_factor_grace_period: 48,
diff --git a/app/models/concerns/sortable.rb b/app/models/concerns/sortable.rb
index fdacfa5a194..a155a064032 100644
--- a/app/models/concerns/sortable.rb
+++ b/app/models/concerns/sortable.rb
@@ -5,25 +5,6 @@
module Sortable
extend ActiveSupport::Concern
- module DropDefaultScopeOnFinders
- # Override these methods to drop the `ORDER BY id DESC` default scope.
- # See http://dba.stackexchange.com/a/110919 for why we do this.
- %i[find find_by find_by!].each do |meth|
- define_method meth do |*args, &block|
- return super(*args, &block) if block
-
- unordered_relation = unscope(:order)
-
- # We cannot simply call `meth` on `unscope(:order)`, since that is also
- # an instance of the same relation class this module is included into,
- # which means we'd get infinite recursion.
- # We explicitly use the original implementation to prevent this.
- original_impl = method(__method__).super_method.unbind
- original_impl.bind(unordered_relation).call(*args)
- end
- end
- end
-
included do
# By default all models should be ordered
# by created_at field starting from newest
@@ -37,10 +18,6 @@ module Sortable
scope :order_updated_asc, -> { reorder(updated_at: :asc) }
scope :order_name_asc, -> { reorder(name: :asc) }
scope :order_name_desc, -> { reorder(name: :desc) }
-
- # All queries (relations) on this model are instances of this `relation_klass`.
- relation_klass = relation_delegate_class(ActiveRecord::Relation)
- relation_klass.prepend DropDefaultScopeOnFinders
end
module ClassMethods
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 815c5b43406..e4e7999d0f2 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -32,9 +32,6 @@ class MergeRequest < ActiveRecord::Base
after_create :ensure_merge_request_diff, unless: :importing?
after_update :reload_diff_if_branch_changed
- delegate :commits, :real_size, :commit_shas, :commits_count,
- to: :merge_request_diff, prefix: nil
-
# When this attribute is true some MR validation is ignored
# It allows us to close or modify broken merge requests
attr_accessor :allow_broken
@@ -224,6 +221,36 @@ class MergeRequest < ActiveRecord::Base
"#{project.to_reference(from, full: full)}#{reference}"
end
+ def commits
+ if persisted?
+ merge_request_diff.commits
+ elsif compare_commits
+ compare_commits.reverse
+ else
+ []
+ end
+ end
+
+ def commits_count
+ if persisted?
+ merge_request_diff.commits_count
+ elsif compare_commits
+ compare_commits.size
+ else
+ 0
+ end
+ end
+
+ def commit_shas
+ if persisted?
+ merge_request_diff.commit_shas
+ elsif compare_commits
+ compare_commits.reverse.map(&:sha)
+ else
+ []
+ end
+ end
+
def first_commit
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
end
@@ -246,9 +273,7 @@ class MergeRequest < ActiveRecord::Base
def diff_size
# Calling `merge_request_diff.diffs.real_size` will also perform
# highlighting, which we don't need here.
- return real_size if merge_request_diff
-
- diffs.real_size
+ merge_request_diff&.real_size || diffs.real_size
end
def diff_base_commit
diff --git a/app/models/project.rb b/app/models/project.rb
index e9d93cda1c4..0b357d5d003 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -847,7 +847,7 @@ class Project < ActiveRecord::Base
end
def ci_service
- @ci_service ||= ci_services.find_by(active: true)
+ @ci_service ||= ci_services.reorder(nil).find_by(active: true)
end
def deployment_services
@@ -855,7 +855,7 @@ class Project < ActiveRecord::Base
end
def deployment_service
- @deployment_service ||= deployment_services.find_by(active: true)
+ @deployment_service ||= deployment_services.reorder(nil).find_by(active: true)
end
def monitoring_services
@@ -863,7 +863,7 @@ class Project < ActiveRecord::Base
end
def monitoring_service
- @monitoring_service ||= monitoring_services.find_by(active: true)
+ @monitoring_service ||= monitoring_services.reorder(nil).find_by(active: true)
end
def jira_tracker?
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 10b429c707e..8663cf5e602 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -123,6 +123,7 @@ class Repository
commits
end
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/384
def find_commits_by_message(query, ref = nil, path = nil, limit = 1000, offset = 0)
unless exists? && has_visible_content? && query.present?
return []
@@ -610,6 +611,7 @@ class Repository
commit(sha)
end
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/383
def last_commit_id_for_path(sha, path)
key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}"
diff --git a/app/models/user.rb b/app/models/user.rb
index 2d39b1c1c34..dd1a391773a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -580,16 +580,20 @@ class User < ActiveRecord::Base
keys.count == 0 && Gitlab::ProtocolAccess.allowed?('ssh')
end
- def require_password?
- password_automatically_set? && !ldap_user? && current_application_settings.signin_enabled?
+ def require_password_creation?
+ password_automatically_set? && allow_password_authentication?
end
- def require_personal_access_token?
- return false if current_application_settings.signin_enabled? || ldap_user?
+ def require_personal_access_token_creation_for_git_auth?
+ return false if allow_password_authentication? || ldap_user?
PersonalAccessTokensFinder.new(user: self, impersonation: false, state: 'active').execute.none?
end
+ def allow_password_authentication?
+ !ldap_user? && current_application_settings.password_authentication_enabled?
+ end
+
def can_change_username?
gitlab_config.username_changing_enabled
end
diff --git a/app/services/git_operation_service.rb b/app/services/git_operation_service.rb
index 43636fde0be..32925e9c1f2 100644
--- a/app/services/git_operation_service.rb
+++ b/app/services/git_operation_service.rb
@@ -129,6 +129,7 @@ class GitOperationService
end
end
+ # Gitaly note: JV: wait with migrating #update_ref until we know how to migrate its call sites.
def update_ref(ref, newrev, oldrev)
# We use 'git update-ref' because libgit2/rugged currently does not
# offer 'compare and swap' ref updates. Without compare-and-swap we can
diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb
index 71d37797bb4..19189e64acf 100644
--- a/app/services/merge_requests/create_service.rb
+++ b/app/services/merge_requests/create_service.rb
@@ -7,9 +7,8 @@ module MergeRequests
source_project = @project
@project = Project.find(params[:target_project_id]) if params[:target_project_id]
- params[:target_project_id] ||= source_project.id
-
merge_request = MergeRequest.new
+ merge_request.target_project = @project
merge_request.source_project = source_project
merge_request.source_branch = params[:source_branch]
merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch)
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index 7f1e13c7989..26f7c1a473a 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -145,9 +145,9 @@
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
- = f.label :signin_enabled do
- = f.check_box :signin_enabled
- Sign-in enabled
+ = f.label :password_authentication_enabled do
+ = f.check_box :password_authentication_enabled
+ Password authentication enabled
- if omniauth_enabled? && button_based_providers.any?
.form-group
= f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth sign-in sources', class: 'control-label col-sm-2'
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index af87129e49e..dd61dcf2a7b 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -6,15 +6,15 @@
- else
= render 'devise/shared/tabs_normal'
.tab-content
- - if signin_enabled? || ldap_enabled? || crowd_enabled?
+ - if password_authentication_enabled? || ldap_enabled? || crowd_enabled?
= render 'devise/shared/signin_box'
-# Signup only makes sense if you can also sign-in
- - if signin_enabled? && signup_enabled?
+ - if password_authentication_enabled? && signup_enabled?
= render 'devise/shared/signup_box'
-# Show a message if none of the mechanisms above are enabled
- - if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?)
+ - if !password_authentication_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?)
%div
No authentication methods configured.
diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml
index da4769e214e..3b06008febe 100644
--- a/app/views/devise/shared/_signin_box.html.haml
+++ b/app/views/devise/shared/_signin_box.html.haml
@@ -7,12 +7,12 @@
.login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && !crowd_enabled?) }
.login-body
= render 'devise/sessions/new_ldap', server: server
- - if signin_enabled?
+ - if password_authentication_enabled?
.login-box.tab-pane{ id: 'ldap-standard', role: 'tabpanel' }
.login-body
= render 'devise/sessions/new_base'
-- elsif signin_enabled?
+- elsif password_authentication_enabled?
.login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' }
.login-body
= render 'devise/sessions/new_base'
diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml
index dd34600490e..6d0243a325d 100644
--- a/app/views/devise/shared/_tabs_ldap.html.haml
+++ b/app/views/devise/shared/_tabs_ldap.html.haml
@@ -5,9 +5,9 @@
- @ldap_servers.each_with_index do |server, i|
%li{ class: active_when(i.zero? && !crowd_enabled?) }
= link_to server['label'], "##{server['provider_name']}", 'data-toggle' => 'tab'
- - if signin_enabled?
+ - if password_authentication_enabled?
%li
= link_to 'Standard', '#ldap-standard', 'data-toggle' => 'tab'
- - if signin_enabled? && signup_enabled?
+ - if password_authentication_enabled? && signup_enabled?
%li
= link_to 'Register', '#register-pane', 'data-toggle' => 'tab'
diff --git a/app/views/devise/shared/_tabs_normal.html.haml b/app/views/devise/shared/_tabs_normal.html.haml
index c225d800a98..212856c0676 100644
--- a/app/views/devise/shared/_tabs_normal.html.haml
+++ b/app/views/devise/shared/_tabs_normal.html.haml
@@ -1,6 +1,6 @@
%ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist' }
%li.active{ role: 'presentation' }
%a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab' } Sign in
- - if signin_enabled? && signup_enabled?
+ - if password_authentication_enabled? && signup_enabled?
%li{ role: 'presentation' }
%a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab' } Register
diff --git a/app/views/layouts/_broadcast.html.haml b/app/views/layouts/_broadcast.html.haml
index bcd2f03e83c..e2dbdcbb939 100644
--- a/app/views/layouts/_broadcast.html.haml
+++ b/app/views/layouts/_broadcast.html.haml
@@ -1,2 +1,2 @@
-- BroadcastMessage.current.each do |message|
+- BroadcastMessage.current&.each do |message|
= broadcast_message(message)
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 81f83b74826..38b95d11fd4 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -1,7 +1,7 @@
!!! 5
%html{ lang: I18n.locale, class: "#{page_class}" }
= render "layouts/head"
- %body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } }
+ %body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}", find_file: find_file_path } }
= render "layouts/init_auto_complete" if @gfm_form
- if show_new_nav?
= render "layouts/header/new"
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 25acdb700ef..bc3293fd100 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -91,8 +91,3 @@
= yield :header_content
= render 'shared/outdated_browser'
-
-- if @project && !@project.empty_repo?
- - if ref = @ref || @project.repository.root_ref
- :javascript
- var findFileURL = "#{project_find_file_path(@project, ref)}";
diff --git a/app/views/layouts/header/_new.html.haml b/app/views/layouts/header/_new.html.haml
index 5bc15d68631..4697d91724b 100644
--- a/app/views/layouts/header/_new.html.haml
+++ b/app/views/layouts/header/_new.html.haml
@@ -84,8 +84,3 @@
= icon('times', class: 'js-navbar-toggle-left', style: 'display: none;')
= render 'shared/outdated_browser'
-
-- if @project && !@project.empty_repo?
- - if ref = @ref || @project.repository.root_ref
- :javascript
- var findFileURL = "#{project_find_file_path(@project, ref)}";
diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml
index ae1e1361f0f..424905ea890 100644
--- a/app/views/layouts/nav/_profile.html.haml
+++ b/app/views/layouts/nav/_profile.html.haml
@@ -29,7 +29,7 @@
= link_to profile_emails_path, title: 'Emails' do
%span
Emails
- - unless current_user.ldap_user?
+ - if current_user.allow_password_authentication?
= nav_link(controller: :passwords) do
= link_to edit_profile_password_path, title: 'Password' do
%span
diff --git a/app/views/projects/jobs/_sidebar.html.haml b/app/views/projects/jobs/_sidebar.html.haml
index bddb587ddc6..f2db71e8838 100644
--- a/app/views/projects/jobs/_sidebar.html.haml
+++ b/app/views/projects/jobs/_sidebar.html.haml
@@ -11,7 +11,7 @@
#js-details-block-vue
- if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?)
- .block{ class: ("block-first" if !@build.coverage) }
+ .block
.title
Job artifacts
- if @build.artifacts_expired?
@@ -37,7 +37,7 @@
Browse
- if @build.trigger_request
- .build-widget
+ .build-widget.block
%h4.title
Trigger
@@ -55,7 +55,7 @@
.js-build-variable.trigger-build-variable= key
.js-build-value.trigger-build-value= value
- .block
+ %div{ class: (@build.pipeline.stages_count > 1 ? "block" : "block-last") }
%p
Commit
= link_to @build.pipeline.short_sha, project_commit_path(@project, @build.pipeline.sha), class: 'commit-sha link-commit'
@@ -69,7 +69,7 @@
- if @build.pipeline.stages_count > 1
.dropdown.build-dropdown
- .title
+ %div
%span{ class: "ci-status-icon-#{@build.pipeline.status}" }
= ci_icon_for_status(@build.pipeline.status)
Pipeline
diff --git a/app/views/projects/protected_branches/_branches_list.html.haml b/app/views/projects/protected_branches/_branches_list.html.haml
index cf0db943865..5377d745371 100644
--- a/app/views/projects/protected_branches/_branches_list.html.haml
+++ b/app/views/projects/protected_branches/_branches_list.html.haml
@@ -1,28 +1,4 @@
-.panel.panel-default.protected-branches-list
- - if @protected_branches.empty?
- .panel-heading
- %h3.panel-title
- Protected branch (#{@protected_branches.size})
- %p.settings-message.text-center
- There are currently no protected branches, protect a branch with the form above.
- - else
- - can_admin_project = can?(current_user, :admin_project, @project)
+- can_admin_project = can?(current_user, :admin_project, @project)
- %table.table.table-bordered
- %colgroup
- %col{ width: "25%" }
- %col{ width: "30%" }
- %col{ width: "25%" }
- %col{ width: "20%" }
- %thead
- %tr
- %th Protected branch (#{@protected_branches.size})
- %th Last commit
- %th Allowed to merge
- %th Allowed to push
- - if can_admin_project
- %th
- %tbody
- = render partial: 'projects/protected_branches/protected_branch', collection: @protected_branches, locals: { can_admin_project: can_admin_project}
-
- = paginate @protected_branches, theme: 'gitlab'
+= render layout: 'projects/protected_branches/shared/branches_list', locals: { can_admin_project: can_admin_project } do
+ = render partial: 'projects/protected_branches/protected_branch', collection: @protected_branches, locals: { can_admin_project: can_admin_project}
diff --git a/app/views/projects/protected_branches/_create_protected_branch.html.haml b/app/views/projects/protected_branches/_create_protected_branch.html.haml
index 99bc2516366..98d56a3e5c5 100644
--- a/app/views/projects/protected_branches/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/_create_protected_branch.html.haml
@@ -1,41 +1,14 @@
-= form_for [@project.namespace.becomes(Namespace), @project, @protected_branch] do |f|
- .panel.panel-default
- .panel-heading
- %h3.panel-title
- Protect a branch
- .panel-body
- .form-horizontal
- = form_errors(@protected_branch)
- .form-group
- = f.label :name, class: 'col-md-2 text-right' do
- Branch:
- .col-md-10
- = render partial: "projects/protected_branches/dropdown", locals: { f: f }
- .help-block
- = link_to 'Wildcards', help_page_path('user/project/protected_branches', anchor: 'wildcard-protected-branches')
- such as
- %code *-stable
- or
- %code production/*
- are supported
- .form-group
- %label.col-md-2.text-right{ for: 'merge_access_levels_attributes' }
- Allowed to merge:
- .col-md-10
- .merge_access_levels-container
- = dropdown_tag('Select',
- options: { toggle_class: 'js-allowed-to-merge wide',
- dropdown_class: 'dropdown-menu-selectable capitalize-header',
- data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }})
- .form-group
- %label.col-md-2.text-right{ for: 'push_access_levels_attributes' }
- Allowed to push:
- .col-md-10
- .push_access_levels-container
- = dropdown_tag('Select',
- options: { toggle_class: 'js-allowed-to-push wide',
- dropdown_class: 'dropdown-menu-selectable capitalize-header',
- data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes' }})
+- content_for :merge_access_levels do
+ .merge_access_levels-container
+ = dropdown_tag('Select',
+ options: { toggle_class: 'js-allowed-to-merge wide',
+ dropdown_class: 'dropdown-menu-selectable capitalize-header',
+ data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }})
+- content_for :push_access_levels do
+ .push_access_levels-container
+ = dropdown_tag('Select',
+ options: { toggle_class: 'js-allowed-to-push wide',
+ dropdown_class: 'dropdown-menu-selectable capitalize-header',
+ data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes' }})
- .panel-footer
- = f.submit 'Protect', class: 'btn-create btn', disabled: true
+= render 'projects/protected_branches/shared/create_protected_branch'
diff --git a/app/views/projects/protected_branches/_index.html.haml b/app/views/projects/protected_branches/_index.html.haml
index 5d2422bdf54..2f30fe33a97 100644
--- a/app/views/projects/protected_branches/_index.html.haml
+++ b/app/views/projects/protected_branches/_index.html.haml
@@ -1,26 +1,10 @@
-- expanded = Rails.env.test?
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('protected_branches')
-%section.settings
- .settings-header
- %h4
- Protected Branches
- %button.btn.js-settings-toggle
- = expanded ? 'Collapse' : 'Expand'
- %p
- Keep stable branches secure and force developers to use merge requests.
- .settings-content.no-animate{ class: ('expanded' if expanded) }
- %p
- By default, protected branches are designed to:
- %ul
- %li prevent their creation, if not already created, from everybody except Masters
- %li prevent pushes from everybody except Masters
- %li prevent <strong>anyone</strong> from force pushing to the branch
- %li prevent <strong>anyone</strong> from deleting the branch
- %p Read more about #{link_to "protected branches", help_page_path("user/project/protected_branches"), class: "underlined-link"} and #{link_to "project permissions", help_page_path("user/permissions"), class: "underlined-link"}.
+- content_for :create_protected_branch do
+ = render 'projects/protected_branches/create_protected_branch'
- - if can? current_user, :admin_project, @project
- = render 'projects/protected_branches/create_protected_branch'
+- content_for :branches_list do
+ = render "projects/protected_branches/branches_list"
- = render "projects/protected_branches/branches_list"
+= render 'projects/protected_branches/shared/index'
diff --git a/app/views/projects/protected_branches/_protected_branch.html.haml b/app/views/projects/protected_branches/_protected_branch.html.haml
index e4dadc42cc0..b12ae995ece 100644
--- a/app/views/projects/protected_branches/_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/_protected_branch.html.haml
@@ -1,22 +1,2 @@
-%tr.js-protected-branch-edit-form{ data: { url: project_protected_branch_path(@project, protected_branch) } }
- %td
- %span.ref-name= protected_branch.name
-
- - if @project.root_ref?(protected_branch.name)
- %span.label.label-info.prepend-left-5 default
- %td
- - if protected_branch.wildcard?
- - matching_branches = protected_branch.matching(repository.branches)
- = link_to pluralize(matching_branches.count, "matching branch"), project_protected_branch_path(@project, protected_branch)
- - else
- - if commit = protected_branch.commit
- = link_to(commit.short_id, project_commit_path(@project, commit.id), class: 'commit-sha')
- = time_ago_with_tooltip(commit.committed_date)
- - else
- (branch was removed from repository)
-
+= render layout: 'projects/protected_branches/shared/protected_branch', locals: { protected_branch: protected_branch } do
= render partial: 'projects/protected_branches/update_protected_branch', locals: { protected_branch: protected_branch }
-
- - if can_admin_project
- %td
- = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: 'btn btn-warning'
diff --git a/app/views/projects/protected_branches/shared/_branches_list.html.haml b/app/views/projects/protected_branches/shared/_branches_list.html.haml
new file mode 100644
index 00000000000..5c00bb6883c
--- /dev/null
+++ b/app/views/projects/protected_branches/shared/_branches_list.html.haml
@@ -0,0 +1,28 @@
+.panel.panel-default.protected-branches-list
+ - if @protected_branches.empty?
+ .panel-heading
+ %h3.panel-title
+ Protected branch (#{@protected_branches.size})
+ %p.settings-message.text-center
+ There are currently no protected branches, protect a branch with the form above.
+ - else
+ %table.table.table-bordered
+ %colgroup
+ %col{ width: "20%" }
+ %col{ width: "20%" }
+ %col{ width: "20%" }
+ %col{ width: "20%" }
+ - if can_admin_project
+ %col
+ %thead
+ %tr
+ %th Protected branch (#{@protected_branches.size})
+ %th Last commit
+ %th Allowed to merge
+ %th Allowed to push
+ - if can_admin_project
+ %th
+ %tbody
+ = yield
+
+ = paginate @protected_branches, theme: 'gitlab'
diff --git a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
new file mode 100644
index 00000000000..b619fa57e05
--- /dev/null
+++ b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
@@ -0,0 +1,33 @@
+= form_for [@project.namespace.becomes(Namespace), @project, @protected_branch] do |f|
+ .panel.panel-default
+ .panel-heading
+ %h3.panel-title
+ Protect a branch
+ .panel-body
+ .form-horizontal
+ = form_errors(@protected_branch)
+ .form-group
+ = f.label :name, class: 'col-md-2 text-right' do
+ Branch:
+ .col-md-10
+ = render partial: "projects/protected_branches/shared/dropdown", locals: { f: f }
+ .help-block
+ = link_to 'Wildcards', help_page_path('user/project/protected_branches', anchor: 'wildcard-protected-branches')
+ such as
+ %code *-stable
+ or
+ %code production/*
+ are supported
+ .form-group
+ %label.col-md-2.text-right{ for: 'merge_access_levels_attributes' }
+ Allowed to merge:
+ .col-md-10
+ = yield :merge_access_levels
+ .form-group
+ %label.col-md-2.text-right{ for: 'push_access_levels_attributes' }
+ Allowed to push:
+ .col-md-10
+ = yield :push_access_levels
+
+ .panel-footer
+ = f.submit 'Protect', class: 'btn-create btn', disabled: true
diff --git a/app/views/projects/protected_branches/_dropdown.html.haml b/app/views/projects/protected_branches/shared/_dropdown.html.haml
index 6e9c473494e..6e9c473494e 100644
--- a/app/views/projects/protected_branches/_dropdown.html.haml
+++ b/app/views/projects/protected_branches/shared/_dropdown.html.haml
diff --git a/app/views/projects/protected_branches/shared/_index.html.haml b/app/views/projects/protected_branches/shared/_index.html.haml
new file mode 100644
index 00000000000..6a47cbdf724
--- /dev/null
+++ b/app/views/projects/protected_branches/shared/_index.html.haml
@@ -0,0 +1,24 @@
+- expanded = Rails.env.test?
+
+%section.settings
+ .settings-header
+ %h4
+ Protected Branches
+ %button.btn.js-settings-toggle
+ = expanded ? 'Collapse' : 'Expand'
+ %p
+ Keep stable branches secure and force developers to use merge requests.
+ .settings-content.no-animate{ class: ('expanded' if expanded) }
+ %p
+ By default, protected branches are designed to:
+ %ul
+ %li prevent their creation, if not already created, from everybody except Masters
+ %li prevent pushes from everybody except Masters
+ %li prevent <strong>anyone</strong> from force pushing to the branch
+ %li prevent <strong>anyone</strong> from deleting the branch
+ %p Read more about #{link_to "protected branches", help_page_path("user/project/protected_branches"), class: "underlined-link"} and #{link_to "project permissions", help_page_path("user/permissions"), class: "underlined-link"}.
+
+ - if can? current_user, :admin_project, @project
+ = content_for :create_protected_branch
+
+ = content_for :branches_list
diff --git a/app/views/projects/protected_branches/_matching_branch.html.haml b/app/views/projects/protected_branches/shared/_matching_branch.html.haml
index 98793d632e6..98793d632e6 100644
--- a/app/views/projects/protected_branches/_matching_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_matching_branch.html.haml
diff --git a/app/views/projects/protected_branches/shared/_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_protected_branch.html.haml
new file mode 100644
index 00000000000..10b81e42572
--- /dev/null
+++ b/app/views/projects/protected_branches/shared/_protected_branch.html.haml
@@ -0,0 +1,24 @@
+- can_admin_project = can?(current_user, :admin_project, @project)
+
+%tr.js-protected-branch-edit-form{ data: { url: namespace_project_protected_branch_path(@project.namespace, @project, protected_branch) } }
+ %td
+ %span.ref-name= protected_branch.name
+
+ - if @project.root_ref?(protected_branch.name)
+ %span.label.label-info.prepend-left-5 default
+ %td
+ - if protected_branch.wildcard?
+ - matching_branches = protected_branch.matching(repository.branches)
+ = link_to pluralize(matching_branches.count, "matching branch"), namespace_project_protected_branch_path(@project.namespace, @project, protected_branch)
+ - else
+ - if commit = protected_branch.commit
+ = link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit-sha')
+ = time_ago_with_tooltip(commit.committed_date)
+ - else
+ (branch was removed from repository)
+
+ = yield
+
+ - if can_admin_project
+ %td
+ = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: 'btn btn-warning'
diff --git a/app/views/projects/protected_branches/show.html.haml b/app/views/projects/protected_branches/show.html.haml
index a806a0756ec..1012ceefe93 100644
--- a/app/views/projects/protected_branches/show.html.haml
+++ b/app/views/projects/protected_branches/show.html.haml
@@ -19,7 +19,7 @@
%th Last commit
%tbody
- @matching_refs.each do |matching_branch|
- = render partial: "matching_branch", object: matching_branch
+ = render partial: "projects/protected_branches/shared/matching_branch", object: matching_branch
- else
%p.settings-message.text-center
Couldn't find any matching branches.
diff --git a/app/views/projects/protected_tags/_create_protected_tag.html.haml b/app/views/projects/protected_tags/_create_protected_tag.html.haml
index dd5b346d922..ea91e8af70e 100644
--- a/app/views/projects/protected_tags/_create_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/_create_protected_tag.html.haml
@@ -1,32 +1,8 @@
-= form_for [@project.namespace.becomes(Namespace), @project, @protected_tag], html: { class: 'new-protected-tag js-new-protected-tag' } do |f|
- .panel.panel-default
- .panel-heading
- %h3.panel-title
- Protect a tag
- .panel-body
- .form-horizontal
- = form_errors(@protected_tag)
- .form-group
- = f.label :name, class: 'col-md-2 text-right' do
- Tag:
- .col-md-10.protected-tags-dropdown
- = render partial: "projects/protected_tags/dropdown", locals: { f: f }
- .help-block
- = link_to 'Wildcards', help_page_path('user/project/protected_tags', anchor: 'wildcard-protected-tags')
- such as
- %code v*
- or
- %code *-release
- are supported
- .form-group
- %label.col-md-2.text-right{ for: 'create_access_levels_attributes' }
- Allowed to create:
- .col-md-10
- .create_access_levels-container
- = dropdown_tag('Select',
- options: { toggle_class: 'js-allowed-to-create wide',
- dropdown_class: 'dropdown-menu-selectable',
- data: { field_name: 'protected_tag[create_access_levels_attributes][0][access_level]', input_id: 'create_access_levels_attributes' }})
+- content_for :create_access_levels do
+ .create_access_levels-container
+ = dropdown_tag('Select',
+ options: { toggle_class: 'js-allowed-to-create wide',
+ dropdown_class: 'dropdown-menu-selectable',
+ data: { field_name: 'protected_tag[create_access_levels_attributes][0][access_level]', input_id: 'create_access_levels_attributes' }})
- .panel-footer
- = f.submit 'Protect', class: 'btn-create btn', disabled: true
+= render 'projects/protected_tags/shared/create_protected_tag'
diff --git a/app/views/projects/protected_tags/_index.html.haml b/app/views/projects/protected_tags/_index.html.haml
index 8250f692a69..955220562a6 100644
--- a/app/views/projects/protected_tags/_index.html.haml
+++ b/app/views/projects/protected_tags/_index.html.haml
@@ -1,26 +1,10 @@
-- expanded = Rails.env.test?
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('protected_tags')
-%section.settings
- .settings-header
- %h4
- Protected Tags
- %button.btn.js-settings-toggle
- = expanded ? 'Collapse' : 'Expand'
- %p
- Limit access to creating and updating tags.
- .settings-content.no-animate{ class: ('expanded' if expanded) }
- %p
- By default, protected tags are designed to:
- %ul
- %li Prevent tag creation by everybody except Masters
- %li Prevent <strong>anyone</strong> from updating the tag
- %li Prevent <strong>anyone</strong> from deleting the tag
+- content_for :create_protected_tag do
+ = render 'projects/protected_tags/create_protected_tag'
- %p Read more about #{link_to "protected tags", help_page_path("user/project/protected_tags"), class: "underlined-link"}.
+- content_for :tag_list do
+ = render "projects/protected_tags/tags_list"
- - if can? current_user, :admin_project, @project
- = render 'projects/protected_tags/create_protected_tag'
-
- = render "projects/protected_tags/tags_list"
+= render 'projects/protected_tags/shared/index'
diff --git a/app/views/projects/protected_tags/_protected_tag.html.haml b/app/views/projects/protected_tags/_protected_tag.html.haml
index 5162da5e429..da1f97c8d6a 100644
--- a/app/views/projects/protected_tags/_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/_protected_tag.html.haml
@@ -1,22 +1,2 @@
-%tr.js-protected-tag-edit-form{ data: { url: project_protected_tag_path(@project, protected_tag) } }
- %td
- %span.ref-name= protected_tag.name
-
- - if @project.root_ref?(protected_tag.name)
- %span.label.label-info.prepend-left-5 default
- %td
- - if protected_tag.wildcard?
- - matching_tags = protected_tag.matching(repository.tags)
- = link_to pluralize(matching_tags.count, "matching tag"), project_protected_tag_path(@project, protected_tag)
- - else
- - if commit = protected_tag.commit
- = link_to(commit.short_id, project_commit_path(@project, commit.id), class: 'commit-sha')
- = time_ago_with_tooltip(commit.committed_date)
- - else
- (tag was removed from repository)
-
+= render layout: 'projects/protected_tags/shared/protected_tag', locals: { protected_tag: protected_tag } do
= render partial: 'projects/protected_tags/update_protected_tag', locals: { protected_tag: protected_tag }
-
- - if can_admin_project
- %td
- = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_tag], data: { confirm: 'Tag will be writable for developers. Are you sure?' }, method: :delete, class: 'btn btn-warning'
diff --git a/app/views/projects/protected_tags/_tags_list.html.haml b/app/views/projects/protected_tags/_tags_list.html.haml
index d432a5c9113..a6b18cc9f8f 100644
--- a/app/views/projects/protected_tags/_tags_list.html.haml
+++ b/app/views/projects/protected_tags/_tags_list.html.haml
@@ -1,30 +1,4 @@
-.panel.panel-default.protected-tags-list
- - if @protected_tags.empty?
- .panel-heading
- %h3.panel-title
- Protected tag (#{@protected_tags.size})
- %p.settings-message.text-center
- There are currently no protected tags, protect a tag with the form above.
- - else
- - can_admin_project = can?(current_user, :admin_project, @project)
+- can_admin_project = can?(current_user, :admin_project, @project)
- %table.table.table-bordered
- %colgroup
- %col{ width: "25%" }
- %col{ width: "25%" }
- %col{ width: "50%" }
- - if can_admin_project
- %col
- %thead
- %tr
- %th Protected tag (#{@protected_tags.size})
- %th Last commit
- %th Allowed to create
- - if can_admin_project
- %th
- %tbody
- %tr
- %td.flash-container{ colspan: 4 }
- = render partial: 'projects/protected_tags/protected_tag', collection: @protected_tags, locals: { can_admin_project: can_admin_project}
-
- = paginate @protected_tags, theme: 'gitlab'
+= render layout: 'projects/protected_tags/shared/tags_list' do
+ = render partial: 'projects/protected_tags/protected_tag', collection: @protected_tags, locals: { can_admin_project: can_admin_project}
diff --git a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
new file mode 100644
index 00000000000..5a53c704fcb
--- /dev/null
+++ b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
@@ -0,0 +1,29 @@
+= form_for [@project.namespace.becomes(Namespace), @project, @protected_tag], html: { class: 'new-protected-tag js-new-protected-tag' } do |f|
+ .panel.panel-default
+ .panel-heading
+ %h3.panel-title
+ Protect a tag
+ .panel-body
+ .form-horizontal
+ = form_errors(@protected_tag)
+ .form-group
+ = f.label :name, class: 'col-md-2 text-right' do
+ Tag:
+ .col-md-10.protected-tags-dropdown
+ = render partial: "projects/protected_tags/shared/dropdown", locals: { f: f }
+ .help-block
+ = link_to 'Wildcards', help_page_path('user/project/protected_tags', anchor: 'wildcard-protected-tags')
+ such as
+ %code v*
+ or
+ %code *-release
+ are supported
+ .form-group
+ %label.col-md-2.text-right{ for: 'create_access_levels_attributes' }
+ Allowed to create:
+ .col-md-10
+ .create_access_levels-container
+ = yield :create_access_levels
+
+ .panel-footer
+ = f.submit 'Protect', class: 'btn-create btn', disabled: true
diff --git a/app/views/projects/protected_tags/_dropdown.html.haml b/app/views/projects/protected_tags/shared/_dropdown.html.haml
index 9b6923210f7..9b6923210f7 100644
--- a/app/views/projects/protected_tags/_dropdown.html.haml
+++ b/app/views/projects/protected_tags/shared/_dropdown.html.haml
diff --git a/app/views/projects/protected_tags/shared/_index.html.haml b/app/views/projects/protected_tags/shared/_index.html.haml
new file mode 100644
index 00000000000..c07bd454ff6
--- /dev/null
+++ b/app/views/projects/protected_tags/shared/_index.html.haml
@@ -0,0 +1,24 @@
+- expanded = Rails.env.test?
+
+%section.settings
+ .settings-header
+ %h4
+ Protected Tags
+ %button.btn.js-settings-toggle
+ = expanded ? 'Collapse' : 'Expand'
+ %p
+ Limit access to creating and updating tags.
+ .settings-content.no-animate{ class: ('expanded' if expanded) }
+ %p
+ By default, protected tags are designed to:
+ %ul
+ %li Prevent tag creation by everybody except Masters
+ %li Prevent <strong>anyone</strong> from updating the tag
+ %li Prevent <strong>anyone</strong> from deleting the tag
+
+ %p Read more about #{link_to "protected tags", help_page_path("user/project/protected_tags"), class: "underlined-link"}.
+
+ - if can? current_user, :admin_project, @project
+ = yield :create_protected_tag
+
+ = yield :tag_list
diff --git a/app/views/projects/protected_tags/_matching_tag.html.haml b/app/views/projects/protected_tags/shared/_matching_tag.html.haml
index 05f102d1ca3..05f102d1ca3 100644
--- a/app/views/projects/protected_tags/_matching_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_matching_tag.html.haml
diff --git a/app/views/projects/protected_tags/shared/_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_protected_tag.html.haml
new file mode 100644
index 00000000000..c778f7b9781
--- /dev/null
+++ b/app/views/projects/protected_tags/shared/_protected_tag.html.haml
@@ -0,0 +1,22 @@
+%tr.js-protected-tag-edit-form{ data: { url: project_protected_tag_path(@project, protected_tag) } }
+ %td
+ %span.ref-name= protected_tag.name
+
+ - if @project.root_ref?(protected_tag.name)
+ %span.label.label-info.prepend-left-5 default
+ %td
+ - if protected_tag.wildcard?
+ - matching_tags = protected_tag.matching(repository.tags)
+ = link_to pluralize(matching_tags.count, "matching tag"), project_protected_tag_path(@project, protected_tag)
+ - else
+ - if commit = protected_tag.commit
+ = link_to(commit.short_id, project_commit_path(@project, commit.id), class: 'commit-sha')
+ = time_ago_with_tooltip(commit.committed_date)
+ - else
+ (tag was removed from repository)
+
+ = yield
+
+ - if can? current_user, :admin_project, @project
+ %td
+ = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_tag], data: { confirm: 'Tag will be writable for developers. Are you sure?' }, method: :delete, class: 'btn btn-warning'
diff --git a/app/views/projects/protected_tags/shared/_tags_list.html.haml b/app/views/projects/protected_tags/shared/_tags_list.html.haml
new file mode 100644
index 00000000000..6e3cd4ada71
--- /dev/null
+++ b/app/views/projects/protected_tags/shared/_tags_list.html.haml
@@ -0,0 +1,30 @@
+.panel.panel-default.protected-tags-list
+ - if @protected_tags.empty?
+ .panel-heading
+ %h3.panel-title
+ Protected tag (#{@protected_tags.size})
+ %p.settings-message.text-center
+ There are currently no protected tags, protect a tag with the form above.
+ - else
+ - can_admin_project = can?(current_user, :admin_project, @project)
+
+ %table.table.table-bordered
+ %colgroup
+ %col{ width: "25%" }
+ %col{ width: "25%" }
+ %col{ width: "50%" }
+ - if can_admin_project
+ %col
+ %thead
+ %tr
+ %th Protected tag (#{@protected_tags.size})
+ %th Last commit
+ %th Allowed to create
+ - if can_admin_project
+ %th
+ %tbody
+ %tr
+ %td.flash-container{ colspan: 4 }
+ = yield
+
+ = paginate @protected_tags, theme: 'gitlab'
diff --git a/app/views/projects/protected_tags/show.html.haml b/app/views/projects/protected_tags/show.html.haml
index 16fc02fe9f4..86629f1753b 100644
--- a/app/views/projects/protected_tags/show.html.haml
+++ b/app/views/projects/protected_tags/show.html.haml
@@ -19,7 +19,7 @@
%th Last commit
%tbody
- @matching_refs.each do |matching_tag|
- = render partial: "matching_tag", object: matching_tag
+ = render partial: "projects/protected_tags/shared/matching_tag", object: matching_tag
- else
%p.settings-message.text-center
Couldn't find any matching tags.
diff --git a/app/views/projects/settings/repository/show.html.haml b/app/views/projects/settings/repository/show.html.haml
index 40ea02abce9..0f20ecf8c69 100644
--- a/app/views/projects/settings/repository/show.html.haml
+++ b/app/views/projects/settings/repository/show.html.haml
@@ -6,6 +6,10 @@
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('deploy_keys')
+-# Protected branches & tags use a lot of nested partials.
+-# The shared parts of the views can be found in the `shared` directory.
+-# Those are used throughout the actual views. These `shared` views are then
+-# reused in EE.
= render "projects/protected_branches/index"
= render "projects/protected_tags/index"
= render @deploy_keys
diff --git a/app/views/shared/_personal_access_tokens_table.html.haml b/app/views/shared/_personal_access_tokens_table.html.haml
index ab7a2db002e..c5e4d6e2871 100644
--- a/app/views/shared/_personal_access_tokens_table.html.haml
+++ b/app/views/shared/_personal_access_tokens_table.html.haml
@@ -39,22 +39,3 @@
- else
.settings-message.text-center
This user has no active #{type} Tokens.
-
-%hr
-
-%h5 Inactive #{type} Tokens (#{inactive_tokens.length})
-- if inactive_tokens.present?
- .table-responsive
- %table.table.inactive-tokens
- %thead
- %tr
- %th Name
- %th Created
- %tbody
- - inactive_tokens.each do |token|
- %tr
- %td= token.name
- %td= token.created_at.to_date.to_s(:medium)
-- else
- .settings-message.text-center
- This user has no inactive #{type} Tokens.
diff --git a/changelogs/unreleased/19629-remove-inactive-tokens-list.yml b/changelogs/unreleased/19629-remove-inactive-tokens-list.yml
new file mode 100644
index 00000000000..414e3d49e29
--- /dev/null
+++ b/changelogs/unreleased/19629-remove-inactive-tokens-list.yml
@@ -0,0 +1,4 @@
+---
+title: Remove Inactive Personal Access Tokens list from Access Tokens page
+merge_request: 12866
+author:
diff --git a/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml
new file mode 100644
index 00000000000..d2bdc631d2a
--- /dev/null
+++ b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml
@@ -0,0 +1,4 @@
+---
+title: Supplement Portuguese Brazil translation of Project Page & Repository Page
+merge_request: 12156
+author: Huang Tao
diff --git a/changelogs/unreleased/35035-sidebar-job-spaces.yml b/changelogs/unreleased/35035-sidebar-job-spaces.yml
new file mode 100644
index 00000000000..a9a0211efd9
--- /dev/null
+++ b/changelogs/unreleased/35035-sidebar-job-spaces.yml
@@ -0,0 +1,4 @@
+---
+title: Fix vertical space in job details sidebar
+merge_request:
+author:
diff --git a/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml b/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml
new file mode 100644
index 00000000000..7d47c60e262
--- /dev/null
+++ b/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml
@@ -0,0 +1,4 @@
+---
+title: Increase width of dropdown menus automatically
+merge_request: 12809
+author: Thomas Wucher
diff --git a/changelogs/unreleased/dm-drop-default-scope-on-sortable-finders.yml b/changelogs/unreleased/dm-drop-default-scope-on-sortable-finders.yml
deleted file mode 100644
index b359a25053a..00000000000
--- a/changelogs/unreleased/dm-drop-default-scope-on-sortable-finders.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve performance of lookups of issues, merge requests etc by dropping unnecessary ORDER BY clause
-merge_request:
-author:
diff --git a/changelogs/unreleased/fixes-for-internal-auth-disabled.yml b/changelogs/unreleased/fixes-for-internal-auth-disabled.yml
new file mode 100644
index 00000000000..188d2770455
--- /dev/null
+++ b/changelogs/unreleased/fixes-for-internal-auth-disabled.yml
@@ -0,0 +1,4 @@
+---
+title: Fixes needed when GitLab sign-in is not enabled
+merge_request: 12491
+author: Robin Bobbitt
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index eb4a1e390a9..ec7ce51b542 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -223,7 +223,7 @@ rescue ArgumentError # no user configured
end
Settings.gitlab['time_zone'] ||= nil
Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil?
-Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil?
+Settings.gitlab['password_authentication_enabled'] ||= true if Settings.gitlab['password_authentication_enabled'].nil?
Settings.gitlab['restricted_visibility_levels'] = Settings.__send__(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing))(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil?
diff --git a/config/initializers/8_metrics.rb b/config/initializers/8_metrics.rb
index 5e34aac6527..c80d28746d6 100644
--- a/config/initializers/8_metrics.rb
+++ b/config/initializers/8_metrics.rb
@@ -174,6 +174,10 @@ if Gitlab::Metrics.enabled?
loc && loc[0].start_with?(models) && method.source =~ regex
end
end
+
+ # Ability is in app/models, is not an ActiveRecord model, but should still
+ # be instrumented.
+ Gitlab::Metrics::Instrumentation.instrument_methods(Ability)
end
Gitlab::Metrics::Instrumentation.configure do |config|
diff --git a/config/webpack.config.js b/config/webpack.config.js
index c3fdca59a86..1113241e402 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -66,7 +66,7 @@ var config = {
stl_viewer: './blob/stl_viewer.js',
terminal: './terminal/terminal_bundle.js',
u2f: ['vendor/u2f'],
- users: './users/users_bundle.js',
+ users: './users/index.js',
raven: './raven/index.js',
vue_merge_request_widget: './vue_merge_request_widget/index.js',
test: './test.js',
diff --git a/db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb b/db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb
new file mode 100644
index 00000000000..858b3bebace
--- /dev/null
+++ b/db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb
@@ -0,0 +1,15 @@
+class RenameApplicationSettingsSigninEnabledToPasswordAuthenticationEnabled < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ rename_column_concurrently :application_settings, :signin_enabled, :password_authentication_enabled
+ end
+
+ def down
+ cleanup_concurrent_column_rename :application_settings, :password_authentication_enabled, :signin_enabled
+ end
+end
diff --git a/db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb b/db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb
new file mode 100644
index 00000000000..52a773ddfee
--- /dev/null
+++ b/db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb
@@ -0,0 +1,15 @@
+class CleanupApplicationSettingsSigninEnabledRename < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :application_settings, :signin_enabled, :password_authentication_enabled
+ end
+
+ def down
+ rename_column_concurrently :application_settings, :password_authentication_enabled, :signin_enabled
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 3dbe52c9c80..5264fc99557 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -41,7 +41,6 @@ ActiveRecord::Schema.define(version: 20170707184244) do
create_table "application_settings", force: :cascade do |t|
t.integer "default_projects_limit"
t.boolean "signup_enabled"
- t.boolean "signin_enabled"
t.boolean "gravatar_enabled"
t.text "sign_in_text"
t.datetime "created_at"
@@ -127,6 +126,7 @@ ActiveRecord::Schema.define(version: 20170707184244) do
t.boolean "help_page_hide_commercial_content", default: false
t.string "help_page_support_url"
t.integer "performance_bar_allowed_group_id"
+ t.boolean "password_authentication_enabled"
end
create_table "audit_events", force: :cascade do |t|
diff --git a/doc/api/settings.md b/doc/api/settings.md
index eefbdda42ce..0b4cc98cea6 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -25,7 +25,7 @@ Example response:
"id" : 1,
"default_branch_protection" : 2,
"restricted_visibility_levels" : [],
- "signin_enabled" : true,
+ "password_authentication_enabled" : true,
"after_sign_out_path" : null,
"max_attachment_size" : 10,
"user_oauth_applications" : true,
@@ -63,7 +63,7 @@ PUT /application/settings
| --------- | ---- | :------: | ----------- |
| `default_projects_limit` | integer | no | Project limit per user. Default is `100000` |
| `signup_enabled` | boolean | no | Enable registration. Default is `true`. |
-| `signin_enabled` | boolean | no | Enable login via a GitLab account. Default is `true`. |
+| `password_authentication_enabled` | boolean | no | Enable authentication via a GitLab account password. Default is `true`. |
| `gravatar_enabled` | boolean | no | Enable Gravatar |
| `sign_in_text` | string | no | Text on login page |
| `home_page_url` | string | no | Redirect to this URL when not logged in |
@@ -102,7 +102,7 @@ Example response:
"id": 1,
"default_projects_limit": 100000,
"signup_enabled": true,
- "signin_enabled": true,
+ "password_authentication_enabled": true,
"gravatar_enabled": true,
"sign_in_text": "",
"created_at": "2015-06-12T15:51:55.432Z",
diff --git a/doc/development/fe_guide/droplab/plugins/input_setter.md b/doc/development/fe_guide/droplab/plugins/input_setter.md
index a549603c20d..94f3c8254a8 100644
--- a/doc/development/fe_guide/droplab/plugins/input_setter.md
+++ b/doc/development/fe_guide/droplab/plugins/input_setter.md
@@ -1,6 +1,6 @@
# InputSetter
-`InputSetter` is a plugin that allows for udating DOM out of the scope of droplab when a list item is clicked.
+`InputSetter` is a plugin that allows for updating DOM out of the scope of droplab when a list item is clicked.
## Usage
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index fdaaa65fa28..42bb5e8619c 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -12,6 +12,56 @@ The `setup` task is a alias for `gitlab:setup`.
This tasks calls `db:reset` to create the database, calls `add_limits_mysql` that adds limits to the database schema in case of a MySQL database and finally it calls `db:seed_fu` to seed the database.
Note: `db:setup` calls `db:seed` but this does nothing.
+### Automation
+
+If you're very sure that you want to **wipe the current database** and refill
+seeds, you could:
+
+``` shell
+echo 'yes' | bundle exec rake setup
+```
+
+To save you from answering `yes` manually.
+
+### Discard stdout
+
+Since the script would print a lot of information, it could be slowing down
+your terminal, and it would generate more than 20G logs if you just redirect
+it to a file. If we don't care about the output, we could just redirect it to
+`/dev/null`:
+
+``` shell
+echo 'yes' | bundle exec rake setup > /dev/null
+```
+
+Note that since you can't see the questions from stdout, you might just want
+to `echo 'yes'` to keep it running. It would still print the errors on stderr
+so no worries about missing errors.
+
+### Notes for MySQL
+
+Since the seeds would contain various UTF-8 characters, such as emojis or so,
+we'll need to make sure that we're using `utf8mb4` for all the encoding
+settings and `utf8mb4_unicode_ci` for collation. Please check
+[MySQL utf8mb4 support](../install/database_mysql.md#mysql-utf8mb4-support)
+
+Make sure that `config/database.yml` has `encoding: utf8mb4`, too.
+
+Next, we'll need to update the schema to make the indices fit:
+
+``` shell
+sed -i 's/limit: 255/limit: 191/g' db/schema.rb
+```
+
+Then run the setup script:
+
+``` shell
+bundle exec rake setup
+```
+
+To make sure that indices still fit. You could find great details in:
+[How to support full Unicode in MySQL databases](https://mathiasbynens.be/notes/mysql-utf8mb4)
+
## Run tests
In order to run the test you can use the following commands:
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 47742a164fc..09a88869063 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -621,7 +621,8 @@ module API
expose :id
expose :default_projects_limit
expose :signup_enabled
- expose :signin_enabled
+ expose :password_authentication_enabled
+ expose :password_authentication_enabled, as: :signin_enabled
expose :gravatar_enabled
expose :sign_in_text
expose :after_sign_up_text
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index ef2c08e902c..465363da582 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -101,7 +101,7 @@ module API
end
get "/broadcast_message" do
- if message = BroadcastMessage.current.last
+ if message = BroadcastMessage.current&.last
present message, with: Entities::BroadcastMessage
else
{}
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index d598f9a62a2..b19095d1252 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -65,6 +65,7 @@ module API
:shared_runners_enabled,
:sidekiq_throttling_enabled,
:sign_in_text,
+ :password_authentication_enabled,
:signin_enabled,
:signup_enabled,
:terminal_max_session_time,
@@ -95,7 +96,9 @@ module API
requires :domain_blacklist, type: String, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com'
end
optional :after_sign_up_text, type: String, desc: 'Text shown after sign up'
- optional :signin_enabled, type: Boolean, desc: 'Flag indicating if sign in is enabled'
+ optional :password_authentication_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled'
+ optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled'
+ mutually_exclusive :password_authentication_enabled, :signin_enabled
optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to setup Two-factor authentication'
given require_two_factor_authentication: ->(val) { val } do
requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication'
@@ -176,6 +179,10 @@ module API
put "application/settings" do
attrs = declared_params(include_missing: false)
+ if attrs.has_key?(:signin_enabled)
+ attrs[:password_authentication_enabled] = attrs.delete(:signin_enabled)
+ end
+
if current_settings.update_attributes(attrs)
present current_settings, with: Entities::ApplicationSetting
else
diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb
index c848f52723b..3759250f7f6 100644
--- a/lib/api/v3/entities.rb
+++ b/lib/api/v3/entities.rb
@@ -161,7 +161,8 @@ module API
expose :id
expose :default_projects_limit
expose :signup_enabled
- expose :signin_enabled
+ expose :password_authentication_enabled
+ expose :password_authentication_enabled, as: :signin_enabled
expose :gravatar_enabled
expose :sign_in_text
expose :after_sign_up_text
diff --git a/lib/api/v3/settings.rb b/lib/api/v3/settings.rb
index 748d6b97d4f..202011cfcbe 100644
--- a/lib/api/v3/settings.rb
+++ b/lib/api/v3/settings.rb
@@ -44,7 +44,9 @@ module API
requires :domain_blacklist, type: String, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com'
end
optional :after_sign_up_text, type: String, desc: 'Text shown after sign up'
- optional :signin_enabled, type: Boolean, desc: 'Flag indicating if sign in is enabled'
+ optional :password_authentication_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled'
+ optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled'
+ mutually_exclusive :password_authentication_enabled, :signin_enabled
optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to setup Two-factor authentication'
given require_two_factor_authentication: ->(val) { val } do
requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication'
@@ -116,7 +118,7 @@ module API
:max_attachment_size, :session_expire_delay, :disabled_oauth_sign_in_sources,
:user_oauth_applications, :user_default_external, :signup_enabled,
:send_user_confirmation_email, :domain_whitelist, :domain_blacklist_enabled,
- :after_sign_up_text, :signin_enabled, :require_two_factor_authentication,
+ :after_sign_up_text, :password_authentication_enabled, :signin_enabled, :require_two_factor_authentication,
:home_page_url, :after_sign_out_path, :sign_in_text, :help_page_text,
:shared_runners_enabled, :max_artifacts_size, :max_pages_size, :container_registry_token_expire_delay,
:metrics_enabled, :sidekiq_throttling_enabled, :recaptcha_enabled,
@@ -126,7 +128,13 @@ module API
:housekeeping_enabled, :terminal_max_session_time
end
put "application/settings" do
- if current_settings.update_attributes(declared_params(include_missing: false))
+ attrs = declared_params(include_missing: false)
+
+ if attrs.has_key?(:signin_enabled)
+ attrs[:password_authentication_enabled] = attrs.delete(:signin_enabled)
+ end
+
+ if current_settings.update_attributes(attrs)
present current_settings, with: Entities::ApplicationSetting
else
render_validation_error!(current_settings)
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index ccb5d886bab..9bed81e7327 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -37,7 +37,7 @@ module Gitlab
rate_limit!(ip, success: result.success?, login: login)
Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor)
- return result if result.success? || current_application_settings.signin_enabled? || Gitlab::LDAP::Config.enabled?
+ return result if result.success? || current_application_settings.password_authentication_enabled? || Gitlab::LDAP::Config.enabled?
# If sign-in is disabled and LDAP is not configured, recommend a
# personal access token on failed auth attempts
@@ -48,6 +48,10 @@ module Gitlab
# Avoid resource intensive login checks if password is not provided
return unless password.present?
+ # Nothing to do here if internal auth is disabled and LDAP is
+ # not configured
+ return unless current_application_settings.password_authentication_enabled? || Gitlab::LDAP::Config.enabled?
+
Gitlab::Auth::UniqueIpsLimiter.limit_user! do
user = User.by_login(login)
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index 8ab3b0498ff..d0f04d25db2 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -38,7 +38,7 @@ module Gitlab
repo = options.delete(:repo)
raise 'Gitlab::Git::Repository is required' unless repo.respond_to?(:log)
- repo.log(options).map { |c| decorate(c) }
+ repo.log(options)
end
# Get single commit
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index bd9993f275d..639f5625d59 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -331,85 +331,10 @@ module Gitlab
# )
#
def log(options)
- default_options = {
- limit: 10,
- offset: 0,
- path: nil,
- follow: false,
- skip_merges: false,
- disable_walk: false,
- after: nil,
- before: nil
- }
-
- options = default_options.merge(options)
- options[:limit] ||= 0
- options[:offset] ||= 0
- actual_ref = options[:ref] || root_ref
- begin
- sha = sha_from_ref(actual_ref)
- rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
- # Return an empty array if the ref wasn't found
- return []
- end
-
- if log_using_shell?(options)
- log_by_shell(sha, options)
- else
- log_by_walk(sha, options)
- end
- end
-
- def log_using_shell?(options)
- options[:path].present? ||
- options[:disable_walk] ||
- options[:skip_merges] ||
- options[:after] ||
- options[:before]
- end
-
- def log_by_walk(sha, options)
- walk_options = {
- show: sha,
- sort: Rugged::SORT_NONE,
- limit: options[:limit],
- offset: options[:offset]
- }
- Rugged::Walker.walk(rugged, walk_options).to_a
- end
-
- def log_by_shell(sha, options)
- limit = options[:limit].to_i
- offset = options[:offset].to_i
- use_follow_flag = options[:follow] && options[:path].present?
-
- # We will perform the offset in Ruby because --follow doesn't play well with --skip.
- # See: https://gitlab.com/gitlab-org/gitlab-ce/issues/3574#note_3040520
- offset_in_ruby = use_follow_flag && options[:offset].present?
- limit += offset if offset_in_ruby
-
- cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} log]
- cmd << "--max-count=#{limit}"
- cmd << '--format=%H'
- cmd << "--skip=#{offset}" unless offset_in_ruby
- cmd << '--follow' if use_follow_flag
- cmd << '--no-merges' if options[:skip_merges]
- cmd << "--after=#{options[:after].iso8601}" if options[:after]
- cmd << "--before=#{options[:before].iso8601}" if options[:before]
- cmd << sha
-
- # :path can be a string or an array of strings
- if options[:path].present?
- cmd << '--'
- cmd += Array(options[:path])
- end
-
- raw_output = IO.popen(cmd) { |io| io.read }
- lines = offset_in_ruby ? raw_output.lines.drop(offset) : raw_output.lines
-
- lines.map! { |c| Rugged::Commit.new(rugged, c.strip) }
+ raw_log(options).map { |c| Commit.decorate(c) }
end
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/382
def count_commits(options)
cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} rev-list]
cmd << "--after=#{options[:after].iso8601}" if options[:after]
@@ -454,7 +379,7 @@ module Gitlab
# Counts the amount of commits between `from` and `to`.
def count_commits_between(from, to)
- commits_between(from, to).size
+ Commit.between(self, from, to).size
end
# Returns the SHA of the most recent common ancestor of +from+ and +to+
@@ -912,6 +837,89 @@ module Gitlab
private
+ def raw_log(options)
+ default_options = {
+ limit: 10,
+ offset: 0,
+ path: nil,
+ follow: false,
+ skip_merges: false,
+ disable_walk: false,
+ after: nil,
+ before: nil
+ }
+
+ options = default_options.merge(options)
+ options[:limit] ||= 0
+ options[:offset] ||= 0
+ actual_ref = options[:ref] || root_ref
+ begin
+ sha = sha_from_ref(actual_ref)
+ rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
+ # Return an empty array if the ref wasn't found
+ return []
+ end
+
+ if log_using_shell?(options)
+ log_by_shell(sha, options)
+ else
+ log_by_walk(sha, options)
+ end
+ end
+
+ def log_using_shell?(options)
+ options[:path].present? ||
+ options[:disable_walk] ||
+ options[:skip_merges] ||
+ options[:after] ||
+ options[:before]
+ end
+
+ def log_by_walk(sha, options)
+ walk_options = {
+ show: sha,
+ sort: Rugged::SORT_NONE,
+ limit: options[:limit],
+ offset: options[:offset]
+ }
+ Rugged::Walker.walk(rugged, walk_options).to_a
+ end
+
+ # Gitaly note: JV: although #log_by_shell shells out to Git I think the
+ # complexity is such that we should migrate it as Ruby before trying to
+ # do it in Go.
+ def log_by_shell(sha, options)
+ limit = options[:limit].to_i
+ offset = options[:offset].to_i
+ use_follow_flag = options[:follow] && options[:path].present?
+
+ # We will perform the offset in Ruby because --follow doesn't play well with --skip.
+ # See: https://gitlab.com/gitlab-org/gitlab-ce/issues/3574#note_3040520
+ offset_in_ruby = use_follow_flag && options[:offset].present?
+ limit += offset if offset_in_ruby
+
+ cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} log]
+ cmd << "--max-count=#{limit}"
+ cmd << '--format=%H'
+ cmd << "--skip=#{offset}" unless offset_in_ruby
+ cmd << '--follow' if use_follow_flag
+ cmd << '--no-merges' if options[:skip_merges]
+ cmd << "--after=#{options[:after].iso8601}" if options[:after]
+ cmd << "--before=#{options[:before].iso8601}" if options[:before]
+ cmd << sha
+
+ # :path can be a string or an array of strings
+ if options[:path].present?
+ cmd << '--'
+ cmd += Array(options[:path])
+ end
+
+ raw_output = IO.popen(cmd) { |io| io.read }
+ lines = offset_in_ruby ? raw_output.lines.drop(offset) : raw_output.lines
+
+ lines.map! { |c| Rugged::Commit.new(rugged, c.strip) }
+ end
+
# We are trying to deprecate this method because it does a lot of work
# but it seems to be used only to look up submodule URL's.
# https://gitlab.com/gitlab-org/gitaly/issues/329
diff --git a/lib/gitlab/git_ref_validator.rb b/lib/gitlab/git_ref_validator.rb
index 0e87ee30c98..a3c6b21a6a1 100644
--- a/lib/gitlab/git_ref_validator.rb
+++ b/lib/gitlab/git_ref_validator.rb
@@ -1,3 +1,5 @@
+# Gitaly note: JV: does not need to be migrated, works without a repo.
+
module Gitlab
module GitRefValidator
extend self
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 0baea092e6a..4366ff336ef 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -1,3 +1,6 @@
+# Gitaly note: JV: two sets of straightforward RPC's. 1 Hard RPC: fork_repository.
+# SSH key operations are not part of Gitaly so will never be migrated.
+
require 'securerandom'
module Gitlab
@@ -68,6 +71,7 @@ module Gitlab
# Ex.
# add_repository("/path/to/storage", "gitlab/gitlab-ci")
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def add_repository(storage, name)
gitlab_shell_fast_execute([gitlab_shell_projects_path,
'add-project', storage, "#{name}.git"])
@@ -81,6 +85,7 @@ module Gitlab
# Ex.
# import_repository("/path/to/storage", "gitlab/gitlab-ci", "https://github.com/randx/six.git")
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def import_repository(storage, name, url)
# Timeout should be less than 900 ideally, to prevent the memory killer
# to silently kill the process without knowing we are timing out here.
@@ -99,6 +104,7 @@ module Gitlab
# Ex.
# fetch_remote("gitlab/gitlab-ci", "upstream")
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def fetch_remote(storage, name, remote, forced: false, no_tags: false)
args = [gitlab_shell_projects_path, 'fetch-remote', storage, "#{name}.git", remote, "#{Gitlab.config.gitlab_shell.git_timeout}"]
args << '--force' if forced
@@ -115,6 +121,7 @@ module Gitlab
# Ex.
# mv_repository("/path/to/storage", "gitlab/gitlab-ci", "randx/gitlab-ci-new")
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def mv_repository(storage, path, new_path)
gitlab_shell_fast_execute([gitlab_shell_projects_path, 'mv-project',
storage, "#{path}.git", "#{new_path}.git"])
@@ -129,6 +136,7 @@ module Gitlab
# Ex.
# fork_repository("/path/to/forked_from/storage", "gitlab/gitlab-ci", "/path/to/forked_to/storage", "randx")
#
+ # Gitaly note: JV: not easy to migrate because this involves two Gitaly servers, not one.
def fork_repository(forked_from_storage, path, forked_to_storage, fork_namespace)
gitlab_shell_fast_execute([gitlab_shell_projects_path, 'fork-project',
forked_from_storage, "#{path}.git", forked_to_storage,
@@ -143,6 +151,7 @@ module Gitlab
# Ex.
# remove_repository("/path/to/storage", "gitlab/gitlab-ci")
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def remove_repository(storage, name)
gitlab_shell_fast_execute([gitlab_shell_projects_path,
'rm-project', storage, "#{name}.git"])
@@ -194,6 +203,7 @@ module Gitlab
# Ex.
# add_namespace("/path/to/storage", "gitlab")
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def add_namespace(storage, name)
path = full_path(storage, name)
FileUtils.mkdir_p(path, mode: 0770) unless exists?(storage, name)
@@ -207,6 +217,7 @@ module Gitlab
# Ex.
# rm_namespace("/path/to/storage", "gitlab")
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def rm_namespace(storage, name)
FileUtils.rm_r(full_path(storage, name), force: true)
end
@@ -216,6 +227,7 @@ module Gitlab
# Ex.
# mv_namespace("/path/to/storage", "gitlab", "gitlabhq")
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def mv_namespace(storage, old_name, new_name)
return false if exists?(storage, new_name) || !exists?(storage, old_name)
@@ -241,6 +253,7 @@ module Gitlab
# exists?(storage, 'gitlab')
# exists?(storage, 'gitlab/cookies.git')
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def exists?(storage, dir_name)
File.exist?(full_path(storage, dir_name))
end
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index fe6d51c36ac..1ea39894bb8 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -1,29 +1,246 @@
# Alexandre Alencar <alexandre.alencar@gmail.com>, 2017. #zanata
# Fabio Beneditto <fabiobeneditto@gmail.com>, 2017. #zanata
# Leandro Nunes dos Santos <leandronunes@gmail.com>, 2017. #zanata
+# Huang Tao <htve@outlook.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-05-04 19:24-0500\n"
+"POT-Creation-Date: 2017-06-15 21:59-0500\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-06-05 03:29-0400\n"
-"Last-Translator: Alexandre Alencar <alexandre.alencar@gmail.com>\n"
+"PO-Revision-Date: 2017-07-05 02:56-0400\n"
+"Last-Translator: Huang Tao <htve@outlook.com>\n"
"Language-Team: Portuguese (Brazil)\n"
"Language: pt-BR\n"
"X-Generator: Zanata 3.9.6\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+msgid "%{commit_author_link} committed %{commit_timeago}"
+msgstr "%{commit_author_link} fez commit %{commit_timeago}"
+
+msgid "About auto deploy"
+msgstr "Sobre a implantação automática"
+
+msgid "Active"
+msgstr "Ativo"
+
+msgid "Activity"
+msgstr "Atividade"
+
+msgid "Add Changelog"
+msgstr "Adicionar registro de mudanças"
+
+msgid "Add Contribution guide"
+msgstr "Adicionar Guia de contribuição"
+
+msgid "Add License"
+msgstr "Adicionar Licença"
+
+msgid "Add an SSH key to your profile to pull or push via SSH."
+msgstr "Adicionar chave SSH ao seu perfil para fazer pull ou push via SSH."
+
+msgid "Add new directory"
+msgstr "Adicionar novo diretório"
+
+msgid "Archived project! Repository is read-only"
+msgstr "Projeto arquivado! O repositório é somente leitura"
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr "Tem certeza que deseja excluir este agendamento de pipeline?"
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr "Para anexar arquivo, arraste e solte ou %{upload_link}"
+
+msgid "Branch"
+msgid_plural "Branches"
+msgstr[0] "Branch"
+msgstr[1] "Branches"
+
+msgid ""
+"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
+"choose a GitLab CI Yaml template and commit your changes. "
+"%{link_to_autodeploy_doc}"
+msgstr ""
+"O branch <strong>%{branch_name}</strong> foi criado. Para configurar a "
+"implantação automática, selecione um modelo de Yaml do GitLab CI e registre "
+"suas mudanças. %{link_to_autodeploy_doc}"
+
+msgid "Branches"
+msgstr "Branches"
+
+msgid "Browse files"
+msgstr "Navegar pelos arquivos"
+
msgid "ByAuthor|by"
msgstr "por"
+msgid "CI configuration"
+msgstr "Configuração da Integração Contínua"
+
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr "Pick para um branch"
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr "Reverter no branch"
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr "Cherry-pick"
+
+msgid "ChangeTypeAction|Revert"
+msgstr "Reverter"
+
+msgid "Changelog"
+msgstr "Registro de mudanças"
+
+msgid "Charts"
+msgstr "Gráficos"
+
+msgid "Cherry-pick this commit"
+msgstr "Cherry-pick esse commit"
+
+msgid "Cherry-pick this merge request"
+msgstr "Cherry-pick esse merge request"
+
+msgid "CiStatusLabel|canceled"
+msgstr "cancelado"
+
+msgid "CiStatusLabel|created"
+msgstr "criado"
+
+msgid "CiStatusLabel|failed"
+msgstr "falhou"
+
+msgid "CiStatusLabel|manual action"
+msgstr "ação manual"
+
+msgid "CiStatusLabel|passed"
+msgstr "passou"
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr "passou com avisos"
+
+msgid "CiStatusLabel|pending"
+msgstr "pendente"
+
+msgid "CiStatusLabel|skipped"
+msgstr "ignorado"
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr "aguardando ação manual"
+
+msgid "CiStatusText|blocked"
+msgstr "bloqueado"
+
+msgid "CiStatusText|canceled"
+msgstr "cancelado"
+
+msgid "CiStatusText|created"
+msgstr "criado"
+
+msgid "CiStatusText|failed"
+msgstr "falhou"
+
+msgid "CiStatusText|manual"
+msgstr "manual"
+
+msgid "CiStatusText|passed"
+msgstr "passou"
+
+msgid "CiStatusText|pending"
+msgstr "pendente"
+
+msgid "CiStatusText|skipped"
+msgstr "ignorado"
+
+msgid "CiStatus|running"
+msgstr "executando"
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "Commit"
msgstr[1] "Commits"
+msgid "Commit message"
+msgstr "Mensagem de commit"
+
+msgid "CommitBoxTitle|Commit"
+msgstr "Commit"
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr "Adicionar %{file_name}"
+
+msgid "Commits"
+msgstr "Commits"
+
+msgid "Commits|History"
+msgstr "Histórico"
+
+msgid "Committed by"
+msgstr "Commit feito por"
+
+msgid "Compare"
+msgstr "Comparar"
+
+msgid "Contribution guide"
+msgstr "Guia de contribuição"
+
+msgid "Contributors"
+msgstr "Contribuidores"
+
+msgid "Copy URL to clipboard"
+msgstr "Copiar URL para área de transferência"
+
+msgid "Copy commit SHA to clipboard"
+msgstr "Copiar SHA do commit para a área de transferência"
+
+msgid "Create New Directory"
+msgstr "Criar Novo Diretório"
+
+msgid "Create directory"
+msgstr "Criar diretório"
+
+msgid "Create empty bare repository"
+msgstr "Criar repositório bruto vazio"
+
+msgid "Create merge request"
+msgstr "Criar merge request"
+
+msgid "Create new..."
+msgstr "Criar novo..."
+
+msgid "CreateNewFork|Fork"
+msgstr "Fork"
+
+msgid "CreateTag|Tag"
+msgstr "Tag"
+
+msgid "Cron Timezone"
+msgstr "Fuso horário do cron"
+
+msgid "Cron syntax"
+msgstr "Sintaxe do cron"
+
+msgid "Custom notification events"
+msgstr "Eventos de notificação personalizados"
+
+msgid ""
+"Custom notification levels are the same as participating levels. With custom "
+"notification levels you will also receive notifications for select events. "
+"To find out more, check out %{notification_link}."
+msgstr ""
+"Níveis de notificação personalizados são equivalentes a níveis de "
+"participação. Com níveis de notificação personalizados você também será "
+"notificado sobre eventos selecionados. Para mais informações, visite "
+"%{notification_link}."
+
+msgid "Cycle Analytics"
+msgstr "Análise de Ciclo"
+
msgid ""
"Cycle Analytics gives an overview of how much time it takes to go from idea "
"to production in your project."
@@ -35,7 +252,7 @@ msgid "CycleAnalyticsStage|Code"
msgstr "Código"
msgid "CycleAnalyticsStage|Issue"
-msgstr "Tarefa"
+msgstr "Issue"
msgid "CycleAnalyticsStage|Plan"
msgstr "Plano"
@@ -52,43 +269,205 @@ msgstr "Homologação"
msgid "CycleAnalyticsStage|Test"
msgstr "Teste"
+msgid "Define a custom pattern with cron syntax"
+msgstr "Defina um padrão personalizado utilizando a sintaxe do cron"
+
+msgid "Delete"
+msgstr "Excluir"
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "Implantação"
msgstr[1] "Implantações"
+msgid "Description"
+msgstr "Descrição"
+
+msgid "Directory name"
+msgstr "Nome do diretório"
+
+msgid "Don't show again"
+msgstr "Não exibir novamente"
+
+msgid "Download"
+msgstr "Baixar"
+
+msgid "Download tar"
+msgstr "Baixar tar"
+
+msgid "Download tar.bz2"
+msgstr "Baixar tar.bz2"
+
+msgid "Download tar.gz"
+msgstr "Baixar tar.gz"
+
+msgid "Download zip"
+msgstr "Baixar zip"
+
+msgid "DownloadArtifacts|Download"
+msgstr "Baixar"
+
+msgid "DownloadCommit|Email Patches"
+msgstr "Email com as mudanças"
+
+msgid "DownloadCommit|Plain Diff"
+msgstr "Arquivo de texto com as mudanças"
+
+msgid "DownloadSource|Download"
+msgstr "Baixar"
+
+msgid "Edit"
+msgstr "Alterar"
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr "Alterar Agendamento do Pipeline %{id}"
+
+msgid "Every day (at 4:00am)"
+msgstr "Todos os dias (às 4:00)"
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr "Todos os meses (no dia primeiro às 4:00)"
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr "Toda semana (domingos às 4:00)"
+
+msgid "Failed to change the owner"
+msgstr "Erro ao alterar o proprietário"
+
+msgid "Failed to remove the pipeline schedule"
+msgstr "Erro ao excluir o agendamento do pipeline"
+
+msgid "Files"
+msgstr "Arquivos"
+
+msgid "Find by path"
+msgstr "Localizar por caminho"
+
+msgid "Find file"
+msgstr "Localizar arquivo"
+
msgid "FirstPushedBy|First"
msgstr "Primeiro"
msgid "FirstPushedBy|pushed by"
msgstr "publicado por"
+msgid "Fork"
+msgid_plural "Forks"
+msgstr[0] "Fork"
+msgstr[1] "Forks"
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr "Forked de"
+
msgid "From issue creation until deploy to production"
-msgstr "Da criação de tarefas até a implantação para a produção"
+msgstr "Da abertura de tarefas até a implantação para a produção"
msgid "From merge request merge until deploy to production"
-msgstr "Da incorporação do merge request até a implantação em produção"
+msgstr ""
+"Da aceitação da solicitação de incorporação até a implantação em produção"
+
+msgid "Go to your fork"
+msgstr "Ir para seu fork"
+
+msgid "GoToYourFork|Fork"
+msgstr "Fork"
+
+msgid "Home"
+msgstr "Início"
+
+msgid "Housekeeping successfully started"
+msgstr "Manutenção iniciada com sucesso"
+
+msgid "Import repository"
+msgstr "Importar repositório"
+
+msgid "Interval Pattern"
+msgstr "Padrão de intervalo"
msgid "Introducing Cycle Analytics"
msgstr "Apresentando a Análise de Ciclo"
+msgid "LFSStatus|Disabled"
+msgstr "Desabilitado"
+
+msgid "LFSStatus|Enabled"
+msgstr "Habilitado"
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "Último %d dia"
msgstr[1] "Últimos %d dias"
+msgid "Last Pipeline"
+msgstr "Último Pipeline"
+
+msgid "Last Update"
+msgstr "Última Atualização"
+
+msgid "Last commit"
+msgstr "Último commit"
+
+msgid "Learn more in the"
+msgstr "Saiba mais em"
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr "documentação de agendamento de pipeline"
+
+msgid "Leave group"
+msgstr "Sair do grupo"
+
+msgid "Leave project"
+msgstr "Sair do projeto"
+
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
-msgstr[0] "Limitado a mostrar %d evento no máximo"
-msgstr[1] "Limitado a mostrar %d eventos no máximo"
+msgstr[0] "Limitado a mostrar %d evento, no máximo"
+msgstr[1] "Limitado a mostrar %d eventos, no máximo"
msgid "Median"
msgstr "Mediana"
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr "adicione uma chave SSH"
+
msgid "New Issue"
msgid_plural "New Issues"
-msgstr[0] "Nova Tarefa"
-msgstr[1] "Novas Tarefas"
+msgstr[0] "Nova Issue"
+msgstr[1] "Novas Issues"
+
+msgid "New Pipeline Schedule"
+msgstr "Novo Agendamento de Pipeline"
+
+msgid "New branch"
+msgstr "Novo branch"
+
+msgid "New directory"
+msgstr "Novo diretório"
+
+msgid "New file"
+msgstr "Novo arquivo"
+
+msgid "New issue"
+msgstr "Nova issue"
+
+msgid "New merge request"
+msgstr "Novo merge request"
+
+msgid "New schedule"
+msgstr "Novo agendamento"
+
+msgid "New snippet"
+msgstr "Novo snippet"
+
+msgid "New tag"
+msgstr "Nova tag"
+
+msgid "No repository"
+msgstr "Nenhum repositório"
+
+msgid "No schedules"
+msgstr "Nenhum agendamento"
msgid "Not available"
msgstr "Não disponível"
@@ -96,29 +475,201 @@ msgstr "Não disponível"
msgid "Not enough data"
msgstr "Dados insuficientes"
+msgid "Notification events"
+msgstr "Eventos de notificação"
+
+msgid "NotificationEvent|Close issue"
+msgstr "Fechar issue"
+
+msgid "NotificationEvent|Close merge request"
+msgstr "Fechar merge request"
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr "Falha no pipeline"
+
+msgid "NotificationEvent|Merge merge request"
+msgstr "Aceitar merge request"
+
+msgid "NotificationEvent|New issue"
+msgstr "Nova issue"
+
+msgid "NotificationEvent|New merge request"
+msgstr "Novo merge request"
+
+msgid "NotificationEvent|New note"
+msgstr "Novo comentário"
+
+msgid "NotificationEvent|Reassign issue"
+msgstr "Reatribuir issue"
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr "Reatribuir merge request"
+
+msgid "NotificationEvent|Reopen issue"
+msgstr "Reabrir issue"
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr "Pipeline bem sucedido"
+
+msgid "NotificationLevel|Custom"
+msgstr "Personalizar"
+
+msgid "NotificationLevel|Disabled"
+msgstr "Desabilitado"
+
+msgid "NotificationLevel|Global"
+msgstr "Global"
+
+msgid "NotificationLevel|On mention"
+msgstr "Quando mencionado"
+
+msgid "NotificationLevel|Participate"
+msgstr "Participar"
+
+msgid "NotificationLevel|Watch"
+msgstr "Observar"
+
+msgid "OfSearchInADropdown|Filter"
+msgstr "Filtrar"
+
msgid "OpenedNDaysAgo|Opened"
msgstr "Aberto"
+msgid "Options"
+msgstr "Opções"
+
+msgid "Owner"
+msgstr "Proprietário"
+
+msgid "Pipeline"
+msgstr "Pipeline"
+
msgid "Pipeline Health"
msgstr "Saúde da Pipeline"
+msgid "Pipeline Schedule"
+msgstr "Agendamento da Pipeline"
+
+msgid "Pipeline Schedules"
+msgstr "Agendamentos da Pipeline"
+
+msgid "PipelineSchedules|Activated"
+msgstr "Ativado"
+
+msgid "PipelineSchedules|Active"
+msgstr "Ativo"
+
+msgid "PipelineSchedules|All"
+msgstr "Todos"
+
+msgid "PipelineSchedules|Inactive"
+msgstr "Inativo"
+
+msgid "PipelineSchedules|Next Run"
+msgstr "Próxima Execução"
+
+msgid "PipelineSchedules|None"
+msgstr "Nenhum"
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr "Digite uma descrição curta para esta pipeline"
+
+msgid "PipelineSchedules|Take ownership"
+msgstr "Tornar-se proprietário"
+
+msgid "PipelineSchedules|Target"
+msgstr "Destino"
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr "Personalizado"
+
+msgid "Pipeline|with stage"
+msgstr "com etapa"
+
+msgid "Pipeline|with stages"
+msgstr "com etapas"
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr "Projeto'%{project_name}' marcado para exclusão."
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr "Projeto '%{project_name}' criado com sucesso."
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr "Projeto '%{project_name}' atualizado com sucesso."
+
+msgid "Project '%{project_name}' will be deleted."
+msgstr "Projeto '%{project_name}' será excluído."
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+"Acesso ao projeto deve ser concedido explicitamente para cada usuário."
+
+msgid "Project export could not be deleted."
+msgstr "A exportação do projeto não pôde ser excluída."
+
+msgid "Project export has been deleted."
+msgstr "Exportação do projeto excluída."
+
+msgid ""
+"Project export link has expired. Please generate a new export from your "
+"project settings."
+msgstr ""
+"O link para a exportação do projeto expirou. Favor gerar uma nova exportação "
+"a partir das configurações do projeto."
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+"Exportação do projeto iniciada. Um link para baixá-la será enviado por email."
+""
+
+msgid "Project home"
+msgstr "Página inicial do projeto"
+
+msgid "ProjectFeature|Disabled"
+msgstr "Desabilitado"
+
+msgid "ProjectFeature|Everyone with access"
+msgstr "Todos que possuem acesso"
+
+msgid "ProjectFeature|Only team members"
+msgstr "Apenas membros do time"
+
+msgid "ProjectFileTree|Name"
+msgstr "Nome"
+
+msgid "ProjectLastActivity|Never"
+msgstr "Nunca"
+
msgid "ProjectLifecycle|Stage"
msgstr "Etapa"
+msgid "ProjectNetworkGraph|Graph"
+msgstr "Árvore"
+
msgid "Read more"
-msgstr "Ler mais"
+msgstr "Leia mais"
+
+msgid "Readme"
+msgstr "Leia-me"
+
+msgid "RefSwitcher|Branches"
+msgstr "Branches"
+
+msgid "RefSwitcher|Tags"
+msgstr "Tags"
msgid "Related Commits"
msgstr "Commits Relacionados"
msgid "Related Deployed Jobs"
-msgstr "Jobs Relacionados Incorporados"
+msgstr "Tarefas Implantadas Relacionadas"
msgid "Related Issues"
-msgstr "Tarefas Relacionadas"
+msgstr "Issues Relacionadas"
msgid "Related Jobs"
-msgstr "Jobs Relacionados"
+msgstr "Tarefas Relacionadas"
msgid "Related Merge Requests"
msgstr "Merge Requests Relacionados"
@@ -126,84 +677,180 @@ msgstr "Merge Requests Relacionados"
msgid "Related Merged Requests"
msgstr "Merge Requests Relacionados"
+msgid "Remind later"
+msgstr "Lembrar mais tarde"
+
+msgid "Remove project"
+msgstr "Remover projeto"
+
+msgid "Request Access"
+msgstr "Solicitar acesso"
+
+msgid "Revert this commit"
+msgstr "Reverter este commit"
+
+msgid "Revert this merge request"
+msgstr "Reverter esse merge request"
+
+msgid "Save pipeline schedule"
+msgstr "Salvar agendamento da pipeline"
+
+msgid "Schedule a new pipeline"
+msgstr "Agendar nova pipeline"
+
+msgid "Scheduling Pipelines"
+msgstr "Agendando pipelines"
+
+msgid "Search branches and tags"
+msgstr "Procurar branch e tags"
+
+msgid "Select Archive Format"
+msgstr "Selecionar Formato do Arquivo"
+
+msgid "Select a timezone"
+msgstr "Selecionar fuso horário"
+
+msgid "Select target branch"
+msgstr "Selecionar branch de destino"
+
+msgid "Set a password on your account to pull or push via %{protocol}"
+msgstr ""
+"Defina uma senha para sua conta para aceitar ou entregar código via "
+"%{protocol}"
+
+msgid "Set up CI"
+msgstr "Configurar CI"
+
+msgid "Set up Koding"
+msgstr "Configurar Koding"
+
+msgid "Set up auto deploy"
+msgstr "Configurar implantação automática"
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr "defina uma senha"
+
msgid "Showing %d event"
msgid_plural "Showing %d events"
msgstr[0] "Mostrando %d evento"
msgstr[1] "Mostrando %d eventos"
+msgid "Source code"
+msgstr "Código-fonte"
+
+msgid "StarProject|Star"
+msgstr "Marcar"
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr "Iniciar um %{new_merge_request} a partir dessas alterações"
+
+msgid "Switch branch/tag"
+msgstr "Trocar branch/tag"
+
+msgid "Tag"
+msgid_plural "Tags"
+msgstr[0] "Tag"
+msgstr[1] "Tags"
+
+msgid "Tags"
+msgstr "Tags"
+
+msgid "Target Branch"
+msgstr "Branch de destino"
+
msgid ""
"The coding stage shows the time from the first commit to creating the merge "
"request. The data will automatically be added here once you create your "
"first merge request."
msgstr ""
-"O estágio de codificação mostra o tempo desde o primeiro commit até a "
-"criação do merge request. \n"
-"Os dados serão automaticamente adicionados aqui uma vez que você tenha "
-"criado seu primeiro merge request."
+"A etapa de codificação mostra o tempo desde a entrega do primeiro commit até "
+"a criação do merge request. Os dados serão automaticamente adicionados aqui "
+"desde o momento de criação do merge request."
msgid "The collection of events added to the data gathered for that stage."
-msgstr ""
-"A coleção de eventos adicionados aos dados coletados para esse estágio."
+msgstr "A coleção de eventos adicionados aos dados coletados para essa etapa."
+
+msgid "The fork relationship has been removed."
+msgstr "O relacionamento como fork foi removido."
msgid ""
"The issue stage shows the time it takes from creating an issue to assigning "
"the issue to a milestone, or add the issue to a list on your Issue Board. "
"Begin creating issues to see data for this stage."
msgstr ""
-"O estágio em questão mostra o tempo que leva desde a criação de uma tarefa "
-"até a sua assinatura para um milestone, ou a sua adição para a lista no seu "
-"Painel de Tarefas. Comece a criar tarefas para ver dados para esta etapa."
+"A etapa de relatos mostra o tempo que leva desde a criação de uma issue até "
+"sua atribuição a um marco, ou sua adição a uma lista no seu Issue Board. "
+"Comece a criar issues para ver dados para esta etapa."
msgid "The phase of the development lifecycle."
msgstr "A fase do ciclo de vida do desenvolvimento."
msgid ""
+"The pipelines schedule runs pipelines in the future, repeatedly, for "
+"specific branches or tags. Those scheduled pipelines will inherit limited "
+"project access based on their associated user."
+msgstr ""
+"O agendamento de pipeline executa pipelines no futuro, repetidamente, para "
+"branches ou tags específicas. Essas pipelines agendadas terão acesso "
+"limitado ao projeto baseado no seu usuário associado."
+
+msgid ""
"The planning stage shows the time from the previous step to pushing your "
"first commit. This time will be added automatically once you push your first "
"commit."
msgstr ""
-"A fase de planejamento mostra o tempo do passo anterior até empurrar o seu "
-"primeiro commit. Este tempo será adicionado automaticamente assim que você "
-"realizar seu primeiro commit."
+"A etapa de planejamento mostra o tempo do passo anterior até a publicação de "
+"seu primeiro conjunto de mudanças. Este tempo será adicionado "
+"automaticamente assim que você enviar seu primeiro conjunto de mudanças."
msgid ""
"The production stage shows the total time it takes between creating an issue "
"and deploying the code to production. The data will be automatically added "
"once you have completed the full idea to production cycle."
msgstr ""
-"O estágio de produção mostra o tempo total que leva entre criar uma tarefa e "
-"implantar o código na produção. Os dados serão adicionados automaticamente "
-"até que você complete todo o ciclo de produção."
+"A etapa de produção mostra o tempo total que leva entre criar uma issue e "
+"implantar o código em produção. Os dados serão adicionados automaticamente "
+"assim que você completar todo o ciclo de produção."
+
+msgid "The project can be accessed by any logged in user."
+msgstr "O projeto pode ser acessado por qualquer usuário autenticado."
+
+msgid "The project can be accessed without any authentication."
+msgstr "O projeto pode ser acessado sem a necessidade de autenticação."
+
+msgid "The repository for this project does not exist."
+msgstr "Não existe repositório para este projeto."
msgid ""
"The review stage shows the time from creating the merge request to merging "
"it. The data will automatically be added after you merge your first merge "
"request."
msgstr ""
-"A etapa de revisão mostra o tempo de criação de um merge request até que o "
-"merge seja feito. Os dados serão automaticamente adicionados depois que você "
-"fizer seu primeiro merge request."
+"A etapa de revisão mostra o tempo de criação de uma solicitação de "
+"incorporação até sua aceitação. Os dados serão automaticamente adicionados "
+"depois que sua primeira solicitação de incorporação for aceita."
msgid ""
"The staging stage shows the time between merging the MR and deploying code "
"to the production environment. The data will be automatically added once you "
"deploy to production for the first time."
msgstr ""
-"O estágio de estágio mostra o tempo entre a fusão do MR e o código de "
-"implantação para o ambiente de produção. Os dados serão automaticamente "
-"adicionados depois de implantar na produção pela primeira vez."
+"A etapa de homologação mostra o tempo entre o aceite da solicitação de "
+"incorporação e a implantação do código no ambiente de produção. Os dados "
+"serão automaticamente adicionados depois que você implantar em produção pela "
+"primeira vez."
msgid ""
"The testing stage shows the time GitLab CI takes to run every pipeline for "
"the related merge request. The data will automatically be added after your "
"first pipeline finishes running."
msgstr ""
-"A fase de teste mostra o tempo que o GitLab CI leva para executar cada "
-"pipeline para o merge request relacionado. Os dados serão automaticamente "
-"adicionados após a conclusão do primeiro pipeline."
+"A etapa de testes mostra o tempo que o GitLab CI leva para executar cada "
+"pipeline para a solicitação de incorporação associada. Os dados serão "
+"automaticamente adicionados após a conclusão do primeiro pipeline."
msgid "The time taken by each data entry gathered by that stage."
-msgstr "O tempo necessário para cada entrada de dados reunida por essa etapa."
+msgstr "O tempo necessário por cada entrada de dados reunida por essa etapa."
msgid ""
"The value lying at the midpoint of a series of observed values. E.g., "
@@ -211,19 +858,151 @@ msgid ""
" 6."
msgstr ""
"O valor situado no ponto médio de uma série de valores observados. Ex., "
-"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5 + 7) / 2 = 6."
+"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6."
+
+msgid ""
+"This means you can not push code until you create an empty repository or "
+"import existing one."
+msgstr ""
+"Isto significa que você não pode entregar código até que crie um repositório "
+"vazio ou importe um existente."
msgid "Time before an issue gets scheduled"
-msgstr "Tempo até que uma tarefa seja planejada"
+msgstr "Tempo até que uma issue seja agendada"
msgid "Time before an issue starts implementation"
-msgstr "Tempo até que uma tarefa comece a ser implementada"
+msgstr "Tempo até que uma issue comece a ser implementado"
msgid "Time between merge request creation and merge/close"
-msgstr "Tempo entre a criação do merge request e o merge/fechamento"
+msgstr ""
+"Tempo entre a criação da solicitação de incorporação e a aceitação/"
+"fechamento"
msgid "Time until first merge request"
-msgstr "Tempo até o primeiro merge request"
+msgstr "Tempo até a primeira solicitação de incorporação"
+
+msgid "Timeago|%s days ago"
+msgstr "há %s dias"
+
+msgid "Timeago|%s days remaining"
+msgstr "%s dias restantes"
+
+msgid "Timeago|%s hours remaining"
+msgstr "%s horas restantes"
+
+msgid "Timeago|%s minutes ago"
+msgstr "há %s minutos"
+
+msgid "Timeago|%s minutes remaining"
+msgstr "%s minutos restantes"
+
+msgid "Timeago|%s months ago"
+msgstr "há %s meses"
+
+msgid "Timeago|%s months remaining"
+msgstr "%s meses restantes"
+
+msgid "Timeago|%s seconds remaining"
+msgstr "%s segundos restantes"
+
+msgid "Timeago|%s weeks ago"
+msgstr "há %s semanas"
+
+msgid "Timeago|%s weeks remaining"
+msgstr "%s semanas restantes"
+
+msgid "Timeago|%s years ago"
+msgstr "há %s anos"
+
+msgid "Timeago|%s years remaining"
+msgstr "%s anos restantes"
+
+msgid "Timeago|1 day remaining"
+msgstr "1 dia restante"
+
+msgid "Timeago|1 hour remaining"
+msgstr "1 hora restante"
+
+msgid "Timeago|1 minute remaining"
+msgstr "1 minuto restante"
+
+msgid "Timeago|1 month remaining"
+msgstr "1 mês restante"
+
+msgid "Timeago|1 week remaining"
+msgstr "1 semana restante"
+
+msgid "Timeago|1 year remaining"
+msgstr "1 ano restante"
+
+msgid "Timeago|Past due"
+msgstr "Venceu"
+
+msgid "Timeago|a day ago"
+msgstr "há um dia"
+
+msgid "Timeago|a month ago"
+msgstr "há um mês"
+
+msgid "Timeago|a week ago"
+msgstr "há uma semana"
+
+msgid "Timeago|a while"
+msgstr "há algum tempo"
+
+msgid "Timeago|a year ago"
+msgstr "há um ano"
+
+msgid "Timeago|about %s hours ago"
+msgstr "há cerca de %s horas"
+
+msgid "Timeago|about a minute ago"
+msgstr "há cerca de um minuto"
+
+msgid "Timeago|about an hour ago"
+msgstr "há cerca de uma hora"
+
+msgid "Timeago|in %s days"
+msgstr "em %s dias"
+
+msgid "Timeago|in %s hours"
+msgstr "em %s horas"
+
+msgid "Timeago|in %s minutes"
+msgstr "em %s minutos"
+
+msgid "Timeago|in %s months"
+msgstr "em %s meses"
+
+msgid "Timeago|in %s seconds"
+msgstr "em %s segundos"
+
+msgid "Timeago|in %s weeks"
+msgstr "em %s semanas"
+
+msgid "Timeago|in %s years"
+msgstr "em %s anos"
+
+msgid "Timeago|in 1 day"
+msgstr "em 1 dia"
+
+msgid "Timeago|in 1 hour"
+msgstr "em 1 hora"
+
+msgid "Timeago|in 1 minute"
+msgstr "em 1 minuto"
+
+msgid "Timeago|in 1 month"
+msgstr "em 1 mês"
+
+msgid "Timeago|in 1 week"
+msgstr "em 1 semana"
+
+msgid "Timeago|in 1 year"
+msgstr "em 1 ano"
+
+msgid "Timeago|less than a minute ago"
+msgstr "há menos de um minuto"
msgid "Time|hr"
msgid_plural "Time|hrs"
@@ -244,20 +1023,119 @@ msgstr "Tempo Total"
msgid "Total test time for all commits/merges"
msgstr "Tempo de teste total para todos os commits/merges"
+msgid "Unstar"
+msgstr "Desmarcar"
+
+msgid "Upload New File"
+msgstr "Enviar Novo Arquivo"
+
+msgid "Upload file"
+msgstr "Enviar arquivo"
+
+msgid "Use your global notification setting"
+msgstr "Utilizar configuração de notificação global"
+
+msgid "VisibilityLevel|Internal"
+msgstr "Interno"
+
+msgid "VisibilityLevel|Private"
+msgstr "Privado"
+
+msgid "VisibilityLevel|Public"
+msgstr "Público"
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Precisa visualizar os dados? Solicite acesso ao administrador."
msgid "We don't have enough data to show this stage."
-msgstr "Não temos dados suficientes para mostrar esta fase."
+msgstr "Esta etapa não possui dados suficientes para exibição."
-msgid "You have reached your project limit"
+msgid "Withdraw Access Request"
+msgstr "Remover Requisição de Acesso"
+
+msgid ""
+"You are going to remove %{project_name_with_namespace}.\n"
+"Removed project CANNOT be restored!\n"
+"Are you ABSOLUTELY sure?"
msgstr ""
+"Você irá remover %{project_name_with_namespace}.\n"
+"O projeto removido NÃO PODE ser restaurado!\n"
+"Tem certeza ABSOLUTA?"
+
+msgid ""
+"You are going to remove the fork relationship to source project "
+"%{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+"Você ira remover o relacionamento de fork com o projeto original "
+"%{forked_from_project}. Tem certeza ABSOLUTA?"
+
+msgid ""
+"You are going to transfer %{project_name_with_namespace} to another owner. "
+"Are you ABSOLUTELY sure?"
+msgstr ""
+"Você irá transferir %{project_name_with_namespace} para outro proprietário. "
+"Tem certeza ABSOLUTA?"
+
+msgid "You can only add files when you are on a branch"
+msgstr "Você somente pode adicionar arquivos quando estiver em um branch"
+
+msgid "You have reached your project limit"
+msgstr "Você atingiu o limite de seu projeto"
+
+msgid "You must sign in to star a project"
+msgstr "Você deve estar autenticado para marcar um projeto"
msgid "You need permission."
msgstr "Você precisa de permissão."
+msgid "You will not get any notifications via email"
+msgstr "Você não será notificado por email"
+
+msgid "You will only receive notifications for the events you choose"
+msgstr "Você será notificado apenas sobre eventos selecionados"
+
+msgid ""
+"You will only receive notifications for threads you have participated in"
+msgstr "Você será notificado apenas sobre tópicos nos quais participou"
+
+msgid "You will receive notifications for any activity"
+msgstr "Você será notificado sobre qualquer atividade"
+
+msgid ""
+"You will receive notifications only for comments in which you were "
+"@mentioned"
+msgstr "Você será notificado apenas sobre comentários que te @mencionam"
+
+msgid ""
+"You won't be able to pull or push project code via %{protocol} until you "
+"%{set_password_link} on your account"
+msgstr ""
+"Você não poderá fazer pull ou push via %{protocol} até que "
+"%{set_password_link} para sua conta"
+
+msgid ""
+"You won't be able to pull or push project code via SSH until you "
+"%{add_ssh_key_link} to your profile"
+msgstr ""
+"Você não conseguirá fazer pull ou push no projeto via SSH até que adicione "
+"%{add_ssh_key_link} ao seu perfil"
+
+msgid "Your name"
+msgstr "Seu nome"
+
msgid "day"
msgid_plural "days"
msgstr[0] "dia"
msgstr[1] "dias"
+msgid "new merge request"
+msgstr "novo merge request"
+
+msgid "notification emails"
+msgstr "emails de notificação"
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] "pai"
+msgstr[1] "pais"
+
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index a2720c9b81e..1641bddea11 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -30,6 +30,15 @@ describe ApplicationController do
expect(controller).not_to receive(:redirect_to)
controller.send(:check_password_expiration)
end
+
+ it 'does not redirect if the user is over their password expiry but sign-in is disabled' do
+ stub_application_setting(password_authentication_enabled: false)
+ user.password_expires_at = Time.new(2002)
+ allow(controller).to receive(:current_user).and_return(user)
+ expect(controller).not_to receive(:redirect_to)
+
+ controller.send(:check_password_expiration)
+ end
end
describe "#authenticate_user_from_token!" do
diff --git a/spec/controllers/passwords_controller_spec.rb b/spec/controllers/passwords_controller_spec.rb
new file mode 100644
index 00000000000..2955d01fad0
--- /dev/null
+++ b/spec/controllers/passwords_controller_spec.rb
@@ -0,0 +1,29 @@
+require 'spec_helper'
+
+describe PasswordsController do
+ describe '#check_password_authentication_available' do
+ before do
+ @request.env["devise.mapping"] = Devise.mappings[:user]
+ end
+
+ context 'when password authentication is disabled' do
+ it 'prevents a password reset' do
+ stub_application_setting(password_authentication_enabled: false)
+
+ post :create
+
+ expect(flash[:alert]).to eq 'Password authentication is unavailable.'
+ end
+ end
+
+ context 'when reset email belongs to an ldap user' do
+ let(:user) { create(:omniauth_user, provider: 'ldapmain', email: 'ldapuser@gitlab.com') }
+
+ it 'prevents a password reset' do
+ post :create, user: { email: user.email }
+
+ expect(flash[:alert]).to eq 'Password authentication is unavailable.'
+ end
+ end
+ end
+end
diff --git a/spec/factories/ci/triggers.rb b/spec/factories/ci/triggers.rb
index c3a29d8bf04..40c4663c6d8 100644
--- a/spec/factories/ci/triggers.rb
+++ b/spec/factories/ci/triggers.rb
@@ -2,13 +2,6 @@ FactoryGirl.define do
factory :ci_trigger_without_token, class: Ci::Trigger do
factory :ci_trigger do
sequence(:token) { |n| "token#{n}" }
-
- factory :ci_trigger_for_trigger_schedule do
- token { SecureRandom.hex(15) }
- owner factory: :user
- project factory: :project
- ref 'master'
- end
end
end
end
diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
index cd7040891e9..d01722805c4 100644
--- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb
+++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
@@ -8,8 +8,8 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do
find(".table.active-tokens")
end
- def inactive_impersonation_tokens
- find(".table.inactive-tokens")
+ def no_personal_access_tokens_message
+ find(".settings-message")
end
before do
@@ -60,15 +60,17 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do
click_on "Revoke"
- expect(inactive_impersonation_tokens).to have_text(impersonation_token.name)
+ expect(page).to have_selector(".settings-message")
+ expect(no_personal_access_tokens_message).to have_text("This user has no active Impersonation Tokens.")
end
- it "moves expired tokens to the 'inactive' section" do
+ it "removes expired tokens from 'active' section" do
impersonation_token.update(expires_at: 5.days.ago)
visit admin_user_impersonation_tokens_path(user_id: user.username)
- expect(inactive_impersonation_tokens).to have_text(impersonation_token.name)
+ expect(page).to have_selector(".settings-message")
+ expect(no_personal_access_tokens_message).to have_text("This user has no active Impersonation Tokens.")
end
end
end
diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb
index 3e01ea69122..5c0909b6a59 100644
--- a/spec/features/merge_requests/conflicts_spec.rb
+++ b/spec/features/merge_requests/conflicts_spec.rb
@@ -4,6 +4,11 @@ feature 'Merge request conflict resolution', js: true, feature: true do
let(:user) { create(:user) }
let(:project) { create(:project) }
+ before do
+ # In order to have the diffs collapsed, we need to disable the increase feature
+ stub_feature_flags(gitlab_git_diff_size_limit_increase: false)
+ end
+
def create_merge_request(source_branch)
create(:merge_request, source_branch: source_branch, target_branch: 'conflict-start', source_project: project) do |mr|
mr.mark_as_unmergeable
diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb
index 67975a68ee2..26d6d6658aa 100644
--- a/spec/features/profiles/password_spec.rb
+++ b/spec/features/profiles/password_spec.rb
@@ -1,44 +1,74 @@
require 'spec_helper'
describe 'Profile > Password', feature: true do
- let(:user) { create(:user, password_automatically_set: true) }
+ context 'Password authentication enabled' do
+ let(:user) { create(:user, password_automatically_set: true) }
- before do
- sign_in(user)
- visit edit_profile_password_path
- end
+ before do
+ sign_in(user)
+ visit edit_profile_password_path
+ end
- def fill_passwords(password, confirmation)
- fill_in 'New password', with: password
- fill_in 'Password confirmation', with: confirmation
+ def fill_passwords(password, confirmation)
+ fill_in 'New password', with: password
+ fill_in 'Password confirmation', with: confirmation
- click_button 'Save password'
- end
+ click_button 'Save password'
+ end
+
+ context 'User with password automatically set' do
+ describe 'User puts different passwords in the field and in the confirmation' do
+ it 'shows an error message' do
+ fill_passwords('mypassword', 'mypassword2')
- context 'User with password automatically set' do
- describe 'User puts different passwords in the field and in the confirmation' do
- it 'shows an error message' do
- fill_passwords('mypassword', 'mypassword2')
+ page.within('.alert-danger') do
+ expect(page).to have_content("Password confirmation doesn't match Password")
+ end
+ end
+
+ it 'does not contain the current password field after an error' do
+ fill_passwords('mypassword', 'mypassword2')
- page.within('.alert-danger') do
- expect(page).to have_content("Password confirmation doesn't match Password")
+ expect(page).to have_no_field('user[current_password]')
end
end
- it 'does not contain the current password field after an error' do
- fill_passwords('mypassword', 'mypassword2')
+ describe 'User puts the same passwords in the field and in the confirmation' do
+ it 'shows a success message' do
+ fill_passwords('mypassword', 'mypassword')
- expect(page).to have_no_field('user[current_password]')
+ page.within('.flash-notice') do
+ expect(page).to have_content('Password was successfully updated. Please login with it')
+ end
+ end
end
end
+ end
- describe 'User puts the same passwords in the field and in the confirmation' do
- it 'shows a success message' do
- fill_passwords('mypassword', 'mypassword')
+ context 'Password authentication unavailable' do
+ before do
+ gitlab_sign_in(user)
+ end
- page.within('.flash-notice') do
- expect(page).to have_content('Password was successfully updated. Please login with it')
- end
+ context 'Regular user' do
+ let(:user) { create(:user) }
+
+ it 'renders 404 when sign-in is disabled' do
+ stub_application_setting(password_authentication_enabled: false)
+
+ visit edit_profile_password_path
+
+ expect(page).to have_http_status(404)
+ end
+ end
+
+ context 'LDAP user' do
+ let(:user) { create(:omniauth_user, provider: 'ldapmain') }
+
+ it 'renders 404' do
+ visit edit_profile_password_path
+
+ expect(page).to have_http_status(404)
end
end
end
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index 44b7ee101c9..3c08b6bc091 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -7,8 +7,8 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do
find(".table.active-tokens")
end
- def inactive_personal_access_tokens
- find(".table.inactive-tokens")
+ def no_personal_access_tokens_message
+ find(".settings-message")
end
def created_personal_access_token
@@ -80,14 +80,16 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do
visit profile_personal_access_tokens_path
click_on "Revoke"
- expect(inactive_personal_access_tokens).to have_text(personal_access_token.name)
+ expect(page).to have_selector(".settings-message")
+ expect(no_personal_access_tokens_message).to have_text("This user has no active Personal Access Tokens.")
end
- it "moves expired tokens to the 'inactive' section" do
+ it "removes expired tokens from 'active' section" do
personal_access_token.update(expires_at: 5.days.ago)
visit profile_personal_access_tokens_path
- expect(inactive_personal_access_tokens).to have_text(personal_access_token.name)
+ expect(page).to have_selector(".settings-message")
+ expect(no_personal_access_tokens_message).to have_text("This user has no active Personal Access Tokens.")
end
context "when revocation fails" do
diff --git a/spec/features/projects/diffs/diff_show_spec.rb b/spec/features/projects/diffs/diff_show_spec.rb
index b528b283495..4baccb24806 100644
--- a/spec/features/projects/diffs/diff_show_spec.rb
+++ b/spec/features/projects/diffs/diff_show_spec.rb
@@ -110,6 +110,10 @@ feature 'Diff file viewer', :js, feature: true do
context 'binary file that appears to be text in the first 1024 bytes' do
before do
+ # The file we're visiting is smaller than 10 KB and we want it collapsed
+ # so we need to disable the size increase feature.
+ stub_feature_flags(gitlab_git_diff_size_limit_increase: false)
+
visit_commit('7b1cf4336b528e0f3d1d140ee50cafdbc703597c')
end
diff --git a/spec/features/projects/no_password_spec.rb b/spec/features/projects/no_password_spec.rb
index 53ac18fa7cc..d22a6daac08 100644
--- a/spec/features/projects/no_password_spec.rb
+++ b/spec/features/projects/no_password_spec.rb
@@ -30,7 +30,7 @@ feature 'No Password Alert' do
let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml') }
before do
- stub_application_setting(signin_enabled?: false)
+ stub_application_setting(password_authentication_enabled?: false)
stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config])
end
diff --git a/spec/helpers/button_helper_spec.rb b/spec/helpers/button_helper_spec.rb
index 661327d4432..7ecb75da8ce 100644
--- a/spec/helpers/button_helper_spec.rb
+++ b/spec/helpers/button_helper_spec.rb
@@ -35,7 +35,7 @@ describe ButtonHelper do
context 'with internal auth disabled' do
before do
- stub_application_setting(signin_enabled?: false)
+ stub_application_setting(password_authentication_enabled?: false)
end
context 'when user has no personal access tokens' do
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index c462d9006ea..45066a60f50 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -160,7 +160,7 @@ describe ProjectsHelper do
context 'user requires a personal access token' do
it 'returns true' do
- stub_application_setting(signin_enabled?: false)
+ stub_application_setting(password_authentication_enabled?: false)
expect(helper.show_no_password_message?).to be_truthy
end
@@ -184,7 +184,7 @@ describe ProjectsHelper do
let(:user) { create(:user) }
it 'returns link to create a personal access token' do
- stub_application_setting(signin_enabled?: false)
+ stub_application_setting(password_authentication_enabled?: false)
expect(helper.link_to_set_password).to match %r{<a href="#{profile_personal_access_tokens_path}">create a personal access token</a>}
end
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index d09da951869..55780518230 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -206,7 +206,7 @@ describe Gitlab::Auth, lib: true do
end
it 'throws an error suggesting user create a PAT when internal auth is disabled' do
- allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false }
+ allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false }
expect { gl_auth.find_for_git_client('foo', 'bar', project: nil, ip: 'ip') }.to raise_error(Gitlab::Auth::MissingPersonalTokenError)
end
@@ -279,6 +279,16 @@ describe Gitlab::Auth, lib: true do
gl_auth.find_with_user_password('ldap_user', 'password')
end
end
+
+ context "with sign-in disabled" do
+ before do
+ stub_application_setting(password_authentication_enabled: false)
+ end
+
+ it "does not find user by valid login/password" do
+ expect(gl_auth.find_with_user_password(username, password)).to be_nil
+ end
+ end
end
private
diff --git a/spec/lib/gitlab/fake_application_settings_spec.rb b/spec/lib/gitlab/fake_application_settings_spec.rb
index b793176d84a..34322c2a693 100644
--- a/spec/lib/gitlab/fake_application_settings_spec.rb
+++ b/spec/lib/gitlab/fake_application_settings_spec.rb
@@ -1,25 +1,25 @@
require 'spec_helper'
describe Gitlab::FakeApplicationSettings do
- let(:defaults) { { signin_enabled: false, foobar: 'asdf', signup_enabled: true, 'test?' => 123 } }
+ let(:defaults) { { password_authentication_enabled: false, foobar: 'asdf', signup_enabled: true, 'test?' => 123 } }
subject { described_class.new(defaults) }
it 'wraps OpenStruct variables properly' do
- expect(subject.signin_enabled).to be_falsey
+ expect(subject.password_authentication_enabled).to be_falsey
expect(subject.signup_enabled).to be_truthy
expect(subject.foobar).to eq('asdf')
end
it 'defines predicate methods' do
- expect(subject.signin_enabled?).to be_falsey
+ expect(subject.password_authentication_enabled?).to be_falsey
expect(subject.signup_enabled?).to be_truthy
end
it 'predicate method changes when value is updated' do
- subject.signin_enabled = true
+ subject.password_authentication_enabled = true
- expect(subject.signin_enabled?).to be_truthy
+ expect(subject.password_authentication_enabled?).to be_truthy
end
it 'does not define a predicate method' do
diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb
index 0d712f39aea..7ea3386ac2a 100644
--- a/spec/lib/gitlab/git/diff_spec.rb
+++ b/spec/lib/gitlab/git/diff_spec.rb
@@ -34,7 +34,7 @@ EOT
describe 'size limit feature toggles' do
context 'when the feature gitlab_git_diff_size_limit_increase is enabled' do
before do
- Feature.enable('gitlab_git_diff_size_limit_increase')
+ stub_feature_flags(gitlab_git_diff_size_limit_increase: true)
end
it 'returns 200 KB for size_limit' do
@@ -48,7 +48,7 @@ EOT
context 'when the feature gitlab_git_diff_size_limit_increase is disabled' do
before do
- Feature.disable('gitlab_git_diff_size_limit_increase')
+ stub_feature_flags(gitlab_git_diff_size_limit_increase: false)
end
it 'returns 100 KB for size_limit' do
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index acffd335e43..10fa5f4044b 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -705,9 +705,9 @@ describe Gitlab::Git::Repository, seed_helper: true do
# Add new commits so that there's a renamed file in the commit history
repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
- commit_with_old_name = new_commit_edit_old_file(repo)
- rename_commit = new_commit_move_file(repo)
- commit_with_new_name = new_commit_edit_new_file(repo)
+ commit_with_old_name = Gitlab::Git::Commit.decorate(new_commit_edit_old_file(repo))
+ rename_commit = Gitlab::Git::Commit.decorate(new_commit_move_file(repo))
+ commit_with_new_name = Gitlab::Git::Commit.decorate(new_commit_edit_new_file(repo))
end
after(:context) do
@@ -880,8 +880,8 @@ describe Gitlab::Git::Repository, seed_helper: true do
context "compare results between log_by_walk and log_by_shell" do
let(:options) { { ref: "master" } }
- let(:commits_by_walk) { repository.log(options).map(&:oid) }
- let(:commits_by_shell) { repository.log(options.merge({ disable_walk: true })).map(&:oid) }
+ let(:commits_by_walk) { repository.log(options).map(&:id) }
+ let(:commits_by_shell) { repository.log(options.merge({ disable_walk: true })).map(&:id) }
it { expect(commits_by_walk).to eq(commits_by_shell) }
@@ -924,7 +924,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
expect(commits.size).to be > 0
expect(commits).to satisfy do |commits|
- commits.all? { |commit| commit.time >= options[:after] }
+ commits.all? { |commit| commit.committed_date >= options[:after] }
end
end
end
@@ -937,7 +937,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
expect(commits.size).to be > 0
expect(commits).to satisfy do |commits|
- commits.all? { |commit| commit.time <= options[:before] }
+ commits.all? { |commit| commit.committed_date <= options[:before] }
end
end
end
@@ -946,7 +946,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
let(:options) { { ref: 'master', path: ['PROCESS.md', 'README.md'] } }
def commit_files(commit)
- commit.diff(commit.parent_ids.first).deltas.flat_map do |delta|
+ commit.diff_from_parent.deltas.flat_map do |delta|
[delta.old_file[:path], delta.new_file[:path]].uniq.compact
end
end
diff --git a/spec/models/concerns/sortable_spec.rb b/spec/models/concerns/sortable_spec.rb
deleted file mode 100644
index d1e17c4f684..00000000000
--- a/spec/models/concerns/sortable_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'spec_helper'
-
-describe Sortable do
- let(:relation) { Issue.all }
-
- describe '#where' do
- it 'orders by id, descending' do
- order_node = relation.where(iid: 1).order_values.first
- expect(order_node).to be_a(Arel::Nodes::Descending)
- expect(order_node.expr.name).to eq(:id)
- end
- end
-
- describe '#find_by' do
- it 'does not order' do
- expect(relation).to receive(:unscope).with(:order).and_call_original
-
- relation.find_by(iid: 1)
- end
- end
-end
diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
index dcb70ee28a8..6ee30e86495 100644
--- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
+++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
@@ -23,38 +23,29 @@ describe GitlabIssueTrackerService, models: true do
describe 'project and issue urls' do
let(:project) { create(:empty_project) }
+ let(:service) { project.create_gitlab_issue_tracker_service(active: true) }
context 'with absolute urls' do
before do
- GitlabIssueTrackerService.default_url_options[:script_name] = "/gitlab/root"
- @service = project.create_gitlab_issue_tracker_service(active: true)
- end
-
- after do
- @service.destroy!
+ allow(GitlabIssueTrackerService).to receive(:default_url_options).and_return(script_name: "/gitlab/root")
end
it 'gives the correct path' do
- expect(@service.project_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues")
- expect(@service.new_issue_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/new")
- expect(@service.issue_url(432)).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/432")
+ expect(service.project_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues")
+ expect(service.new_issue_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/new")
+ expect(service.issue_url(432)).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/432")
end
end
context 'with relative urls' do
before do
- GitlabIssueTrackerService.default_url_options[:script_name] = "/gitlab/root"
- @service = project.create_gitlab_issue_tracker_service(active: true)
- end
-
- after do
- @service.destroy!
+ allow(GitlabIssueTrackerService).to receive(:default_url_options).and_return(script_name: "/gitlab/root")
end
it 'gives the correct path' do
- expect(@service.project_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues")
- expect(@service.new_issue_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues/new")
- expect(@service.issue_path(432)).to eq("/gitlab/root/#{project.path_with_namespace}/issues/432")
+ expect(service.project_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues")
+ expect(service.new_issue_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues/new")
+ expect(service.issue_path(432)).to eq("/gitlab/root/#{project.path_with_namespace}/issues/432")
end
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index c70f916a8bd..c614df8e98a 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1932,4 +1932,26 @@ describe User, models: true do
user.invalidate_merge_request_cache_counts
end
end
+
+ describe '#allow_password_authentication?' do
+ context 'regular user' do
+ let(:user) { build(:user) }
+
+ it 'returns true when sign-in is enabled' do
+ expect(user.allow_password_authentication?).to be_truthy
+ end
+
+ it 'returns false when sign-in is disabled' do
+ stub_application_setting(password_authentication_enabled: false)
+
+ expect(user.allow_password_authentication?).to be_falsey
+ end
+ end
+
+ it 'returns false for ldap user' do
+ user = create(:omniauth_user, provider: 'ldapmain')
+
+ expect(user.allow_password_authentication?).to be_falsey
+ end
+ end
end
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index 453eb4683a0..beaaf346283 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -35,6 +35,17 @@ describe API::Internal do
expect(json_response).to be_empty
end
end
+
+ context 'nil broadcast message' do
+ it 'returns nothing' do
+ allow(BroadcastMessage).to receive(:current).and_return(nil)
+
+ get api('/internal/broadcast_message'), secret_token: secret_token
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_empty
+ end
+ end
end
describe 'GET /internal/broadcast_messages' do
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index ede48b1c888..b71ac6c30b5 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -10,7 +10,7 @@ describe API::Settings, 'Settings' do
expect(response).to have_http_status(200)
expect(json_response).to be_an Hash
expect(json_response['default_projects_limit']).to eq(42)
- expect(json_response['signin_enabled']).to be_truthy
+ expect(json_response['password_authentication_enabled']).to be_truthy
expect(json_response['repository_storage']).to eq('default')
expect(json_response['koding_enabled']).to be_falsey
expect(json_response['koding_url']).to be_nil
@@ -32,7 +32,7 @@ describe API::Settings, 'Settings' do
it "updates application settings" do
put api("/application/settings", admin),
default_projects_limit: 3,
- signin_enabled: false,
+ password_authentication_enabled: false,
repository_storage: 'custom',
koding_enabled: true,
koding_url: 'http://koding.example.com',
@@ -46,7 +46,7 @@ describe API::Settings, 'Settings' do
help_page_support_url: 'http://example.com/help'
expect(response).to have_http_status(200)
expect(json_response['default_projects_limit']).to eq(3)
- expect(json_response['signin_enabled']).to be_falsey
+ expect(json_response['password_authentication_enabled']).to be_falsey
expect(json_response['repository_storage']).to eq('custom')
expect(json_response['repository_storages']).to eq(['custom'])
expect(json_response['koding_enabled']).to be_truthy
diff --git a/spec/requests/api/v3/settings_spec.rb b/spec/requests/api/v3/settings_spec.rb
index 41d039b7da0..291f6dcc2aa 100644
--- a/spec/requests/api/v3/settings_spec.rb
+++ b/spec/requests/api/v3/settings_spec.rb
@@ -10,7 +10,7 @@ describe API::V3::Settings, 'Settings' do
expect(response).to have_http_status(200)
expect(json_response).to be_an Hash
expect(json_response['default_projects_limit']).to eq(42)
- expect(json_response['signin_enabled']).to be_truthy
+ expect(json_response['password_authentication_enabled']).to be_truthy
expect(json_response['repository_storage']).to eq('default')
expect(json_response['koding_enabled']).to be_falsey
expect(json_response['koding_url']).to be_nil
@@ -28,11 +28,11 @@ describe API::V3::Settings, 'Settings' do
it "updates application settings" do
put v3_api("/application/settings", admin),
- default_projects_limit: 3, signin_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com',
+ default_projects_limit: 3, password_authentication_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com',
plantuml_enabled: true, plantuml_url: 'http://plantuml.example.com'
expect(response).to have_http_status(200)
expect(json_response['default_projects_limit']).to eq(3)
- expect(json_response['signin_enabled']).to be_falsey
+ expect(json_response['password_authentication_enabled']).to be_falsey
expect(json_response['repository_storage']).to eq('custom')
expect(json_response['repository_storages']).to eq(['custom'])
expect(json_response['koding_enabled']).to be_truthy
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index d0443a450a2..d043ab2a974 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -463,7 +463,7 @@ describe 'Git HTTP requests', lib: true do
context 'when internal auth is disabled' do
before do
- allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false }
+ allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false }
end
it 'rejects pulls with personal access token error message' do
diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb
index 5e4cf05748e..8d79ea3dd40 100644
--- a/spec/requests/jwt_controller_spec.rb
+++ b/spec/requests/jwt_controller_spec.rb
@@ -101,7 +101,7 @@ describe JwtController do
context 'when internal auth is disabled' do
it 'rejects the authorization attempt with personal access token message' do
- allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false }
+ allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false }
get '/jwt/auth', parameters, headers
expect(response).to have_http_status(401)
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 3c142764e28..b8ed1e18de0 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -59,6 +59,7 @@ RSpec.configure do |config|
config.include ApiHelpers, :api
config.include Gitlab::Routing, type: :routing
config.include MigrationsHelpers, :migration
+ config.include StubFeatureFlags
config.infer_spec_type_from_file_location!
@@ -79,6 +80,8 @@ RSpec.configure do |config|
config.before(:example) do
# Skip pre-receive hook check so we can use the web editor and merge.
allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil])
+ # Enable all features by default for testing
+ allow(Feature).to receive(:enabled?) { true }
end
config.before(:example, :request_store) do
diff --git a/spec/support/stub_feature_flags.rb b/spec/support/stub_feature_flags.rb
new file mode 100644
index 00000000000..b96338bf548
--- /dev/null
+++ b/spec/support/stub_feature_flags.rb
@@ -0,0 +1,8 @@
+module StubFeatureFlags
+ def stub_feature_flags(features)
+ features.each do |feature_name, enabled|
+ allow(Feature).to receive(:enabled?).with(feature_name) { enabled }
+ allow(Feature).to receive(:enabled?).with(feature_name.to_s) { enabled }
+ end
+ end
+end