From 4a0ca85834b6cf7decb58857986e535ba4e37c53 Mon Sep 17 00:00:00 2001
From: Felipe Artur <felipefac@gmail.com>
Date: Tue, 6 Dec 2016 18:56:59 -0200
Subject: [PATCH] Allow branch names with dots on API endpoint

---
 changelogs/unreleased/issue_25030.yml |  4 ++++
 lib/api/branches.rb                   | 16 +++++++-------
 spec/requests/api/branches_spec.rb    | 31 +++++++++++++++++++++++++++
 3 files changed, 43 insertions(+), 8 deletions(-)
 create mode 100644 changelogs/unreleased/issue_25030.yml

diff --git a/changelogs/unreleased/issue_25030.yml b/changelogs/unreleased/issue_25030.yml
new file mode 100644
index 00000000000..e18b8d6a79b
--- /dev/null
+++ b/changelogs/unreleased/issue_25030.yml
@@ -0,0 +1,4 @@
+---
+title: Allow branch names with dots on API endpoint
+merge_request: 
+author: 
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 73aed624ea7..0950c3d2e88 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -23,9 +23,9 @@ module API
         success Entities::RepoBranch
       end
       params do
-        requires :branch, type: String, regexp: /.+/, desc: 'The name of the branch'
+        requires :branch, type: String, desc: 'The name of the branch'
       end
-      get ':id/repository/branches/:branch' do
+      get ':id/repository/branches/:branch', requirements: { branch: /.+/ } do
         branch = user_project.repository.find_branch(params[:branch])
         not_found!("Branch") unless branch
 
@@ -39,11 +39,11 @@ module API
         success Entities::RepoBranch
       end
       params do
-        requires :branch, type: String, regexp: /.+/, desc: 'The name of the branch'
+        requires :branch, type: String, desc: 'The name of the branch'
         optional :developers_can_push, type: Boolean, desc: 'Flag if developers can push to that branch'
         optional :developers_can_merge, type: Boolean, desc: 'Flag if developers can merge to that branch'
       end
-      put ':id/repository/branches/:branch/protect' do
+      put ':id/repository/branches/:branch/protect', requirements: { branch: /.+/ } do
         authorize_admin_project
 
         branch = user_project.repository.find_branch(params[:branch])
@@ -76,9 +76,9 @@ module API
         success Entities::RepoBranch
       end
       params do
-        requires :branch, type: String, regexp: /.+/, desc: 'The name of the branch'
+        requires :branch, type: String, desc: 'The name of the branch'
       end
-      put ':id/repository/branches/:branch/unprotect' do
+      put ':id/repository/branches/:branch/unprotect', requirements: { branch: /.+/ } do
         authorize_admin_project
 
         branch = user_project.repository.find_branch(params[:branch])
@@ -112,9 +112,9 @@ module API
 
       desc 'Delete a branch'
       params do
-        requires :branch, type: String, regexp: /.+/, desc: 'The name of the branch'
+        requires :branch, type: String, desc: 'The name of the branch'
       end
-      delete ":id/repository/branches/:branch" do
+      delete ":id/repository/branches/:branch", requirements: { branch: /.+/ } do
         authorize_push_project
 
         result = DeleteBranchService.new(user_project, current_user).
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 55b8c8c0c69..2878e0cb59b 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -11,6 +11,7 @@ describe API::Branches, api: true  do
   let!(:guest) { create(:project_member, :guest, user: user2, project: project) }
   let!(:branch_name) { 'feature' }
   let!(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
+  let!(:branch_with_dot) { CreateBranchService.new(project, user).execute("with.1.2.3", "master") }
 
   describe "GET /projects/:id/repository/branches" do
     it "returns an array of project branches" do
@@ -37,6 +38,13 @@ describe API::Branches, api: true  do
       expect(json_response['developers_can_merge']).to eq(false)
     end
 
+    it "returns the branch information for a single branch with dots in the name" do
+      get api("/projects/#{project.id}/repository/branches/with.1.2.3", user)
+
+      expect(response).to have_http_status(200)
+      expect(json_response['name']).to eq("with.1.2.3")
+    end
+
     context 'on a merged branch' do
       it "returns the branch information for a single branch" do
         get api("/projects/#{project.id}/repository/branches/merge-test", user)
@@ -71,6 +79,14 @@ describe API::Branches, api: true  do
         expect(json_response['developers_can_merge']).to eq(false)
       end
 
+      it "protects a single branch with dots in the name" do
+        put api("/projects/#{project.id}/repository/branches/with.1.2.3/protect", user)
+
+        expect(response).to have_http_status(200)
+        expect(json_response['name']).to eq("with.1.2.3")
+        expect(json_response['protected']).to eq(true)
+      end
+
       it 'protects a single branch and developers can push' do
         put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user),
             developers_can_push: true
@@ -220,6 +236,14 @@ describe API::Branches, api: true  do
       expect(json_response['protected']).to eq(false)
     end
 
+    it "update branches with dots in branch name" do
+      put api("/projects/#{project.id}/repository/branches/with.1.2.3/unprotect", user)
+
+      expect(response).to have_http_status(200)
+      expect(json_response['name']).to eq("with.1.2.3")
+      expect(json_response['protected']).to eq(false)
+    end
+
     it "returns success when unprotect branch" do
       put api("/projects/#{project.id}/repository/branches/unknown/unprotect", user)
       expect(response).to have_http_status(404)
@@ -292,6 +316,13 @@ describe API::Branches, api: true  do
       expect(json_response['branch_name']).to eq(branch_name)
     end
 
+    it "removes a branch with dots in the branch name" do
+      delete api("/projects/#{project.id}/repository/branches/with.1.2.3", user)
+
+      expect(response).to have_http_status(200)
+      expect(json_response['branch_name']).to eq("with.1.2.3")
+    end
+
     it 'returns 404 if branch not exists' do
       delete api("/projects/#{project.id}/repository/branches/foobar", user)
       expect(response).to have_http_status(404)
-- 
GitLab