diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 13cb855403..97ff509668 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -22,7 +22,8 @@ from docutils.frontend import OptionParser from docutils.readers.doctree import Reader as DoctreeReader from sphinx import package_dir, __version__ -from sphinx.util import SEP, os_path, relative_uri, ensuredir, ustrftime +from sphinx.util import SEP, os_path, relative_uri, ensuredir, \ + movefile, ustrftime from sphinx.search import js_index from sphinx.builders import Builder, ENV_PICKLE_FILENAME from sphinx.highlighting import PygmentsBridge @@ -566,7 +567,7 @@ class StandaloneHTMLBuilder(Builder): self.indexer.dump(f, self.indexer_format) finally: f.close() - os.rename(searchindexfn + '.tmp', searchindexfn) + movefile(searchindexfn + '.tmp', searchindexfn) self.info('done') self.info(bold('dumping object inventory... '), nonl=True) diff --git a/sphinx/environment.py b/sphinx/environment.py index d280433262..57aef67466 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -43,8 +43,8 @@ from docutils.transforms import Transform from docutils.transforms.parts import ContentsFilter from sphinx import addnodes -from sphinx.util import get_matching_docs, SEP, ustrftime, docname_join, \ - FilenameUniqDict +from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \ + docname_join, FilenameUniqDict from sphinx.directives import additional_xref_types default_settings = { @@ -219,7 +219,7 @@ class BuildEnvironment: pickle.dump(self, picklefile, pickle.HIGHEST_PROTOCOL) finally: picklefile.close() - os.rename(filename + '.tmp', filename) + movefile(filename + '.tmp', filename) # reset attributes self.config.values = values self.set_warnfunc(warnfunc) diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 4aacf67bdf..08e619ee9f 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -361,3 +361,12 @@ def force_decode(string, encoding): # last resort -- can't fail string = string.decode('latin1') return string + + +def movefile(source, dest): + # move a file, removing the destination if it exists + if os.path.exists(dest): + os.unlink(dest) + except OSError: + pass + os.rename(source, dest)