Repository: readthedocs/readthedocs.org

Issue:
checking out wrong branch name
## Details

* Read the Docs project URL: https://readthedocs.org/projects/flatland/
* Build URL (if applicable): https://readthedocs.org/projects/flatland/builds/8034952/
* Read the Docs username (if applicable): thomaswaldmann

## Expected Result

build docs from master branch.

## Actual Result

```
git checkout --force default
error: pathspec 'default' did not match any file(s) known to git. 
```

So it tries to checkout `default` instead of `master`. I  tried changing the branch in the settings, but i can not select `master` and not selecting anything (`------`) does not help either.



Discussion:
Note: the project has recently switched from bitbucket/mercurial to github/git, in case that matters.

Building the docs for the `0.8` tag does not work either.
I already tried "cleaning" the build environment (as it offers on the rtfd site), did not help either.
I think there was an open issue already for this  (I'm searching now.) Did you try changing the default branch from the advanced settings?
Yes, as I said: no `master` there. And not selecting anything (`------`) does obviously **not** choose the VCS default branchname as the help text there says (which would be `master` in case of git). Smells like a bug.
Found the ticket, It was closed recently because it was stale https://github.com/rtfd/readthedocs.org/issues/1170, the current workaround is recreating the project.
Yes, deleting and recreating the project solves the problem.

Having to do that sucks, though. It's likely just a form field not getting updated / processed correctly, right?

Note: deletion of the project invalidated the build URL given in the top post.
Ok, I was able to reproduce without having a real mercurial repo, if someone makes a mistake when creating the project and choose the wrong repo type can have this problem.
> Having to do that sucks, though. It's likely just a form field not getting updated / processed correctly, right?

Yeah, I'm investigating now
So, the problem is that we are relying on the `LATEST` slug rather than calling `get_default_branch`, we could update the latest version or change where we are not using `get_default_branch`.

Resolving patch:
diff --git a/readthedocs/projects/models.py b/readthedocs/projects/models.py
--- a/readthedocs/projects/models.py
+++ b/readthedocs/projects/models.py
@@ -323,11 +323,11 @@ def save(self, *args, **kwargs):  # pylint: disable=arguments-differ
         for owner in self.users.all():
             assign('view_project', owner, self)
         try:
-            if self.default_branch:
-                latest = self.versions.get(slug=LATEST)
-                if latest.identifier != self.default_branch:
-                    latest.identifier = self.default_branch
-                    latest.save()
+            latest = self.versions.get(slug=LATEST)
+            default_branch = self.get_default_branch()
+            if latest.identifier != default_branch:
+                latest.identifier = default_branch
+                latest.save()
         except Exception:
             log.exception('Failed to update latest identifier')
 


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
@@ -16,7 +16,13 @@
 
 from readthedocs.builds.constants import LATEST
 from readthedocs.builds.models import Version
-from readthedocs.projects.constants import PRIVATE, PROTECTED, PUBLIC
+from readthedocs.projects.constants import (
+    PRIVATE,
+    PROTECTED,
+    PUBLIC,
+    REPO_TYPE_GIT,
+    REPO_TYPE_HG,
+)
 from readthedocs.projects.exceptions import ProjectSpamError
 from readthedocs.projects.forms import (
     ProjectAdvancedForm,
@@ -29,6 +35,7 @@
 
 
 class TestProjectForms(TestCase):
+
     @mock.patch.object(ClassifierValidator, '__call__')
     def test_form_spam(self, mocked_validator):
         """Form description field fails spam validation."""
@@ -83,7 +90,7 @@ def test_import_repo_url(self):
             ('ssh+git://github.com/humitos/foo', True),
             ('strangeuser@bitbucket.org:strangeuser/readthedocs.git', True),
             ('user@one-ssh.domain.com:22/_ssh/docs', True),
-         ] + common_urls
+        ] + common_urls
 
         with override_settings(ALLOW_PRIVATE_REPOS=False):
             for url, valid in public_urls:
@@ -115,6 +122,47 @@ def test_empty_slug(self):
         self.assertFalse(form.is_valid())
         self.assertIn('name', form.errors)
 
+    def test_changing_vcs_should_change_latest(self):
+        """When changing the project's VCS, latest should be changed too."""
+        project = get(Project, repo_type=REPO_TYPE_HG, default_branch=None)
+        latest = project.versions.get(slug=LATEST)
+        self.assertEqual(latest.identifier, 'default')
+
+        form = ProjectBasicsForm(
+            {
+                'repo': 'http://github.com/test/test',
+                'name': 'name',
+                'repo_type': REPO_TYPE_GIT,
+            },
+            instance=project,
+        )
+        self.assertTrue(form.is_valid())
+        form.save()
+        latest.refresh_from_db()
+        self.assertEqual(latest.identifier, 'master')
+
+    def test_changing_vcs_should_not_change_latest_is_not_none(self):
+        """
+        When changing the project's VCS,
+        we should respect the custom default branch.
+        """
+        project = get(Project, repo_type=REPO_TYPE_HG, default_branch='custom')
+        latest = project.versions.get(slug=LATEST)
+        self.assertEqual(latest.identifier, 'custom')
+
+        form = ProjectBasicsForm(
+            {
+                'repo': 'http://github.com/test/test',
+                'name': 'name',
+                'repo_type': REPO_TYPE_GIT,
+            },
+            instance=project,
+        )
+        self.assertTrue(form.is_valid())
+        form.save()
+        latest.refresh_from_db()
+        self.assertEqual(latest.identifier, 'custom')
+
 
 class TestProjectAdvancedForm(TestCase):