Skip to content
Snippets Groups Projects
Commit c826ecc3 authored by Bob Van Landuyt's avatar Bob Van Landuyt
Browse files

Port changes for CODEOWNERS to CE

This ports the changes for the CODEOWNERS feature to CE:
- It adds the CODEOWNERS file.
- It adds the mention of the `with-codeowners` branch in TestEnv
parent c6d315b4
No related branches found
No related tags found
1 merge request!10495Merge Requests - Assignee
# Backend Maintainers are the default for all ruby files
*.rb @ayufan @DouweM @dzaporozhets @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
*.rake @ayufan @DouweM @dzaporozhets @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
# Technical writing team are the default reviewers for everything in `doc/`
/doc/ @axil @marcia
# Frontend maintainers should see everything in `app/assets/`
app/assets/ @annabeldunstone @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann
# Someone from the database team should review changes in `db/`
db/ @abrandl @NikolayS
# Feature specific owners
/ee/lib/gitlab/code_owners/ @reprazent
Loading
Loading
@@ -9,23 +9,46 @@ module CaseSensitivity
#
# Unlike other ActiveRecord methods this method only operates on a Hash.
def iwhere(params)
criteria = self
cast_lower = Gitlab::Database.postgresql?
criteria = self
 
params.each do |key, value|
column = ActiveRecord::Base.connection.quote_table_name(key)
criteria = case value
when Array
criteria.where(value_in(key, value))
else
criteria.where(value_equal(key, value))
end
end
criteria
end
 
condition =
if cast_lower
"LOWER(#{column}) = LOWER(:value)"
else
"#{column} = :value"
end
private
def value_equal(column, value)
lower_value = lower_value(value)
lower_column(arel_table[column]).eq(lower_value).to_sql
end
 
criteria = criteria.where(condition, value: value)
def value_in(column, values)
lower_values = values.map do |value|
lower_value(value)
end
 
criteria
lower_column(arel_table[column]).in(lower_values).to_sql
end
def lower_value(value)
return value if Gitlab::Database.mysql?
Arel::Nodes::NamedFunction.new('LOWER', [Arel::Nodes.build_quoted(value)])
end
def lower_column(column)
return column if Gitlab::Database.mysql?
column.lower
end
end
end
Loading
Loading
@@ -257,6 +257,7 @@ class User < ActiveRecord::Base
scope :order_recent_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'DESC')) }
scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'ASC')) }
scope :confirmed, -> { where.not(confirmed_at: nil) }
scope :by_username, -> (usernames) { iwhere(username: usernames) }
 
# Limits the users to those that have TODOs, optionally in the given state.
#
Loading
Loading
@@ -444,11 +445,11 @@ class User < ActiveRecord::Base
end
 
def find_by_username(username)
iwhere(username: username).take
by_username(username).take
end
 
def find_by_username!(username)
iwhere(username: username).take!
by_username(username).take!
end
 
def find_by_personal_access_token(token_string)
Loading
Loading
Loading
Loading
@@ -5,6 +5,7 @@
%ul.blob-commit-info
= render 'projects/commits/commit', commit: @last_commit, project: @project, ref: @ref
 
= render_if_exists 'projects/blob/owners', blob: blob
= render "projects/blob/auxiliary_viewer", blob: blob
 
