summaryrefslogtreecommitdiffstats
path: root/lame_vcs_abstraction.py
diff options
context:
space:
mode:
Diffstat (limited to 'lame_vcs_abstraction.py')
-rw-r--r--lame_vcs_abstraction.py134
1 files changed, 134 insertions, 0 deletions
diff --git a/lame_vcs_abstraction.py b/lame_vcs_abstraction.py
new file mode 100644
index 0000000..67a3c1d
--- /dev/null
+++ b/lame_vcs_abstraction.py
@@ -0,0 +1,134 @@
+#!/usr/bin/python
+# lame_vcs_abstraction.py:
+#
+# Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php)
+# Copyright (C) 2010 Red Hat, Inc.
+# Written by Colin Walters <walters@verbum.org>
+
+# Feel free to replace the bits here with something better...
+
+import os
+import sys
+import re
+import urlparse
+import getopt
+import subprocess
+import shutil
+import hashlib
+import logger
+
+from . import async_subprocess
+
+class Vcs(object):
+ def __init__(self, parsedurl):
+ self._parsed_url = parsedurl
+ # Deliberately drop params/query
+ self._nonfragment_url_string = urlparse.urlunparse((parsedurl.scheme,
+ parsedurl.netloc,
+ parsedurl.path,
+ '', '', ''))
+ self._branch = self._parsed_url.fragment
+
+ self._dir = None
+
+ def get_url(self):
+ return self._parsed_url
+
+ def checkout_async(self, destdir):
+ """Retrieve a new copy of the source tree, saving as destdir"""
+ raise Exception("not implemented")
+
+ def update(self):
+ """Update directory from the latest upstream"""
+ raise Exception("not implemented")
+
+ def export_archive(self, prefix, target_filename):
+ """Export a tarball with minimal (or no) version control data."""
+ raise Exception("not implemented")
+
+ def get_scheme(self):
+ return self._parsed_url.scheme
+
+ def get_id(self):
+ raise Exception("not implemented")
+
+ def get_abbreviated_id(self):
+ raise Exception("not implemented")
+
+ def _vcs_exec_sync_log_error(self, args):
+ logger.info("Synchronously executing: %r" % (args, ))
+ return subprocess.check_output(args, stderr=subprocess.STDOUT, close_fds=True, cwd=self._dir)
+
+ def _vcs_exec_async(self, args, logfile_path, on_exited):
+ logger.info("Asynchronously executing: %r" % (args, ))
+ return async_subprocess.spawn_async_output_to_file(args, logfile_path, on_exited, cwd=self._dir)
+
+ @classmethod
+ def new_from_spec(cls, spec):
+ """See http://maven.apache.org/scm/scm-url-format.html ; we use this format,
+ but without the "scm:" prefix."""
+ # Hack for backwards compatibility
+ if spec.startswith('git://'):
+ (vcstype, url) = ('git', spec)
+ else:
+ (vcstype, url) = spec.split(':', 1)
+ orig = urlparse.urlsplit(url)
+ # We want to support fragments, even if the URL type isn't recognized. So change the
+ # scheme to http temporarily.
+ temp = urlparse.urlunsplit(('http', orig.netloc, orig.path, orig.query, orig.fragment))
+ new = urlparse.urlsplit(temp)
+ combined = urlparse.SplitResult(orig.scheme, new.netloc, new.path, new.query, new.fragment)
+ if vcstype == 'git':
+ return GitVcs(combined)
+
+class GitVcs(Vcs):
+ vcstype = "git"
+
+ def checkout_async(self, destdir, logfile, on_exited):
+ assert self._dir is None
+ args = ['git', 'clone']
+ if self._branch:
+ args.extend(['-b', self._branch])
+ args.extend([self._nonfragment_url_string, destdir])
+ return self._vcs_exec_async(args, logfile, on_exited)
+
+ def update_async(self, logfile, on_exited):
+ assert self._dir is not None
+ return self._vcs_exec_async(['git', 'pull', '-r'], logfile, on_exited)
+
+ def export_archive(self, prefix, target_filename, logfile):
+ if not prefix.endswith('/'):
+ prefix += '/'
+ args = ['git', 'archive', '--format=tar', '--prefix=%s' % (prefix,), 'HEAD']
+ logger.info("Synchronously executing: %r" % (args, ))
+ log_f = open(logfile, 'w')
+ gitproc = subprocess.Popen(args, cwd=src_directory, stdout=subprocess.PIPE, stderr=log_f)
+ if target_filename.endswith('.bz2'):
+ zipbin = 'bzip2'
+ elif target_filename.endswith('.gz'):
+ zipbin = 'gzip'
+ else:
+ raise ValueError("Unknown compression for filename %r" % (target_filename,))
+ args = [zipbin, '-c']
+ logger.info("Synchronously executing: %r" % (args, ))
+ f = open(target_filename, 'w')
+ zipproc = subprocess.Popen(args, cwd=src_directory, stdout=f, stdin=gitproc.stdout, stderr=log_f)
+ zipproc.wait()
+
+ def get_commit_as_patch(self, commitid, destfile):
+ output = self._vcs_exec_sync_log_error(['git', 'format-patch', '--stdout', commitid + '^..' + commitid])
+ f = open(destfile, 'w')
+ f.write(output)
+ f.close()
+
+ def get_id(self):
+ output = self._vcs_exec_sync_log_error(['git', 'show', '--format=%H'])
+ return output.split('\n')[0]
+
+ def get_abbreviated_id(self):
+ full_id = self.get_id()
+ return full_id[0:8]
+
+ def get_commit_summary_as_filename(self, commitid):
+ output = self._vcs_exec_sync_log_error(['git', 'show', '--format=%f', commitid])
+ return output.split('\n')[0]