Commit e4853f21 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-06-27

parents 364cc667 2452f1a7
<script>
import $ from 'jquery';
import { mapState, mapGetters, mapActions } from 'vuex';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import noteForm from '../../notes/components/note_form.vue';
import { getNoteFormData } from '../store/utils';
import Autosave from '../../autosave';
import { DIFF_NOTE_TYPE, NOTE_TYPE } from '../constants';
export default {
components: {
......@@ -37,11 +40,28 @@ export default {
noteableData: state => state.notes.noteableData,
diffViewType: state => state.diffs.diffViewType,
}),
...mapGetters(['noteableType', 'getNotesDataByProp']),
...mapGetters(['isLoggedIn', 'noteableType', 'getNoteableData', 'getNotesDataByProp']),
},
mounted() {
if (this.isLoggedIn) {
const noteableData = this.getNoteableData;
const keys = [
NOTE_TYPE,
this.noteableType,
noteableData.id,
noteableData.diff_head_sha,
DIFF_NOTE_TYPE,
noteableData.source_project_id,
this.line.lineCode,
];
this.autosave = new Autosave($(this.$refs.noteForm.$refs.textarea), keys);
}
},
methods: {
...mapActions(['cancelCommentForm', 'saveNote', 'fetchDiscussions']),
handleCancelCommentForm() {
this.autosave.reset();
this.cancelCommentForm({
lineCode: this.line.lineCode,
});
......@@ -82,6 +102,7 @@ export default {
class="content discussion-form discussion-form-container discussion-notes"
>
<note-form
ref="noteForm"
:is-editing="true"
:line-code="line.lineCode"
save-button-title="Comment"
......
......@@ -7,6 +7,7 @@ export const CONTEXT_LINE_TYPE = 'context';
export const EMPTY_CELL_TYPE = 'empty-cell';
export const COMMENT_FORM_TYPE = 'commentForm';
export const DIFF_NOTE_TYPE = 'DiffNote';
export const NOTE_TYPE = 'Note';
export const NEW_LINE_TYPE = 'new';
export const OLD_LINE_TYPE = 'old';
export const TEXT_DIFF_POSITION_TYPE = 'text';
......
......@@ -190,12 +190,25 @@ export const getParameterByName = (name, urlToParse) => {
return decodeURIComponent(results[2].replace(/\+/g, ' '));
};
const handleSelectedRange = (range) => {
const container = range.commonAncestorContainer;
// add context to fragment if needed
if (container.tagName === 'OL') {
const parentContainer = document.createElement(container.tagName);
parentContainer.appendChild(range.cloneContents());
return parentContainer;
}
return range.cloneContents();
};
export const getSelectedFragment = () => {
const selection = window.getSelection();
if (selection.rangeCount === 0) return null;
const documentFragment = document.createDocumentFragment();
for (let i = 0; i < selection.rangeCount; i += 1) {
documentFragment.appendChild(selection.getRangeAt(i).cloneContents());
const range = selection.getRangeAt(i);
documentFragment.appendChild(handleSelectedRange(range));
}
if (documentFragment.textContent.length === 0) return null;
......
......@@ -289,7 +289,7 @@ export default class SearchAutocomplete {
}
// If the dropdown is closed, we'll open it
if (!this.dropdown.hasClass('open')) {
if (!this.dropdown.hasClass('show')) {
this.loadingSuggestions = false;
this.dropdownToggle.dropdown('toggle');
return this.searchInput.removeClass('disabled');
......@@ -424,9 +424,9 @@ export default class SearchAutocomplete {
}
disableAutocomplete() {
if (!this.searchInput.hasClass('disabled') && this.dropdown.hasClass('open')) {
if (!this.searchInput.hasClass('disabled') && this.dropdown.hasClass('show')) {
this.searchInput.addClass('disabled');
this.dropdown.removeClass('open').trigger('hidden.bs.dropdown');
this.dropdown.removeClass('show').trigger('hidden.bs.dropdown');
this.restoreMenu();
}
}
......
# frozen_string_literal: true
class AdminEmailWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class ArchiveTraceWorker
include ApplicationWorker
include PipelineBackgroundQueue
......
# frozen_string_literal: true
class AuthorizedProjectsWorker
include ApplicationWorker
prepend WaitableWorker
......
# frozen_string_literal: true
class BackgroundMigrationWorker
include ApplicationWorker
......
# frozen_string_literal: true
class BuildCoverageWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class BuildFinishedWorker
prepend EE::BuildFinishedWorker
include ApplicationWorker
......
# frozen_string_literal: true
class BuildHooksWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class BuildQueueWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class BuildSuccessWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class BuildTraceSectionsWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class ClusterInstallAppWorker
include ApplicationWorker
include ClusterQueue
......
# frozen_string_literal: true
class ClusterProvisionWorker
include ApplicationWorker
include ClusterQueue
......
# frozen_string_literal: true
class ClusterWaitForAppInstallationWorker
include ApplicationWorker
include ClusterQueue
......
# frozen_string_literal: true
class ClusterWaitForIngressIpAddressWorker
include ApplicationWorker
include ClusterQueue
......
# frozen_string_literal: true
class CreateGpgSignatureWorker
include ApplicationWorker
......
# frozen_string_literal: true
class CreateNoteDiffFileWorker
include ApplicationWorker
......
# frozen_string_literal: true
class CreatePipelineWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class DeleteMergedBranchesWorker
include ApplicationWorker
......
# frozen_string_literal: true
class DeleteUserWorker
include ApplicationWorker
......
# frozen_string_literal: true
class EmailReceiverWorker
include ApplicationWorker
......
# frozen_string_literal: true
class EmailsOnPushWorker
include ApplicationWorker
......
# frozen_string_literal: true
class ExpireBuildArtifactsWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class ExpireBuildInstanceArtifactsWorker
include ApplicationWorker
......
# frozen_string_literal: true
class ExpireJobCacheWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class ExpirePipelineCacheWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class GitGarbageCollectWorker
include ApplicationWorker
......
# frozen_string_literal: true
class GitlabShellWorker
include ApplicationWorker
include Gitlab::ShellAdapter
......
# frozen_string_literal: true
class GitlabUsagePingWorker
LEASE_TIMEOUT = 86400
......
# frozen_string_literal: true
class GroupDestroyWorker
include ApplicationWorker
include ExceptionBacktrace
......
# frozen_string_literal: true
class ImportExportProjectCleanupWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class InvalidGpgSignatureUpdateWorker
include ApplicationWorker
......
# frozen_string_literal: true
require 'json'
require 'socket'
......@@ -69,8 +71,8 @@ class IrkerWorker
newbranch = "#{Gitlab.config.gitlab.url}/#{repo_path}/branches"
newbranch = "\x0302\x1f#{newbranch}\x0f" if @colors
privmsg = "[#{repo_name}] #{committer} has created a new branch "
privmsg += "#{branch}: #{newbranch}"
privmsg = "[#{repo_name}] #{committer} has created a new branch " \
"#{branch}: #{newbranch}"
sendtoirker privmsg
end
......@@ -112,9 +114,7 @@ class IrkerWorker
url = compare_url data, project.full_path
commits = colorize_commits data['total_commits_count']
new_commits = 'new commit'
new_commits += 's' if data['total_commits_count'] > 1
new_commits = 'new commit'.pluralize(data['total_commits_count'])
sendtoirker "[#{repo}] #{committer} pushed #{commits} #{new_commits} " \
"to #{branch}: #{url}"
end
......@@ -122,8 +122,8 @@ class IrkerWorker
def compare_url(data, repo_path)
sha1 = Commit.truncate_sha(data['before'])
sha2 = Commit.truncate_sha(data['after'])
compare_url = "#{Gitlab.config.gitlab.url}/#{repo_path}/compare"
compare_url += "/#{sha1}...#{sha2}"
compare_url = "#{Gitlab.config.gitlab.url}/#{repo_path}/compare" \
"/#{sha1}...#{sha2}"
colorize_url compare_url
end
......@@ -144,8 +144,7 @@ class IrkerWorker
def files_count(commit)
diff_size = commit.raw_deltas.size
files = "#{diff_size} file"
files += 's' if diff_size > 1
files = "#{diff_size} file".pluralize(diff_size)
files
end
......
# frozen_string_literal: true
class IssueDueSchedulerWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class MergeWorker
include ApplicationWorker
......
# frozen_string_literal: true
# Worker to destroy projects that do not have a namespace
#
# It destroys everything it can without having the info about the namespace it
......
# frozen_string_literal: true
class NewIssueWorker
include ApplicationWorker
include NewIssuable
......
# frozen_string_literal: true
class NewMergeRequestWorker
include ApplicationWorker
include NewIssuable
......
# frozen_string_literal: true
class NewNoteWorker
include ApplicationWorker
......
# frozen_string_literal: true
# @Deprecated - remove once the `object_storage_upload` queue is empty
# The queue has been renamed `object_storage:object_storage_background_upload`
#
......
# frozen_string_literal: true
class PagesDomainVerificationCronWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class PagesDomainVerificationWorker
include ApplicationWorker
......
# frozen_string_literal: true
class PagesWorker
include ApplicationWorker
......
# frozen_string_literal: true
class PipelineHooksWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class PipelineMetricsWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class PipelineNotificationWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class PipelineProcessWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class PipelineScheduleWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class PipelineSuccessWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class PipelineUpdateWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class PluginWorker
include ApplicationWorker
......
# frozen_string_literal: true
class PostReceive
include ApplicationWorker
prepend EE::PostReceive
......
# frozen_string_literal: true
# Worker for processing individiual commit messages pushed to a repository.
#
# Jobs for this worker are scheduled for every commit that is being pushed. As a
......
# frozen_string_literal: true
# Worker for updating any project specific caches.
class ProjectCacheWorker
include ApplicationWorker
......
# frozen_string_literal: true
class ProjectDestroyWorker
include ApplicationWorker
include ExceptionBacktrace
......
# frozen_string_literal: true
class ProjectExportWorker
include ApplicationWorker
include ExceptionBacktrace
......
# frozen_string_literal: true
class ProjectMigrateHashedStorageWorker
include ApplicationWorker
......
# frozen_string_literal: true
class ProjectServiceWorker
include ApplicationWorker
......
# frozen_string_literal: true
# Worker for updating any project specific caches.
class PropagateServiceTemplateWorker
include ApplicationWorker
......
# frozen_string_literal: true
class PruneOldEventsWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class ReactiveCachingWorker
include ApplicationWorker
......
# frozen_string_literal: true
class RebaseWorker
include ApplicationWorker
......
# frozen_string_literal: true
class RemoveExpiredGroupLinksWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class RemoveExpiredMembersWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class RemoveOldWebHookLogsWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class RemoveUnreferencedLfsObjectsWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class RepositoryArchiveCacheWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class RepositoryForkWorker
include ApplicationWorker
include Gitlab::ShellAdapter
......
# frozen_string_literal: true
class RepositoryImportWorker
include ApplicationWorker
include ExceptionBacktrace
......
# frozen_string_literal: true
class RepositoryRemoveRemoteWorker
include ApplicationWorker
include ExclusiveLeaseGuard
......
# frozen_string_literal: true
class RepositoryUpdateRemoteMirrorWorker
UpdateAlreadyInProgressError = Class.new(StandardError)
UpdateError = Class.new(StandardError)
......
# frozen_string_literal: true
class RequestsProfilesWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class RunPipelineScheduleWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class ScheduleUpdateUserActivityWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class StageUpdateWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class StorageMigratorWorker
include ApplicationWorker
......
# frozen_string_literal: true
class StuckCiJobsWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class StuckImportJobsWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class StuckMergeJobsWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class SystemHookPushWorker
include ApplicationWorker
......
# frozen_string_literal: true
class TrendingProjectsWorker
include ApplicationWorker
include CronjobQueue
......
# frozen_string_literal: true
class UpdateHeadPipelineForMergeRequestWorker
include ApplicationWorker
include PipelineQueue
......
# frozen_string_literal: true
class UpdateMergeRequestsWorker
include ApplicationWorker
......
# frozen_string_literal: true
class UpdateUserActivityWorker
include ApplicationWorker
......
# frozen_string_literal: true
class UploadChecksumWorker
include ApplicationWorker
......
# frozen_string_literal: true
class WaitForClusterCreationWorker
include ApplicationWorker
include ClusterQueue
......
# frozen_string_literal: true
class WebHookWorker
include ApplicationWorker
......
---
title: Keep lists ordered when copying only list items
merge_request: 18522
author: Jan Beckmann
type: fixed
---
title: Fix loading screen for search autocomplete dropdown
merge_request:
author:
type: fixed
---
title: Enable frozen string in app/workers/*.rb
merge_request: 19944
author: gfyoung
type: other
......@@ -493,13 +493,18 @@ module Gitlab
def tree_entry(path)
return unless path.present?
@repository.gitaly_migrate(:commit_tree_entry) do |is_migrated|
if is_migrated
gitaly_tree_entry(path)
else
rugged_tree_entry(path)
end
end
# We're only interested in metadata, so limit actual data to 1 byte
# since Gitaly doesn't support "send no data" option.
entry = @repository.gitaly_commit_client.tree_entry(id, path, 1)
return unless entry
# To be compatible with the rugged format
entry = entry.to_h
entry.delete(:data)
entry[:name] = File.basename(path)
entry[:type] = entry[:type].downcase
entry
end
def to_gitaly_commit
......@@ -562,28 +567,6 @@ module Gitlab
SERIALIZE_KEYS
end
def gitaly_tree_entry(path)
# We're only interested in metadata, so limit actual data to 1 byte
# since Gitaly doesn't support "send no data" option.
entry = @repository.gitaly_commit_client.tree_entry(id, path, 1)
return unless entry
# To be compatible with the rugged format
entry = entry.to_h
entry.delete(:data)
entry[:name] = File.basename(path)
entry[:type] = entry[:type].downcase
entry
end
# Is this the same as Blob.find_entry_by_path ?
def rugged_tree_entry(path)
rugged_commit.tree.path(path)
rescue Rugged::TreeError
nil
end
def gitaly_commit_author_from_rugged(author_or_committer)
Gitaly::CommitAuthor.new(
name: author_or_committer[:name].b,
......
......@@ -76,6 +76,13 @@ module Gitlab
end
def tree_entry(ref, path, limit = nil)
if Pathname.new(path).cleanpath.to_s.start_with?('../')
# The TreeEntry RPC should return an empty reponse in this case but in
# Gitaly 0.107.0 and earlier we get an exception instead. This early return
# saves us a Gitaly roundtrip while also avoiding the exception.
return
end
request = Gitaly::TreeEntryRequest.new(
repository: @gitaly_repo,
revision: encode_binary(ref),
......
......@@ -44,4 +44,59 @@ describe('CopyAsGFM', () => {
callPasteGFM();
});
});
describe('CopyAsGFM.copyGFM', () => {
// Stub getSelection to return a purpose-built object.
const stubSelection = (html, parentNode) => ({
getRangeAt: () => ({
commonAncestorContainer: { tagName: parentNode },
cloneContents: () => {
const fragment = document.createDocumentFragment();
const node = document.createElement('div');
node.innerHTML = html;
Array.from(node.childNodes).forEach((item) => fragment.appendChild(item));
return fragment;
},
}),
rangeCount: 1,
});
const clipboardData = {
setData() {},
};
const simulateCopy = () => {
const e = {
originalEvent: {
clipboardData,
},
preventDefault() {},
stopPropagation() {},
};
CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformGFMSelection);
return clipboardData;
};
beforeEach(() => spyOn(clipboardData, 'setData'));
describe('list handling', () => {
it('uses correct gfm for unordered lists', () => {
const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'UL');
spyOn(window, 'getSelection').and.returnValue(selection);
simulateCopy();
const expectedGFM = '- List Item1\n- List Item2';
expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
});
it('uses correct gfm for ordered lists', () => {
const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'OL');
spyOn(window, 'getSelection').and.returnValue(selection);
simulateCopy();
const expectedGFM = '1. List Item1\n1. List Item2';
expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
});
});
});
});
......@@ -19,7 +19,15 @@ describe('DiffLineNoteForm', () => {
diffLines,
line: diffLines[0],
noteTargetLine: diffLines[0],
}).$mount();
});
Object.defineProperty(component, 'isLoggedIn', {
get() {
return true;
},
});
component.$mount();
});
describe('methods', () => {
......@@ -56,6 +64,15 @@ describe('DiffLineNoteForm', () => {
});
});
describe('mounted', () => {
it('should init autosave', () => {
const key = 'autosave/Note/issue///DiffNote//1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_1';
expect(component.autosave).toBeDefined();
expect(component.autosave.key).toEqual(key);
});
});
describe('template', () => {
it('should have note form', () => {
const { $el } = component;
......
......@@ -514,30 +514,21 @@ eos
end
describe '#uri_type' do
shared_examples 'URI type' do
it 'returns the URI type at the given path' do
expect(commit.uri_type('files/html')).to be(:tree)
expect(commit.uri_type('files/images/logo-black.png')).to be(:raw)
expect(project.commit('video').uri_type('files/videos/intro.mp4')).to be(:raw)
expect(commit.uri_type('files/js/application.js')).to be(:blob)
end
it "returns nil if the path doesn't exists" do
expect(commit.uri_type('this/path/doesnt/exist')).to be_nil
end
it 'is nil if the path is nil or empty' do
expect(commit.uri_type(nil)).to be_nil
expect(commit.uri_type("")).to be_nil
end
it 'returns the URI type at the given path' do
expect(commit.uri_type('files/html')).to be(:tree)
expect(commit.uri_type('files/images/logo-black.png')).to be(:raw)
expect(project.commit('video').uri_type('files/videos/intro.mp4')).to be(:raw)
expect(commit.uri_type('files/js/application.js')).to be(:blob)
end
context 'when Gitaly commit_tree_entry feature is enabled' do
it_behaves_like 'URI type'
it "returns nil if the path doesn't exists" do
expect(commit.uri_type('this/path/doesnt/exist')).to be_nil
expect(commit.uri_type('../path/doesnt/exist')).to be_nil
end
context 'when Gitaly commit_tree_entry feature is disabled', :disable_gitaly do
it_behaves_like 'URI type'
it 'is nil if the path is nil or empty' do
expect(commit.uri_type(nil)).to be_nil
expect(commit.uri_type("")).to be_nil
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