#blob-content-holder.blob-content-holder
Loading
Loading
# frozen_string_literal: true
# This class extracts all users found in a piece of text by the username or the
# email adress
module Gitlab
class UserExtractor
# Not using `Devise.email_regexp` to filter out any chars that an email
# does not end with and not pinning the email to a start of end of a string.
EMAIL_REGEXP = /(?<email>([^@\s]+@[^@\s]+(?<!\W)))/
USERNAME_REGEXP = User.reference_pattern
def initialize(text)
@text = text
end
def users
return User.none unless @text.present?
@users ||= User.from("(#{union.to_sql}) users")
end
def usernames
matches[:usernames]
end
def emails
matches[:emails]
end
def references
@references ||= matches.values.flatten
end
def matches
@matches ||= {
emails: @text.scan(EMAIL_REGEXP).flatten.uniq,
usernames: @text.scan(USERNAME_REGEXP).flatten.uniq
}
end
private
def union
relations = []
relations << User.by_any_email(emails) if emails.any?
relations << User.by_username(usernames) if usernames.any?
Gitlab::SQL::Union.new(relations)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::UserExtractor do
let(:text) do
<<~TXT
This is a long texth that mentions some users.
@user-1, @user-2 and user@gitlab.org take a walk in the park.
There they meet @user-4 that was out with other-user@gitlab.org.
@user-1 thought it was late, so went home straight away
TXT
end
subject(:extractor) { described_class.new(text) }
describe '#users' do
it 'returns an empty relation when nil was passed' do
extractor = described_class.new(nil)
expect(extractor.users).to be_empty
expect(extractor.users).to be_a(ActiveRecord::Relation)
end
it 'returns the user case insensitive for usernames' do
user = create(:user, username: "USER-4")
expect(extractor.users).to include(user)
end
it 'returns users by primary email' do
user = create(:user, email: 'user@gitlab.org')
expect(extractor.users).to include(user)
end
it 'returns users by secondary email' do
user = create(:email, email: 'other-user@gitlab.org').user
expect(extractor.users).to include(user)
end
end
describe '#matches' do
it 'includes all mentioned email adresses' do
expect(extractor.matches[:emails]).to contain_exactly('user@gitlab.org', 'other-user@gitlab.org')
end
it 'includes all mentioned usernames' do
expect(extractor.matches[:usernames]).to contain_exactly('user-1', 'user-2', 'user-4')
end
end
describe '#references' do
it 'includes all user-references once' do
expect(extractor.references).to contain_exactly('user-1', 'user-2', 'user@gitlab.org', 'user-4', 'other-user@gitlab.org')
end
end
end
Loading
Loading
@@ -3,186 +3,50 @@ require 'spec_helper'
describe CaseSensitivity do
describe '.iwhere' do
let(:connection) { ActiveRecord::Base.connection }
let(:model) { Class.new { include CaseSensitivity } }
describe 'using PostgreSQL' do
before do
allow(Gitlab::Database).to receive(:postgresql?).and_return(true)
allow(Gitlab::Database).to receive(:mysql?).and_return(false)
end
describe 'with a single column/value pair' do
it 'returns the criteria for a column and a value' do
criteria = double(:criteria)
expect(connection).to receive(:quote_table_name)
.with(:foo)
.and_return('"foo"')
expect(model).to receive(:where)
.with(%q{LOWER("foo") = LOWER(:value)}, value: 'bar')
.and_return(criteria)
expect(model.iwhere(foo: 'bar')).to eq(criteria)
end
it 'returns the criteria for a column with a table, and a value' do
criteria = double(:criteria)
expect(connection).to receive(:quote_table_name)
.with(:'foo.bar')
.and_return('"foo"."bar"')
expect(model).to receive(:where)
.with(%q{LOWER("foo"."bar") = LOWER(:value)}, value: 'bar')
.and_return(criteria)
expect(model.iwhere('foo.bar'.to_sym => 'bar')).to eq(criteria)
end
end
describe 'with multiple column/value pairs' do
it 'returns the criteria for a column and a value' do
initial = double(:criteria)
final = double(:criteria)
expect(connection).to receive(:quote_table_name)
.with(:foo)
.and_return('"foo"')
expect(connection).to receive(:quote_table_name)
.with(:bar)
.and_return('"bar"')
expect(model).to receive(:where)
.with(%q{LOWER("foo") = LOWER(:value)}, value: 'bar')
.and_return(initial)
expect(initial).to receive(:where)
.with(%q{LOWER("bar") = LOWER(:value)}, value: 'baz')
.and_return(final)
got = model.iwhere(foo: 'bar', bar: 'baz')
expect(got).to eq(final)
end
it 'returns the criteria for a column with a table, and a value' do
initial = double(:criteria)
final = double(:criteria)
expect(connection).to receive(:quote_table_name)
.with(:'foo.bar')
.and_return('"foo"."bar"')
expect(connection).to receive(:quote_table_name)
.with(:'foo.baz')
.and_return('"foo"."baz"')
expect(model).to receive(:where)
.with(%q{LOWER("foo"."bar") = LOWER(:value)}, value: 'bar')
.and_return(initial)
expect(initial).to receive(:where)
.with(%q{LOWER("foo"."baz") = LOWER(:value)}, value: 'baz')
.and_return(final)
got = model.iwhere('foo.bar'.to_sym => 'bar',
'foo.baz'.to_sym => 'baz')
expect(got).to eq(final)
end
let(:model) do
Class.new(ActiveRecord::Base) do
include CaseSensitivity
self.table_name = 'namespaces'
end
end
 
describe 'using MySQL' do
before do
allow(Gitlab::Database).to receive(:postgresql?).and_return(false)
allow(Gitlab::Database).to receive(:mysql?).and_return(true)
end
describe 'with a single column/value pair' do
it 'returns the criteria for a column and a value' do
criteria = double(:criteria)
expect(connection).to receive(:quote_table_name)
.with(:foo)
.and_return('`foo`')
expect(model).to receive(:where)
.with(%q{`foo` = :value}, value: 'bar')
.and_return(criteria)
let!(:model_1) { model.create(path: 'mOdEl-1', name: 'mOdEl 1') }
let!(:model_2) { model.create(path: 'mOdEl-2', name: 'mOdEl 2') }
 
