Attempt at making git-drover work on Windows
BUG=404755
R=sammc@chromium.org
Review URL: https://codereview.chromium.org/1387223002
git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@297055 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/git_drover.py b/git_drover.py
index 18756d8..73c9200 100755
--- a/git_drover.py
+++ b/git_drover.py
@@ -20,6 +20,27 @@
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 @@
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 @@
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 @@
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')