Mercurial > treepkg > treepkg
view treepkg/git.py @ 528:e51cf2947fab
log tag date
author | Bjoern Ricks <bricks@intevation.de> |
---|---|
date | Mon, 15 Nov 2010 15:15:52 +0000 |
parents | 8138df69a32e |
children | b5e0c81c9bcc |
line wrap: on
line source
# Copyright (C) 2010 by Intevation GmbH # Authors: # Andre Heinecke <aheinecke@intevation.de> # # This program is free software under the GPL (>=v2) # Read the file COPYING coming with the software for details. """Collection of Git utility code""" import os import shutil import re import StringIO import run from cmdexpand import cmdexpand from util import extract_value_for_key class GitError(Exception): """Base class for Git specific errors raised by TreePKG""" def checkout(url, localdir, branch=None): """Clones the repository at url into the localdir""" run.call(cmdexpand("git clone -q $url $localdir", **locals())) if branch: run.call(cmdexpand("git checkout -q --track -b local $branch", **locals()), cwd=localdir) def update(localdir, revision=None): """Runs git pull on the localdir.""" run.call(cmdexpand("git pull -q"), cwd=localdir) def export(src, dest): """Exports the local branch from src to dest""" dest = dest + os.sep run.call(cmdexpand("git checkout-index -a -f --prefix=$dest", **locals()), cwd=src) def last_changed_revision(git_working_copy): """Return the SHA1 sum of the latest commit""" output = run.capture_output(cmdexpand("git rev-parse HEAD"), cwd=git_working_copy) if output is None: raise GitError("Cannot determine last changed revision for %r" % git_working_copy) return output.strip() class GitRepository(object): """Describes a git repository""" def __init__(self, url, branch=None): """Initialize the git repository description Parameters: url -- The url of the repository branch -- The name of the remote Branch to track defaults to master """ self.url = url self.branch = branch def checkout(self, localdir): """Checks out the repository into localdir.""" checkout(self.url , localdir, self.branch) def export(self, localdir, destdir): """Exports the working copy in localdir to destdir""" export(localdir, destdir) def last_changed_revision(self, localdir): """Returns the last changed revision of the working copy in localdir""" return last_changed_revision(localdir) def check_working_copy(self, localdir): """FIXME STUB: Not implemented for git""" return None class GitWorkingCopy(object): """Represents a checkout of a git repository""" def __init__(self, repository, localdir, logger=None): """ Initialize the working copy. Parameters: repository -- The GitRepository instance describing the repository localdir -- The directory for the working copy logger -- logging object to use for some info/debug messages """ self.repository = repository self.localdir = localdir self.logger = logger def log_info(self, *args): if self.logger is not None: self.logger.info(*args) def update_or_checkout(self, revision=0): """Updates the working copy or creates by checking out the repository. Revision number included for compatibility """ gitdir = os.path.join(self.localdir, ".git") if os.path.exists(gitdir): self.log_info("Updating the working copy in %r", self.localdir) update(self.localdir, self.repository.branch) else: # TODO: better check if localdir contains files if os.path.exists(self.localdir): raise GitError("Working copy dir %s already exists. " \ " files. Can't checkout from %s" % (self.localdir, self.repository.url)) self.log_info("The working copy in %r doesn't exist yet." " Checking out from %r", self.localdir, self.repository.url) self.repository.checkout(self.localdir) def export(self, destdir): """Exports the working copy to destdir""" self.repository.export(self.localdir, destdir) def export_tag(self, url, destdir, revision=None): """Export tag to destir """ self.export(destdir) def last_changed_revision(self): """Returns the last changed rev of the working copy""" return self.repository.last_changed_revision(self.localdir) def list_tags(self, pattern): output = run.capture_output(cmdexpand("git tag -l $pattern", pattern=pattern), cwd=self.localdir) return output.splitlines() def get_revision(self, refname="HEAD"): """Return the SHA1 sum of the latest commit""" output = run.capture_output(cmdexpand("git rev-parse $refname", refname=refname), cwd=self.localdir) if output is None: raise GitError("Cannot determine revision for %r" % self.localdir) return output.strip() class TagDetector: """Class to detect tags from a git repository The tags are found using the parameters: url -- The url of the git repository to use pattern -- A regular expression matching the tags """ def __init__(self, url, pattern, localdir): self.url = url self.pattern = pattern repo = GitRepository(url) self.workingcopy = GitWorkingCopy(repo, localdir) def list_tags(self): self.workingcopy.update_or_checkout() tags = self.workingcopy.list_tags(self.pattern) return sorted(tags) def newest_tag_revision(self): candidates = self.list_tags() urlrev = (None, None) if candidates: newest = candidates[-1] try: rev = self.workingcopy.get_revision(newest) urlrev = (newest, rev) except GitError: pass return urlrev def tag_pkg_parameters(self, tag_name): # FIXME: Don't hardcore regex #match = re.search(r"enterprise[^.]*\.[^.]*\." match = re.search(r"enterprise[^.]*" r"(?P<date>[0-9]{8})", tag_name) if match: date = match.group("date") return (date, 1) else: raise GitError("Cannot determine tag parameters from %s" % tag_name)