expect(model.iwhere(foo: 'bar')).to eq(criteria)
end
it 'finds a single instance by a single attribute regardless of case' do
expect(model.iwhere(path: 'MODEL-1')).to contain_exactly(model_1)
end
 
it 'returns the criteria for a column with a table, and a value' do
criteria = double(:criteria)
it 'finds multiple instances by a single attribute regardless of case' do
expect(model.iwhere(path: %w(MODEL-1 model-2))).to contain_exactly(model_1, model_2)
end
 
expect(connection).to receive(:quote_table_name)
.with(:'foo.bar')
.and_return('`foo`.`bar`')
it 'finds instances by multiple attributes' do
expect(model.iwhere(path: %w(MODEL-1 model-2), name: 'model 1'))
.to contain_exactly(model_1)
end
 
expect(model).to receive(:where)
.with(%q{`foo`.`bar` = :value}, value: 'bar')
.and_return(criteria)
# Using `mysql` & `postgresql` metadata-tags here because both adapters build
# the query slightly differently
context 'for MySQL', :mysql do
it 'builds a simple query' do
query = model.iwhere(path: %w(MODEL-1 model-2), name: 'model 1').to_sql
expected_query = <<~QRY.strip
SELECT `namespaces`.* FROM `namespaces` WHERE (`namespaces`.`path` IN ('MODEL-1', 'model-2')) AND (`namespaces`.`name` = 'model 1')
QRY
 
expect(model.iwhere('foo.bar'.to_sym => 'bar'))
.to eq(criteria)
end
expect(query).to eq(expected_query)
end
end
 
describe 'with multiple column/value pairs' do
it 'returns the criteria for a column and a value' do
initial = double(:criteria)
final = double(:criteria)
expect(connection).to receive(:quote_table_name)
.with(:foo)
.and_return('`foo`')
expect(connection).to receive(:quote_table_name)
.with(:bar)
.and_return('`bar`')
expect(model).to receive(:where)
.with(%q{`foo` = :value}, value: 'bar')
.and_return(initial)
expect(initial).to receive(:where)
.with(%q{`bar` = :value}, value: 'baz')
.and_return(final)
got = model.iwhere(foo: 'bar', bar: 'baz')
expect(got).to eq(final)
end
it 'returns the criteria for a column with a table, and a value' do
initial = double(:criteria)
final = double(:criteria)
expect(connection).to receive(:quote_table_name)
.with(:'foo.bar')
.and_return('`foo`.`bar`')
expect(connection).to receive(:quote_table_name)
.with(:'foo.baz')
.and_return('`foo`.`baz`')
expect(model).to receive(:where)
.with(%q{`foo`.`bar` = :value}, value: 'bar')
.and_return(initial)
expect(initial).to receive(:where)
.with(%q{`foo`.`baz` = :value}, value: 'baz')
.and_return(final)
got = model.iwhere('foo.bar'.to_sym => 'bar',
'foo.baz'.to_sym => 'baz')
context 'for PostgreSQL', :postgresql do
it 'builds a query using LOWER' do
query = model.iwhere(path: %w(MODEL-1 model-2), name: 'model 1').to_sql
expected_query = <<~QRY.strip
SELECT \"namespaces\".* FROM \"namespaces\" WHERE (LOWER(\"namespaces\".\"path\") IN (LOWER('MODEL-1'), LOWER('model-2'))) AND (LOWER(\"namespaces\".\"name\") = LOWER('model 1'))
QRY
 
expect(got).to eq(final)
end
expect(query).to eq(expected_query)
end
end
end
Loading
Loading
Loading
Loading
@@ -405,6 +405,23 @@ describe User do
end
end
end
describe '.by_username' do
it 'finds users regardless of the case passed' do
user = create(:user, username: 'CaMeLcAsEd')
user2 = create(:user, username: 'UPPERCASE')
expect(described_class.by_username(%w(CAMELCASED uppercase)))
.to contain_exactly(user, user2)
end
it 'finds a single user regardless of the case passed' do
user = create(:user, username: 'CaMeLcAsEd')
expect(described_class.by_username('CAMELCASED'))
.to contain_exactly(user)
end
end
end
 
describe "Respond to" do
Loading
Loading
Loading
Loading
@@ -52,7 +52,8 @@ module TestEnv
'add_images_and_changes' => '010d106',
'update-gitlab-shell-v-6-0-1' => '2f61d70',
'update-gitlab-shell-v-6-0-3' => 'de78448',
'2-mb-file' => 'bf12d25'
'2-mb-file' => 'bf12d25',
'with-codeowners' => '219560e'
}.freeze
 
# gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment