Commit 2f7fc7e9 authored by Douwe Maan's avatar Douwe Maan

Prefer project with exact path to differently cased one when both exist.

parent 97eafd4b
...@@ -118,8 +118,8 @@ class ApplicationController < ActionController::Base ...@@ -118,8 +118,8 @@ class ApplicationController < ActionController::Base
end end
project_path = "#{namespace}/#{id}" project_path = "#{namespace}/#{id}"
@project = Project.find_with_namespace(project_path) @project = Project.find_with_namespace(project_path) ||
Project.find_with_namespace(project_path, case_sensitive: false)
if @project and can?(current_user, :read_project, @project) if @project and can?(current_user, :read_project, @project)
if @project.path_with_namespace != project_path if @project.path_with_namespace != project_path
......
...@@ -235,7 +235,7 @@ class Project < ActiveRecord::Base ...@@ -235,7 +235,7 @@ class Project < ActiveRecord::Base
where('projects.archived = ?', false).where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%") where('projects.archived = ?', false).where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%")
end end
def find_with_namespace(id) def find_with_namespace(id, case_sensitive: true)
namespace_path, project_path = id.split('/') namespace_path, project_path = id.split('/')
return nil if !namespace_path || !project_path return nil if !namespace_path || !project_path
...@@ -243,11 +243,18 @@ class Project < ActiveRecord::Base ...@@ -243,11 +243,18 @@ class Project < ActiveRecord::Base
# Use of unscoped ensures we're not secretly adding any ORDER BYs, which # Use of unscoped ensures we're not secretly adding any ORDER BYs, which
# have a negative impact on performance (and aren't needed for this # have a negative impact on performance (and aren't needed for this
# query). # query).
unscoped. projects = unscoped.
joins(:namespace). joins(:namespace).
iwhere('namespaces.path' => namespace_path). iwhere('namespaces.path' => namespace_path)
iwhere('projects.path' => project_path).
take projects =
if case_sensitive
projects.where('projects.path' => project_path)
else
projects.iwhere('projects.path' => project_path)
end
projects.take
end end
def visibility_levels def visibility_levels
......
...@@ -51,19 +51,37 @@ describe ProjectsController do ...@@ -51,19 +51,37 @@ describe ProjectsController do
end end
context "when requested with case sensitive namespace and project path" do context "when requested with case sensitive namespace and project path" do
it "redirects to the normalized path for case mismatch" do context "when there is a match with the same casing" do
it "loads the project" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path
expect(assigns(:project)).to eq(public_project)
expect(response.status).to eq(200)
end
end
context "when there is a match with different casing" do
it "redirects to the normalized path" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase
expect(assigns(:project)).to eq(public_project)
expect(response).to redirect_to("/#{public_project.path_with_namespace}") expect(response).to redirect_to("/#{public_project.path_with_namespace}")
end end
it "loads the page if normalized path matches request path" do context "when there is also a match with the same casing" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path
let!(:other_project) { create(:project, :public, namespace: public_project.namespace, path: public_project.path.upcase) }
it "loads the exactly matched project" do
get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase
expect(assigns(:project)).to eq(other_project)
expect(response.status).to eq(200) expect(response.status).to eq(200)
end end
end end
end end
end
end
describe "POST #toggle_star" do describe "POST #toggle_star" do
it "toggles star if user is signed in" do it "toggles star if user is signed in" do
......
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