diff --git a/app/assets/javascripts/namespace_select.js b/app/assets/javascripts/namespace_select.js index 514556ade0ba89c6a11d52b9c61a159283e821be..2ae5617206eded471fe746f89cd255daaa3564c0 100644 --- a/app/assets/javascripts/namespace_select.js +++ b/app/assets/javascripts/namespace_select.js @@ -29,7 +29,7 @@ if (selected.id == null) { return selected.text; } else { - return selected.kind + ": " + selected.path; + return selected.kind + ": " + selected.full_path; } }, data: function(term, dataCallback) { @@ -50,7 +50,7 @@ if (namespace.id == null) { return namespace.text; } else { - return namespace.kind + ": " + namespace.path; + return namespace.kind + ": " + namespace.full_path; } }, renderRow: this.renderRow, diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb index e0b8dc1393bb31c8630d6e1d0f887495d9624373..0676767d910cbf1b6b788705eb79e5f8f41cd8b8 100644 --- a/app/helpers/namespaces_helper.rb +++ b/app/helpers/namespaces_helper.rb @@ -10,7 +10,7 @@ module NamespacesHelper data_attr_users = { 'data-options-parent' => 'users' } group_opts = [ - "Groups", groups.sort_by(&:human_name).map { |g| [display_path ? g.path : g.human_name, g.id, data_attr_group] } + "Groups", groups.sort_by(&:human_name).map { |g| [display_path ? g.full_path : g.human_name, g.id, data_attr_group] } ] users_opts = [ diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb index b3f50ceebe44f4da580fedbc773fbba21e7068d3..9a748aaaf338104131131944c686c6c2142bbdd6 100644 --- a/app/helpers/submodule_helper.rb +++ b/app/helpers/submodule_helper.rb @@ -63,7 +63,7 @@ module SubmoduleHelper namespace = components.pop.gsub(/^\.\.$/, '') if namespace.empty? - namespace = @project.namespace.path + namespace = @project.namespace.full_path end [ diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 38646eba3acb8c4abf4a0501dc53a45d8d2b19c7..204d2b153ad82ca1f8e29842883809b78fb1e9c4 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -598,7 +598,7 @@ class MergeRequest < ActiveRecord::Base def source_project_namespace if source_project && source_project.namespace - source_project.namespace.path + source_project.namespace.full_path else "(removed)" end @@ -606,7 +606,7 @@ class MergeRequest < ActiveRecord::Base def target_project_namespace if target_project && target_project.namespace - target_project.namespace.path + target_project.namespace.full_path else "(removed)" end diff --git a/app/models/project.rb b/app/models/project.rb index aa408b4556e594f7974390ad6b86210617fbda6e..ed43fc2e57545c5963f07c2c3e36f3181f89f09f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -454,7 +454,7 @@ class Project < ActiveRecord::Base if forked? job_id = RepositoryForkWorker.perform_async(id, forked_from_project.repository_storage_path, forked_from_project.path_with_namespace, - self.namespace.path) + self.namespace.full_path) else job_id = RepositoryImportWorker.perform_async(self.id) end @@ -942,8 +942,8 @@ class Project < ActiveRecord::Base Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}" - Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.path) - Gitlab::PagesTransfer.new.rename_project(path_was, path, namespace.path) + 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. @@ -1150,19 +1150,25 @@ class Project < ActiveRecord::Base end def pages_url + subdomain, _, url_path = full_path.partition('/') + # The hostname always needs to be in downcased # All web servers convert hostname to lowercase - host = "#{namespace.path}.#{Settings.pages.host}".downcase + host = "#{subdomain}.#{Settings.pages.host}".downcase # The host in URL always needs to be downcased url = Gitlab.config.pages.url.sub(/^https?:\/\//) do |prefix| - "#{prefix}#{namespace.path}." + "#{prefix}#{subdomain}." end.downcase # If the project path is the same as host, we serve it as group page - return url if host == path + return url if host == url_path + + "#{url}/#{url_path}" + end - "#{url}/#{path}" + def pages_subdomain + full_path.partition('/').first end def pages_path @@ -1179,8 +1185,8 @@ class Project < ActiveRecord::Base # 3. We asynchronously remove pages with force temp_path = "#{path}.#{SecureRandom.hex}.deleted" - if Gitlab::PagesTransfer.new.rename_project(path, temp_path, namespace.path) - PagesWorker.perform_in(5.minutes, :remove, namespace.path, temp_path) + if Gitlab::PagesTransfer.new.rename_project(path, temp_path, namespace.full_path) + PagesWorker.perform_in(5.minutes, :remove, namespace.full_path, temp_path) end end @@ -1230,7 +1236,7 @@ class Project < ActiveRecord::Base end def ensure_dir_exist - gitlab_shell.add_namespace(repository_storage_path, namespace.path) + gitlab_shell.add_namespace(repository_storage_path, namespace.full_path) end def predefined_variables @@ -1238,7 +1244,7 @@ class Project < ActiveRecord::Base { 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_NAMESPACE', value: namespace.path, public: true }, + { key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path, public: true }, { key: 'CI_PROJECT_URL', value: web_url, public: true } ] end diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb index 0a217d8cabab8379aeedda02e2f655b80ccf8712..942ec9371e567cb45c1c5f1cfa7c7f490f273142 100644 --- a/app/models/project_services/drone_ci_service.rb +++ b/app/models/project_services/drone_ci_service.rb @@ -12,7 +12,7 @@ class DroneCiService < CiService def compose_service_hook hook = service_hook || build_service_hook # If using a service template, project may not be available - hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.path}", "&name=#{project.path}", "&access_token=#{token}"].join if project + hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.full_path}", "&name=#{project.path}", "&access_token=#{token}"].join if project hook.enable_ssl_verification = !!enable_ssl_verification hook.save end @@ -38,7 +38,7 @@ class DroneCiService < CiService def commit_status_path(sha, ref) url = [drone_url, - "gitlab/#{project.namespace.path}/#{project.path}/commits/#{sha}", + "gitlab/#{project.full_path}/commits/#{sha}", "?branch=#{URI::encode(ref.to_s)}&access_token=#{token}"] URI.join(*url).to_s @@ -73,7 +73,7 @@ class DroneCiService < CiService def build_page(sha, ref) url = [drone_url, - "gitlab/#{project.namespace.path}/#{project.path}/redirect/commits/#{sha}", + "gitlab/#{project.full_path}/redirect/commits/#{sha}", "?branch=#{URI::encode(ref.to_s)}"] URI.join(*url).to_s diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index 484700c8c29b91b1dcd79ce094352695d0d523af..20dfbddc823c0bd7b66f5b9d6bdbf340c1702c65 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -30,7 +30,7 @@ module Projects Project.transaction do old_path = project.path_with_namespace old_group = project.group - new_path = File.join(new_namespace.try(:path) || '', project.path) + new_path = File.join(new_namespace.try(:full_path) || '', project.path) if Project.where(path: project.path, namespace_id: new_namespace.try(:id)).present? raise TransferError.new("Project with same path in target namespace already exists") @@ -63,10 +63,10 @@ module Projects Labels::TransferService.new(current_user, old_group, project).execute # Move uploads - Gitlab::UploadsTransfer.new.move_project(project.path, old_namespace.path, new_namespace.path) + Gitlab::UploadsTransfer.new.move_project(project.path, old_namespace.full_path, new_namespace.full_path) # Move pages - Gitlab::PagesTransfer.new.move_project(project.path, old_namespace.path, new_namespace.path) + Gitlab::PagesTransfer.new.move_project(project.path, old_namespace.full_path, new_namespace.full_path) project.old_path_with_namespace = old_path diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 5238623e936efdc64db0f7fdc89a11ae028035a4..e67ad6637204e14f6f139a6c03e95dd8ca668834 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -163,6 +163,6 @@ - @groups.each do |group| %p = link_to [:admin, group], class: 'str-truncated-60' do - = group.name + = group.full_name %span.light.pull-right #{time_ago_with_tooltip(group.created_at)} diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index cf8d438670bc6b2ac0d07ce94e86fa2b999da919..cdef63daca95d3c3f3c08d93e6d6996bb13886b2 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -30,7 +30,7 @@ - toggle_text = 'Namespace' - if params[:namespace_id].present? - namespace = Namespace.find(params[:namespace_id]) - - toggle_text = "#{namespace.kind}: #{namespace.path}" + - toggle_text = "#{namespace.kind}: #{namespace.full_path}" = dropdown_toggle(toggle_text, { toggle: 'dropdown' }, { toggle_class: 'js-namespace-select large' }) .dropdown-menu.dropdown-select.dropdown-menu-align-right = dropdown_title('Namespaces') diff --git a/app/views/import/base/unauthorized.js.haml b/app/views/import/base/unauthorized.js.haml index 36f8069c1f7951696d0826640cfd447d0324badf..ada5f99f4e2c93c41c794b604386f5abaac8a74f 100644 --- a/app/views/import/base/unauthorized.js.haml +++ b/app/views/import/base/unauthorized.js.haml @@ -4,7 +4,7 @@ import_button = tr.find(".btn-import") origin_target = target_field.text() project_name = "#{@project_name}" - origin_namespace = "#{@target_namespace.path}" + origin_namespace = "#{@target_namespace.full_path}" target_field.empty() target_field.append("

