Commit f91e92ef authored by Nick Thomas's avatar Nick Thomas

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2017-07-28

parents 5cae41b1 a770e807
Please view this file on the master branch, on stable branches it's out of date.
## 9.4.3 (2017-07-31)
- Present Related Issues widget for logged-out users when available.
## 9.4.2 (2017-07-28)
- Adds lower bound to pull mirror scheduling feature. !2366
......
......@@ -2,6 +2,16 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 9.4.3 (2017-07-31)
- Fix Prometheus client PID reuse bug. !13130
- Improve deploy environment chatops slash command. !13150
- Fix asynchronous javascript paths when GitLab is installed under a relative URL. !13165
- Fix LDAP authentication to Git repository or container registry.
- Fixed new navigation breadcrumb title on help pages.
- Ensure filesystem metrics test files are deleted.
- Properly affixes nav bar in job view in microsoft edge.
## 9.4.2 (2017-07-28)
- Fix job merge request link to a forked source project. !12965
......
......@@ -8,6 +8,7 @@ import BlobFileDropzone from '../blob/blob_file_dropzone';
$(() => {
const editBlobForm = $('.js-edit-blob-form');
const uploadBlobForm = $('.js-upload-blob-form');
const deleteBlobForm = $('.js-delete-blob-form');
if (editBlobForm.length) {
const urlRoot = editBlobForm.data('relative-url-root');
......@@ -30,4 +31,8 @@ $(() => {
'.btn-upload-file',
);
}
if (deleteBlobForm.length) {
new NewCommitForm(deleteBlobForm);
}
});
......@@ -8,6 +8,8 @@
/* global LabelsSelect */
/* global MilestoneSelect */
/* global Commit */
/* global CommitsList */
/* global NewCommitForm */
/* global NewBranchForm */
/* global NotificationsForm */
/* global NotificationsDropdown */
......@@ -25,10 +27,13 @@
/* global Compare */
/* global CompareAutocomplete */
/* global PathLocks */
/* global ProjectFindFile */
/* global ProjectNew */
/* global ProjectShow */
/* global ProjectImport */
/* global Labels */
/* global Shortcuts */
/* global ShortcutsFindFile */
/* global Sidebar */
/* global WeightSelect */
/* global AdminEmailSelect */
......@@ -226,6 +231,10 @@ import AuditLogs from './audit_logs';
case 'projects:compare:show':
new gl.Diff();
break;
case 'projects:branches:new':
case 'projects:branches:create':
new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML));
break;
case 'projects:branches:index':
gl.AjaxLoadingSpinner.init();
new DeleteModal();
......@@ -312,22 +321,36 @@ import AuditLogs from './audit_logs';
container: '.js-commit-pipeline-graph',
}).bindEvents();
initNotes();
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
break;
case 'projects:commit:pipelines':
new MiniPipelineGraph({
container: '.js-commit-pipeline-graph',
}).bindEvents();
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
break;
<<<<<<< HEAD
case 'projects:commits:show':
shortcut_handler = new ShortcutsNavigation();
GpgBadges.fetch();
break;
=======
>>>>>>> upstream/master
case 'projects:activity':
new gl.Activities();
shortcut_handler = new ShortcutsNavigation();
break;
case 'projects:commits:show':
CommitsList.init(document.querySelector('.js-project-commits-show').dataset.commitsLimit);
new gl.Activities();
shortcut_handler = new ShortcutsNavigation();
break;
case 'projects:edit':
new UsersSelect();
break;
case 'projects:imports:show':
new ProjectImport();
break;
case 'projects:show':
shortcut_handler = new ShortcutsNavigation();
new NotificationsForm();
......@@ -397,6 +420,7 @@ import AuditLogs from './audit_logs';
shortcut_handler = new ShortcutsNavigation();
new TreeView();
new BlobViewer();
new NewCommitForm($('.js-create-dir-form'));
if (document.querySelector('.js-tree-content').dataset.pathLocksAvailable === 'true') {
PathLocks.init(
......@@ -410,6 +434,13 @@ import AuditLogs from './audit_logs';
});
break;
case 'projects:find_file:show':
const findElement = document.querySelector('.js-file-finder');
const projectFindFile = new ProjectFindFile($(".file-finder-holder"), {
url: findElement.dataset.fileFindUrl,
treeUrl: findElement.dataset.findTreeUrl,
blobUrlTemplate: findElement.dataset.blobUrlTemplate,
});
new ShortcutsFindFile(projectFindFile);
shortcut_handler = true;
break;
case 'projects:blob:show':
......
import Chart from 'vendor/Chart';
import ContributorsStatGraph from './stat_graph_contributors';
// export to global scope
window.Chart = Chart;
window.ContributorsStatGraph = ContributorsStatGraph;
import Chart from 'vendor/Chart';
document.addEventListener('DOMContentLoaded', () => {
const projectChartData = JSON.parse(document.getElementById('projectChartData').innerHTML);
const responsiveChart = (selector, data) => {
const options = {
scaleOverlay: true,
responsive: true,
pointHitDetectionRadius: 2,
maintainAspectRatio: false,
};
// get selector by context
const ctx = selector.get(0).getContext('2d');
// pointing parent container to make chart.js inherit its width
const container = $(selector).parent();
const generateChart = () => {
selector.attr('width', $(container).width());
if (window.innerWidth < 768) {
// Scale fonts if window width lower than 768px (iPad portrait)
options.scaleFontSize = 8;
}
return new Chart(ctx).Bar(data, options);
};
// enabling auto-resizing
$(window).resize(generateChart);
return generateChart();
};
const chartData = (keys, values) => {
const data = {
labels: keys,
datasets: [{
fillColor: 'rgba(220,220,220,0.5)',
strokeColor: 'rgba(220,220,220,1)',
barStrokeWidth: 1,
barValueSpacing: 1,
barDatasetSpacing: 1,
data: values,
}],
};
return data;
};
const hourData = chartData(projectChartData.hour.keys, projectChartData.hour.values);
responsiveChart($('#hour-chart'), hourData);
const dayData = chartData(projectChartData.weekDays.keys, projectChartData.weekDays.values);
responsiveChart($('#weekday-chart'), dayData);
const monthData = chartData(projectChartData.month.keys, projectChartData.month.values);
responsiveChart($('#month-chart'), monthData);
const data = projectChartData.languages;
const ctx = $('#languages-chart').get(0).getContext('2d');
const options = {
scaleOverlay: true,
responsive: true,
maintainAspectRatio: false,
};
new Chart(ctx).Pie(data, options);
});
import ContributorsStatGraph from './stat_graph_contributors';
document.addEventListener('DOMContentLoaded', () => {
$.ajax({
type: 'GET',
url: document.querySelector('.js-graphs-show').dataset.projectGraphPath,
dataType: 'json',
success(data) {
const graph = new ContributorsStatGraph();
graph.init(data);
$('#brush_change').change(() => {
graph.change_date_header();
graph.redraw_authors();
});
$('.stat-graph').fadeIn();
$('.loading-graph').hide();
},
});
});
/* global U2FRegister */
document.addEventListener('DOMContentLoaded', () => {
const twoFactorNode = document.querySelector('.js-two-factor-auth');
const skippable = twoFactorNode.dataset.twoFactorSkippable === 'true';
if (skippable) {
const button = `<a class="btn btn-xs btn-warning pull-right" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>`;
const flashAlert = document.querySelector('.flash-alert .container-fluid');
if (flashAlert) flashAlert.insertAdjacentHTML('beforeend', button);
}
const u2fRegister = new U2FRegister($('#js-register-u2f'), gon.u2f);
u2fRegister.start();
});
import Api from './api';
document.addEventListener('DOMContentLoaded', () => {
$('#js-project-dropdown').glDropdown({
data: (term, callback) => {
Api.projects(term, {
order_by: 'last_activity_at',
}, (data) => {
callback(data);
});
},
text: project => (project.name_with_namespace || project.name),
selectable: true,
fieldName: 'author_id',
filterable: true,
search: {
fields: ['name_with_namespace'],
},
id: data => data.id,
isSelected: data => (data.id === 2),
});
});
......@@ -8,7 +8,7 @@ module EE
end
def geo_primary_ssh_url_to_repo(project)
"#{::Gitlab::Geo.primary_node.clone_url_prefix}#{project.path_with_namespace}.git"
"#{::Gitlab::Geo.primary_node.clone_url_prefix}#{project.full_path}.git"
end
def geo_primary_http_url_to_repo(project)
......
......@@ -40,7 +40,7 @@ module MergeRequestsHelper
def merge_path_description(merge_request, separator)
if merge_request.for_fork?
"Project:Branches: #{@merge_request.source_project_path}:#{@merge_request.source_branch} #{separator} #{@merge_request.target_project.path_with_namespace}:#{@merge_request.target_branch}"
"Project:Branches: #{@merge_request.source_project_path}:#{@merge_request.source_branch} #{separator} #{@merge_request.target_project.full_path}:#{@merge_request.target_branch}"
else
"Branches: #{@merge_request.source_branch} #{separator} #{@merge_request.target_branch}"
end
......
......@@ -417,7 +417,7 @@ module ProjectsHelper
if project
import_path = "/Home/Stacks/import"
repo = project.path_with_namespace
repo = project.full_path
branch ||= project.default_branch
sha ||= project.commit.short_id
......@@ -491,7 +491,7 @@ module ProjectsHelper
def readme_cache_key
sha = @project.commit.try(:sha) || 'nil'
[@project.path_with_namespace, sha, "readme"].join('-')
[@project.full_path, sha, "readme"].join('-')
end
def current_ref
......
......@@ -169,7 +169,7 @@ class Notify < BaseMailer
headers['X-GitLab-Project'] = @project.name
headers['X-GitLab-Project-Id'] = @project.id
headers['X-GitLab-Project-Path'] = @project.path_with_namespace
headers['X-GitLab-Project-Path'] = @project.full_path
end
def add_unsubscription_headers_and_links
......
......@@ -330,7 +330,7 @@ module Ci
return @config_processor if defined?(@config_processor)
@config_processor ||= begin
Ci::GitlabCiYamlProcessor.new(ci_yaml_file, project.path_with_namespace)
Ci::GitlabCiYamlProcessor.new(ci_yaml_file, project.full_path)
rescue Ci::GitlabCiYamlProcessor::ValidationError, Psych::SyntaxError => e
self.yaml_errors = e.message
nil
......
......@@ -4,11 +4,11 @@ module RepositoryMirroring
end
def push_remote_branches(remote, branches)
gitlab_shell.push_remote_branches(storage_path, path_with_namespace, remote, branches)
gitlab_shell.push_remote_branches(storage_path, disk_path, remote, branches)
end
def delete_remote_branches(remote, branches)
gitlab_shell.delete_remote_branches(storage_path, path_with_namespace, remote, branches)
gitlab_shell.delete_remote_branches(storage_path, disk_path, remote, branches)
end
def set_remote_as_mirror(name)
......@@ -28,7 +28,7 @@ module RepositoryMirroring
end
def remote_tags(remote)
gitlab_shell.list_remote_tags(storage_path, path_with_namespace, remote).map do |name, target|
gitlab_shell.list_remote_tags(storage_path, disk_path, remote).map do |name, target|
target_commit = Gitlab::Git::Commit.find(raw_repository, target)
Gitlab::Git::Tag.new(raw_repository, name, target, target_commit)
end
......
module Storage
module LegacyNamespace
extend ActiveSupport::Concern
def move_dir
if any_project_has_container_registry_tags?
raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has tags in container registry')
end
# Move the namespace directory in all storage paths used by member projects
repository_storage_paths.each do |repository_storage_path|
# Ensure old directory exists before moving it
gitlab_shell.add_namespace(repository_storage_path, full_path_was)
unless gitlab_shell.mv_namespace(repository_storage_path, full_path_was, full_path)
Rails.logger.error "Exception moving path #{repository_storage_path} from #{full_path_was} to #{full_path}"
# if we cannot move namespace directory we should rollback
# db changes in order to prevent out of sync between db and fs
raise Gitlab::UpdatePathError.new('namespace directory cannot be moved')
end
end
Gitlab::UploadsTransfer.new.rename_namespace(full_path_was, full_path)
Gitlab::PagesTransfer.new.rename_namespace(full_path_was, full_path)
remove_exports!
# If repositories moved successfully we need to
# send update instructions to users.
# However we cannot allow rollback since we moved namespace dir
# So we basically we mute exceptions in next actions
begin
send_update_instructions
true
rescue
# Returning false does not rollback after_* transaction but gives
# us information about failing some of tasks
false
end
end
# Hooks
# Save the storage paths before the projects are destroyed to use them on after destroy
def prepare_for_destroy
old_repository_storage_paths
end
private
def old_repository_storage_paths
@old_repository_storage_paths ||= repository_storage_paths
end
def repository_storage_paths
# We need to get the storage paths for all the projects, even the ones that are
# pending delete. Unscoping also get rids of the default order, which causes
# problems with SELECT DISTINCT.
Project.unscoped do
all_projects.select('distinct(repository_storage)').to_a.map(&:repository_storage_path)
end
end
def rm_dir
# Remove the namespace directory in all storages paths used by member projects
old_repository_storage_paths.each do |repository_storage_path|
# Move namespace directory into trash.
# We will remove it later async
new_path = "#{full_path}+#{id}+deleted"
if gitlab_shell.mv_namespace(repository_storage_path, full_path, new_path)
Gitlab::AppLogger.info %Q(Namespace directory "#{full_path}" moved to "#{new_path}")
# Remove namespace directroy async with delay so
# GitLab has time to remove all projects first
run_after_commit do
GitlabShellWorker.perform_in(5.minutes, :rm_namespace, repository_storage_path, new_path)
end
end
end
remove_exports!
end
def remove_exports!
Gitlab::Popen.popen(%W(find #{export_path} -not -path #{export_path} -delete))
end
def export_path
File.join(Gitlab::ImportExport.storage_path, full_path_was)
end
def full_path_was
if parent
parent.full_path + '/' + path_was
else
path_was
end
end
end
end
module Storage
module LegacyProject
extend ActiveSupport::Concern
def disk_path
full_path
end
def ensure_storage_path_exist
gitlab_shell.add_namespace(repository_storage_path, namespace.full_path)
end
def rename_repo
path_was = previous_changes['path'].first
old_path_with_namespace = File.join(namespace.full_path, path_was)
new_path_with_namespace = File.join(namespace.full_path, path)
Rails.logger.error "Attempting to rename #{old_path_with_namespace} -> #{new_path_with_namespace}"
if has_container_registry_tags?
Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present!"
# we currently doesn't support renaming repository if it contains images in container registry
raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
end
expire_caches_before_rename(old_path_with_namespace)
if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace)
# If repository moved successfully we need to send update instructions to users.
# However we cannot allow rollback since we moved repository
# So we basically we mute exceptions in next actions
begin
gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
send_move_instructions(old_path_with_namespace)
expires_full_path_cache
@old_path_with_namespace = old_path_with_namespace
SystemHooksService.new.execute_hooks_for(self, :rename)
@repository = nil
rescue => e
Rails.logger.error "Exception renaming #{old_path_with_namespace} -> #{new_path_with_namespace}: #{e}"
# Returning false does not rollback after_* transaction but gives
# us information about failing some of tasks
false
end
else
Rails.logger.error "Repository could not be renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
# if we cannot move namespace directory we should rollback
# db changes in order to prevent out of sync between db and fs
raise StandardError.new('repository cannot be renamed')
end
Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.full_path)
Gitlab::PagesTransfer.new.rename_project(path_was, path, namespace.full_path)
end
def create_repository(force: false)
# Forked import is handled asynchronously
return if forked? && !force
if gitlab_shell.add_repository(repository_storage_path, path_with_namespace)
repository.after_create
true
else
errors.add(:base, 'Failed to create repository via gitlab-shell')
false
end
end
end
end
module Storage
module LegacyProjectWiki
extend ActiveSupport::Concern
def disk_path
project.disk_path + '.wiki'
end
end
end
module Storage
module LegacyRepository
extend ActiveSupport::Concern
delegate :disk_path, to: :project
end
end
......@@ -441,6 +441,7 @@ module EE
end
alias_method :merge_requests_ff_only_enabled?, :merge_requests_ff_only_enabled
# TODO: check storage type and NOOP when not using Legacy
def rename_repo
raise NotImplementedError unless defined?(super)
......
......@@ -651,7 +651,7 @@ class MergeRequest < ActiveRecord::Base
def target_project_path
if target_project
target_project.path_with_namespace
target_project.full_path
else
"(removed)"
end
......@@ -659,7 +659,7 @@ class MergeRequest < ActiveRecord::Base
def source_project_path
if source_project
source_project.path_with_namespace
source_project.full_path
else
"(removed)"
end
......
......@@ -9,6 +9,7 @@ class Namespace < ActiveRecord::Base
include Gitlab::VisibilityLevel
include Routable
include AfterCommitQueue
include Storage::LegacyNamespace
# Prevent users from creating unreasonably deep level of nesting.
# The number 20 was taken based on maximum nesting level of
......@@ -42,10 +43,11 @@ class Namespace < ActiveRecord::Base
delegate :name, to: :owner, allow_nil: true, prefix: true
after_update :move_dir, if: :path_changed?
after_commit :refresh_access_of_projects_invited_groups, on: :update, if: -> { previous_changes.key?('share_with_group_lock') }
# Save the storage paths before the projects are destroyed to use them on after destroy
# Legacy Storage specific hooks
after_update :move_dir, if: :path_changed?
before_destroy(prepend: true) { prepare_for_destroy }
after_destroy :rm_dir
......@@ -119,44 +121,6 @@ class Namespace < ActiveRecord::Base
owner_name
end
def move_dir
if any_project_has_container_registry_tags?
raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has tags in container registry')
end
# Move the namespace directory in all storages paths used by member projects
repository_storage_paths.each do |repository_storage_path|
# Ensure old directory exists before moving it
gitlab_shell.add_namespace(repository_storage_path, full_path_was)
unless gitlab_shell.mv_namespace(repository_storage_path, full_path_was, full_path)
Rails.logger.error "Exception moving path #{repository_storage_path} from #{full_path_was} to #{full_path}"
# if we cannot move namespace directory we should rollback
# db changes in order to prevent out of sync between db and fs
raise Gitlab::UpdatePathError.new('namespace directory cannot be moved')
end
end
Gitlab::UploadsTransfer.new.rename_namespace(full_path_was, full_path)
Gitlab::PagesTransfer.new.rename_namespace(full_path_was, full_path)
remove_exports!
# If repositories moved successfully we need to
# send update instructions to users.
# However we cannot allow rollback since we moved namespace dir
# So we basically we mute exceptions in next actions
begin
send_update_instructions
true
rescue
# Returning false does not rollback after_* transaction but gives
# us information about failing some of tasks
false
end
end
def any_project_has_container_registry_tags?
all_projects.any?(&:has_container_registry_tags?)
end
......@@ -212,14 +176,6 @@ class Namespace < ActiveRecord::Base
parent_id_changed?
end
def prepare_for_destroy
old_repository_storage_paths
end
def old_repository_storage_paths
@old_repository_storage_paths ||= repository_storage_paths
end
# Includes projects from this namespace and projects from all subgroups
# that belongs to this namespace
def all_projects
......@@ -238,37 +194,6 @@ class Namespace < ActiveRecord::Base
private
def repository_storage_paths
# We need to get the storage paths for all the projects, even the ones that are
# pending delete. Unscoping also get rids of the default order, which causes
# problems with SELECT DISTINCT.
Project.unscoped do
all_projects.select('distinct(repository_storage)').to_a.map(&:repository_storage_path)
end
end
def rm_dir
# Remove the namespace directory in all storages paths used by member projects
old_repository_storage_paths.each do |repository_storage_path|
# Move namespace directory into trash.
# We will remove it later async
new_path = "#{full_path}+#{id}+deleted"
if gitlab_shell.mv_namespace(repository_storage_path, full_path, new_path)
message = "Namespace directory \"#{full_path}\" moved to \"#{new_path}\""
Gitlab::AppLogger.info message
# Remove namespace directroy async with delay so
# GitLab has time to remove all projects first
run_after_commit do
GitlabShellWorker.perform_in(5.minutes, :rm_namespace, repository_storage_path, new_path)
end
end
end
remove_exports!
end
def refresh_access_of_projects_invited_groups
Group
.joins(project_group_links: :project)
......@@ -276,22 +201,6 @@ class Namespace < ActiveRecord::Base
.find_each(&:refresh_members_authorized_projects)
end
def remove_exports!
Gitlab::Popen.popen(%W(find #{export_path} -not -path #{export_path} -delete))
end
def export_path
File.join(Gitlab::ImportExport.storage_path, full_path_was)
end
def full_path_was
if parent
parent.full_path + '/' + path_was
else
path_was
end
end
def nesting_level_allowed
if ancestors.count > Group::NUMBER_OF_ANCESTORS_ALLOWED
errors.add(:parent_id, "has too deep level of nesting")
......
......@@ -17,6 +17,7 @@ class Project < ActiveRecord::Base
include ProjectFeaturesCompatibility
include SelectForProjectAuthorization
include Routable
include Storage::LegacyProject
# EE specific modules
prepend EE::Project
......@@ -46,9 +47,8 @@ class Project < ActiveRecord::Base
default_value_for :snippets_enabled, gitlab_config_features.snippets
default_value_for :only_allow_merge_if_all_discussions_are_resolved, false
after_create :ensure_dir_exist
after_create :ensure_storage_path_exist
after_create :create_project_feature, unless: :project_feature
after_save :ensure_dir_exist, if: :namespace_id_changed?
after_save :update_project_statistics, if: :namespace_id_changed?
# set last_activity_at to the same as created_at
......@@ -70,6 +70,10 @@ class Project < ActiveRecord::Base
after_validation :check_pending_delete
# Legacy Storage specific hooks
after_save :ensure_storage_path_exist, if: :namespace_id_changed?
acts_as_taggable
attr_accessor :new_default_branch
......@@ -374,7 +378,7 @@ class Project < ActiveRecord::Base
begin
Projects::HousekeepingService.new(project).execute
rescue Projects::HousekeepingService::LeaseTaken => e
Rails.logger.info("Could not perform housekeeping for project #{project.path_with_namespace} (#{project.id}): #{e}")
Rails.logger.info("Could not perform housekeeping for project #{project.full_path} (#{project.id}): #{e}")
end
end
end
......@@ -475,12 +479,12 @@ class Project < ActiveRecord::Base
end
def repository
@repository ||= Repository.new(path_with_namespace, self)
@repository ||= Repository.new(full_path, self, disk_path: disk_path)
end
def container_registry_url
if Gitlab.config.registry.enabled
"#{Gitlab.config.registry.host_port}/#{path_with_namespace.downcase}"
"#{Gitlab.config.registry.host_port}/#{full_path.downcase}"
end
end
......@@ -519,16 +523,16 @@ class Project < ActiveRecord::Base
job_id =
if forked?
RepositoryForkWorker.perform_async(id, forked_from_project.repository_storage_path,
forked_from_project.path_with_namespace,
forked_from_project.full_path,
self.namespace.full_path)
else
RepositoryImportWorker.perform_async(self.id)
end
if job_id
Rails.logger.info "Import job started for #{path_with_namespace} with job ID #{job_id}"
Rails.logger.info "Import job started for #{full_path} with job ID #{job_id}"
else
Rails.logger.error "Import job failed to start for #{path_with_namespace}"
Rails.logger.error "Import job failed to start for #{full_path}"
end
end
......@@ -689,7 +693,7 @@ class Project < ActiveRecord::Base
# `from` argument can be a Namespace or Project.
def to_reference(from = nil, full: false)
if full || cross_namespace_reference?(from)
path_with_namespace
full_path
elsif cross_project_reference?(from)
path
end
......@@ -713,7 +717,7 @@ class Project < ActiveRecord::Base
author.ensure_incoming_email_token!
Gitlab::IncomingEmail.reply_address(
"#{path_with_namespace}+#{author.incoming_email_token}")
"#{full_path}+#{author.incoming_email_token}")
end
def build_commit_note(commit)
......@@ -940,7 +944,7 @@ class Project < ActiveRecord::Base
end
def url_to_repo
gitlab_shell.url_to_repo(path_with_namespace)
gitlab_shell.url_to_repo(full_path)
end
def repo_exists?
......@@ -973,58 +977,9 @@ class Project < ActiveRecord::Base
!group
end
def rename_repo
path_was = previous_changes['path'].first
old_path_with_namespace = File.join(namespace.full_path, path_was)
new_path_with_namespace = File.join(namespace.full_path, path)
Rails.logger.error "Attempting to rename #{old_path_with_namespace} -> #{new_path_with_namespace}"
if has_container_registry_tags?
Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present!"
# we currently doesn't support renaming repository if it contains images in container registry
raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
end
expire_caches_before_rename(old_path_with_namespace)
if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace)
# If repository moved successfully we need to send update instructions to users.
# However we cannot allow rollback since we moved repository
# So we basically we mute exceptions in next actions
begin
gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
send_move_instructions(old_path_with_namespace)
expires_full_path_cache
@old_path_with_namespace = old_path_with_namespace
SystemHooksService.new.execute_hooks_for(self, :rename)
@repository = nil
rescue => e
Rails.logger.error "Exception renaming #{old_path_with_namespace} -> #{new_path_with_namespace}: #{e}"
# Returning false does not rollback after_* transaction but gives
# us information about failing some of tasks
false
end
else
Rails.logger.error "Repository could not be renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
# if we cannot move namespace directory we should rollback
# db changes in order to prevent out of sync between db and fs
raise StandardError.new('repository cannot be renamed')
end
Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.full_path)
Gitlab::PagesTransfer.new.rename_project(path_was, path, namespace.full_path)
end
# Expires various caches before a project is renamed.
def expire_caches_before_rename(old_path)
# TODO: if we start using UUIDs for cache, we don't need to do this HACK anymore
repo = Repository.new(old_path, self)
wiki = Repository.new("#{old_path}.wiki", self)
......@@ -1047,7 +1002,7 @@ class Project < ActiveRecord::Base
git_http_url: http_url_to_repo,
namespace: namespace.name,
visibility_level: visibility_level,
path_with_namespace: path_with_namespace,
path_with_namespace: full_path,
default_branch: default_branch,
ci_config_path: ci_config_path
}
......@@ -1108,19 +1063,6 @@ class Project < ActiveRecord::Base
merge_requests.where(source_project_id: self.id)
end
def create_repository(force: false)
# Forked import is handled asynchronously
return if forked? && !force
if gitlab_shell.add_repository(repository_storage_path, path_with_namespace)
repository.after_create
true
else
errors.add(:base, 'Failed to create repository via gitlab-shell')
false
end
end
def ensure_repository
create_repository(force: true) unless repository_exists?
end
......@@ -1256,7 +1198,7 @@ class Project < ActiveRecord::Base
end
def pages_path
File.join(Settings.pages.path, path_with_namespace)
File.join(Settings.pages.path, disk_path)
end
def public_pages_path
......@@ -1267,6 +1209,7 @@ class Project < ActiveRecord::Base
deploy_keys.where(public: false).delete_all
end
# TODO: what to do here when not using Legacy Storage? Do we still need to rename and delay removal?
def remove_pages
::Projects::UpdatePagesConfigurationService.new(self).execute
......@@ -1314,7 +1257,7 @@ class Project < ActiveRecord::Base
end
def export_path
File.join(Gitlab::ImportExport.storage_path, path_with_namespace)
File.join(Gitlab::ImportExport.storage_path, disk_path)
end
def export_project_path
......@@ -1326,16 +1269,12 @@ class Project < ActiveRecord::Base
status.zero?
end
def ensure_dir_exist
gitlab_shell.add_namespace(repository_storage_path, namespace.full_path)
end
def predefined_variables
[
{ key: 'CI_PROJECT_ID', value: id.to_s, public: true },
{ key: 'CI_PROJECT_NAME', value: path, public: true },
{ key: 'CI_PROJECT_PATH', value: path_with_namespace, public: true },
{ key: 'CI_PROJECT_PATH_SLUG', value: path_with_namespace.parameterize, public: true },
{ key: 'CI_PROJECT_PATH', value: full_path, public: true },
{ key: 'CI_PROJECT_PATH_SLUG', value: full_path.parameterize, public: true },
{ key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path, public: true },
{ key: 'CI_PROJECT_URL', value: web_url, public: true }
]
......@@ -1440,6 +1379,7 @@ class Project < ActiveRecord::Base
alias_method :name_with_namespace, :full_name
alias_method :human_name, :full_name
# @deprecated cannot remove yet because it has an index with its name in elasticsearch
alias_method :path_with_namespace, :full_path
private
......@@ -1494,7 +1434,7 @@ class Project < ActiveRecord::Base
def pending_delete_twin
return false unless path
Project.pending_delete.find_by_full_path(path_with_namespace)
Project.pending_delete.find_by_full_path(full_path)
end
##
......
......@@ -35,9 +35,9 @@ class FlowdockService < Service
data[:after],
token: token,
repo: project.repository.path_to_repo,
repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}",
commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s",
diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s"
repo_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}",
commit_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/commit/%s",
diff_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/compare/%s...%s"
)
end
end
......@@ -140,7 +140,7 @@ class JiraService < IssueTrackerService
url: resource_url(user_path(author))
},
project: {
name: project.path_with_namespace,
name: project.full_path,
url: resource_url(namespace_project_path(project.namespace, project)) # rubocop:disable Cop/ProjectPathHelper
},
entity: {
......
......@@ -2,6 +2,7 @@ class ProjectWiki
include Gitlab::ShellAdapter
include Elastic::WikiRepositoriesSearch
include Gitlab::CurrentSettings
include Storage::LegacyProjectWiki
MARKUPS = {
'Markdown' => :markdown,
......@@ -28,16 +29,19 @@ class ProjectWiki
@project.path + '.wiki'
end
def path_with_namespace
@project.path_with_namespace + ".wiki"
def full_path
@project.full_path + '.wiki'
end
# @deprecated use full_path when you need it for an URL route or disk_path when you want to point to the filesystem
alias_method :path_with_namespace, :full_path
def web_url
Gitlab::Routing.url_helpers.project_wiki_url(@project, :home)
end
def url_to_repo
gitlab_shell.url_to_repo(path_with_namespace)
gitlab_shell.url_to_repo(full_path)
end
def ssh_url_to_repo
......@@ -45,16 +49,16 @@ class ProjectWiki
end
def http_url_to_repo
"#{Gitlab.config.gitlab.url}/#{path_with_namespace}.git"
"#{Gitlab.config.gitlab.url}/#{full_path}.git"
end
# No need to have a Kerberos Web url. Kerberos URL will be used only to clone
def kerberos_url_to_repo
[Gitlab.config.build_gitlab_kerberos_url, "/", path_with_namespace, ".git"].join('')
[Gitlab.config.build_gitlab_kerberos_url, '/', full_path, '.git'].join('')
end
def wiki_base_path
[Gitlab.config.gitlab.relative_url_root, "/", @project.path_with_namespace, "/wikis"].join('')
[Gitlab.config.gitlab.relative_url_root, '/', @project.full_path, '/wikis'].join('')
end
# Returns the Gollum::Wiki object.
......@@ -147,7 +151,7 @@ class ProjectWiki
end
def repository
@repository ||= Repository.new(path_with_namespace, @project)
@repository ||= Repository.new(full_path, @project, disk_path: disk_path)
end
def default_branch
......@@ -155,7 +159,7 @@ class ProjectWiki
end
def create_repo!
if init_repo(path_with_namespace)
if init_repo(disk_path)
wiki = Gollum::Wiki.new(path_to_repo)
else
raise CouldNotCreateWikiError
......@@ -175,15 +179,15 @@ class ProjectWiki
web_url: web_url,
git_ssh_url: ssh_url_to_repo,
git_http_url: http_url_to_repo,
path_with_namespace: path_with_namespace,
path_with_namespace: full_path,
default_branch: default_branch
}
end
private
def init_repo(path_with_namespace)
gitlab_shell.add_repository(project.repository_storage_path, path_with_namespace)
def init_repo(disk_path)
gitlab_shell.add_repository(project.repository_storage_path, disk_path)
end
def commit_details(action, message = nil, title = nil)
......@@ -197,7 +201,7 @@ class ProjectWiki
end
def path_to_repo
@path_to_repo ||= File.join(project.repository_storage_path, "#{path_with_namespace}.git")
@path_to_repo ||= File.join(project.repository_storage_path, "#{disk_path}.git")
end
def update_project_activity
......
......@@ -8,7 +8,7 @@ class Repository
include RepositoryMirroring
prepend EE::Repository
attr_accessor :path_with_namespace, :project
attr_accessor :full_path, :disk_path, :project
delegate :ref_name_for_sha, to: :raw_repository
......@@ -59,13 +59,14 @@ class Repository
end
end
def initialize(path_with_namespace, project)
@path_with_namespace = path_with_namespace
def initialize(full_path, project, disk_path: nil)
@full_path = full_path
@disk_path = disk_path || full_path
@project = project
end
def raw_repository
return nil unless path_with_namespace
return nil unless full_path
@raw_repository ||= initialize_raw_repository
end
......@@ -73,7 +74,7 @@ class Repository
# Return absolute path to repository
def path_to_repo
@path_to_repo ||= File.expand_path(
File.join(repository_storage_path, path_with_namespace + ".git")
File.join(repository_storage_path, disk_path + '.git')
)
end
......@@ -476,7 +477,7 @@ class Repository
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/314
def exists?
return false unless path_with_namespace
return false unless full_path
Gitlab::GitalyClient.migrate(:repository_exists) do |enabled|
if enabled
......@@ -1079,7 +1080,7 @@ class Repository
end
def fetch_remote(remote, forced: false, no_tags: false)
gitlab_shell.fetch_remote(repository_storage_path, path_with_namespace, remote, forced: forced, no_tags: no_tags)
gitlab_shell.fetch_remote(repository_storage_path, disk_path, remote, forced: forced, no_tags: no_tags)
end
def fetch_ref(source_path, source_ref, target_ref)
......@@ -1184,7 +1185,8 @@ class Repository
end
def cache
@cache ||= RepositoryCache.new(path_with_namespace, @project.id)
# TODO: should we use UUIDs here? We could move repositories without clearing this cache
@cache ||= RepositoryCache.new(full_path, @project.id)
end
def tags_sorted_by_committed_date
......@@ -1207,7 +1209,7 @@ class Repository
end
def repository_event(event, tags = {})
Gitlab::Metrics.add_event(event, { path: path_with_namespace }.merge(tags))
Gitlab::Metrics.add_event(event, { path: full_path }.merge(tags))
end
def create_commit(params = {})
......@@ -1221,6 +1223,6 @@ class Repository
end
def initialize_raw_repository
Gitlab::Git::Repository.new(project.repository_storage, path_with_namespace + '.git')
Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git')
end
end
......@@ -32,7 +32,6 @@ module Ci
return unless can?(job.user, :read_project, project)
return error("400 Job has to be running", 400) unless job.running?
return error("400 Variables not supported", 400) if params[:variables].any?
pipeline = Ci::CreatePipelineService.new(project, job.user, ref: params[:ref])
.execute(:pipeline, ignore_skip_ci: true) do |pipeline|
......@@ -41,6 +40,8 @@ module Ci
source_project: job.project,
pipeline: pipeline,
project: project)
create_pipeline_variables!(pipeline)
end
if pipeline.persisted?
......
......@@ -49,7 +49,7 @@ module Geo
message: message,
error: error,
project_id: project.id,
project_path: project.path_with_namespace)
project_path: project.full_path)
end
end
end
......@@ -16,7 +16,7 @@ module Geo
project.expire_caches_before_rename(old_path_with_namespace)
# Make sure target directory exists (used when transfering repositories)
project.ensure_dir_exist
project.ensure_storage_path_exist
if gitlab_shell.mv_repository(project.repository_storage_path,
old_path_with_namespace, new_path_with_namespace)
......
......@@ -27,7 +27,7 @@ module Geo
end
def new_wiki_path_with_namespace
project.wiki.path_with_namespace
project.wiki.full_path
end
end
end
......@@ -33,7 +33,7 @@ module Geo
end
def ssh_url_to_repo
"#{primary_ssh_path_prefix}#{project.path_with_namespace}.git"
"#{primary_ssh_path_prefix}#{project.full_path}.git"
end
end
end
......@@ -26,7 +26,7 @@ module Geo
end
def ssh_url_to_wiki
"#{primary_ssh_path_prefix}#{project.path_with_namespace}.wiki.git"
"#{primary_ssh_path_prefix}#{project.full_path}.wiki.git"
end
end
end
......@@ -60,7 +60,7 @@ class GitOperationService
start_branch_name = nil if start_repository.empty_repo?
if start_branch_name && !start_repository.branch_exists?(start_branch_name)
raise ArgumentError, "Cannot find branch #{start_branch_name} in #{start_repository.path_with_namespace}"
raise ArgumentError, "Cannot find branch #{start_branch_name} in #{start_repository.full_path}"
end
update_branch_with_hooks(branch_name) do
......
......@@ -10,7 +10,7 @@ module Projects
def async_execute
project.update_attribute(:pending_delete, true)
job_id = ProjectDestroyWorker.perform_async(project.id, current_user.id, params)
Rails.logger.info("User #{current_user.id} scheduled destruction of project #{project.path_with_namespace} with job ID #{job_id}")
Rails.logger.info("User #{current_user.id} scheduled destruction of project #{project.full_path} with job ID #{job_id}")
end
def execute
......@@ -41,7 +41,7 @@ module Projects
private
def repo_path
project.path_with_namespace
project.disk_path
end
def wiki_path
......@@ -128,7 +128,7 @@ module Projects
def flush_caches(project)
project.repository.before_delete
Repository.new(wiki_path, project).before_delete
Repository.new(wiki_path, project, disk_path: repo_path).before_delete
end
end
end
......@@ -2,7 +2,7 @@ module Projects
module ImportExport
class ExportService < BaseService
def execute(_options = {})
@shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work'))
@shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.disk_path, 'work'))
save_all
end
......
......@@ -11,7 +11,7 @@ module Projects
success
rescue => e
error("Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}")
error("Error importing repository #{project.import_url} into #{project.full_path} - #{e.message}")
end
private
......@@ -51,7 +51,7 @@ module Projects
end
def clone_repository
gitlab_shell.import_repository(project.repository_storage_path, project.path_with_namespace, project.import_url)
gitlab_shell.import_repository(project.repository_storage_path, project.disk_path, project.import_url)
end
def fetch_repository
......
......@@ -19,7 +19,7 @@ module Projects
service_id: service.id,
team_id: slack_data['team_id'],
team_name: slack_data['team_name'],
alias: project.path_with_namespace,
alias: project.full_path,
user_id: slack_data['user_id']
)
......
......@@ -36,7 +36,7 @@ module Projects
private
def transfer(project)
@old_path = project.path_with_namespace
@old_path = project.full_path
@old_group = project.group
@new_path = File.join(@new_namespace.try(:full_path) || '', project.path)
@old_namespace = project.namespace
......@@ -63,11 +63,13 @@ module Projects
project.send_move_instructions(@old_path)
# Move main repository
# TODO: check storage type and NOOP when not using Legacy
unless move_repo_folder(@old_path, @new_path)
raise TransferError.new('Cannot move project')
end
# Move wiki repo also if present
# TODO: check storage type and NOOP when not using Legacy
move_repo_folder("#{@old_path}.wiki", "#{@new_path}.wiki")
# Move missing group labels to project
......
......@@ -128,7 +128,7 @@ module Projects
remote_ref_id = remote_ref.dereferenced_target.try(:id)
if remote_ref_id && project.repository.is_ancestor?(remote_ref_id, default_branch_id)
if remote_ref_id && project.repository.rugged_is_ancestor?(remote_ref_id, default_branch_id)
refs_to_delete << name
end
end
......
......@@ -8,10 +8,10 @@ module Projects
def execute(new_repository_storage_key)
new_storage_path = Gitlab.config.repositories.storages[new_repository_storage_key]['path']
result = move_storage(project.path_with_namespace, new_storage_path)
result = move_storage(project.disk_path, new_storage_path)
if project.wiki.repository_exists?
result &&= move_storage("#{project.path_with_namespace}.wiki", new_storage_path)
result &&= move_storage("#{project.disk_path}.wiki", new_storage_path)
end
if result
......@@ -31,20 +31,20 @@ module Projects
def mark_old_paths_for_archive
old_repository_storage_path = project.repository_storage_path
new_project_path = moved_path(project.path_with_namespace)
new_project_path = moved_path(project.disk_path)
# Notice that the block passed to `run_after_commit` will run with `project`
# as its context
project.run_after_commit do
GitlabShellWorker.perform_async(:mv_repository,
old_repository_storage_path,
path_with_namespace,
disk_path,
new_project_path)
if wiki.repository_exists?
GitlabShellWorker.perform_async(:mv_repository,
old_repository_storage_path,
"#{path_with_namespace}.wiki",
"#{disk_path}.wiki",
"#{new_project_path}.wiki")
end
end
......
......@@ -24,7 +24,7 @@ class SystemHooksService
key: model.key,
id: model.id
)
if model.user
data[:username] = model.user.username
end
......@@ -56,7 +56,7 @@ class SystemHooksService
when GroupMember
data.merge!(group_member_data(model))
end
data
end
......@@ -79,7 +79,7 @@ class SystemHooksService
{
name: model.name,
path: model.path,
path_with_namespace: model.path_with_namespace,
path_with_namespace: model.full_path,
project_id: model.id,
owner_name: owner.name,
owner_email: owner.respond_to?(:email) ? owner.email : "",
......@@ -93,7 +93,7 @@ class SystemHooksService
{
project_name: project.name,
project_path: project.path,
project_path_with_namespace: project.path_with_namespace,
project_path_with_namespace: project.full_path,
project_id: project.id,
user_username: model.user.username,
user_name: model.user.name,
......
......@@ -30,7 +30,7 @@ class FileUploader < GitlabUploader
#
# Returns a String without a trailing slash
def self.dynamic_path_segment(model)
File.join(CarrierWave.root, base_dir, model.path_with_namespace)
File.join(CarrierWave.root, base_dir, model.full_path)
end
attr_accessor :model
......
......@@ -85,7 +85,7 @@
%span.badge
= storage_counter(project.statistics.storage_size)
%span.pull-right.light
%span.monospace= project.path_with_namespace + ".git"
%span.monospace= project.full_path + '.git'
.panel-footer
= paginate @projects, param_name: 'projects_page', theme: 'gitlab'
......@@ -103,7 +103,7 @@
%span.badge
= storage_counter(project.statistics.storage_size)
%span.pull-right.light
%span.monospace= project.path_with_namespace + ".git"
%span.monospace= project.full_path + '.git'
.col-md-6
- if can?(current_user, :admin_group_member, @group)
......
- page_title "UI Development Kit", "Help"
- lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed fermentum nisi sapien, non consequat lectus aliquam ultrices. Suspendisse sodales est euismod nunc condimentum, a consectetur diam ornare."
- content_for :page_specific_javascripts do
= webpack_bundle_tag('ui_development_kit')
.gitlab-ui-dev-kit
%h1 GitLab UI development kit
......@@ -407,29 +409,6 @@
.dropdown-content
.dropdown-loading
= icon('spinner spin')
:javascript
$('#js-project-dropdown').glDropdown({
data: function (term, callback) {
Api.projects(term, { order_by: 'last_activity_at' }, function (data) {
callback(data);
});
},
text: function (project) {
return project.name_with_namespace || project.name;
},
selectable: true,
fieldName: "author_id",
filterable: true,
search: {
fields: ['name_with_namespace']
},
id: function (data) {
return data.id;
},
isSelected: function (data) {
return data.id === 2;
}
})
.example
%div
......
......@@ -25,7 +25,7 @@
%td
= provider_project_link(provider, project.import_source)
%td
= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
%td.job-status
- if project.import_status == 'finished'
%span
......
......@@ -4,7 +4,7 @@
job.attr("id", "project_#{@project.id}")
target_field = job.find(".import-target")
target_field.empty()
target_field.append('#{link_to @project.path_with_namespace, project_path(@project)}')
target_field.append('#{link_to @project.full_path, project_path(@project)}')
$("table.import-jobs tbody").prepend(job)
job.addClass("active").find(".import-actions").html("<i class='fa fa-spinner fa-spin'></i> started")
- else
......
......@@ -35,7 +35,7 @@
%td
= link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: '_blank', rel: 'noopener noreferrer'
%td
= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
%td.job-status
- if project.import_status == 'finished'
%span
......
......@@ -33,7 +33,7 @@
%td
= project.import_source
%td
= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
%td.job-status
- if project.import_status == 'finished'
%span
......
......@@ -28,7 +28,7 @@
%td
= link_to project.import_source, "https://gitlab.com/#{project.import_source}", target: "_blank"
%td
= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
%td.job-status
- if project.import_status == 'finished'
%span
......
......@@ -38,7 +38,7 @@
%td
= link_to project.import_source, "https://code.google.com/p/#{project.import_source}", target: "_blank", rel: 'noopener noreferrer'
%td
= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
%td.job-status
- if project.import_status == 'finished'
%span
......
-# haml-lint:disable InlineJavaScript
:javascript
var _gaq = _gaq || [];
_gaq.push(['_setAccount', '#{extra_config.google_analytics_id}']);
......
......@@ -2,6 +2,7 @@
- noteable_type = @noteable.class if @noteable.present?
- if project
-# haml-lint:disable InlineJavaScript
:javascript
gl.GfmAutoComplete = gl.GfmAutoComplete || {};
gl.GfmAutoComplete.dataSources = {
......
<!-- Piwik -->
-# haml-lint:disable InlineJavaScript
:javascript
var _paq = _paq || [];
_paq.push(['trackPageView']);
......
......@@ -10,6 +10,7 @@
- content_for :project_javascripts do
- project = @target_project || @project
- if current_user
-# haml-lint:disable InlineJavaScript
:javascript
window.uploads_path = "#{project_uploads_path(project)}";
window.preview_markdown_path = "#{preview_markdown_path(project)}";
......
......@@ -2,6 +2,7 @@
- content_for :page_specific_javascripts do
- if @snippet && current_user
-# haml-lint:disable InlineJavaScript
:javascript
window.uploads_path = "#{upload_path('personal_snippet', id: @snippet.id)}";
......
- page_title "Personal Access Tokens"
- @content_class = "limit-container-width" unless fluid_layout
= render 'profiles/head'
.row.prepend-top-default
......@@ -19,7 +20,7 @@
%h5.prepend-top-0
Your New Personal Access Token
.form-group
= text_field_tag 'created-personal-access-token', flash[:personal_access_token], readonly: true, class: "form-control", 'aria-describedby' => "created-personal-access-token-help-block"
= text_field_tag 'created-personal-access-token', flash[:personal_access_token], readonly: true, class: "form-control js-select-on-focus", 'aria-describedby' => "created-personal-access-token-help-block"
= clipboard_button(text: flash[:personal_access_token], title: "Copy personal access token to clipboard", placement: "left")
%span#created-personal-access-token-help-block.help-block.text-danger Make sure you save it - you won't be able to access it again.
......@@ -28,8 +29,3 @@
= render "shared/personal_access_tokens_form", path: profile_personal_access_tokens_path, impersonation: false, token: @personal_access_token, scopes: @scopes
= render "shared/personal_access_tokens_table", impersonation: false, active_tokens: @active_personal_access_tokens, inactive_tokens: @inactive_personal_access_tokens
:javascript
$("#created-personal-access-token").click(function() {
this.select();
});
......@@ -7,97 +7,92 @@
= render 'profiles/head'
- if inject_u2f_api?
- content_for :page_specific_javascripts do
- content_for :page_specific_javascripts do
- if inject_u2f_api?
= page_specific_javascript_bundle_tag('u2f')
= page_specific_javascript_bundle_tag('two_factor_auth')
.row.prepend-top-default
.col-lg-4
%h4.prepend-top-0
Register Two-Factor Authentication App
%p
Use an app on your mobile device to enable two-factor authentication (2FA).
.col-lg-8
- if current_user.two_factor_otp_enabled?
= icon "check inverse", base: "circle", class: "text-success", text: "You've already enabled two-factor authentication using mobile authenticator applications. You can disable it from your account settings page."
- else
.js-two-factor-auth{ 'data-two-factor-skippable' => "#{two_factor_skippable?}", 'data-two_factor_skip_url' => skip_profile_two_factor_auth_path }
.row.prepend-top-default
.col-lg-4
%h4.prepend-top-0
Register Two-Factor Authentication App
%p
Download the Google Authenticator application from App Store or Google Play Store and scan this code.
More information is available in the #{link_to('documentation', help_page_path('profile/two_factor_authentication'))}.
.row.append-bottom-10
.col-md-4
= raw @qr_code
.col-md-8
.account-well
%p.prepend-top-0.append-bottom-0
Can't scan the code?
%p.prepend-top-0.append-bottom-0
To add the entry manually, provide the following details to the application on your phone.
%p.prepend-top-0.append-bottom-0
Account:
= @account_string
%p.prepend-top-0.append-bottom-0
Key:
= current_user.otp_secret.scan(/.{4}/).join(' ')
%p.two-factor-new-manual-content
Time based: Yes
= form_tag profile_two_factor_auth_path, method: :post do |f|
- if @error
.alert.alert-danger
= @error
.form-group
= label_tag :pin_code, nil, class: "label-light"
= text_field_tag :pin_code, nil, class: "form-control", required: true
.prepend-top-default
= submit_tag 'Register with two-factor app', class: 'btn btn-success'
Use an app on your mobile device to enable two-factor authentication (2FA).
.col-lg-8
- if current_user.two_factor_otp_enabled?
= icon "check inverse", base: "circle", class: "text-success", text: "You've already enabled two-factor authentication using mobile authenticator applications. You can disable it from your account settings page."
- else
%p
Download the Google Authenticator application from App Store or Google Play Store and scan this code.
More information is available in the #{link_to('documentation', help_page_path('profile/two_factor_authentication'))}.
.row.append-bottom-10
.col-md-4
= raw @qr_code
.col-md-8
.account-well
%p.prepend-top-0.append-bottom-0
Can't scan the code?
%p.prepend-top-0.append-bottom-0
To add the entry manually, provide the following details to the application on your phone.
%p.prepend-top-0.append-bottom-0
Account:
= @account_string
%p.prepend-top-0.append-bottom-0
Key:
= current_user.otp_secret.scan(/.{4}/).join(' ')
%p.two-factor-new-manual-content
Time based: Yes
= form_tag profile_two_factor_auth_path, method: :post do |f|
- if @error
.alert.alert-danger
= @error
.form-group
= label_tag :pin_code, nil, class: "label-light"
= text_field_tag :pin_code, nil, class: "form-control", required: true
.prepend-top-default
= submit_tag 'Register with two-factor app', class: 'btn btn-success'
%hr
%hr
.row.prepend-top-default
.col-lg-4
%h4.prepend-top-0
Register Universal Two-Factor (U2F) Device
%p
Use a hardware device to add the second factor of authentication.
%p
As U2F devices are only supported by a few browsers, we require that you set up a
two-factor authentication app before a U2F device. That way you'll always be able to
log in - even when you're using an unsupported browser.
.col-lg-8
- if @u2f_registration.errors.present?
= form_errors(@u2f_registration)
= render "u2f/register"
.row.prepend-top-default
.col-lg-4
%h4.prepend-top-0
Register Universal Two-Factor (U2F) Device
%p
Use a hardware device to add the second factor of authentication.
%p
As U2F devices are only supported by a few browsers, we require that you set up a
two-factor authentication app before a U2F device. That way you'll always be able to
log in - even when you're using an unsupported browser.
.col-lg-8
- if @u2f_registration.errors.present?
= form_errors(@u2f_registration)
= render "u2f/register"
%hr
%hr
%h5 U2F Devices (#{@u2f_registrations.length})
%h5 U2F Devices (#{@u2f_registrations.length})
- if @u2f_registrations.present?
.table-responsive
%table.table.table-bordered.u2f-registrations
%colgroup
%col{ width: "50%" }
%col{ width: "30%" }
%col{ width: "20%" }
%thead
%tr
%th Name
%th Registered On
%th
%tbody
- @u2f_registrations.each do |registration|
- if @u2f_registrations.present?
.table-responsive
%table.table.table-bordered.u2f-registrations
%colgroup
%col{ width: "50%" }
%col{ width: "30%" }
%col{ width: "20%" }
%thead
%tr
%td= registration.name.presence || "<no name set>"
%td= registration.created_at.to_date.to_s(:medium)
%td= link_to "Delete", profile_u2f_registration_path(registration), method: :delete, class: "btn btn-danger pull-right", data: { confirm: "Are you sure you want to delete this device? This action cannot be undone." }
- else
.settings-message.text-center
You don't have any U2F devices registered yet.
%th Name
%th Registered On
%th
%tbody
- @u2f_registrations.each do |registration|
%tr
%td= registration.name.presence || "<no name set>"
%td= registration.created_at.to_date.to_s(:medium)
%td= link_to "Delete", profile_u2f_registration_path(registration), method: :delete, class: "btn btn-danger pull-right", data: { confirm: "Are you sure you want to delete this device? This action cannot be undone." }
- if two_factor_skippable?
:javascript
var button = "<a class='btn btn-xs btn-warning pull-right' data-method='patch' href='#{skip_profile_two_factor_auth_path}'>Configure it later</a>";
$(".flash-alert").append(button);
- else
.settings-message.text-center
You don't have any U2F devices registered yet.
......@@ -8,9 +8,3 @@
.content_list.project-activity{ :"data-href" => activity_project_path(@project) }
= spinner
:javascript
var activity = new gl.Activities();
$(document).on('page:restore', function (event) {
activity.reloadActivities()
})
......@@ -3,6 +3,6 @@
= render "projects/settings/head"
%h3.page-title Project Audit Events
%p.light Events in #{@project.path_with_namespace}
%p.light Events in #{@project.full_path}
= render 'shared/audit_events/event_table', events: @events
......@@ -20,6 +20,3 @@
- unless can?(current_user, :push_code, @project)
.inline.prepend-left-10
= commit_in_fork_help
:javascript
new NewCommitForm($('.js-create-dir-form'))
......@@ -13,6 +13,3 @@
.col-sm-offset-2.col-sm-10
= button_tag 'Delete file', class: 'btn btn-remove btn-remove-file'
= link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
:javascript
new NewCommitForm($('.js-delete-blob-form'))
......@@ -28,8 +28,4 @@
.form-actions
= button_tag 'Create branch', class: 'btn btn-create', tabindex: 3
= link_to 'Cancel', project_branches_path(@project), class: 'btn btn-cancel'
:javascript
var availableRefs = #{@project.repository.ref_names.to_json};
new NewBranchForm($('.js-create-branch-form'), availableRefs)
%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe
.page-content-header
.page-content-header.js-commit-box{ 'data-commit-path' => branches_project_commit_path(@project, @commit.id) }
.header-main-content
= render partial: 'signature', object: @commit.signature
%strong
......@@ -79,6 +79,3 @@
= render 'shared/mini_pipeline_graph', pipeline: last_pipeline, klass: 'js-commit-pipeline-graph'
in
= time_interval_in_words last_pipeline.duration
:javascript
$(".commit-info.branches").load("#{branches_project_commit_path(@project, @commit.id)}");
......@@ -6,7 +6,7 @@
- notes = commit.notes
- note_count = notes.user.count
- cache_key = [project.path_with_namespace, commit.id, current_application_settings, note_count, @path.presence, current_controller?(:commits)]
- cache_key = [project.full_path, commit.id, current_application_settings, note_count, @path.presence, current_controller?(:commits)]
- cache_key.push(commit.status(ref)) if commit.status(ref)
= cache(cache_key, expires_in: 1.day) do
......
......@@ -11,21 +11,29 @@
= content_for :sub_nav do
= render "head"
%div{ class: container_class }
.tree-holder
.nav-block
.tree-ref-container
.tree-ref-holder
= render 'shared/ref_switcher', destination: 'commits'
%ul.breadcrumb.repo-breadcrumb
= commits_breadcrumbs
.tree-controls.hidden-xs.hidden-sm
- if @merge_request.present?
.js-project-commits-show{ 'data-commits-limit' => @limit }
%div{ class: container_class }
.tree-holder
.nav-block
.tree-ref-container
.tree-ref-holder
= render 'shared/ref_switcher', destination: 'commits'
%ul.breadcrumb.repo-breadcrumb
= commits_breadcrumbs
.tree-controls.hidden-xs.hidden-sm
- if @merge_request.present?
.control
= link_to _("View open merge request"), project_merge_request_path(@project, @merge_request), class: 'btn'
- elsif create_mr_button?(@repository.root_ref, @ref)
.control
= link_to _("Create merge request"), create_mr_path(@repository.root_ref, @ref), class: 'btn btn-success'
.control
= link_to _("View open merge request"), project_merge_request_path(@project, @merge_request), class: 'btn'
- elsif create_mr_button?(@repository.root_ref, @ref)
= form_tag(project_commits_path(@project, @id), method: :get, class: 'commits-search-form') do
= search_field_tag :search, params[:search], { placeholder: _('Filter by commit message'), id: 'commits-search', class: 'form-control search-text-input input-short', spellcheck: false }
.control
<<<<<<< HEAD
= link_to _("Create merge request"), create_mr_path(@repository.root_ref, @ref), class: 'btn btn-success'
.control
......@@ -36,11 +44,14 @@
= icon("rss")
= render 'projects/commits/mirror_status'
=======
= link_to project_commits_path(@project, @ref, rss_url_options), title: _("Commits feed"), class: 'btn' do
= icon("rss")
>>>>>>> upstream/master
%div{ id: dom_id(@project) }
%ol#commits-list.list-unstyled.content_list
= render 'commits', project: @project, ref: @ref
= spinner
= render 'projects/commits/mirror_status'
:javascript
CommitsList.init(#{@limit});
%div{ id: dom_id(@project) }
%ol#commits-list.list-unstyled.content_list
= render 'commits', project: @project, ref: @ref
= spinner
- page_title "Find File", @ref
= render "projects/commits/head"
.file-finder-holder.tree-holder.clearfix
.file-finder-holder.tree-holder.clearfix.js-file-finder{ 'data-file-find-url': "#{escape_javascript(project_files_path(@project, @ref, @options.merge(format: :json)))}", 'data-find-tree-url': escape_javascript(project_tree_path(@project, @ref)), 'data-blob-url-template': escape_javascript(project_blob_path(@project, @id || @commit.id)) }
.nav-block
.tree-ref-holder
= render 'shared/ref_switcher', destination: 'find_file', path: @path
......@@ -17,11 +17,3 @@
%table.table.files-slider{ class: "table_#{@hex_path} tree-table table-striped" }
%tbody
= spinner nil, true
:javascript
var projectFindFile = new ProjectFindFile($(".file-finder-holder"), {
url: "#{escape_javascript(project_files_path(@project, @ref, @options.merge(format: :json)))}",
treeUrl: "#{escape_javascript(project_tree_path(@project, @ref))}",
blobUrlTemplate: "#{escape_javascript(project_blob_path(@project, @id || @commit.id))}"
});
new ShortcutsFindFile(projectFindFile);
......@@ -3,8 +3,9 @@
- if show_new_nav?
- add_to_breadcrumbs("Repository", project_tree_path(@project))
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_d3')
= page_specific_javascript_bundle_tag('graphs')
= webpack_bundle_tag('common_d3')
= webpack_bundle_tag('graphs')
= webpack_bundle_tag('graphs_charts')
= render "projects/commits/head"
.repo-charts{ class: container_class }
......@@ -75,55 +76,10 @@
Commits per day hour (UTC)
%canvas#hour-chart
:javascript
var responsiveChart = function (selector, data) {
var options = { "scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2, maintainAspectRatio: false };
// get selector by context
var ctx = selector.get(0).getContext("2d");
// pointing parent container to make chart.js inherit its width
var container = $(selector).parent();
var generateChart = function() {
selector.attr('width', $(container).width());
if (window.innerWidth < 768) {
// Scale fonts if window width lower than 768px (iPad portrait)
options.scaleFontSize = 8
}
return new Chart(ctx).Bar(data, options);
};
// enabling auto-resizing
$(window).resize(generateChart);
return generateChart();
};
var chartData = function (keys, values) {
var data = {
labels : keys,
datasets : [{
fillColor : "rgba(220,220,220,0.5)",
strokeColor : "rgba(220,220,220,1)",
barStrokeWidth: 1,
barValueSpacing: 1,
barDatasetSpacing: 1,
data : values
}]
};
return data;
};
var hourData = chartData(#{@commits_per_time.keys.to_json}, #{@commits_per_time.values.to_json});
responsiveChart($('#hour-chart'), hourData);
var dayData = chartData(#{@commits_per_week_days.keys.to_json}, #{@commits_per_week_days.values.to_json});
responsiveChart($('#weekday-chart'), dayData);
var monthData = chartData(#{@commits_per_month.keys.to_json}, #{@commits_per_month.values.to_json});
responsiveChart($('#month-chart'), monthData);
var data = #{@languages.to_json};
var ctx = $("#languages-chart").get(0).getContext("2d");
var options = {
scaleOverlay: true,
responsive: true,
maintainAspectRatio: false
}
var myPieChart = new Chart(ctx).Pie(data, options);
%script#projectChartData{ type: "application/json" }
- projectChartData = {};
- projectChartData['hour'] = { 'keys' => @commits_per_time.keys, 'values' => @commits_per_time.values }
- projectChartData['weekDays'] = { 'keys' => @commits_per_week_days.keys, 'values' => @commits_per_week_days.values }
- projectChartData['month'] = { 'keys' => @commits_per_month.keys, 'values' => @commits_per_month.values }
- projectChartData['languages'] = @languages
= projectChartData.to_json.html_safe
- @no_container = true
- page_title "Contributors"
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_d3')
= page_specific_javascript_bundle_tag('graphs')
= webpack_bundle_tag('common_d3')
= webpack_bundle_tag('graphs')
= webpack_bundle_tag('graphs_show')
- if show_new_nav?
- add_to_breadcrumbs("Repository", project_tree_path(@project))
= render 'projects/commits/head'
%div{ class: container_class }
.js-graphs-show{ class: container_class, 'data-project-graph-path': project_graph_path(@project, current_ref, format: :json) }
.sub-header-block
.tree-ref-holder
= render 'shared/ref_switcher', destination: 'graphs'
......@@ -33,24 +34,3 @@
#contributors-master
#contributors.clearfix
%ol.contributors-list.clearfix
:javascript
$.ajax({
type: "GET",
url: "#{project_graph_path(@project, current_ref, format: :json)}",
dataType: "json",
success: function (data) {
var graph = new ContributorsStatGraph();
graph.init(data);
$("#brush_change").change(function(){
graph.change_date_header();
graph.redraw_authors();
});
$(".stat-graph").fadeIn();
$(".loading-graph").hide();
}
});
......@@ -10,5 +10,3 @@
- if @project.external_import?
%p.monospace git clone --bare #{@project.safe_import_url}
%p Please wait while we import the repository for you. Refresh at will.
:javascript
new ProjectImport();
......@@ -33,7 +33,7 @@
Suggestions:
%code= 'gitlab'
%code= @project.path # Path contains no spaces, but dashes
%code= @project.path_with_namespace
%code= @project.full_path
%p
Reserved:
= link_to 'https://docs.mattermost.com/help/messaging/executing-commands.html#built-in-commands', target: '__blank' do
......
......@@ -41,7 +41,7 @@
- projects = target_projects(@project)
.merge-request-select.dropdown
= f.hidden_field :target_project_id
= dropdown_toggle f.object.target_project.path_with_namespace, { toggle: "dropdown", field_name: "#{f.object_name}[target_project_id]", disabled: @merge_request.persisted? }, { toggle_class: "js-compare-dropdown js-target-project" }
= dropdown_toggle f.object.target_project.full_path, { toggle: "dropdown", field_name: "#{f.object_name}[target_project_id]", disabled: @merge_request.persisted? }, { toggle_class: "js-compare-dropdown js-target-project" }
.dropdown-menu.dropdown-menu-selectable.dropdown-target-project
= dropdown_title("Select target project")
= dropdown_filter("Search projects")
......
......@@ -2,4 +2,4 @@
- projects.each do |project|
%li
%a{ href: "#", class: "#{('is-active' if selected == project.id)}", data: { id: project.id } }
= project.path_with_namespace
= project.full_path
......@@ -39,7 +39,7 @@
Suggestions:
%code= 'gitlab'
%code= @project.path # Path contains no spaces, but dashes
%code= @project.path_with_namespace
%code= @project.full_path
.form-group
= label_tag :request_url, 'Request URL', class: 'col-sm-2 col-xs-12 control-label'
......
......@@ -33,7 +33,7 @@
Suggestions:
%code= 'gitlab'
%code= @project.path # Path contains no spaces, but dashes
%code= @project.path_with_namespace
%code= @project.full_path
.form-group
= label_tag :url, 'URL', class: 'col-sm-2 col-xs-12 control-label'
......
......@@ -7,7 +7,7 @@
.git-access-header
Clone repository
%strong= @project_wiki.path_with_namespace
%strong= @project_wiki.full_path
= render "shared/clone_panel", project: @project_wiki
......
......@@ -37,7 +37,3 @@
.col-md-3
= hidden_field_tag 'u2f_registration[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
= submit_tag "Register U2F device", class: "btn btn-success"
:javascript
var u2fRegister = new U2FRegister($("#js-register-u2f"), gon.u2f);
u2fRegister.start();
......@@ -5,7 +5,7 @@ class GeoRepositoryCreateWorker
def perform(id)
project = Project.find(id)
project.ensure_dir_exist
project.ensure_storage_path_exist
project.create_repository unless project.repository_exists? || project.import?
end
end
......@@ -21,9 +21,9 @@ class GeoRepositoryDestroyWorker
# we need to probe on all existing ones.
#
# if we don't find it means it has already been deleted and we just return
def probe_repository_storage(full_path)
def probe_repository_storage(repo_path)
Gitlab.config.repositories.storages.each do |repository_storage, rs_data|
return repository_storage if gitlab_shell.exists?(rs_data['path'], full_path + '.git')
return repository_storage if gitlab_shell.exists?(rs_data['path'], repo_path + '.git')
end
nil
......
......@@ -66,7 +66,7 @@ class IrkerWorker
end
def send_new_branch(project, repo_name, committer, branch)
repo_path = project.path_with_namespace
repo_path = project.full_path
newbranch = "#{Gitlab.config.gitlab.url}/#{repo_path}/branches"
newbranch = "\x0302\x1f#{newbranch}\x0f" if @colors
......@@ -109,7 +109,7 @@ class IrkerWorker
end
def send_commits_count(data, project, repo, committer, branch)
url = compare_url data, project.path_with_namespace
url = compare_url data, project.full_path
commits = colorize_commits data['total_commits_count']
new_commits = 'new commit'
......
......@@ -16,7 +16,7 @@ class RepositoryImportWorker
Gitlab::Metrics.add_event(:import_repository,
import_url: @project.import_url,
path: @project.path_with_namespace)
path: @project.full_path)
project.update_columns(import_jid: self.jid, import_error: nil)
......
---
title: Present Related Issues widget for logged-out users when available
merge_request:
author:
---
title: Support variables on Trigger API for Cross-project pipeline
merge_request: 2557
author:
......@@ -40,6 +40,8 @@ var config = {
environments_folder: './environments/folder/environments_folder_bundle.js',
filtered_search: './filtered_search/filtered_search_bundle.js',
graphs: './graphs/graphs_bundle.js',
graphs_charts: './graphs/graphs_charts.js',
graphs_show: './graphs/graphs_show.js',
group: './group.js',
groups: './groups/index.js',
groups_list: './groups_list.js',
......@@ -76,9 +78,15 @@ var config = {
stl_viewer: './blob/stl_viewer.js',
terminal: './terminal/terminal_bundle.js',
u2f: ['vendor/u2f'],
<<<<<<< HEAD
=======
ui_development_kit: './ui_development_kit.js',
users: './users/index.js',
>>>>>>> upstream/master
raven: './raven/index.js',
vue_merge_request_widget: './vue_merge_request_widget/index.js',
test: './test.js',
two_factor_auth: './two_factor_auth.js',
performance_bar: './performance_bar.js',
webpack_runtime: './webpack.js',
},
......
......@@ -16,6 +16,7 @@ class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration
end
def repository_path
# TODO: review if the change from Legacy storage needs to reflect here as well.
File.join(repository_storage_path, read_attribute(:path_with_namespace) + '.git')
end
......
......@@ -38,8 +38,7 @@ build_docs:
```
Pipelines triggered that way also expose a special variable:
`CI_PIPELINE_SOURCE=pipeline`. This method currently doesn't support
[the usage of trigger variables](#making-use-of-trigger-variables).
`CI_PIPELINE_SOURCE=pipeline`.
For more information, read about [triggering a pipeline](#triggering-a-pipeline).
......
......@@ -4,9 +4,12 @@
## Overview
If you are using [GitLab CI][ci], you can analyze your source code quality using
the [Code Climate][cc] analyzer [Docker image][cd]. Going a step further, GitLab
can show the Code Climate report right in the merge request widget area.
If you are using [GitLab CI/CD][ci], you can analyze your source code quality
using GitLab Code Quality. Code Quality uses [Code Climate Engines][cc], which are
free and open source. Code Quality doesn’t require a Code Climate subscription.
Going a step further, GitLab Code Quality can show the Code Climate report right
in the merge request widget area:
![Code Quality Widget][quality-widget]
......
......@@ -51,7 +51,7 @@ class Spinach::Features::GroupsManagement < Spinach::FeatureSteps
end
page.within '.sub-nav' do
find('a', text: 'General').trigger('click')
end
end
end
step 'I enable membership lock' do
......@@ -65,7 +65,7 @@ class Spinach::Features::GroupsManagement < Spinach::FeatureSteps
click_link 'Projects'
end
link = "/#{@project.path_with_namespace}/project_members"
link = "/#{@project.full_path}/project_members"
find(:xpath, "//a[@href=\"#{link}\"]").click
end
......
......@@ -30,8 +30,8 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
expect(@merge_request.source_project).to eq @forked_project
expect(@merge_request.source_branch).to eq "fix"
expect(@merge_request.target_branch).to eq "master"
expect(page).to have_content @forked_project.path_with_namespace
expect(page).to have_content @project.path_with_namespace
expect(page).to have_content @forked_project.full_path
expect(page).to have_content @project.full_path
expect(page).to have_content @merge_request.source_branch
expect(page).to have_content @merge_request.target_branch
......@@ -43,10 +43,10 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
expect(page).to have_content('Target branch')
first('.js-source-project').click
first('.dropdown-source-project a', text: @forked_project.path_with_namespace)
first('.dropdown-source-project a', text: @forked_project.full_path)
first('.js-target-project').click
first('.dropdown-target-project a', text: @project.path_with_namespace)
first('.dropdown-target-project a', text: @project.full_path)
first('.js-source-branch').click
wait_for_requests
......@@ -81,8 +81,8 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
expect(@merge_request.source_project).to eq @forked_project
expect(@merge_request.source_branch).to eq "fix"
expect(@merge_request.target_branch).to eq "master"
expect(page).to have_content @forked_project.path_with_namespace
expect(page).to have_content @project.path_with_namespace
expect(page).to have_content @forked_project.full_path
expect(page).to have_content @project.full_path
expect(page).to have_content @merge_request.source_branch
expect(page).to have_content @merge_request.target_branch
end
......
......@@ -47,7 +47,7 @@ class Spinach::Features::ProjectRedirects < Spinach::FeatureSteps
step 'I should be redirected to "Community" page' do
project = Project.find_by(name: 'Community')
expect(current_path).to eq "/#{project.path_with_namespace}"
expect(current_path).to eq "/#{project.full_path}"
expect(status_code).to eq 200
end
......@@ -61,7 +61,7 @@ class Spinach::Features::ProjectRedirects < Spinach::FeatureSteps
step 'I should be redirected to "Enterprise" page' do
project = Project.find_by(name: 'Enterprise')
expect(current_path).to eq "/#{project.path_with_namespace}"
expect(current_path).to eq "/#{project.full_path}"
expect(status_code).to eq 200
end
end
......@@ -142,7 +142,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps
end
step 'I should see non-escaped link in the pages list' do
expect(page).to have_xpath("//a[@href='/#{project.path_with_namespace}/wikis/one/two/three-test']")
expect(page).to have_xpath("//a[@href='/#{project.full_path}/wikis/one/two/three-test']")
end
step 'I edit the Wiki page with a path' do
......
......@@ -90,7 +90,7 @@ module API
if result.valid?
if result.build
Gitlab::Metrics.add_event(:build_found,
project: result.build.project.path_with_namespace)
project: result.build.project.full_path)
present result.build, with: Entities::JobRequest::Response
else
Gitlab::Metrics.add_event(:build_not_found)
......@@ -119,7 +119,7 @@ module API
job.trace.set(params[:trace]) if params[:trace]
Gitlab::Metrics.add_event(:update_build,
project: job.project.path_with_namespace)
project: job.project.full_path)
case params[:state].to_s
when 'success'
......
......@@ -7,7 +7,7 @@ module Backup
prepare
Project.find_each(batch_size: 1000) do |project|
progress.print " * #{project.path_with_namespace} ... "
progress.print " * #{project.full_path} ... "
path_to_project_repo = path_to_repo(project)
path_to_project_bundle = path_to_bundle(project)
......@@ -42,7 +42,7 @@ module Backup
path_to_wiki_bundle = path_to_bundle(wiki)
if File.exist?(path_to_wiki_repo)
progress.print " * #{wiki.path_with_namespace} ... "
progress.print " * #{wiki.full_path} ... "
if empty_repo?(wiki)
progress.puts " [SKIPPED]".color(:cyan)
else
......@@ -71,11 +71,11 @@ module Backup
end
Project.find_each(batch_size: 1000) do |project|
progress.print " * #{project.path_with_namespace} ... "
progress.print " * #{project.full_path} ... "
path_to_project_repo = path_to_repo(project)
path_to_project_bundle = path_to_bundle(project)
project.ensure_dir_exist
project.ensure_storage_path_exist
cmd = if File.exist?(path_to_project_bundle)
%W(#{Gitlab.config.git.bin_path} clone --bare #{path_to_project_bundle} #{path_to_project_repo})
......@@ -104,7 +104,7 @@ module Backup
path_to_wiki_bundle = path_to_bundle(wiki)
if File.exist?(path_to_wiki_bundle)
progress.print " * #{wiki.path_with_namespace} ... "
progress.print " * #{wiki.full_path} ... "
# If a wiki bundle exists, first remove the empty repo
# that was initialized with ProjectWiki.new() and then
......@@ -142,11 +142,11 @@ module Backup
end
def path_to_bundle(project)
File.join(backup_repos_path, project.path_with_namespace + '.bundle')
File.join(backup_repos_path, project.disk_path + '.bundle')
end
def path_to_tars(project, dir = nil)
path = File.join(backup_repos_path, project.path_with_namespace)
path = File.join(backup_repos_path, project.disk_path)
if dir
File.join(path, "#{dir}.tar")
......@@ -185,13 +185,13 @@ module Backup
def progress_warn(project, cmd, output)
progress.puts "[WARNING] Executing #{cmd}".color(:orange)
progress.puts "Ignoring error on #{project.path_with_namespace} - #{output}".color(:orange)
progress.puts "Ignoring error on #{project.full_path} - #{output}".color(:orange)
end
def empty_repo?(project_or_wiki)
project_or_wiki.repository.empty_repo?
rescue => e
progress.puts "Ignoring repository error and continuing backing up project: #{project_or_wiki.path_with_namespace} - #{e.message}".color(:orange)
progress.puts "Ignoring repository error and continuing backing up project: #{project_or_wiki.full_path} - #{e.message}".color(:orange)
false
end
......
......@@ -259,7 +259,7 @@ module Banzai
found = []
projects.each do |project|
ref = project.path_with_namespace
ref = project.full_path
get_or_set_cache(cache, ref) { project }
found << ref
end
......@@ -277,7 +277,7 @@ module Banzai
end
def current_project_path
@current_project_path ||= project.path_with_namespace
@current_project_path ||= project.full_path
end
def current_project_namespace_path
......
......@@ -51,7 +51,7 @@ module Banzai
uri.path = [
relative_url_root,
context[:project].path_with_namespace,
context[:project].full_path,
uri_type(file_path),
Addressable::URI.escape(ref),
Addressable::URI.escape(file_path)
......
......@@ -29,9 +29,9 @@ module Banzai
def build_url(uri)
if Gitlab::Geo.secondary?
File.join(Gitlab::Geo.primary_node.url, context[:project].path_with_namespace, uri)
File.join(Gitlab::Geo.primary_node.url, project.full_path, uri)
else
File.join(Gitlab.config.gitlab.url, context[:project].path_with_namespace, uri)
File.join(Gitlab.config.gitlab.url, project.full_path, uri)
end
end
......
......@@ -29,7 +29,7 @@ module Ci
if result.valid?
if result.build
Gitlab::Metrics.add_event(:build_found,
project: result.build.project.path_with_namespace)
project: result.build.project.full_path)
present result.build, with: Entities::BuildDetails
else
......@@ -64,7 +64,7 @@ module Ci
build.trace.set(params[:trace]) if params[:trace]
Gitlab::Metrics.add_event(:update_build,
project: build.project.path_with_namespace)
project: build.project.full_path)
case params[:state].to_s
when 'success'
......
......@@ -93,7 +93,7 @@ module Github
def fetch_wiki_repository
wiki_url = "https://#{options.fetch(:token)}@github.com/#{repo}.wiki.git"
wiki_path = "#{project.path_with_namespace}.wiki"
wiki_path = "#{project.full_path}.wiki"
unless project.wiki.repository_exists?
gitlab_shell.import_repository(project.repository_storage_path, wiki_path, wiki_url)
......
......@@ -61,7 +61,7 @@ module Gitlab
def import_wiki
return if project.wiki.repository_exists?
path_with_namespace = "#{project.path_with_namespace}.wiki"
path_with_namespace = "#{project.full_path}.wiki"
import_url = project.import_url.sub(/\.git\z/, ".git/wiki")
gitlab_shell.import_repository(project.repository_storage_path, path_with_namespace, import_url)
rescue StandardError => e
......
......@@ -117,7 +117,7 @@ module Gitlab
def subject
subject_text = '[Git]'
subject_text << "[#{project.path_with_namespace}]"
subject_text << "[#{project.full_path}]"
subject_text << "[#{ref_name}]" if @action == :push
subject_text << ' '
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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