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 """ |