This namespace has already been taken! Please choose another one.

") target_field.append("") diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 9c5c1a6d707830ff051d12130bc2f94ebc8514d8..f2905fa3ce9aa30b7ddf8ce84e128e92b395bf0a 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -232,7 +232,7 @@ .form-group .input-group .input-group-addon - #{URI.join(root_url, @project.namespace.path)}/ + #{URI.join(root_url, @project.namespace.full_path)}/ = f.text_field :path, class: 'form-control' %ul %li Be careful. Renaming a project's repository can have unintended side effects. diff --git a/app/views/projects/group_links/_index.html.haml b/app/views/projects/group_links/_index.html.haml index 99d0df2ac34e42ef94d2f08ad70424addcd2c9d3..b6116dbec414a616d477f272c69c179c28f123c1 100644 --- a/app/views/projects/group_links/_index.html.haml +++ b/app/views/projects/group_links/_index.html.haml @@ -39,7 +39,7 @@ = icon("folder-open-o", class: "settings-list-icon") .pull-left = link_to group do - = group.name + = group.full_name %br up to #{group_link.human_access} - if group_link.expires? diff --git a/app/views/projects/pages_domains/show.html.haml b/app/views/projects/pages_domains/show.html.haml index 52dddb052a79e1fa3f0769413e62701b35fb6f46..876cac0dacba3480dba7c13546cd81111bef6ee7 100644 --- a/app/views/projects/pages_domains/show.html.haml +++ b/app/views/projects/pages_domains/show.html.haml @@ -17,7 +17,7 @@ %p To access the domain create a new DNS record: %pre - #{@domain.domain} CNAME #{@domain.project.namespace.path}.#{Settings.pages.host}. + #{@domain.domain} CNAME #{@domain.project.pages_subdomain}.#{Settings.pages.host}. %tr %td Certificate diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml index 81b5bc1de300c2ccfc8767f83afcafe72a7e2089..1d5a61cffce463d2ab9b3e51092afb6ef9b716d3 100644 --- a/app/views/shared/members/_group.html.haml +++ b/app/views/shared/members/_group.html.haml @@ -6,7 +6,7 @@ %span.list-item-name = image_tag group_icon(group), class: "avatar s40", alt: '' %strong - = link_to group.name, group_path(group) + = link_to group.full_name, group_path(group) .cgray Joined #{time_ago_with_tooltip(group.created_at)} - if group_link.expires? diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md index 88cd407d792b3e3ecfd334e698a173e8f8d4dbfe..1d97b5de688401b0e789a62efc4b778e191556eb 100644 --- a/doc/api/namespaces.md +++ b/doc/api/namespaces.md @@ -35,6 +35,12 @@ Example response: "id": 2, "path": "group1", "kind": "group" + }, + { + "id": 3, + "path": "bar", + "kind": "group", + "full_path": "foo/bar", } ] ``` @@ -64,7 +70,8 @@ Example response: { "id": 4, "path": "twitter", - "kind": "group" + "kind": "group", + "full_path": "twitter", } ] ``` diff --git a/doc/api/projects.md b/doc/api/projects.md index fa51158956aa6f84bcd13729199f3a8ff7a4bd82..b3136be67316184c95498dbb2058368e36810c75 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -77,7 +77,8 @@ Parameters: "id": 3, "name": "Diaspora", "path": "diaspora", - "kind": "group" + "kind": "group", + "full_path": "diaspora" }, "archived": false, "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", @@ -127,7 +128,8 @@ Parameters: "id": 4, "name": "Brightbox", "path": "brightbox", - "kind": "group" + "kind": "group", + "full_path": "brightbox" }, "permissions": { "project_access": { @@ -207,7 +209,8 @@ Parameters: "id": 3, "name": "Diaspora", "path": "diaspora", - "kind": "group" + "kind": "group", + "full_path": "diaspora" }, "permissions": { "project_access": { @@ -585,7 +588,8 @@ Example response: "id": 3, "name": "Diaspora", "path": "diaspora", - "kind": "group" + "kind": "group", + "full_path": "diaspora" }, "archived": true, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", @@ -650,7 +654,8 @@ Example response: "id": 3, "name": "Diaspora", "path": "diaspora", - "kind": "group" + "kind": "group", + "full_path": "diaspora" }, "archived": true, "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", @@ -721,7 +726,8 @@ Example response: "id": 3, "name": "Diaspora", "path": "diaspora", - "kind": "group" + "kind": "group", + "full_path": "diaspora" }, "permissions": { "project_access": { @@ -803,7 +809,8 @@ Example response: "id": 3, "name": "Diaspora", "path": "diaspora", - "kind": "group" + "kind": "group", + "full_path": "diaspora" }, "permissions": { "project_access": { @@ -1187,4 +1194,4 @@ Parameters: | --------- | ---- | -------- | ----------- | | `query` | string | yes | A string contained in the project name | | `order_by` | string | no | Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields | -| `sort` | string | no | Return requests sorted in `asc` or `desc` order | +| `sort` | string | no | Return requests sorted in `asc` or `desc` order | \ No newline at end of file diff --git a/lib/api/entities.rb b/lib/api/entities.rb index d4234ffe818ed8f0efe23a4eba015eec763662fb..3806470ac9440b14c5a67893c092c221075fe6c9 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -414,7 +414,7 @@ module API end class Namespace < Grape::Entity - expose :id, :name, :path, :kind + expose :id, :name, :path, :kind, :full_path end class MemberAccess < Grape::Entity diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index d746070913d3008b1082b764e61c781c915b084f..91e43dcb1145df3693803b0c2b22269795426394 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -12,7 +12,7 @@ module Backup path_to_project_bundle = path_to_bundle(project) # Create namespace dir if missing - FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.path)) if project.namespace + FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.full_path)) if project.namespace if project.empty_repo? $progress.puts "[SKIPPED]".color(:cyan) diff --git a/lib/gitlab/google_code_import/importer.rb b/lib/gitlab/google_code_import/importer.rb index 1f4edc369288060fb5f75231783e259417ba5bf9..b02b9737493dedd800506129cbea498f2ea55f11 100644 --- a/lib/gitlab/google_code_import/importer.rb +++ b/lib/gitlab/google_code_import/importer.rb @@ -310,7 +310,7 @@ module Gitlab if name == project.import_source "##{id}" else - "#{project.namespace.path}/#{name}##{id}" + "#{project.namespace.full_path}/#{name}##{id}" end text = "~~#{text}~~" if deleted text diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index d679edec36b621c05875c5be34d135e5f305bade..a46a41bc56ea7bb839b5bb984acfc784876974d1 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -35,7 +35,7 @@ module Gitlab end def export_filename(project:) - basename = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_#{project.namespace.path}_#{project.path}" + basename = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_#{project.namespace.full_path}_#{project.path}" "#{basename[0..FILENAME_LIMIT]}_export.tar.gz" end diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index e9ee47fc090d5091bed7cfbccee80fa129c6006e..063ce74ecad4fcd6c5b6441238a3dc9cffe9ed8b 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -56,7 +56,7 @@ module Gitlab end def path_with_namespace - File.join(@project.namespace.path, @project.path) + File.join(@project.namespace.full_path, @project.path) end def repo_path diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb index 82e194c1af12f32943e9fe67478c4583161d39dd..942cedd6cd493895ca6d8d0c18ceb3cb2390b2ab 100644 --- a/lib/gitlab/shell.rb +++ b/lib/gitlab/shell.rb @@ -172,7 +172,7 @@ module Gitlab # add_namespace("/path/to/storage", "gitlab") # def add_namespace(storage, name) - FileUtils.mkdir(full_path(storage, name), mode: 0770) unless exists?(storage, name) + FileUtils.mkdir_p(full_path(storage, name), mode: 0770) unless exists?(storage, name) end # Remove directory from repositories storage diff --git a/spec/lib/gitlab/import_export/import_export_spec.rb b/spec/lib/gitlab/import_export/import_export_spec.rb index 53f7d244d88bd81b5d9f18518cf60d4cb1ba9d32..20743811dab9b302c7cdd221b65b5c70abb6fdc8 100644 --- a/spec/lib/gitlab/import_export/import_export_spec.rb +++ b/spec/lib/gitlab/import_export/import_export_spec.rb @@ -2,14 +2,15 @@ require 'spec_helper' describe Gitlab::ImportExport, services: true do describe 'export filename' do - let(:project) { create(:empty_project, :public, path: 'project-path') } + let(:group) { create(:group, :nested) } + let(:project) { create(:empty_project, :public, path: 'project-path', namespace: group) } it 'contains the project path' do expect(described_class.export_filename(project: project)).to include(project.path) end it 'contains the namespace path' do - expect(described_class.export_filename(project: project)).to include(project.namespace.path) + expect(described_class.export_filename(project: project)).to include(project.namespace.full_path) end it 'does not go over a certain length' do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 35f3dd00870a65a5d5eef3b16089cc653582f21a..b0087a9e15da4e3d11f4e434014393ddd6ba2426 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1852,8 +1852,8 @@ describe Project, models: true do end describe '#pages_url' do - let(:group) { create :group, name: group_name } - let(:project) { create :empty_project, namespace: group, name: project_name } + let(:group) { create :group, name: 'Group' } + let(:nested_group) { create :group, parent: group } let(:domain) { 'Example.com' } subject { project.pages_url } @@ -1863,18 +1863,37 @@ describe Project, models: true do allow(Gitlab.config.pages).to receive(:url).and_return('http://example.com') end - context 'group page' do - let(:group_name) { 'Group' } - let(:project_name) { 'group.example.com' } + context 'top-level group' do + let(:project) { create :empty_project, namespace: group, name: project_name } - it { is_expected.to eq("http://group.example.com") } + context 'group page' do + let(:project_name) { 'group.example.com' } + + it { is_expected.to eq("http://group.example.com") } + end + + context 'project page' do + let(:project_name) { 'Project' } + + it { is_expected.to eq("http://group.example.com/project") } + end end - context 'project page' do - let(:group_name) { 'Group' } - let(:project_name) { 'Project' } + context 'nested group' do + let(:project) { create :empty_project, namespace: nested_group, name: project_name } + let(:expected_url) { "http://group.example.com/#{nested_group.path}/#{project.path}" } - it { is_expected.to eq("http://group.example.com/project") } + context 'group page' do + let(:project_name) { 'group.example.com' } + + it { is_expected.to eq(expected_url) } + end + + context 'project page' do + let(:project_name) { 'Project' } + + it { is_expected.to eq(expected_url) } + end end end end diff --git a/spec/requests/api/namespaces_spec.rb b/spec/requests/api/namespaces_spec.rb index c1edf384d5cccd3622b31bb985f7ec1f1f12cd35..a945d56f529ee1b94a0c31b1e4821fb877515c8f 100644 --- a/spec/requests/api/namespaces_spec.rb +++ b/spec/requests/api/namespaces_spec.rb @@ -5,7 +5,7 @@ describe API::Namespaces, api: true do let(:admin) { create(:admin) } let(:user) { create(:user) } let!(:group1) { create(:group) } - let!(:group2) { create(:group) } + let!(:group2) { create(:group, :nested) } describe "GET /namespaces" do context "when unauthenticated" do @@ -25,11 +25,13 @@ describe API::Namespaces, api: true do end it "admin: returns an array of matched namespaces" do - get api("/namespaces?search=#{group1.name}", admin) + get api("/namespaces?search=#{group2.name}", admin) expect(response).to have_http_status(200) expect(json_response).to be_an Array expect(json_response.length).to eq(1) + expect(json_response.last['path']).to eq(group2.path) + expect(json_response.last['full_path']).to eq(group2.full_path) end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index bca7642b6fc8c4bbbc13ac4dde90e7aafd140853..741815a780e105c456a8f6e4757f2c7765bfb15b 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -585,6 +585,7 @@ describe API::Projects, api: true do 'name' => user.namespace.name, 'path' => user.namespace.path, 'kind' => user.namespace.kind, + 'full_path' => user.namespace.full_path, }) end diff --git a/spec/requests/api/v3/projects_spec.rb b/spec/requests/api/v3/projects_spec.rb index a495122bba7678b2c0cf22d5b59e11d13ed3c62e..36d99d80e798ccca032aa5af5ce9590d49db6ae1 100644 --- a/spec/requests/api/v3/projects_spec.rb +++ b/spec/requests/api/v3/projects_spec.rb @@ -682,6 +682,7 @@ describe API::V3::Projects, api: true do 'name' => user.namespace.name, 'path' => user.namespace.path, 'kind' => user.namespace.kind, + 'full_path' => user.namespace.full_path, }) end