########################################################################## # Copyright (c) 2009, ETH Zurich. # All rights reserved. # # This file is distributed under the terms in the attached LICENSE file. # If you do not find this file, copies can be found by writing to: # ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. ########################################################################## try: from mercurial import hg, ui, node, error, commands mercurial_module = True except ImportError: mercurial_module = False try: import git git_module = True except ImportError: git_module = False class Checkout(object): '''Checkout Base class: Maintain information about revision number, and directory locations ''' def __init__(self, base_dir): # Set parameters self.base_dir = base_dir def get_base_dir(self): return self.base_dir ''' Returns a unique commit identifier as string ''' def get_revision(self): return '(repository information/git/hg module not available)' ''' Return a string (or None) containing a patch file representing local changes''' def get_diff(self): return None ''' Return a dict of additional info ''' def get_meta(self): return {} class CheckoutHg(Checkout): def __init__(self, base_dir, repo): super(CheckoutHg, self).__init__(base_dir) self.repo = repo def get_revision(self): # identify the parents of the working revision context = self.repo[None] parents = context.parents() s = ', '.join(map(lambda p: node.short(p.node()), parents)) if context.files() or context.deleted(): s += ' with local changes' else: s += ' unmodified' return s def get_diff(self): context = self.repo[None] if not context.files() and not context.deleted(): return None diffui = ui.ui() diffui.pushbuffer() commands.diff(diffui, self.repo, git=True) return diffui.popbuffer() class CheckoutGit(Checkout): def __init__(self, base_dir, repo): super(CheckoutGit, self).__init__(base_dir) self.repo = repo def get_diff(self): gitc = self.repo.git return gitc.diff() + "\n\n" + gitc.diff(cached=True) def get_revision(self): return self.repo.head.commit.hexsha def get_meta(self): repo = self.repo headc = repo.head.commit ret = {} shortsha = self.repo.git.rev_parse(headc.hexsha, short=7) try: ret["branch"] = repo.active_branch.name except TypeError, e: ret["branch"] = "(HEAD detached at %s)" % shortsha ret["shortrev"] = shortsha ret["commitmsg"] = headc.message.split("\n")[0] ret["commitmsg-tail"] = "".join(headc.message.split("\n")[1:]) ret["dirty"] = str(self.repo.is_dirty()) ret["untracked-files"] = ",".join(self.repo.untracked_files) return ret ''' Factory method that checks a directory and instantiates the correct Checkout class ''' def create_for_dir(base_dir): if git_module: try: return CheckoutGit(base_dir, git.Repo(base_dir)) except git.InvalidGitRepositoryError: pass if mercurial_module: try: return CheckoutHg(base_dir, hg.repository(ui.ui(), base_dir)) except error.RepoError: pass return Checkout(base_dir)