Repository: readthedocs/readthedocs.org

Issue:
Extra slash in "Edit on GitHub" link
## Details

* Read the Docs project URL: http://glom.readthedocs.io/
* GitHub URL: https://github.com/mahmoud/glom
* Build URL (if applicable): N/A
* Read the Docs username (if applicable): mahmoud

## Expected Result

"Edit on GitHub" link at the top of the page should link to doc on GitHub.

## Actual Result

"Edit on GitHub" link at the top of the page links to 404. There is an extra slash in the URL: `https://github.com/mahmoud/glom//master/docs/index.rst` (after `glom`, before `master`)

Interestingly, the "Edit" link in the bottom left menu seems to work fine.


Discussion:
Hi @mahmoud ,
I don't think it happens because of the extra slash but because of the missing word `blob`. The url should be `https://github.com/mahmoud/glom/blob/master/docs/index.rst`. Isn't it?
Can you try updating the rtd-theme? https://github.com/mahmoud/glom/blob/5a10e66c2f1204988f97e6545055bfc5b36e052f/requirements-rtd.txt#L36 Current one is `0.4.3` https://pypi.python.org/pypi/sphinx_rtd_theme
@rexzing you're absolutely right!

@stsewd trying this now, thanks!
@stsewd Hmm, no luck I'm afraid. In fact, I see 3 slashes now: `https://github.com/mahmoud/glom///master/docs/index.rst`. 
Thanks, I'll try to replicate this locally and dig a little more
Whoops, I lied, did stuff on the wrong local branch. Updating the theme got me a working link, with `blob`, but it does have an extra slash fwiw: `https://github.com/mahmoud/glom//blob/master/docs/index.rst`

It still gets me to GitHub though, so I'm happy enough! :) Thanks for your help!
The extra slash is from the repo url, we could strip it, tho
I'll leave it up to you, but I think an rstrip and join of a single slash should yield a nicely normalized URL. :)

Resolving patch:
diff --git a/readthedocs/projects/forms.py b/readthedocs/projects/forms.py
--- a/readthedocs/projects/forms.py
+++ b/readthedocs/projects/forms.py
@@ -131,6 +131,10 @@ def clean_name(self):
 
         return name
 
+    def clean_repo(self):
+        repo = self.cleaned_data.get('repo', '')
+        return repo.rstrip('/')
+
     def clean_remote_repository(self):
         remote_repo = self.cleaned_data.get('remote_repository', None)
         if not remote_repo:


Test patch:
diff --git a/readthedocs/rtd_tests/tests/test_project_forms.py b/readthedocs/rtd_tests/tests/test_project_forms.py
--- a/readthedocs/rtd_tests/tests/test_project_forms.py
+++ b/readthedocs/rtd_tests/tests/test_project_forms.py
@@ -1,12 +1,9 @@
-# -*- coding: utf-8 -*-
-
 import mock
 from django.contrib.auth.models import User
 from django.test import TestCase
 from django.test.utils import override_settings
 from django_dynamic_fixture import get
 from textclassifier.validators import ClassifierValidator
-from django.core.exceptions import ValidationError
 
 from readthedocs.builds.constants import LATEST
 from readthedocs.builds.models import Version
@@ -180,6 +177,18 @@ def test_length_of_tags(self):
         error_msg = 'Length of each tag must be less than or equal to 100 characters.'
         self.assertDictEqual(form.errors, {'tags': [error_msg]})
 
+    def test_strip_repo_url(self):
+        form = ProjectBasicsForm({
+            'name': 'foo',
+            'repo_type': 'git',
+            'repo': 'https://github.com/rtfd/readthedocs.org/'
+        })
+        self.assertTrue(form.is_valid())
+        self.assertEqual(
+            form.cleaned_data['repo'],
+            'https://github.com/rtfd/readthedocs.org'
+        )
+
 
 class TestProjectAdvancedForm(TestCase):
 
@@ -514,7 +523,7 @@ class TestNotificationForm(TestCase):
 
     def setUp(self):
         self.project = get(Project)
-        
+
     def test_webhookform(self):
         self.assertEqual(self.project.webhook_notifications.all().count(), 0)