diff options
author | Michał Górny <mgorny@gentoo.org> | 2017-12-07 23:15:05 +0100 |
---|---|---|
committer | Michał Górny <mgorny@gentoo.org> | 2017-12-16 09:50:09 +0100 |
commit | 14af6b429ef2355ba0e8342c4af0f9dd9aafab1d (patch) | |
tree | 388174d42a31ab43af04e472430666ad78bb5ced /sphinx/quickstart.py | |
parent | 7cabd6cbb053965e1930b53c27d596fd1a52dd78 (diff) | |
download | sphinx-git-14af6b429ef2355ba0e8342c4af0f9dd9aafab1d.tar.gz |
Use ensuredir() instead of os.makedirs() to fix race conditions
Use the ensuredir() function consistently across Sphinx code to avoid
race conditions e.g. when multiple Sphinx instances attempt to create
the same output directory. The ensuredir() function that was already
present in sphinx.util.osutil correctly catches EEXIST exception that
occurs if the specified directory already exists (i.e. it was created
between the call to os.path.isdir() and os.makedirs() that follows it).
While at it, remove redundant os.path.isdir() calls when they only
guarded the os.makedirs() call, and replace mkdir_p() which had pretty
much the same purpose, except for being prone to race conditions.
I did not modify testing-related code as race conditions mostly affect
real applications and not the test environment.
Fix #4281: Race conditions when creating output directory
Diffstat (limited to 'sphinx/quickstart.py')
-rw-r--r-- | sphinx/quickstart.py | 19 |
1 files changed, 6 insertions, 13 deletions
diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index d23dc3b74..5d8738996 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -35,7 +35,7 @@ from six.moves.urllib.parse import quote as urlquote from docutils.utils import column_width from sphinx import __display_version__, package_dir -from sphinx.util.osutil import make_filename +from sphinx.util.osutil import ensuredir, make_filename from sphinx.util.console import ( # type: ignore purple, bold, red, turquoise, nocolor, color_terminal ) @@ -69,13 +69,6 @@ EXTENSIONS = ('autodoc', 'doctest', 'intersphinx', 'todo', 'coverage', PROMPT_PREFIX = '> ' -def mkdir_p(dir): - # type: (unicode) -> None - if path.isdir(dir): - return - os.makedirs(dir) - - # function to get input from terminal -- overridden by the test suite def term_input(prompt): # type: (unicode) -> unicode @@ -433,11 +426,11 @@ def generate(d, overwrite=True, silent=False, templatedir=None): d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'") if not path.isdir(d['path']): - mkdir_p(d['path']) + ensuredir(d['path']) srcdir = d['sep'] and path.join(d['path'], 'source') or d['path'] - mkdir_p(srcdir) + ensuredir(srcdir) if d['sep']: builddir = path.join(d['path'], 'build') d['exclude_patterns'] = '' @@ -448,9 +441,9 @@ def generate(d, overwrite=True, silent=False, templatedir=None): 'Thumbs.db', '.DS_Store', ]) d['exclude_patterns'] = ', '.join(exclude_patterns) - mkdir_p(builddir) - mkdir_p(path.join(srcdir, d['dot'] + 'templates')) - mkdir_p(path.join(srcdir, d['dot'] + 'static')) + ensuredir(builddir) + ensuredir(path.join(srcdir, d['dot'] + 'templates')) + ensuredir(path.join(srcdir, d['dot'] + 'static')) def write_file(fpath, content, newline=None): # type: (unicode, unicode, unicode) -> None |