diff options
author | Benjamin Schubert <ben.c.schubert@gmail.com> | 2018-11-07 13:07:09 +0000 |
---|---|---|
committer | richardmaw-codethink <richard.maw@codethink.co.uk> | 2018-11-19 11:39:51 +0000 |
commit | a6defc0b47423180c3f17a723692019458603bb6 (patch) | |
tree | af58414e2b742b0c98f11a718472f2c1ac6bef6f /buildstream/plugins/sources | |
parent | f23b6031b1b6bd27858f44d3deb63282483e6197 (diff) | |
download | buildstream-a6defc0b47423180c3f17a723692019458603bb6.tar.gz |
Fix os.rename in git source element to correctly handle error codes
According to the documentation
(https://www.unix.com/man-page/POSIX/3posix/rename/), when the directory
already is there, either EEXIST or ENOTEMPTY could be thrown.
Previously only ENOTEMPTY was checked.
Done:
- Separated the move into its own function
- Check for both errors
- Create unit tests for it, covering most test cases
Diffstat (limited to 'buildstream/plugins/sources')
-rw-r--r-- | buildstream/plugins/sources/git.py | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/buildstream/plugins/sources/git.py b/buildstream/plugins/sources/git.py index 23e3369b1..b51ed79d9 100644 --- a/buildstream/plugins/sources/git.py +++ b/buildstream/plugins/sources/git.py @@ -141,21 +141,24 @@ class GitMirror(SourceFetcher): fail="Failed to clone git repository {}".format(url), fail_temporarily=True) - # Attempt atomic rename into destination, this will fail if - # another process beat us to the punch - try: - os.rename(tmpdir, self.mirror) - except OSError as e: - - # When renaming and the destination repo already exists, os.rename() - # will fail with ENOTEMPTY, since an empty directory will be silently - # replaced - if e.errno == errno.ENOTEMPTY: - self.source.status("{}: Discarding duplicate clone of {}" - .format(self.source, url)) - else: - raise SourceError("{}: Failed to move cloned git repository {} from '{}' to '{}': {}" - .format(self.source, url, tmpdir, self.mirror, e)) from e + self._atomic_move_mirror(tmpdir, url) + + def _atomic_move_mirror(self, tmpdir, url): + # Attempt atomic rename into destination, this will fail if + # another process beat us to the punch + try: + os.rename(tmpdir, self.mirror) + except OSError as e: + # When renaming and the destination repo already exists, os.rename() + # will fail with either ENOTEMPTY or EEXIST, depending on the underlying + # implementation. + # An empty directory would always be replaced. + if e.errno in (errno.EEXIST, errno.ENOTEMPTY): + self.source.status("{}: Discarding duplicate clone of {}" + .format(self.source, url)) + else: + raise SourceError("{}: Failed to move cloned git repository {} from '{}' to '{}': {}" + .format(self.source, url, tmpdir, self.mirror, e)) from e def _fetch(self, alias_override=None): url = self.source.translate_url(self.url, |