| Index: git_drover.py
 | 
| diff --git a/git_drover.py b/git_drover.py
 | 
| index 18756d84fbb092f5665afbd83db58e5d46afc7b2..73c92004aa66eb613f6ea2f31179f95044bd7e77 100755
 | 
| --- a/git_drover.py
 | 
| +++ b/git_drover.py
 | 
| @@ -20,6 +20,27 @@ class Error(Exception):
 | 
|    pass
 | 
|  
 | 
|  
 | 
| +if os.name == 'nt':
 | 
| +  # This is a just-good-enough emulation of os.symlink for drover to work on
 | 
| +  # Windows. It uses junctioning of directories (most of the contents of
 | 
| +  # the .git directory), but copies files. Note that we can't use
 | 
| +  # CreateSymbolicLink or CreateHardLink here, as they both require elevation.
 | 
| +  # Creating reparse points is what we want for the directories, but doing so
 | 
| +  # is a relatively messy set of DeviceIoControl work at the API level, so we
 | 
| +  # simply shell to `mklink /j` instead.
 | 
| +  def emulate_symlink_windows(source, link_name):
 | 
| +    if os.path.isdir(source):
 | 
| +      subprocess.check_call(['mklink', '/j',
 | 
| +                             link_name.replace('/', '\\'),
 | 
| +                             source.replace('/', '\\')],
 | 
| +                            shell=True)
 | 
| +    else:
 | 
| +      shutil.copy(source, link_name)
 | 
| +  mk_symlink = emulate_symlink_windows
 | 
| +else:
 | 
| +  mk_symlink = os.symlink
 | 
| +
 | 
| +
 | 
|  class _Drover(object):
 | 
|  
 | 
|    def __init__(self, branch, revision, parent_repo, dry_run):
 | 
| @@ -72,7 +93,11 @@ class _Drover(object):
 | 
|        self._run_git_command(['branch', '-D', self._branch_name])
 | 
|      if self._workdir:
 | 
|        logging.debug('Deleting %s', self._workdir)
 | 
| -      shutil.rmtree(self._workdir)
 | 
| +      if os.name == 'nt':
 | 
| +        # Use rmdir to properly handle the junctions we created.
 | 
| +        subprocess.check_call(['rmdir', '/s', '/q', self._workdir], shell=True)
 | 
| +      else:
 | 
| +        shutil.rmtree(self._workdir)
 | 
|      self._dev_null_file.close()
 | 
|  
 | 
|    @staticmethod
 | 
| @@ -95,8 +120,6 @@ class _Drover(object):
 | 
|  
 | 
|      if not os.path.isdir(self._parent_repo):
 | 
|        raise Error('Invalid parent repo path %r' % self._parent_repo)
 | 
| -    if not hasattr(os, 'symlink'):
 | 
| -      raise Error('Symlink support is required')
 | 
|  
 | 
|      self._run_git_command(['--help'], error_message='Unable to run git')
 | 
|      self._run_git_command(['status'],
 | 
| @@ -140,7 +163,7 @@ class _Drover(object):
 | 
|      logging.debug('Creating checkout in %s', self._workdir)
 | 
|      git_dir = os.path.join(self._workdir, '.git')
 | 
|      git_common.make_workdir_common(parent_git_dir, git_dir, self.FILES_TO_LINK,
 | 
| -                                   self.FILES_TO_COPY)
 | 
| +                                   self.FILES_TO_COPY, mk_symlink)
 | 
|      self._run_git_command(['config', 'core.sparsecheckout', 'true'])
 | 
|      with open(os.path.join(git_dir, 'info', 'sparse-checkout'), 'w') as f:
 | 
|        f.write('codereview.settings')
 | 
| 
 |