Repository: spack/spack

Issue:
spack test : garbage in modulefiles directory
Running `spack test` leaves garbage in modulefiles directory, and requires a `spack module refresh` to restore them:

```
$ module av

---------------------------------------------------------------------- /home/massimiliano/PycharmProjects/spack/share/spack/modules/nuvolari -----------------------------------------------------------------------
   bzip2@1.0.6%gcc@4.9.2-e3bwbia    ncurses@6.0%gcc@4.9.2-caskfyb       python@2.7.10%gcc@4.9.2-vbb3f5s    sqlite@3.8.5%gcc@4.9.2-i4myxr6
   cmake@3.4.0%gcc@4.9.2-2tyf6fw    openssl@1.0.2d%gcc@4.9.2-xb37kae    readline@6.3%gcc@4.9.2-z73wj2m     zlib@1.2.8%gcc@4.9.2-rprth3i

---------------------------------------------------------------------- /home/massimiliano/production/lmod/install/lmod/lmod/modulefiles/Core -----------------------------------------------------------------------
   lmod/6.0.1    settarg/6.0.1

$ spack test
... 
<omitted>
...

$ module av

---------------------------------------------------------------------- /home/massimiliano/PycharmProjects/spack/share/spack/modules/nuvolari -----------------------------------------------------------------------
   bzip2@1.0.6%gcc@4.9.2-e3bwbia     dyninst@8.2%gcc@4.5.0-tjtqaad          mpich@3.0.4%gcc@4.5.0~debug-j7hmv6g         openssl@1.0.2d%gcc@4.9.2-xb37kae    zmpi@1.0%gcc@4.5.0-urlkint
   callpath@1.0%gcc@4.5.0-kumvrri    fake@1.0%gcc@4.5.0-jkhqqze             mpileaks@2.3%gcc@4.5.0~debug~opt-7uhdolm    python@2.7.10%gcc@4.9.2-vbb3f5s
   callpath@1.0%gcc@4.5.0-ppdrnp7    libdwarf@20130729%gcc@4.5.0-ad3hcol    mpileaks@2.3%gcc@4.5.0~debug~opt-kzqiqui    readline@6.3%gcc@4.9.2-z73wj2m
   callpath@1.0%gcc@4.5.0-ubeljio    libelf@0.8.13%gcc@4.5.0-i6fzr4y        mpileaks@2.3%gcc@4.5.0~debug~opt-zyrnzdt    sqlite@3.8.5%gcc@4.9.2-i4myxr6
   cmake@3.4.0%gcc@4.9.2-2tyf6fw     mpich2@1.5%gcc@4.5.0-6lygf2f           ncurses@6.0%gcc@4.9.2-caskfyb               zlib@1.2.8%gcc@4.9.2-rprth3i

---------------------------------------------------------------------- /home/massimiliano/production/lmod/install/lmod/lmod/modulefiles/Core -----------------------------------------------------------------------
   lmod/6.0.1    settarg/6.0.1

Use "module spider" to find all possible modules.
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".

$ spack module refresh
==> Regenerating tcl module files.
==> Regenerating dotkit module files.
$ module av

---------------------------------------------------------------------- /home/massimiliano/PycharmProjects/spack/share/spack/modules/nuvolari -----------------------------------------------------------------------
   bzip2@1.0.6%gcc@4.9.2-e3bwbia    ncurses@6.0%gcc@4.9.2-caskfyb       python@2.7.10%gcc@4.9.2-vbb3f5s    sqlite@3.8.5%gcc@4.9.2-i4myxr6
   cmake@3.4.0%gcc@4.9.2-2tyf6fw    openssl@1.0.2d%gcc@4.9.2-xb37kae    readline@6.3%gcc@4.9.2-z73wj2m     zlib@1.2.8%gcc@4.9.2-rprth3i

---------------------------------------------------------------------- /home/massimiliano/production/lmod/install/lmod/lmod/modulefiles/Core -----------------------------------------------------------------------
   lmod/6.0.1    settarg/6.0.1

Use "module spider" to find all possible modules.
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
```



Discussion:

Resolving patch:
diff --git a/lib/spack/spack/cmd/module.py b/lib/spack/spack/cmd/module.py
--- a/lib/spack/spack/cmd/module.py
+++ b/lib/spack/spack/cmd/module.py
@@ -22,21 +22,16 @@
 # along with this program; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 ##############################################################################
-import sys
 import os
 import shutil
-import argparse
+import sys
 
 import llnl.util.tty as tty
-from llnl.util.lang import partition_list
-from llnl.util.filesystem import mkdirp
-
 import spack.cmd
+from llnl.util.filesystem import mkdirp
 from spack.modules import module_types
 from spack.util.string import *
 
-from spack.spec import Spec
-
 description ="Manipulate modules and dotkits."
 
 
@@ -98,7 +93,6 @@ def module_refresh():
             cls(spec).write()
 
 
-
 def module(parser, args):
     if args.module_command == 'refresh':
         module_refresh()
diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py
--- a/lib/spack/spack/modules.py
+++ b/lib/spack/spack/modules.py
@@ -211,7 +211,11 @@ def use_name(self):
     def remove(self):
         mod_file = self.file_name
         if os.path.exists(mod_file):
-            shutil.rmtree(mod_file, ignore_errors=True)
+            try:
+                os.remove(mod_file)  # Remove the module file
+                os.removedirs(os.path.dirname(mod_file))  # Remove all the empty directories from the leaf up
+            except OSError:
+                pass  # removedirs throws OSError on first non-empty directory found
 
 
 class Dotkit(EnvModule):


Test patch:
diff --git a/lib/spack/spack/test/mock_database.py b/lib/spack/spack/test/mock_database.py
--- a/lib/spack/spack/test/mock_database.py
+++ b/lib/spack/spack/test/mock_database.py
@@ -17,7 +17,7 @@ def _mock_install(self, spec):
 
     def _mock_remove(self, spec):
         specs = spack.installed_db.query(spec)
-        assert(len(specs) == 1)
+        assert len(specs) == 1
         spec = specs[0]
         spec.package.do_uninstall(spec)
 
@@ -71,6 +71,8 @@ def setUp(self):
             self._mock_install('mpileaks ^zmpi')
 
     def tearDown(self):
+        for spec in spack.installed_db.query():
+            spec.package.do_uninstall(spec)
         super(MockDatabase, self).tearDown()
         shutil.rmtree(self.install_path)
         spack.install_path = self.spack_install_path