PolicyStat/terrarium — pull request #9 by kylegibson (2012-11-06 07:53:40+00:00)
Title: Gracefully handle permission failures when creating environment backup

If you attempt to build an environment, the default `.bak` location might be somewhere to which you don't have file permissions. For example:

```
[ec2-174-129-250-147.compute-1.amazonaws.com] run: /home/policystat/env/bin/python /home/policystat/env/bin/terrarium --target /home/policystat/env install /var/www/pstattraining.com/config/ec2_scripts/tpl/pstat/requirements.txt /var/www/pstattraining.com/config/ec2_scripts/tpl/pstat/dev_requirements.txt /var/www/pstattraining.com/config/ec2_scripts/tpl/pstat/src_requirements.txt /var/www/pstattraining.com/config/ec2_scripts/tpl/pstat/sys_requirements.txt
[ec2-174-129-250-147.compute-1.amazonaws.com] err: Traceback (most recent call last):
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/home/policystat/env/bin/terrarium", line 12, in
[ec2-174-129-250-147.compute-1.amazonaws.com] err: load_entry_point('terrarium==0.1.2dev', 'console_scripts', 'terrarium')()
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/home/policystat/env/src/terrarium/terrarium/terrarium.py", line 639, in main
[ec2-174-129-250-147.compute-1.amazonaws.com] err: terrarium.install()
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/home/policystat/env/src/terrarium/terrarium/terrarium.py", line 144, in install
[ec2-174-129-250-147.compute-1.amazonaws.com] err: shutil.rmtree(old_target_backup)
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/usr/lib/python2.6/shutil.py", line 216, in rmtree
[ec2-174-129-250-147.compute-1.amazonaws.com] err: rmtree(fullname, ignore_errors, onerror)
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/usr/lib/python2.6/shutil.py", line 216, in rmtree
[ec2-174-129-250-147.compute-1.amazonaws.com] err: rmtree(fullname, ignore_errors, onerror)
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/usr/lib/python2.6/shutil.py", line 216, in rmtree
[ec2-174-129-250-147.compute-1.amazonaws.com] err: rmtree(fullname, ignore_errors, onerror)
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/usr/lib/python2.6/shutil.py", line 216, in rmtree
[ec2-174-129-250-147.compute-1.amazonaws.com] err: rmtree(fullname, ignore_errors, onerror)
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/usr/lib/python2.6/shutil.py", line 216, in rmtree
[ec2-174-129-250-147.compute-1.amazonaws.com] err: rmtree(fullname, ignore_errors, onerror)
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/usr/lib/python2.6/shutil.py", line 216, in rmtree
[ec2-174-129-250-147.compute-1.amazonaws.com] err: rmtree(fullname, ignore_errors, onerror)
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/usr/lib/python2.6/shutil.py", line 216, in rmtree
[ec2-174-129-250-147.compute-1.amazonaws.com] err: rmtree(fullname, ignore_errors, onerror)
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/usr/lib/python2.6/shutil.py", line 221, in rmtree
[ec2-174-129-250-147.compute-1.amazonaws.com] err: onerror(os.remove, fullname, sys.exc_info())
[ec2-174-129-250-147.compute-1.amazonaws.com] err: File "/usr/lib/python2.6/shutil.py", line 219, in rmtree
[ec2-174-129-250-147.compute-1.amazonaws.com] err: os.remove(fullname)
[ec2-174-129-250-147.compute-1.amazonaws.com] err: OSError: [Errno 13] Permission denied:
'/home/policystat/env.bak/src/terrarium/.git/logs/refs/remotes/origin/issue_5'
/var/www/pstattraining.com/config/ec2_scripts/tpl/pstat/requirements.txt /var/www/pstattraining.com/config/ec2_scripts/tpl/pstat/dev_requirements.txt /var/www/pstattraining.com/config/ec2_scripts/tpl/pstat/src_requirements.txt /var/www/pstattraining.com/config/ec2_scripts/tpl/pstat/sys_requirements.txt '
```

Instead of dumping a traceback:

* Catch any OSError when writing the backup and print a warning that the user needs permission to `foo.bak` along with the specific file that is causing the problem (which maybe be inside that directory)
* Try to recover by writing the `.bak` to a NamedTemporaryDirectory, which we print with a warning to the console
* If the write a NamedTemporaryDirectory fails, give a non-zero exit code and say that we can't backup the directory and that either permissions need to change or they need to re-run the command with the ``--nobackup`` option