| Index: gclient_scm.py
|
| diff --git a/gclient_scm.py b/gclient_scm.py
|
| index fe0ac9839794dd5651f6d985340c65f2c464247c..78118ec1f265185ae3f6ea77b4038ceb33e10eb7 100644
|
| --- a/gclient_scm.py
|
| +++ b/gclient_scm.py
|
| @@ -34,7 +34,14 @@ def CreateSCM(url=None, root_dir=None, relpath=None, scm_name='svn'):
|
| # TODO(maruel): Deduce the SCM from the url.
|
| scm_map = {
|
| 'svn' : SVNWrapper,
|
| + 'git' : GitWrapper,
|
| }
|
| +
|
| + if url and (url.startswith('git:') or
|
| + url.startswith('ssh:') or
|
| + url.endswith('.git')):
|
| + scm_name = 'git'
|
| +
|
| if not scm_name in scm_map:
|
| raise gclient_utils.Error('Unsupported scm %s' % scm_name)
|
| return scm_map[scm_name](url, root_dir, relpath, scm_name)
|
| @@ -58,6 +65,8 @@ class SCMWrapper(object):
|
| self.relpath = relpath
|
| if self.relpath:
|
| self.relpath = self.relpath.replace('/', os.sep)
|
| + if self.relpath and self._root_dir:
|
| + self.checkout_path = os.path.join(self._root_dir, self.relpath)
|
|
|
| def FullUrlForRelativeUrl(self, url):
|
| # Find the forth '/' and strip from there. A bit hackish.
|
| @@ -81,6 +90,99 @@ class SCMWrapper(object):
|
| return getattr(self, command)(options, args, file_list)
|
|
|
|
|
| +class GitWrapper(SCMWrapper):
|
| + """Wrapper for Git"""
|
| +
|
| + def cleanup(self, options, args, file_list):
|
| + """Cleanup working copy."""
|
| + self._RunGit(['prune'])
|
| + self._RunGit(['fsck'])
|
| + self._RunGit(['gc'])
|
| +
|
| + def diff(self, options, args, file_list):
|
| + # NOTE: This function does not currently modify file_list.
|
| + merge_base = self._RunGit(['merge-base', 'HEAD', 'origin'])
|
| + print self._RunGit(['diff', merge_base])
|
| +
|
| + def export(self, options, args, file_list):
|
| + assert len(args) == 1
|
| + export_path = os.path.abspath(os.path.join(args[0], self.relpath))
|
| + if not os.path.exists(export_path):
|
| + os.makedirs(export_path)
|
| + self._RunGit(['checkout-index', '-a', '--prefix=%s/' % export_path])
|
| +
|
| + def update(self, options, args, file_list):
|
| + """Runs git to update or transparently checkout the working copy.
|
| +
|
| + All updated files will be appended to file_list.
|
| +
|
| + Raises:
|
| + Error: if can't get URL for relative path.
|
| + """
|
| +
|
| + if args:
|
| + raise gclient_utils.Error("Unsupported argument(s): %s" % ",".join(args))
|
| +
|
| + components = self.url.split("@")
|
| + url = components[0]
|
| + revision = None
|
| + if options.revision:
|
| + revision = options.revision
|
| + elif len(components) == 2:
|
| + revision = components[1]
|
| +
|
| + if not os.path.exists(self.checkout_path):
|
| + self._RunGit(['clone', '-q', url, self.checkout_path], cwd=self._root_dir)
|
| + if revision:
|
| + self._RunGit(['reset', '--hard', revision])
|
| + files = self._RunGit(['ls-files']).split()
|
| + file_list.extend([os.path.join(self.checkout_path, f) for f in files])
|
| + return
|
| +
|
| + self._RunGit(['remote', 'update'])
|
| + new_base = 'origin'
|
| + if revision:
|
| + new_base = revision
|
| + files = self._RunGit(['diff', new_base, '--name-only']).split()
|
| + file_list.extend([os.path.join(self.checkout_path, f) for f in files])
|
| + self._RunGit(['rebase', new_base])
|
| +
|
| + def revert(self, options, args, file_list):
|
| + """Reverts local modifications.
|
| +
|
| + All reverted files will be appended to file_list.
|
| + """
|
| + merge_base = self._RunGit(['merge-base', 'HEAD', 'origin'])
|
| + files = self._RunGit(['diff', merge_base, '--name-only']).split()
|
| + print self._RunGit(['reset', '--hard', merge_base])
|
| + file_list.extend([os.path.join(self.checkout_path, f) for f in files])
|
| +
|
| + def runhooks(self, options, args, file_list):
|
| + self.status(options, args, file_list)
|
| +
|
| + def status(self, options, args, file_list):
|
| + """Display status information."""
|
| + if not os.path.isdir(self.checkout_path):
|
| + print('\n________ couldn\'t run status in %s:\nThe directory '
|
| + 'does not exist.' % checkout_path)
|
| + else:
|
| + merge_base = self._RunGit(['merge-base', 'HEAD', 'origin'])
|
| + print self._RunGit(['diff', '--name-status', merge_base])
|
| + files = self._RunGit(['diff', '--name-only', merge_base]).split()
|
| + file_list.extend([os.path.join(self.checkout_path, f) for f in files])
|
| +
|
| + def _RunGit(self, args, cwd=None, checkrc=True):
|
| + if cwd == None:
|
| + cwd = self.checkout_path
|
| + cmd = ['git']
|
| + cmd.extend(args)
|
| + sp = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE)
|
| + if checkrc and sp.returncode:
|
| + raise gclient_utils.Error('git command %s returned %d' %
|
| + (args[0], sp.returncode))
|
| + return sp.communicate()[0].strip()
|
| +
|
| +
|
| class SVNWrapper(SCMWrapper):
|
| """ Wrapper for SVN """
|
|
|
|
|