Source code for changes.models.revision

from datetime import datetime
from sqlalchemy import Column, String, DateTime, ForeignKey, Text
from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.schema import Index
from fnmatch import fnmatch

from changes.config import db
from changes.db.types.guid import GUID


[docs]class Revision(db.Model): """ Represents a commit in a repository, including some metadata. Author and committer are stored as references to the author table. Ideally there will be one revision row for every commit in every repository tracked by changes, though this is not always true, and some code tries to degrade gracefully when this happens. Revisions are keyed by repository, sha. They do not have unique UUIDs """ __tablename__ = 'revision' __table_args__ = ( Index('revision_author_id', 'author_id'), ) repository_id = Column(GUID, ForeignKey('repository.id'), primary_key=True) sha = Column(String(40), primary_key=True) author_id = Column(GUID, ForeignKey('author.id')) committer_id = Column(GUID, ForeignKey('author.id')) message = Column(Text) # The optional git patch id patch_hash = Column(String(40), nullable=True) parents = Column(ARRAY(String(40))) branches = Column(ARRAY(String(128))) date_created = Column(DateTime, default=datetime.utcnow) date_committed = Column(DateTime, default=datetime.utcnow) # When 'revision.created' signal was fired, and null if it has not been fired. date_created_signal = Column(DateTime, nullable=True) repository = relationship('Repository') author = relationship('Author', foreign_keys=[author_id], innerjoin=False) committer = relationship('Author', foreign_keys=[committer_id], innerjoin=False) def __init__(self, **kwargs): super(Revision, self).__init__(**kwargs) if self.date_created is None: self.date_created = datetime.utcnow() if self.date_committed is None: self.date_committed = self.date_created @classmethod def get_by_sha_prefix_query(self, repository_id, sha_prefix): """Gets a revision by a prefix. This allows for "short shas" which work in the same way git's does. This returns the raw query and does not evaluate it. """ return Revision.query.filter( Revision.repository_id == repository_id, Revision.sha.like('{}%'.format(sha_prefix)), ) @property def subject(self): return self.message.splitlines()[0] def should_build_branch(self, allowed_branches): if not self.branches and '*' in allowed_branches: return True for branch in self.branches: if any(fnmatch(branch, pattern) for pattern in allowed_branches): return True return False