Skip to content

Commit 353578b

Browse files
committed
Git backend: make defaul_branch to point to VCS' default branch
Currently, importing a project manually without setting the `default_branch`, will make Git VCS to use `master` as the default branch. However, with the last swap about `master` and `main` branches, repositories defaulting to `main` branch fail when being imported on Read the Docs. Leaving the user in a blocked state they can get out. This commit allows `Version.identifier` to be NULL meaning that "it won't try to guess what's the default branch of the VCS" and just leave the repository in the immediate state after being cloned (which is already the default branch). To do this, I'm removing the command `git checkout --force <branch>` from the steps executed for this case. Closes #9367
1 parent 9245074 commit 353578b

File tree

6 files changed

+73
-29
lines changed

6 files changed

+73
-29
lines changed

readthedocs/builds/managers.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""Build and Version class model Managers."""
22

33
import structlog
4-
54
from django.core.exceptions import ObjectDoesNotExist
65
from django.db import models
76
from polymorphic.managers import PolymorphicManager
@@ -62,7 +61,6 @@ def create_latest(self, **kwargs):
6261
'verbose_name': LATEST_VERBOSE_NAME,
6362
'machine': True,
6463
'active': True,
65-
'identifier': LATEST,
6664
'type': BRANCH,
6765
}
6866
defaults.update(kwargs)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Generated by Django 3.2.13 on 2022-07-11 08:53
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("builds", "0044_alter_version_documentation_type"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="version",
15+
name="identifier",
16+
field=models.CharField(
17+
blank=True, max_length=255, null=True, verbose_name="Identifier"
18+
),
19+
),
20+
]

readthedocs/builds/models.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,14 @@ class Version(TimeStampedModel):
120120
)
121121
# used by the vcs backend
122122

123-
#: The identifier is the ID for the revision this is version is for. This
124-
#: might be the revision number (e.g. in SVN), or the commit hash (e.g. in
125-
#: Git). If the this version is pointing to a branch, then ``identifier``
126-
#: will contain the branch name.
127-
identifier = models.CharField(_('Identifier'), max_length=255)
123+
# The identifier is the ID for the revision this is version is for. This
124+
# might be the revision number (e.g. in SVN), or the commit hash (e.g. in
125+
# Git). If the this version is pointing to a branch, then ``identifier``
126+
# will contain the branch name. NULL value means it will use the VCS
127+
# default branch cloned.
128+
identifier = models.CharField(
129+
_("Identifier"), max_length=255, null=True, blank=True
130+
)
128131

129132
#: This is the actual name that we got for the commit stored in
130133
#: ``identifier``. This might be the tag or branch name like ``"v1.0.4"``.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Generated by Django 3.2.13 on 2022-07-11 09:06
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("projects", "0089_update_help_text"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="historicalproject",
15+
name="default_branch",
16+
field=models.CharField(
17+
blank=True,
18+
default=None,
19+
help_text='What branch "latest" points to. Leave empty to use the default value for your VCS.',
20+
max_length=255,
21+
null=True,
22+
verbose_name="Default branch",
23+
),
24+
),
25+
migrations.AlterField(
26+
model_name="project",
27+
name="default_branch",
28+
field=models.CharField(
29+
blank=True,
30+
default=None,
31+
help_text='What branch "latest" points to. Leave empty to use the default value for your VCS.',
32+
max_length=255,
33+
null=True,
34+
verbose_name="Default branch",
35+
),
36+
),
37+
]

readthedocs/projects/models.py

+4-14
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ class Project(models.Model):
164164
default=LATEST,
165165
help_text=_('The version of your project that / redirects to'),
166166
)
167-
# In default_branch, None means the backend should choose the
168-
# appropriate branch. Eg 'master' for git
167+
# In default_branch, ``None`` means the backend will use the default branch
168+
# clonned for each backend.
169169
default_branch = models.CharField(
170170
_('Default branch'),
171171
max_length=255,
@@ -174,8 +174,7 @@ class Project(models.Model):
174174
blank=True,
175175
help_text=_(
176176
'What branch "latest" points to. Leave empty '
177-
'to use the default value for your VCS (eg. '
178-
'<code>trunk</code> or <code>master</code>).',
177+
"to use the default value for your VCS.",
179178
),
180179
)
181180
requirements_file = models.CharField(
@@ -468,19 +467,10 @@ def save(self, *args, **kwargs): # pylint: disable=arguments-differ
468467
if not self.slug:
469468
raise Exception(_('Model must have slug'))
470469
super().save(*args, **kwargs)
471-
try:
472-
latest = self.versions.filter(slug=LATEST).first()
473-
default_branch = self.get_default_branch()
474-
if latest and latest.identifier != default_branch:
475-
latest.identifier = default_branch
476-
latest.save()
477-
except Exception:
478-
log.exception('Failed to update latest identifier')
479470

480471
try:
481-
branch = self.get_default_branch()
482472
if not self.versions.filter(slug=LATEST).exists():
483-
self.versions.create_latest(identifier=branch)
473+
self.versions.create_latest()
484474
except Exception:
485475
log.exception('Error creating default branches')
486476

readthedocs/vcs_support/backends/git.py

+4-8
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,7 @@ def fetch(self):
174174
code, stdout, stderr = self.run(*cmd)
175175
return code, stdout, stderr
176176

177-
def checkout_revision(self, revision=None):
178-
if not revision:
179-
branch = self.default_branch or self.fallback_branch
180-
revision = 'origin/%s' % branch
181-
177+
def checkout_revision(self, revision):
182178
try:
183179
code, out, err = self.run('git', 'checkout', '--force', revision)
184180
return [code, out, err]
@@ -322,12 +318,12 @@ def submodules(self):
322318
def checkout(self, identifier=None):
323319
"""Checkout to identifier or latest."""
324320
super().checkout()
325-
# Find proper identifier
321+
322+
# NOTE: if there is no identifier, we default to default branch cloned
326323
if not identifier:
327-
identifier = self.default_branch or self.fallback_branch
324+
return
328325

329326
identifier = self.find_ref(identifier)
330-
331327
# Checkout the correct identifier for this branch.
332328
code, out, err = self.checkout_revision(identifier)
333329

0 commit comments

Comments
 (0)