diff options
Diffstat (limited to 'lame_vcs_abstraction.py')
-rw-r--r-- | lame_vcs_abstraction.py | 134 |
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] |