We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
After build is triggered, state is shown as failed
To reproduce, fire off a new build, make sure to catch the build list page while VCS operations are happening. Build will be in a failure state. This is a regression where we are setting the state of the build to failed without checking that the build has completed. This might be a byproduct of using multiple environments during the build process.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `readthedocs/vcs_support/backends/git.py`
Content:
```
1 """Git-related utilities."""
2 
3 from __future__ import absolute_import
4 
5 import csv
6 import logging
7 import os
8 import re
9 
10 from builtins import str
11 from six import StringIO
12 
13 from readthedocs.projects.exceptions import RepositoryError
14 from readthedocs.vcs_support.base import BaseVCS, VCSVersion
15 
16 
17 log = logging.getLogger(__name__)
18 
19 
20 class Backend(BaseVCS):
21 
22     """Git VCS backend."""
23 
24     supports_tags = True
25     supports_branches = True
26     fallback_branch = 'master'  # default branch
27 
28     def __init__(self, *args, **kwargs):
29         super(Backend, self).__init__(*args, **kwargs)
30         self.token = kwargs.get('token', None)
31         self.repo_url = self._get_clone_url()
32 
33     def _get_clone_url(self):
34         if '://' in self.repo_url:
35             hacked_url = self.repo_url.split('://')[1]
36             hacked_url = re.sub('.git$', '', hacked_url)
37             clone_url = 'https://%s' % hacked_url
38             if self.token:
39                 clone_url = 'https://%s@%s' % (self.token, hacked_url)
40                 return clone_url
41             # Don't edit URL because all hosts aren't the same
42 
43             # else:
44                 # clone_url = 'git://%s' % (hacked_url)
45         return self.repo_url
46 
47     def set_remote_url(self, url):
48         return self.run('git', 'remote', 'set-url', 'origin', url)
49 
50     def update(self):
51         # Use checkout() to update repo
52         self.checkout()
53 
54     def repo_exists(self):
55         code, _, _ = self.run('git', 'status', record=False)
56         return code == 0
57 
58     def submodules_exists(self):
59         code, out, _ = self.run('git', 'submodule', 'status', record=False)
60         return code == 0 and bool(out)
61 
62     def fetch(self):
63         code, _, _ = self.run('git', 'fetch', '--tags', '--prune')
64         if code != 0:
65             raise RepositoryError
66 
67     def checkout_revision(self, revision=None):
68         if not revision:
69             branch = self.default_branch or self.fallback_branch
70             revision = 'origin/%s' % branch
71 
72         code, out, err = self.run(
73             'git', 'checkout', '--force', revision)
74         if code != 0:
75             log.warning("Failed to checkout revision '%s': %s",
76                         revision, code)
77         return [code, out, err]
78 
79     def clone(self):
80         code, _, _ = self.run(
81             'git', 'clone', '--recursive', self.repo_url, '.')
82         if code != 0:
83             raise RepositoryError
84 
85     @property
86     def tags(self):
87         retcode, stdout, _ = self.run('git', 'show-ref', '--tags', record_as_success=True)
88         # error (or no tags found)
89         if retcode != 0:
90             return []
91         return self.parse_tags(stdout)
92 
93     def parse_tags(self, data):
94         """
95         Parses output of show-ref --tags, eg:
96 
97             3b32886c8d3cb815df3793b3937b2e91d0fb00f1 refs/tags/2.0.0
98             bd533a768ff661991a689d3758fcfe72f455435d refs/tags/2.0.1
99             c0288a17899b2c6818f74e3a90b77e2a1779f96a refs/tags/2.0.2
100             a63a2de628a3ce89034b7d1a5ca5e8159534eef0 refs/tags/2.1.0.beta2
101             c7fc3d16ed9dc0b19f0d27583ca661a64562d21e refs/tags/2.1.0.rc1
102             edc0a2d02a0cc8eae8b67a3a275f65cd126c05b1 refs/tags/2.1.0.rc2
103 
104         Into VCSTag objects with the tag name as verbose_name and the commit
105         hash as identifier.
106         """
107         # parse the lines into a list of tuples (commit-hash, tag ref name)
108         # StringIO below is expecting Unicode data, so ensure that it gets it.
109         if not isinstance(data, str):
110             data = str(data)
111         raw_tags = csv.reader(StringIO(data), delimiter=' ')
112         vcs_tags = []
113         for row in raw_tags:
114             row = [f for f in row if f != '']
115             if row == []:
116                 continue
117             commit_hash, name = row
118             clean_name = name.replace('refs/tags/', '')
119             vcs_tags.append(VCSVersion(self, commit_hash, clean_name))
120         return vcs_tags
121 
122     @property
123     def branches(self):
124         # Only show remote branches
125         retcode, stdout, _ = self.run('git', 'branch', '-r')
126         # error (or no tags found)
127         if retcode != 0:
128             return []
129         return self.parse_branches(stdout)
130 
131     def parse_branches(self, data):
132         """
133         Parse output of git branch -r
134 
135         e.g.:
136 
137               origin/2.0.X
138               origin/HEAD -> origin/master
139               origin/develop
140               origin/master
141               origin/release/2.0.0
142               origin/release/2.1.0
143         """
144         clean_branches = []
145         # StringIO below is expecting Unicode data, so ensure that it gets it.
146         if not isinstance(data, str):
147             data = str(data)
148         raw_branches = csv.reader(StringIO(data), delimiter=' ')
149         for branch in raw_branches:
150             branch = [f for f in branch if f != '' and f != '*']
151             # Handle empty branches
152             if branch:
153                 branch = branch[0]
154                 if branch.startswith('origin/'):
155                     verbose_name = branch.replace('origin/', '')
156                     if verbose_name in ['HEAD']:
157                         continue
158                     clean_branches.append(VCSVersion(self, branch, verbose_name))
159                 else:
160                     clean_branches.append(VCSVersion(self, branch, branch))
161         return clean_branches
162 
163     @property
164     def commit(self):
165         _, stdout, _ = self.run('git', 'rev-parse', 'HEAD')
166         return stdout.strip()
167 
168     def checkout(self, identifier=None):
169         self.check_working_dir()
170 
171         # Clone or update repository
172         if self.repo_exists():
173             self.set_remote_url(self.repo_url)
174             self.fetch()
175         else:
176             self.make_clean_working_dir()
177             self.clone()
178 
179         # Find proper identifier
180         if not identifier:
181             identifier = self.default_branch or self.fallback_branch
182 
183         identifier = self.find_ref(identifier)
184 
185         # Checkout the correct identifier for this branch.
186         code, out, err = self.checkout_revision(identifier)
187         if code != 0:
188             return code, out, err
189 
190         # Clean any remains of previous checkouts
191         self.run('git', 'clean', '-d', '-f', '-f')
192 
193         # Update submodules
194         if self.submodules_exists():
195             self.run('git', 'submodule', 'sync')
196             self.run('git', 'submodule', 'update',
197                      '--init', '--recursive', '--force')
198 
199         return code, out, err
200 
201     def find_ref(self, ref):
202         # Check if ref starts with 'origin/'
203         if ref.startswith('origin/'):
204             return ref
205 
206         # Check if ref is a branch of the origin remote
207         if self.ref_exists('remotes/origin/' + ref):
208             return 'origin/' + ref
209 
210         return ref
211 
212     def ref_exists(self, ref):
213         code, _, _ = self.run('git', 'show-ref', ref, record_as_success=True)
214         return code == 0
215 
216     @property
217     def env(self):
218         env = super(Backend, self).env
219         env['GIT_DIR'] = os.path.join(self.working_dir, '.git')
220         # Don't prompt for username, this requires Git 2.3+
221         env['GIT_TERMINAL_PROMPT'] = '0'
222         return env
223
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/readthedocs/vcs_support/backends/git.py b/readthedocs/vcs_support/backends/git.py
--- a/readthedocs/vcs_support/backends/git.py
+++ b/readthedocs/vcs_support/backends/git.py
@@ -122,8 +122,8 @@
     @property
     def branches(self):
         # Only show remote branches
-        retcode, stdout, _ = self.run('git', 'branch', '-r')
-        # error (or no tags found)
+        retcode, stdout, _ = self.run('git', 'branch', '-r', record_as_success=True)
+        # error (or no branches found)
         if retcode != 0:
             return []
         return self.parse_branches(stdout)

{"golden_diff": "diff --git a/readthedocs/vcs_support/backends/git.py b/readthedocs/vcs_support/backends/git.py\n--- a/readthedocs/vcs_support/backends/git.py\n+++ b/readthedocs/vcs_support/backends/git.py\n@@ -122,8 +122,8 @@\n     @property\n     def branches(self):\n         # Only show remote branches\n-        retcode, stdout, _ = self.run('git', 'branch', '-r')\n-        # error (or no tags found)\n+        retcode, stdout, _ = self.run('git', 'branch', '-r', record_as_success=True)\n+        # error (or no branches found)\n         if retcode != 0:\n             return []\n         return self.parse_branches(stdout)\n", "issue": "After build is triggered, state is shown as failed\nTo reproduce, fire off a new build, make sure to catch the build list page while VCS operations are happening. Build will be in a failure state. This is a regression where we are setting the state of the build to failed without checking that the build has completed. This might be a byproduct of using multiple environments during the build process.\n", "before_files": [{"content": "\"\"\"Git-related utilities.\"\"\"\n\nfrom __future__ import absolute_import\n\nimport csv\nimport logging\nimport os\nimport re\n\nfrom builtins import str\nfrom six import StringIO\n\nfrom readthedocs.projects.exceptions import RepositoryError\nfrom readthedocs.vcs_support.base import BaseVCS, VCSVersion\n\n\nlog = logging.getLogger(__name__)\n\n\nclass Backend(BaseVCS):\n\n    \"\"\"Git VCS backend.\"\"\"\n\n    supports_tags = True\n    supports_branches = True\n    fallback_branch = 'master'  # default branch\n\n    def __init__(self, *args, **kwargs):\n        super(Backend, self).__init__(*args, **kwargs)\n        self.token = kwargs.get('token', None)\n        self.repo_url = self._get_clone_url()\n\n    def _get_clone_url(self):\n        if '://' in self.repo_url:\n            hacked_url = self.repo_url.split('://')[1]\n            hacked_url = re.sub('.git$', '', hacked_url)\n            clone_url = 'https://%s' % hacked_url\n            if self.token:\n                clone_url = 'https://%s@%s' % (self.token, hacked_url)\n                return clone_url\n            # Don't edit URL because all hosts aren't the same\n\n            # else:\n                # clone_url = 'git://%s' % (hacked_url)\n        return self.repo_url\n\n    def set_remote_url(self, url):\n        return self.run('git', 'remote', 'set-url', 'origin', url)\n\n    def update(self):\n        # Use checkout() to update repo\n        self.checkout()\n\n    def repo_exists(self):\n        code, _, _ = self.run('git', 'status', record=False)\n        return code == 0\n\n    def submodules_exists(self):\n        code, out, _ = self.run('git', 'submodule', 'status', record=False)\n        return code == 0 and bool(out)\n\n    def fetch(self):\n        code, _, _ = self.run('git', 'fetch', '--tags', '--prune')\n        if code != 0:\n            raise RepositoryError\n\n    def checkout_revision(self, revision=None):\n        if not revision:\n            branch = self.default_branch or self.fallback_branch\n            revision = 'origin/%s' % branch\n\n        code, out, err = self.run(\n            'git', 'checkout', '--force', revision)\n        if code != 0:\n            log.warning(\"Failed to checkout revision '%s': %s\",\n                        revision, code)\n        return [code, out, err]\n\n    def clone(self):\n        code, _, _ = self.run(\n            'git', 'clone', '--recursive', self.repo_url, '.')\n        if code != 0:\n            raise RepositoryError\n\n    @property\n    def tags(self):\n        retcode, stdout, _ = self.run('git', 'show-ref', '--tags', record_as_success=True)\n        # error (or no tags found)\n        if retcode != 0:\n            return []\n        return self.parse_tags(stdout)\n\n    def parse_tags(self, data):\n        \"\"\"\n        Parses output of show-ref --tags, eg:\n\n            3b32886c8d3cb815df3793b3937b2e91d0fb00f1 refs/tags/2.0.0\n            bd533a768ff661991a689d3758fcfe72f455435d refs/tags/2.0.1\n            c0288a17899b2c6818f74e3a90b77e2a1779f96a refs/tags/2.0.2\n            a63a2de628a3ce89034b7d1a5ca5e8159534eef0 refs/tags/2.1.0.beta2\n            c7fc3d16ed9dc0b19f0d27583ca661a64562d21e refs/tags/2.1.0.rc1\n            edc0a2d02a0cc8eae8b67a3a275f65cd126c05b1 refs/tags/2.1.0.rc2\n\n        Into VCSTag objects with the tag name as verbose_name and the commit\n        hash as identifier.\n        \"\"\"\n        # parse the lines into a list of tuples (commit-hash, tag ref name)\n        # StringIO below is expecting Unicode data, so ensure that it gets it.\n        if not isinstance(data, str):\n            data = str(data)\n        raw_tags = csv.reader(StringIO(data), delimiter=' ')\n        vcs_tags = []\n        for row in raw_tags:\n            row = [f for f in row if f != '']\n            if row == []:\n                continue\n            commit_hash, name = row\n            clean_name = name.replace('refs/tags/', '')\n            vcs_tags.append(VCSVersion(self, commit_hash, clean_name))\n        return vcs_tags\n\n    @property\n    def branches(self):\n        # Only show remote branches\n        retcode, stdout, _ = self.run('git', 'branch', '-r')\n        # error (or no tags found)\n        if retcode != 0:\n            return []\n        return self.parse_branches(stdout)\n\n    def parse_branches(self, data):\n        \"\"\"\n        Parse output of git branch -r\n\n        e.g.:\n\n              origin/2.0.X\n              origin/HEAD -> origin/master\n              origin/develop\n              origin/master\n              origin/release/2.0.0\n              origin/release/2.1.0\n        \"\"\"\n        clean_branches = []\n        # StringIO below is expecting Unicode data, so ensure that it gets it.\n        if not isinstance(data, str):\n            data = str(data)\n        raw_branches = csv.reader(StringIO(data), delimiter=' ')\n        for branch in raw_branches:\n            branch = [f for f in branch if f != '' and f != '*']\n            # Handle empty branches\n            if branch:\n                branch = branch[0]\n                if branch.startswith('origin/'):\n                    verbose_name = branch.replace('origin/', '')\n                    if verbose_name in ['HEAD']:\n                        continue\n                    clean_branches.append(VCSVersion(self, branch, verbose_name))\n                else:\n                    clean_branches.append(VCSVersion(self, branch, branch))\n        return clean_branches\n\n    @property\n    def commit(self):\n        _, stdout, _ = self.run('git', 'rev-parse', 'HEAD')\n        return stdout.strip()\n\n    def checkout(self, identifier=None):\n        self.check_working_dir()\n\n        # Clone or update repository\n        if self.repo_exists():\n            self.set_remote_url(self.repo_url)\n            self.fetch()\n        else:\n            self.make_clean_working_dir()\n            self.clone()\n\n        # Find proper identifier\n        if not identifier:\n            identifier = self.default_branch or self.fallback_branch\n\n        identifier = self.find_ref(identifier)\n\n        # Checkout the correct identifier for this branch.\n        code, out, err = self.checkout_revision(identifier)\n        if code != 0:\n            return code, out, err\n\n        # Clean any remains of previous checkouts\n        self.run('git', 'clean', '-d', '-f', '-f')\n\n        # Update submodules\n        if self.submodules_exists():\n            self.run('git', 'submodule', 'sync')\n            self.run('git', 'submodule', 'update',\n                     '--init', '--recursive', '--force')\n\n        return code, out, err\n\n    def find_ref(self, ref):\n        # Check if ref starts with 'origin/'\n        if ref.startswith('origin/'):\n            return ref\n\n        # Check if ref is a branch of the origin remote\n        if self.ref_exists('remotes/origin/' + ref):\n            return 'origin/' + ref\n\n        return ref\n\n    def ref_exists(self, ref):\n        code, _, _ = self.run('git', 'show-ref', ref, record_as_success=True)\n        return code == 0\n\n    @property\n    def env(self):\n        env = super(Backend, self).env\n        env['GIT_DIR'] = os.path.join(self.working_dir, '.git')\n        # Don't prompt for username, this requires Git 2.3+\n        env['GIT_TERMINAL_PROMPT'] = '0'\n        return env\n", "path": "readthedocs/vcs_support/backends/git.py"}], "after_files": [{"content": "\"\"\"Git-related utilities.\"\"\"\n\nfrom __future__ import absolute_import\n\nimport csv\nimport logging\nimport os\nimport re\n\nfrom builtins import str\nfrom six import StringIO\n\nfrom readthedocs.projects.exceptions import RepositoryError\nfrom readthedocs.vcs_support.base import BaseVCS, VCSVersion\n\n\nlog = logging.getLogger(__name__)\n\n\nclass Backend(BaseVCS):\n\n    \"\"\"Git VCS backend.\"\"\"\n\n    supports_tags = True\n    supports_branches = True\n    fallback_branch = 'master'  # default branch\n\n    def __init__(self, *args, **kwargs):\n        super(Backend, self).__init__(*args, **kwargs)\n        self.token = kwargs.get('token', None)\n        self.repo_url = self._get_clone_url()\n\n    def _get_clone_url(self):\n        if '://' in self.repo_url:\n            hacked_url = self.repo_url.split('://')[1]\n            hacked_url = re.sub('.git$', '', hacked_url)\n            clone_url = 'https://%s' % hacked_url\n            if self.token:\n                clone_url = 'https://%s@%s' % (self.token, hacked_url)\n                return clone_url\n            # Don't edit URL because all hosts aren't the same\n\n            # else:\n                # clone_url = 'git://%s' % (hacked_url)\n        return self.repo_url\n\n    def set_remote_url(self, url):\n        return self.run('git', 'remote', 'set-url', 'origin', url)\n\n    def update(self):\n        # Use checkout() to update repo\n        self.checkout()\n\n    def repo_exists(self):\n        code, _, _ = self.run('git', 'status', record=False)\n        return code == 0\n\n    def submodules_exists(self):\n        code, out, _ = self.run('git', 'submodule', 'status', record=False)\n        return code == 0 and bool(out)\n\n    def fetch(self):\n        code, _, _ = self.run('git', 'fetch', '--tags', '--prune')\n        if code != 0:\n            raise RepositoryError\n\n    def checkout_revision(self, revision=None):\n        if not revision:\n            branch = self.default_branch or self.fallback_branch\n            revision = 'origin/%s' % branch\n\n        code, out, err = self.run(\n            'git', 'checkout', '--force', revision)\n        if code != 0:\n            log.warning(\"Failed to checkout revision '%s': %s\",\n                        revision, code)\n        return [code, out, err]\n\n    def clone(self):\n        code, _, _ = self.run(\n            'git', 'clone', '--recursive', self.repo_url, '.')\n        if code != 0:\n            raise RepositoryError\n\n    @property\n    def tags(self):\n        retcode, stdout, _ = self.run('git', 'show-ref', '--tags', record_as_success=True)\n        # error (or no tags found)\n        if retcode != 0:\n            return []\n        return self.parse_tags(stdout)\n\n    def parse_tags(self, data):\n        \"\"\"\n        Parses output of show-ref --tags, eg:\n\n            3b32886c8d3cb815df3793b3937b2e91d0fb00f1 refs/tags/2.0.0\n            bd533a768ff661991a689d3758fcfe72f455435d refs/tags/2.0.1\n            c0288a17899b2c6818f74e3a90b77e2a1779f96a refs/tags/2.0.2\n            a63a2de628a3ce89034b7d1a5ca5e8159534eef0 refs/tags/2.1.0.beta2\n            c7fc3d16ed9dc0b19f0d27583ca661a64562d21e refs/tags/2.1.0.rc1\n            edc0a2d02a0cc8eae8b67a3a275f65cd126c05b1 refs/tags/2.1.0.rc2\n\n        Into VCSTag objects with the tag name as verbose_name and the commit\n        hash as identifier.\n        \"\"\"\n        # parse the lines into a list of tuples (commit-hash, tag ref name)\n        # StringIO below is expecting Unicode data, so ensure that it gets it.\n        if not isinstance(data, str):\n            data = str(data)\n        raw_tags = csv.reader(StringIO(data), delimiter=' ')\n        vcs_tags = []\n        for row in raw_tags:\n            row = [f for f in row if f != '']\n            if row == []:\n                continue\n            commit_hash, name = row\n            clean_name = name.replace('refs/tags/', '')\n            vcs_tags.append(VCSVersion(self, commit_hash, clean_name))\n        return vcs_tags\n\n    @property\n    def branches(self):\n        # Only show remote branches\n        retcode, stdout, _ = self.run('git', 'branch', '-r', record_as_success=True)\n        # error (or no branches found)\n        if retcode != 0:\n            return []\n        return self.parse_branches(stdout)\n\n    def parse_branches(self, data):\n        \"\"\"\n        Parse output of git branch -r\n\n        e.g.:\n\n              origin/2.0.X\n              origin/HEAD -> origin/master\n              origin/develop\n              origin/master\n              origin/release/2.0.0\n              origin/release/2.1.0\n        \"\"\"\n        clean_branches = []\n        # StringIO below is expecting Unicode data, so ensure that it gets it.\n        if not isinstance(data, str):\n            data = str(data)\n        raw_branches = csv.reader(StringIO(data), delimiter=' ')\n        for branch in raw_branches:\n            branch = [f for f in branch if f != '' and f != '*']\n            # Handle empty branches\n            if branch:\n                branch = branch[0]\n                if branch.startswith('origin/'):\n                    verbose_name = branch.replace('origin/', '')\n                    if verbose_name in ['HEAD']:\n                        continue\n                    clean_branches.append(VCSVersion(self, branch, verbose_name))\n                else:\n                    clean_branches.append(VCSVersion(self, branch, branch))\n        return clean_branches\n\n    @property\n    def commit(self):\n        _, stdout, _ = self.run('git', 'rev-parse', 'HEAD')\n        return stdout.strip()\n\n    def checkout(self, identifier=None):\n        self.check_working_dir()\n\n        # Clone or update repository\n        if self.repo_exists():\n            self.set_remote_url(self.repo_url)\n            self.fetch()\n        else:\n            self.make_clean_working_dir()\n            self.clone()\n\n        # Find proper identifier\n        if not identifier:\n            identifier = self.default_branch or self.fallback_branch\n\n        identifier = self.find_ref(identifier)\n\n        # Checkout the correct identifier for this branch.\n        code, out, err = self.checkout_revision(identifier)\n        if code != 0:\n            return code, out, err\n\n        # Clean any remains of previous checkouts\n        self.run('git', 'clean', '-d', '-f', '-f')\n\n        # Update submodules\n        if self.submodules_exists():\n            self.run('git', 'submodule', 'sync')\n            self.run('git', 'submodule', 'update',\n                     '--init', '--recursive', '--force')\n\n        return code, out, err\n\n    def find_ref(self, ref):\n        # Check if ref starts with 'origin/'\n        if ref.startswith('origin/'):\n            return ref\n\n        # Check if ref is a branch of the origin remote\n        if self.ref_exists('remotes/origin/' + ref):\n            return 'origin/' + ref\n\n        return ref\n\n    def ref_exists(self, ref):\n        code, _, _ = self.run('git', 'show-ref', ref, record_as_success=True)\n        return code == 0\n\n    @property\n    def env(self):\n        env = super(Backend, self).env\n        env['GIT_DIR'] = os.path.join(self.working_dir, '.git')\n        # Don't prompt for username, this requires Git 2.3+\n        env['GIT_TERMINAL_PROMPT'] = '0'\n        return env\n", "path": "readthedocs/vcs_support/backends/git.py"}]}