[Python-checkins] cpython (2.7): Ignore .nfs* files in distutils (#7719).

eric.araujo python-checkins at python.org
Tue Jul 3 07:14:08 CEST 2012


http://hg.python.org/cpython/rev/a56cebff113a
changeset:   77925:a56cebff113a
branch:      2.7
user:        Éric Araujo <merwok at netwok.org>
date:        Tue Jul 03 01:12:42 2012 -0400
summary:
  Ignore .nfs* files in distutils (#7719).

These files are created by some NFS clients a file is edited and removed
concurrently (see added link in doc for more info).  If such a file is
removed between distutils calls listdir and copy, it will get confused.
Other special files are ignored in sdist (namely VCS directories), but
this has to be filtered out earlier.

files:
  Doc/distutils/apiref.rst             |   8 +++++-
  Lib/distutils/dir_util.py            |   4 +++
  Lib/distutils/tests/test_dir_util.py |  18 ++++++++++++++++
  Lib/distutils/tests/test_sdist.py    |   7 +++--
  Misc/ACKS                            |   1 +
  Misc/NEWS                            |   3 ++
  6 files changed, 36 insertions(+), 5 deletions(-)


diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst
--- a/Doc/distutils/apiref.rst
+++ b/Doc/distutils/apiref.rst
@@ -973,8 +973,8 @@
    Copy an entire directory tree *src* to a new location *dst*.  Both *src* and
    *dst* must be directory names.  If *src* is not a directory, raise
    :exc:`DistutilsFileError`.  If *dst* does  not exist, it is created with
-   :func:`mkpath`.  The end result of the  copy is that every file in *src* is
-   copied to *dst*, and  directories under *src* are recursively copied to *dst*.
+   :func:`mkpath`.  The end result of the copy is that every file in *src* is
+   copied to *dst*, and directories under *src* are recursively copied to *dst*.
    Return the list of files that were copied or might have been copied, using their
    output name. The return value is unaffected by *update* or *dry_run*: it is
    simply the list of all files under *src*, with the names changed to be under
@@ -987,6 +987,10 @@
    destination of the symlink will be copied.  *update* and *verbose* are the same
    as for :func:`copy_file`.
 
+   Files in *src* that begin with :file:`.nfs` are skipped (more information on
+   these files is available in answer D2 of the `NFS FAQ page
+   <http://nfs.sourceforge.net/#section_d>`_.
+
 
 .. function:: remove_tree(directory[, verbose=0, dry_run=0])
 
diff --git a/Lib/distutils/dir_util.py b/Lib/distutils/dir_util.py
--- a/Lib/distutils/dir_util.py
+++ b/Lib/distutils/dir_util.py
@@ -144,6 +144,10 @@
         src_name = os.path.join(src, n)
         dst_name = os.path.join(dst, n)
 
+        if n.startswith('.nfs'):
+            # skip NFS rename files
+            continue
+
         if preserve_symlinks and os.path.islink(src_name):
             link_dest = os.readlink(src_name)
             if verbose >= 1:
diff --git a/Lib/distutils/tests/test_dir_util.py b/Lib/distutils/tests/test_dir_util.py
--- a/Lib/distutils/tests/test_dir_util.py
+++ b/Lib/distutils/tests/test_dir_util.py
@@ -101,6 +101,24 @@
         remove_tree(self.root_target, verbose=0)
         remove_tree(self.target2, verbose=0)
 
+    def test_copy_tree_skips_nfs_temp_files(self):
+        mkpath(self.target, verbose=0)
+
+        a_file = os.path.join(self.target, 'ok.txt')
+        nfs_file = os.path.join(self.target, '.nfs123abc')
+        for f in a_file, nfs_file:
+            fh = open(f, 'w')
+            try:
+                fh.write('some content')
+            finally:
+                fh.close()
+
+        copy_tree(self.target, self.target2)
+        self.assertEqual(os.listdir(self.target2), ['ok.txt'])
+
+        remove_tree(self.root_target, verbose=0)
+        remove_tree(self.target2, verbose=0)
+
     def test_ensure_relative(self):
         if os.sep == '/':
             self.assertEqual(ensure_relative('/home/foo'), 'home/foo')
diff --git a/Lib/distutils/tests/test_sdist.py b/Lib/distutils/tests/test_sdist.py
--- a/Lib/distutils/tests/test_sdist.py
+++ b/Lib/distutils/tests/test_sdist.py
@@ -91,9 +91,8 @@
 
     @unittest.skipUnless(zlib, "requires zlib")
     def test_prune_file_list(self):
-        # this test creates a package with some vcs dirs in it
-        # and launch sdist to make sure they get pruned
-        # on all systems
+        # this test creates a project with some VCS dirs and an NFS rename
+        # file, then launches sdist to check they get pruned on all systems
 
         # creating VCS directories with some files in them
         os.mkdir(join(self.tmp_dir, 'somecode', '.svn'))
@@ -107,6 +106,8 @@
         self.write_file((self.tmp_dir, 'somecode', '.git',
                          'ok'), 'xxx')
 
+        self.write_file((self.tmp_dir, 'somecode', '.nfs0001'), 'xxx')
+
         # now building a sdist
         dist, cmd = self.get_cmd()
 
diff --git a/Misc/ACKS b/Misc/ACKS
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -688,6 +688,7 @@
 Brian Quinlan
 Anders Qvist
 Burton Radons
+Jeff Ramnani
 Brodie Rao
 Antti Rasinen
 Sridhar Ratnakumar
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -14,6 +14,9 @@
   longer raised due to a read system call returning EINTR from within these
   methods.
 
+- Issue #7719: Make distutils ignore ``.nfs*`` files instead of choking later
+  on.  Initial patch by SilentGhost and Jeff Ramnani.
+
 - Issue #10053: Don't close FDs when FileIO.__init__ fails. Loosely based on
   the work by Hirokazu Yamamoto.
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list