Commit 7248ad97 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-05-18

# Conflicts:
#	lib/gitlab/auth/ldap/access.rb

[ci skip]
parents e234c4ea fa04ec11
......@@ -5,7 +5,7 @@ import LoadingButton from '~/vue_shared/components/loading_button.vue';
import CommitMessageField from './message_field.vue';
import Actions from './actions.vue';
import SuccessMessage from './success_message.vue';
import { activityBarViews, MAX_WINDOW_HEIGHT_COMPACT, COMMIT_ITEM_PADDING } from '../../constants';
import { activityBarViews, MAX_WINDOW_HEIGHT_COMPACT } from '../../constants';
export default {
components: {
......@@ -70,7 +70,7 @@ export default {
? this.$refs.formEl && this.$refs.formEl.offsetHeight
: this.$refs.compactEl && this.$refs.compactEl.offsetHeight;
this.componentHeight = elHeight + COMMIT_ITEM_PADDING;
this.componentHeight = elHeight;
},
enterTransition() {
this.$nextTick(() => {
......@@ -78,7 +78,7 @@ export default {
? this.$refs.compactEl && this.$refs.compactEl.offsetHeight
: this.$refs.formEl && this.$refs.formEl.offsetHeight;
this.componentHeight = elHeight + COMMIT_ITEM_PADDING;
this.componentHeight = elHeight;
});
},
afterEndTransition() {
......
......@@ -122,11 +122,11 @@ export default {
<div
class="file"
:class="fileClass"
@click="clickFile"
role="button"
>
<div
class="file-name"
@click="clickFile"
role="button"
>
<span
class="ide-file-name str-truncated"
......
......@@ -5,8 +5,6 @@ export const FILE_FINDER_EMPTY_ROW_HEIGHT = 33;
export const MAX_WINDOW_HEIGHT_COMPACT = 750;
export const COMMIT_ITEM_PADDING = 32;
// Commit message textarea
export const MAX_TITLE_LENGTH = 50;
export const MAX_BODY_LENGTH = 72;
......
......@@ -291,236 +291,8 @@ ul.indent-list {
to { transform: rotate(360deg); }
}
.groups-list-tree-container {
.has-no-search-results {
text-align: center;
padding: $gl-padding;
font-style: italic;
color: $well-light-text-color;
}
> .group-list-tree > .group-row.has-children:first-child {
border-top: 0;
}
}
.group-list-tree {
.avatar-container.content-loading {
position: relative;
> a,
> a .avatar {
height: 100%;
border-radius: 50%;
}
> a {
padding: 2px;
.avatar {
border: 2px solid $white-normal;
&.identicon {
line-height: 15px;
}
}
}
&::after {
content: "";
position: absolute;
height: 100%;
width: 100%;
background-color: transparent;
border: 2px outset $kdb-border;
border-radius: 50%;
animation: spin-avatar 3s infinite linear;
}
}
.folder-toggle-wrap {
float: left;
line-height: $list-text-height;
font-size: 0;
span {
font-size: $gl-font-size;
}
}
.folder-caret,
.item-type-icon {
display: inline-block;
}
.folder-caret {
width: 15px;
svg {
margin-bottom: 2px;
}
}
.item-type-icon {
margin-top: 2px;
width: 20px;
}
> .group-row:not(.has-children) {
.folder-caret {
opacity: 0;
}
}
.content-list li:last-child {
padding-bottom: 0;
}
.group-list-tree {
margin-bottom: 0;
margin-left: 30px;
position: relative;
&::before {
content: '';
display: block;
width: 0;
position: absolute;
top: 5px;
bottom: 0;
left: -16px;
border-left: 2px solid $border-white-normal;
}
.group-row {
position: relative;
&::before {
content: "";
display: block;
width: 10px;
height: 0;
border-top: 2px solid $border-white-normal;
position: absolute;
top: 30px;
left: -16px;
}
&:last-child::before {
background: $white-light;
height: auto;
top: 30px;
bottom: 0;
}
&.being-removed {
opacity: 0.5;
}
}
}
.group-row {
padding: 0;
&.has-children {
border-top: 0;
}
&:first-child {
border-top: 1px solid $white-normal;
}
}
.group-row-contents {
padding: $gl-padding-top;
&:hover {
border-color: $row-hover-border;
background-color: $row-hover;
cursor: pointer;
}
.avatar-container > a {
width: 100%;
text-decoration: none;
}
&.has-more-items {
display: block;
padding: 20px 10px;
}
.stats {
position: relative;
line-height: 46px;
> span {
display: inline-flex;
align-items: center;
height: 16px;
min-width: 30px;
}
> span:last-child {
margin-right: 0;
}
.stat-value {
margin: 2px 0 0 5px;
}
}
.controls {
margin-left: 5px;
> .btn {
margin-right: $btn-xs-side-margin;
}
}
}
.project-row-contents .stats {
line-height: inherit;
> span:first-child {
margin-left: 25px;
}
.item-visibility {
margin-right: 0;
}
.last-updated {
position: absolute;
right: 12px;
min-width: 250px;
text-align: right;
color: $gl-text-color-secondary;
}
}
}
.namespace-title {
.tooltip-inner {
max-width: 350px;
}
}
ul.group-list-tree {
li.group-row {
> .group-row-contents .title {
line-height: $list-text-height;
}
&.has-description > .group-row-contents .title {
line-height: inherit;
}
}
}
.js-groups-list-holder {
.groups-list-loading {
font-size: 34px;
text-align: center;
}
}
......@@ -290,3 +290,231 @@ table.pipeline-project-metrics tr td {
overflow-y: unset;
}
}
.groups-list-tree-container {
.has-no-search-results {
text-align: center;
padding: $gl-padding;
font-style: italic;
color: $well-light-text-color;
}
> .group-list-tree > .group-row.has-children:first-child {
border-top: 0;
}
}
.group-list-tree {
.avatar-container.content-loading {
position: relative;
> a,
> a .avatar {
height: 100%;
border-radius: 50%;
}
> a {
padding: 2px;
.avatar {
border: 2px solid $white-normal;
&.identicon {
line-height: 15px;
}
}
}
&::after {
content: "";
position: absolute;
height: 100%;
width: 100%;
background-color: transparent;
border: 2px outset $kdb-border;
border-radius: 50%;
animation: spin-avatar 3s infinite linear;
}
}
.folder-toggle-wrap {
float: left;
line-height: $list-text-height;
font-size: 0;
span {
font-size: $gl-font-size;
}
}
.folder-caret,
.item-type-icon {
display: inline-block;
}
.folder-caret {
width: 15px;
svg {
margin-bottom: 2px;
}
}
.item-type-icon {
margin-top: 2px;
width: 20px;
}
> .group-row:not(.has-children) {
.folder-caret {
opacity: 0;
}
}
.content-list li:last-child {
padding-bottom: 0;
}
.group-list-tree {
margin-bottom: 0;
margin-left: 30px;
position: relative;
&::before {
content: '';
display: block;
width: 0;
position: absolute;
top: 5px;
bottom: 0;
left: -16px;
border-left: 2px solid $border-white-normal;
}
.group-row {
position: relative;
&::before {
content: "";
display: block;
width: 10px;
height: 0;
border-top: 2px solid $border-white-normal;
position: absolute;
top: 30px;
left: -16px;
}
&:last-child::before {
background: $white-light;
height: auto;
top: 30px;
bottom: 0;
}
&.being-removed {
opacity: 0.5;
}
}
}
.group-row {
padding: 0;
&.has-children {
border-top: 0;
}
&:first-child {
border-top: 1px solid $white-normal;
}
}
.group-row-contents {
padding: $gl-padding-top;
&:hover {
border-color: $row-hover-border;
background-color: $row-hover;
cursor: pointer;
}
.avatar-container > a {
width: 100%;
text-decoration: none;
}
&.has-more-items {
display: block;
padding: 20px 10px;
}
.stats {
position: relative;
line-height: 46px;
> span {
display: inline-flex;
align-items: center;
height: 16px;
min-width: 30px;
}
> span:last-child {
margin-right: 0;
}
.stat-value {
margin: 2px 0 0 5px;
}
}
.controls {
margin-left: 5px;
> .btn {
margin-right: $btn-xs-side-margin;
}
}
}
.project-row-contents .stats {
line-height: inherit;
> span:first-child {
margin-left: 25px;
}
.item-visibility {
margin-right: 0;
}
.last-updated {
position: absolute;
right: 12px;
min-width: 250px;
text-align: right;
color: $gl-text-color-secondary;
}
}
}
ul.group-list-tree {
li.group-row {
> .group-row-contents .title {
line-height: $list-text-height;
}
&.has-description > .group-row-contents .title {
line-height: inherit;
}
}
}
.js-groups-list-holder {
.groups-list-loading {
font-size: 34px;
text-align: center;
}
}
......@@ -39,12 +39,15 @@
.ide-file-list {
flex: 1;
padding-left: $gl-padding;
padding-right: $gl-padding;
padding-bottom: $grid-size;
.file {
cursor: pointer;
&.file-open {
background: $link-active-background;
background: $white-normal;
}
&.file-active {
......@@ -84,12 +87,11 @@
.ide-new-btn {
display: none;
margin-right: -8px;
}
&:hover,
&:focus {
background: $link-active-background;
background: $white-normal;
.ide-new-btn {
display: block;
......@@ -111,12 +113,11 @@
}
}
.file-name,
.file-col-commit-message {
.file-name {
display: flex;
overflow: visible;
align-items: center;
padding: 6px 12px;
width: 100%;
}
.multi-file-loading-container {
......@@ -507,7 +508,7 @@
align-items: center;
margin-bottom: 0;
border-bottom: 1px solid $white-dark;
padding: $gl-btn-padding $gl-padding;
padding: 12px 0;
}
.multi-file-commit-panel-header-title {
......@@ -529,32 +530,31 @@
.multi-file-commit-list {
flex: 1;
overflow: auto;
padding: $gl-padding;
padding: $grid-size 0;
margin-left: -$grid-size;
margin-right: -$grid-size;
min-height: 60px;
.multi-file-commit-list-item {
margin-left: 0;
margin-right: 0;
}
&.help-block {
margin-left: 0;
right: 0;
}
}
.multi-file-commit-list-item {
display: flex;
padding: 0;
align-items: center;
border-radius: $border-radius-default;
.multi-file-discard-btn {
display: none;
margin-top: -2px;
margin-left: auto;
margin-right: $grid-size;
color: $gl-link-color;
&:focus,
&:hover {
text-decoration: underline;
}
}
&:hover {
background: $white-normal;
.multi-file-discard-btn {
display: flex;
}
......@@ -590,25 +590,39 @@
}
}
.multi-file-commit-list-item,
.ide-file-list .file {
display: flex;
align-items: center;
margin-left: -$grid-size;
margin-right: -$grid-size;
padding: $grid-size / 2 $grid-size;
border-radius: $border-radius-default;
text-align: left;
&:hover,
&:focus {
background: $white-normal;
}
}
.multi-file-commit-list-path {
padding: $grid-size / 2;
padding-left: $grid-size;
padding: 0;
background: none;
border: 0;
text-align: left;
width: 100%;
min-width: 0;
&:hover,
&:focus {
outline: 0;
}
svg {
min-width: 16px;
vertical-align: middle;
display: inline-block;
}
&:hover,
&:focus {
outline: 0;
}
}
.multi-file-commit-list-file-path {
......@@ -625,12 +639,18 @@
.multi-file-commit-form {
position: relative;
padding: $gl-padding;
background-color: $white-light;
border-top: 1px solid $white-dark;
border-left: 1px solid $white-dark;
transition: all 0.3s ease;
> form,
> .commit-form-compact {
padding: $gl-padding 0;
margin-left: $gl-padding;
margin-right: $gl-padding;
border-top: 1px solid $white-dark;
}
.btn {
font-size: $gl-font-size;
}
......@@ -793,8 +813,9 @@
display: flex;
flex: 1;
flex-direction: column;
width: 100%;
min-height: 140px;
margin-left: $gl-padding;
margin-right: $gl-padding;
&.is-first {
border-bottom: 1px solid $white-dark;
......@@ -985,9 +1006,8 @@
.ide-tree-header {
display: flex;
align-items: center;
padding: 10px 0;
margin-left: 10px;
margin-right: 10px;
margin-bottom: 8px;
padding: 12px 0;
border-bottom: 1px solid $white-dark;
.ide-new-btn {
......@@ -1018,9 +1038,9 @@
.commit-form-slide-up-enter-active,
.commit-form-slide-up-leave-active {
position: absolute;
top: 16px;
left: 16px;
right: 16px;
top: 0;
left: 0;
right: 0;
transition: all 0.3s ease;
}
......
......@@ -163,7 +163,7 @@
= nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts]) do
= link_to project_pipelines_path(@project), class: 'shortcuts-pipelines' do
.nav-icon-container
= sprite_icon('pipeline')
= sprite_icon('rocket')
%span.nav-item-name
= _('CI / CD')
......
---
title: Memoize Gitlab::Database.version
merge_request:
author:
type: performance
---
title: Remove shellout implementation for Repository checksums
merge_request:
author:
type: other
......@@ -37,12 +37,13 @@ import state from './state';
Vue.use(Vuex);
export default new Vuex.Store({
export const createStore = () => new Vuex.Store({
actions,
getters,
mutations,
state,
});
export default createStore();
```
### `state.js`
......@@ -320,10 +321,11 @@ In order to write unit tests for those components, we need to include the store
```javascript
//component_spec.js
import Vue from 'vue';
import store from './store';
import { createStore } from './store';
import component from './component.vue'
describe('component', () => {
let store;
let vm;
let Component;
......@@ -340,6 +342,8 @@ describe('component', () => {
name: 'Foo',
age: '30',
};
store = createStore();
// populate the store
store.dispatch('addUser', user);
......
......@@ -6,8 +6,11 @@ module Gitlab
module Auth
module LDAP
class Access
<<<<<<< HEAD
prepend ::EE::Gitlab::Auth::LDAP::Access
=======
>>>>>>> upstream/master
attr_reader :provider, :user, :ldap_identity
def self.open(user, &block)
......
......@@ -43,7 +43,7 @@ module Gitlab
end
def self.version
database_version.match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1]
@version ||= database_version.match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1]
end
def self.postgresql_9_or_less?
......
......@@ -1586,14 +1586,12 @@ module Gitlab
end
def checksum
gitaly_migrate(:calculate_checksum,
status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled|
if is_enabled
gitaly_repository_client.calculate_checksum
else
calculate_checksum_by_shelling_out
end
end
# The exists? RPC is much cheaper, so we perform this request first
raise NoRepository, "Repository does not exists" unless exists?
gitaly_repository_client.calculate_checksum
rescue GRPC::NotFound
raise NoRepository # Guard against data races.
end
private
......@@ -2500,36 +2498,6 @@ module Gitlab
rev_parse_target(ref).oid
end
def calculate_checksum_by_shelling_out
raise NoRepository unless exists?
args = %W(--git-dir=#{path} show-ref --heads --tags)
output, status = run_git(args)
if status.nil? || !status.zero?
# Non-valid git repositories return 128 as the status code and an error output
raise InvalidRepository if status == 128 && output.to_s.downcase =~ /not a git repository/
# Empty repositories returns with a non-zero status and an empty output.
raise ChecksumError, output unless output.blank?
return EMPTY_REPOSITORY_CHECKSUM
end
refs = output.split("\n")
result = refs.inject(nil) do |checksum, ref|
value = Digest::SHA1.hexdigest(ref).hex
if checksum.nil?
value
else
checksum ^ value
end
end
result.to_s(16)
end
def build_git_cmd(*args)
object_directories = alternate_object_directories.join(File::PATH_SEPARATOR)
......
......@@ -32,6 +32,12 @@ describe Gitlab::Database do
end
describe '.version' do
around do |example|
described_class.instance_variable_set(:@version, nil)
example.run
described_class.instance_variable_set(:@version, nil)
end
context "on mysql" do
it "extracts the version number" do
allow(described_class).to receive(:database_version)
......@@ -49,6 +55,14 @@ describe Gitlab::Database do
expect(described_class.version).to eq '9.4.4'
end
end
it 'memoizes the result' do
count = ActiveRecord::QueryRecorder
.new { 2.times { described_class.version } }
.count
expect(count).to eq(1)
end
end
describe '.postgresql_9_or_less?' do
......
......@@ -2247,66 +2247,42 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
describe '#checksum' do
shared_examples 'calculating checksum' do
it 'calculates the checksum for non-empty repo' do
expect(repository.checksum).to eq '54f21be4c32c02f6788d72207fa03ad3bce725e4'
end
it 'returns 0000000000000000000000000000000000000000 for an empty repo' do
FileUtils.rm_rf(File.join(storage_path, 'empty-repo.git'))
system(git_env, *%W(#{Gitlab.config.git.bin_path} init --bare empty-repo.git),
chdir: storage_path,
out: '/dev/null',
err: '/dev/null')
it 'calculates the checksum for non-empty repo' do
expect(repository.checksum).to eq '54f21be4c32c02f6788d72207fa03ad3bce725e4'
end
empty_repo = described_class.new('default', 'empty-repo.git', '')
it 'returns 0000000000000000000000000000000000000000 for an empty repo' do
FileUtils.rm_rf(File.join(storage_path, 'empty-repo.git'))
expect(empty_repo.checksum).to eq '0000000000000000000000000000000000000000'
end
system(git_env, *%W(#{Gitlab.config.git.bin_path} init --bare empty-repo.git),
chdir: storage_path,
out: '/dev/null',
err: '/dev/null')
it 'raises Gitlab::Git::Repository::InvalidRepository error for non-valid git repo' do
FileUtils.rm_rf(File.join(storage_path, 'non-valid.git'))
empty_repo = described_class.new('default', 'empty-repo.git', '')
system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{TEST_REPO_PATH} non-valid.git),
chdir: SEED_STORAGE_PATH,
out: '/dev/null',
err: '/dev/null')
expect(empty_repo.checksum).to eq '0000000000000000000000000000000000000000'
end
File.truncate(File.join(storage_path, 'non-valid.git/HEAD'), 0)
it 'raises Gitlab::Git::Repository::InvalidRepository error for non-valid git repo' do
FileUtils.rm_rf(File.join(storage_path, 'non-valid.git'))
non_valid = described_class.new('default', 'non-valid.git', '')
system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{TEST_REPO_PATH} non-valid.git),
chdir: SEED_STORAGE_PATH,
out: '/dev/null',
err: '/dev/null')
expect { non_valid.checksum }.to raise_error(Gitlab::Git::Repository::InvalidRepository)
end
File.truncate(File.join(storage_path, 'non-valid.git/HEAD'), 0)
it 'raises Gitlab::Git::Repository::NoRepository error when there is no repo' do
broken_repo = described_class.new('default', 'a/path.git', '')
non_valid = described_class.new('default', 'non-valid.git', '')
expect { broken_repo.checksum }.to raise_error(Gitlab::Git::Repository::NoRepository)
end
expect { non_valid.checksum }.to raise_error(Gitlab::Git::Repository::InvalidRepository)
end
context 'when calculate_checksum Gitaly feature is enabled' do
it_behaves_like 'calculating checksum'
end
context 'when calculate_checksum Gitaly feature is disabled', :disable_gitaly do
it_behaves_like 'calculating checksum'
describe 'when storage is broken', :broken_storage do
it 'raises a storage exception when storage is not available' do
broken_repo = described_class.new('broken', 'a/path.git', '')
expect { broken_repo.rugged }.to raise_error(Gitlab::Git::Storage::Inaccessible)
end
end
it "raises a Gitlab::Git::Repository::Failure error if the `popen` call to git returns a non-zero exit code" do
allow(repository).to receive(:popen).and_return(['output', nil])
it 'raises Gitlab::Git::Repository::NoRepository error when there is no repo' do
broken_repo = described_class.new('default', 'a/path.git', '')
expect { repository.checksum }.to raise_error Gitlab::Git::Repository::ChecksumError
end
expect { broken_repo.checksum }.to raise_error(Gitlab::Git::Repository::NoRepository)
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment