| OLD | NEW | 
|    1 #!/usr/bin/python |    1 #!/usr/bin/python | 
|    2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |    2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 
|    3 # Use of this source code is governed by a BSD-style license that can be |    3 # Use of this source code is governed by a BSD-style license that can be | 
|    4 # found in the LICENSE file. |    4 # found in the LICENSE file. | 
|    5  |    5  | 
|    6 """Generate fake repositories for testing.""" |    6 """Generate fake repositories for testing.""" | 
|    7  |    7  | 
|    8 import atexit |    8 import atexit | 
|    9 import datetime |    9 import datetime | 
|   10 import errno |  | 
|   11 import logging |   10 import logging | 
|   12 import os |   11 import os | 
|   13 import pprint |   12 import pprint | 
|   14 import re |   13 import re | 
|   15 import socket |   14 import socket | 
|   16 import stat |  | 
|   17 import subprocess |   15 import subprocess | 
|   18 import sys |   16 import sys | 
|   19 import tempfile |   17 import tempfile | 
|   20 import time |  | 
|   21  |   18  | 
|   22 # trial_dir must be first for non-system libraries. |   19 # trial_dir must be first for non-system libraries. | 
|   23 from tests import trial_dir |   20 from tests import trial_dir | 
 |   21 import gclient_utils | 
|   24 import scm |   22 import scm | 
|   25  |   23  | 
|   26 ## Utility functions |   24 ## Utility functions | 
|   27  |   25  | 
|   28  |   26  | 
|   29 def kill_pid(pid): |   27 def kill_pid(pid): | 
|   30   """Kills a process by its process id.""" |   28   """Kills a process by its process id.""" | 
|   31   try: |   29   try: | 
|   32     # Unable to import 'module' |   30     # Unable to import 'module' | 
|   33     # pylint: disable=F0401 |   31     # pylint: disable=F0401 | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
|   59     return |   57     return | 
|   60  |   58  | 
|   61   if sys.platform == 'win32': |   59   if sys.platform == 'win32': | 
|   62     subprocess.Popen.kill = kill_win |   60     subprocess.Popen.kill = kill_win | 
|   63   else: |   61   else: | 
|   64     def kill_nix(process): |   62     def kill_nix(process): | 
|   65       return kill_pid(process.pid) |   63       return kill_pid(process.pid) | 
|   66     subprocess.Popen.kill = kill_nix |   64     subprocess.Popen.kill = kill_nix | 
|   67  |   65  | 
|   68  |   66  | 
|   69 def rmtree(*path): |  | 
|   70   """Recursively removes a directory, even if it's marked read-only. |  | 
|   71  |  | 
|   72   Remove the directory located at *path, if it exists. |  | 
|   73  |  | 
|   74   shutil.rmtree() doesn't work on Windows if any of the files or directories |  | 
|   75   are read-only, which svn repositories and some .svn files are.  We need to |  | 
|   76   be able to force the files to be writable (i.e., deletable) as we traverse |  | 
|   77   the tree. |  | 
|   78  |  | 
|   79   Even with all this, Windows still sometimes fails to delete a file, citing |  | 
|   80   a permission error (maybe something to do with antivirus scans or disk |  | 
|   81   indexing).  The best suggestion any of the user forums had was to wait a |  | 
|   82   bit and try again, so we do that too.  It's hand-waving, but sometimes it |  | 
|   83   works. :/ |  | 
|   84   """ |  | 
|   85   file_path = os.path.join(*path) |  | 
|   86   if not os.path.exists(file_path): |  | 
|   87     return |  | 
|   88  |  | 
|   89   def RemoveWithRetry_win(rmfunc, path): |  | 
|   90     os.chmod(path, stat.S_IWRITE) |  | 
|   91     if win32_api_avail: |  | 
|   92       win32api.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_NORMAL) |  | 
|   93     try: |  | 
|   94       return rmfunc(path) |  | 
|   95     except EnvironmentError, e: |  | 
|   96       if e.errno != errno.EACCES: |  | 
|   97         raise |  | 
|   98       print 'Failed to delete %s: trying again' % repr(path) |  | 
|   99       time.sleep(0.1) |  | 
|  100       return rmfunc(path) |  | 
|  101  |  | 
|  102   def RemoveWithRetry_non_win(rmfunc, path): |  | 
|  103     if os.path.islink(path): |  | 
|  104       return os.remove(path) |  | 
|  105     else: |  | 
|  106       return rmfunc(path) |  | 
|  107  |  | 
|  108   win32_api_avail = False |  | 
|  109   remove_with_retry = None |  | 
|  110   if sys.platform.startswith('win'): |  | 
|  111     # Some people don't have the APIs installed. In that case we'll do without. |  | 
|  112     try: |  | 
|  113       win32api = __import__('win32api') |  | 
|  114       win32con = __import__('win32con') |  | 
|  115       win32_api_avail = True |  | 
|  116     except ImportError: |  | 
|  117       pass |  | 
|  118     remove_with_retry = RemoveWithRetry_win |  | 
|  119   else: |  | 
|  120     remove_with_retry = RemoveWithRetry_non_win |  | 
|  121  |  | 
|  122   for root, dirs, files in os.walk(file_path, topdown=False): |  | 
|  123     # For POSIX:  making the directory writable guarantees removability. |  | 
|  124     # Windows will ignore the non-read-only bits in the chmod value. |  | 
|  125     os.chmod(root, 0770) |  | 
|  126     for name in files: |  | 
|  127       remove_with_retry(os.remove, os.path.join(root, name)) |  | 
|  128     for name in dirs: |  | 
|  129       remove_with_retry(os.rmdir, os.path.join(root, name)) |  | 
|  130  |  | 
|  131   remove_with_retry(os.rmdir, file_path) |  | 
|  132  |  | 
|  133  |  | 
|  134 def write(path, content): |   67 def write(path, content): | 
|  135   f = open(path, 'wb') |   68   f = open(path, 'wb') | 
|  136   f.write(content) |   69   f.write(content) | 
|  137   f.close() |   70   f.close() | 
|  138  |   71  | 
|  139  |   72  | 
|  140 join = os.path.join |   73 join = os.path.join | 
|  141  |   74  | 
|  142  |   75  | 
|  143 def check_call(*args, **kwargs): |   76 def check_call(*args, **kwargs): | 
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  302     self.trial = None |  235     self.trial = None | 
|  303  |  236  | 
|  304   def tear_down_svn(self): |  237   def tear_down_svn(self): | 
|  305     if self.svnserve: |  238     if self.svnserve: | 
|  306       logging.debug('Killing svnserve pid %s' % self.svnserve.pid) |  239       logging.debug('Killing svnserve pid %s' % self.svnserve.pid) | 
|  307       self.svnserve.kill() |  240       self.svnserve.kill() | 
|  308       self.wait_for_port_to_free(self.svn_port) |  241       self.wait_for_port_to_free(self.svn_port) | 
|  309       self.svnserve = None |  242       self.svnserve = None | 
|  310       if not self.trial.SHOULD_LEAK: |  243       if not self.trial.SHOULD_LEAK: | 
|  311         logging.debug('Removing %s' % self.svn_repo) |  244         logging.debug('Removing %s' % self.svn_repo) | 
|  312         rmtree(self.svn_repo) |  245         gclient_utils.rmtree(self.svn_repo) | 
|  313         logging.debug('Removing %s' % self.svn_checkout) |  246         logging.debug('Removing %s' % self.svn_checkout) | 
|  314         rmtree(self.svn_checkout) |  247         gclient_utils.rmtree(self.svn_checkout) | 
|  315       else: |  248       else: | 
|  316         return False |  249         return False | 
|  317     return True |  250     return True | 
|  318  |  251  | 
|  319   def tear_down_git(self): |  252   def tear_down_git(self): | 
|  320     if self.gitdaemon: |  253     if self.gitdaemon: | 
|  321       logging.debug('Killing git-daemon pid %s' % self.gitdaemon.pid) |  254       logging.debug('Killing git-daemon pid %s' % self.gitdaemon.pid) | 
|  322       self.gitdaemon.kill() |  255       self.gitdaemon.kill() | 
|  323       self.gitdaemon = None |  256       self.gitdaemon = None | 
|  324       if self.git_pid_file: |  257       if self.git_pid_file: | 
|  325         pid = int(self.git_pid_file.read()) |  258         pid = int(self.git_pid_file.read()) | 
|  326         self.git_pid_file.close() |  259         self.git_pid_file.close() | 
|  327         logging.debug('Killing git daemon pid %s' % pid) |  260         logging.debug('Killing git daemon pid %s' % pid) | 
|  328         kill_pid(pid) |  261         kill_pid(pid) | 
|  329         self.git_pid_file = None |  262         self.git_pid_file = None | 
|  330       self.wait_for_port_to_free(self.git_port) |  263       self.wait_for_port_to_free(self.git_port) | 
|  331       if not self.trial.SHOULD_LEAK: |  264       if not self.trial.SHOULD_LEAK: | 
|  332         logging.debug('Removing %s' % self.git_root) |  265         logging.debug('Removing %s' % self.git_root) | 
|  333         rmtree(self.git_root) |  266         gclient_utils.rmtree(self.git_root) | 
|  334       else: |  267       else: | 
|  335         return False |  268         return False | 
|  336     return True |  269     return True | 
|  337  |  270  | 
|  338   @staticmethod |  271   @staticmethod | 
|  339   def _genTree(root, tree_dict): |  272   def _genTree(root, tree_dict): | 
|  340     """For a dictionary of file contents, generate a filesystem.""" |  273     """For a dictionary of file contents, generate a filesystem.""" | 
|  341     if not os.path.isdir(root): |  274     if not os.path.isdir(root): | 
|  342       os.makedirs(root) |  275       os.makedirs(root) | 
|  343     for (k, v) in tree_dict.iteritems(): |  276     for (k, v) in tree_dict.iteritems(): | 
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  794     fake.set_up_git() |  727     fake.set_up_git() | 
|  795     print('Fake setup, press enter to quit or Ctrl-C to keep the checkouts.') |  728     print('Fake setup, press enter to quit or Ctrl-C to keep the checkouts.') | 
|  796     sys.stdin.readline() |  729     sys.stdin.readline() | 
|  797   except KeyboardInterrupt: |  730   except KeyboardInterrupt: | 
|  798     trial_dir.TrialDir.SHOULD_LEAK.leak = True |  731     trial_dir.TrialDir.SHOULD_LEAK.leak = True | 
|  799   return 0 |  732   return 0 | 
|  800  |  733  | 
|  801  |  734  | 
|  802 if __name__ == '__main__': |  735 if __name__ == '__main__': | 
|  803   sys.exit(main(sys.argv)) |  736   sys.exit(main(sys.argv)) | 
| OLD | NEW |