# Copyright 2008 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""App Engine data model (schema) definition for Gerrit."""

# Python imports
import base64
import datetime
import hashlib
import logging
import random
import re
import zlib

# AppEngine imports
from google.appengine.ext import db
from google.appengine.api import memcache
from google.appengine.api import users

# Local imports
from memcache import Key as MemCacheKey
import patching


DEFAULT_CONTEXT = 10
CONTEXT_CHOICES = (3, 10, 25, 50, 75, 100)
FETCH_MAX = 1000
MAX_DELTA_DEPTH = 10

LGTM_CHOICES = (
    ('lgtm', 'Looks good to me, approved.'),
    ('yes', 'Looks good to me, but someone else must approve.'),
    ('abstain', 'No score.'),
    ('no', 'I would prefer that you didn\'t submit this.'),
    ('reject', 'Do not submit.'),
  )
LIMITED_LGTM_CHOICES = [choice for choice in LGTM_CHOICES
        if choice[0] != 'lgtm' and choice[0] != 'reject']

### GQL query cache ###


_query_cache = {}

class BackedUpModel(db.Model):
  """Base class for our models that keeps a property used for backup."""

  last_backed_up = db.IntegerProperty(default=0)

  def __init__(self, *args, **kwargs):
    db.Model.__init__(self, *args, **kwargs)

def gql(cls, clause, *args, **kwds):
  """Return a query object, from the cache if possible.

  Args:
    cls: a BackedUpModel subclass.
    clause: a query clause, e.g. 'WHERE draft = TRUE'.
    *args, **kwds: positional and keyword arguments to be bound to the query.

  Returns:
    A db.GqlQuery instance corresponding to the query with *args and
    **kwds bound to the query.
  """
  query_string = 'SELECT * FROM %s %s' % (cls.kind(), clause)
  query = _query_cache.get(query_string)
  if query is None:
    _query_cache[query_string] = query = db.GqlQuery(query_string)
  query.bind(*args, **kwds)
  return query


### Exceptions ###

class InvalidLgtmException(Exception):
  """User is not alloewd to LGTM this change."""

class InvalidVerifierException(Exception):
  """User is not alloewd to verify this change."""

class InvalidSubmitMergeException(Exception):
  """The change cannot me scheduled for merge."""

class DeltaPatchingException(Exception):
  """Applying a patch yield the wrong hash."""


### Settings ###

def _genkey(n=26):
  k = ''.join(map(chr, (random.randrange(256) for i in xrange(n))))
  return base64.b64encode(k)

class Settings(BackedUpModel):
  """Global settings for the application instance."""

  analytics = db.StringProperty()
  internal_api_key = db.StringProperty()
  xsrf_key = db.StringProperty()
  from_email = db.StringProperty()

  _Key = MemCacheKey('Settings_Singleton')

  @classmethod
  def get_settings(cls):
    """Get the Settings singleton.

    If possible, get it from memcache.  If it's not there, it tries to do a 
    normal get().  Only if that fails does it call get_or_insert, because of
    possible contention errors due to get_or_insert's transaction.
    """
    def read():
      result = cls.get_by_key_name('settings')
      if result:
        return result
      else:
        return cls.get_or_insert('settings',
                                  internal_api_key=_genkey(26),
                                  xsrf_key=_genkey(26))
    return Settings._Key.get(read)

  def put(self):
    BackedUpModel.put(self)
    self._Key.clear()


### Approval rights ###

def _flatten_users_and_groups(users, groups):
  """Returns a set of the users and the groups provided"""
  result = set()
  for user in users:
    result.add(user)
  if groups:
    for group in db.get(groups):
      for user in group.members:
        result.add(user)
  return result


class ApprovalRight(BackedUpModel):
  """The tuple of a set of path patterns and a set of users who can approve
  changes for those paths."""
  files = db.StringListProperty()
  approvers_users = db.ListProperty(users.User)
  approvers_groups = db.ListProperty(db.Key)
  verifiers_users = db.ListProperty(users.User)
  verifiers_groups = db.ListProperty(db.Key)
  required = db.BooleanProperty()

  def approvers(self):
    """Returns a set of the users who are approvers."""
    return _flatten_users_and_groups(self.approvers_users,
        self.approvers_groups)

  def verifiers(self):
    """Returns a set of the users who are verifiers."""
    return _flatten_users_and_groups(self.verifiers_users,
        self.verifiers_groups)

  @classmethod
  def validate_file(cls, file):
    """Returns whether this is a valid file path.
    
    The rules:
      - The length must be > 0
      - The file path must start with a '/'
      - The file path must contain either 0 or 1 '...'
      - If it contains one '...', it must either be last or directly
        after the first '/'
        
        These last two limitations could be removed someday but are
        good enough for now.
    """
    if len(file) == 0:
      return False
    if file[0] != '/':
      return False
    (before, during, after) = file.partition("...")
    if during == "" and after == "":
      return True
    if before != "/":
      return False
    if after.find("...") != -1:
      return False
    return True

### Projects ###

class Project(BackedUpModel):
  """An open source project.

  Projects have owners who can set approvers and stuff.
  """

  name = db.StringProperty(required=True)
  comment = db.StringProperty(required=False)
  owners_users = db.ListProperty(users.User)
  owners_groups = db.ListProperty(db.Key)
  code_reviews = db.ListProperty(db.Key)

  @classmethod
  def get_all_projects(cls):
    """Return all projects"""
    all = cls.all()
    all.order('name')
    return list(all)

  @classmethod
  def get_project_for_name(cls, name):
    return cls.gql('WHERE name=:name', name=name).get()

  def remove(self):
    """delete this project"""
    db.delete(ApprovalRight.get(self.code_reviews))
    self.delete()

  def set_code_reviews(self, approval_right_keys):
    for key in self.code_reviews:
      val = ApprovalRight.get(key)
      if val:
        db.delete(val)
    self.code_reviews = approval_right_keys

  def get_code_reviews(self):
    return [ApprovalRight.get(key) for key in self.code_reviews]

  def is_code_reviewed(self):
    return True

  def put(self):
    memcache.flush_all()
    BackedUpModel.put(self)

  @classmethod
  def projects_owned_by_user(cls, user):
    memcache.flush_all()
    key = "projects_owned_by_user_%s" % user.email()
    result = memcache.get(key)
    if result is None:
      result = set(
          Project.gql("WHERE owner_users=:user", user=user).fetch(1000))
      groups = AccountGroup.gql("WHERE members=:user", user=user).fetch(1000)
      if groups:
        pr = Project.gql(
            "WHERE owners_groups IN :groups",
            groups=[g.key() for g in groups]).fetch(1000)
        result.update(pr)
      memcache.set(key, [p.key() for p in result])
    return result


class Branch(BackedUpModel):
  """A branch in a specific Project."""

  project = db.ReferenceProperty(Project, required=True)
  name = db.StringProperty(required=True) # == key

  status = db.StringProperty(choices=('NEEDS_MERGE',
                                      'MERGING',
                                      'BUILDING'))
  merge_submitted = db.DateTimeProperty()
  to_merge = db.ListProperty(db.Key) # PatchSets
  merging = db.ListProperty(db.Key) # PatchSets
  waiting = db.ListProperty(db.Key) # PatchSets

  @classmethod
  def get_or_insert_branch(cls, project, name):
    key = 'p.%s %s' % (project.key().id(), name)
    return cls.get_or_insert(key, project=project, name=name)

  @classmethod
  def get_branch_for_name(cls, project, name):
    key = 'p.%s %s' % (project.key().id(), name)
    return cls.get_by_key_name(key)

  @property
  def short_name(self):
    if self.name.startswith("refs/heads/"):
      return self.name[len("refs/heads/"):]
    return self.name

  def is_code_reviewed(self):
    return True

  def merge_patchset(self, patchset):
    """Add a patchset to the end of the branch's merge queue

    This method runs in an independent transaction.
    """
    ps_key = patchset.key()
    def trans(key):
      b = db.get(key)
      if not ps_key in b.to_merge:
        b.to_merge.append(ps_key)
        if b.status is None:
          b.status = 'NEEDS_MERGE'
          b.merge_submitted = datetime.datetime.now()
        b.put()
    db.run_in_transaction(trans, self.key())

  def begin_merge(self):
    """Lock this branch and start merging patchsets.

    This method runs in an independent transaction.
    """
    def trans(key):
      b = db.get(key)
      if b.status == 'NEEDS_MERGE':
        b.status = 'MERGING'
        b.merging.extend(b.waiting)
        b.merging.extend(b.to_merge)
        b.waiting = []
        b.to_merge = []
        b.put()
        return b.merging
      return []
    keys = db.run_in_transaction(trans, self.key())
    objs = db.get(keys)

    good = []
    torm = []
    for k, o in zip(keys, objs):
      if o:
        good.append(o)
      else:
        torm.append(k)

    if torm:
      def clear_branch(key):
        b = db.get(key)

        for ps_key in torm:
          if ps_key in b.merging:
            b.merging.remove(ps_key)

        if not good and b.status in ('MERGING', 'BUILDING'):
          if b.to_merge:
            b.status = 'NEEDS_MERGE'
          else:
            b.status = None

        b.put()
      db.run_in_transaction(clear_branch, self.key())
    return good

  def finish_merge(self, success, fail, defer):
    """Update our patchset lists with the results of a merge.

    This method runs in an independent transaction.
    """
    def trans(key):
      b = db.get(key)

      rm = []
      rm.extend(success)
      rm.extend(fail)
      for ps in rm:
        ps_key = ps.key()

        if ps_key in b.to_merge:
          b.to_merge.remove(ps_key)
        if ps_key in b.merging:
          b.merging.remove(ps_key)
        if ps_key in b.waiting:
          b.waiting.remove(ps_key)

      for ps in defer:
        ps_key = ps.key()

        if ps_key in b.to_merge:
          b.to_merge.remove(ps_key)
        if ps_key in b.merging:
          b.merging.remove(ps_key)
        if ps_key not in b.waiting:
          b.waiting.append(ps_key)

      b.put()
    db.run_in_transaction(trans, self.key())

  def merged(self, merged):
    """Updates the branch to include pending PatchSets.

    This method runs in an independent transaction.
    """
    def trans(key):
      b = db.get(key)

      for ps in merged:
        ps_key = ps.key()

        if ps_key in b.to_merge:
          b.to_merge.remove(ps_key)
        if ps_key in b.merging:
          b.merging.remove(ps_key)
        if ps_key in b.waiting:
          b.waiting.remove(ps_key)

      if b.status in ('MERGING', 'BUILDING'):
        if b.to_merge:
          b.status = 'NEEDS_MERGE'
        else:
          b.status = None
      b.put()
    db.run_in_transaction(trans, self.key())


### Revisions ###

class RevisionId(BackedUpModel):
  """A specific revision of a project."""

  project = db.ReferenceProperty(Project, required=True)
  id = db.StringProperty(required=True) # == key

  author_name = db.StringProperty()
  author_email = db.EmailProperty()
  author_when = db.DateTimeProperty()
  author_tz = db.IntegerProperty()

  committer_name = db.StringProperty()
  committer_email = db.EmailProperty()
  committer_when = db.DateTimeProperty()
  committer_tz = db.IntegerProperty()

  ancestors = db.StringListProperty() # other RevisionId.id
  message = db.TextProperty()

  patchset_key = db.StringProperty()
  def _get_patchset(self):
    try:
      return self._patchset_obj
    except AttributeError:
      k_str = self._patchset_key
      if k_str:
        self._patchset_obj = db.get(db.Key(k_str))
      else:
        self._patchset_obj = None
    return self._patchset_obj

  def _set_patchset(self, p):
    if p is None:
      self._patchset_key = None
      self._patchset_obj = None
    else:
      self._patchset_key = str(p.key())
      self._patchset_obj = p
  patchset = property(_get_patchset, _set_patchset)

  @classmethod
  def get_or_insert_revision(cls, project, id, **kw):
    key = 'p.%s %s' % (project.key().id(), id)
    return cls.get_or_insert(key, project=project, id=id, **kw)

  @classmethod
  def get_revision(cls, project, id):
    key = 'p.%s %s' % (project.key().id(), id)
    return cls.get_by_key_name(key)

  @classmethod
  def get_for_patchset(cls, patchset):
    """Get all revisions linked to a patchset.
    """
    return gql(cls, 'WHERE patchset_key = :1', str(patchset.key()))

  def add_ancestor(self, other_id):
    """Adds the other revision as an ancestor for this one.

    If the other rev is already in the list, does nothing.
    """
    if not other_id in self.ancestors:
      self.ancestors.append(other_id)

  def remove_ancestor(self, other_id):
    """Removes an ancestor previously stored.

    If the other rev is not already in the list, does nothing.
    """
    if other_id in self.ancestors:
      self.ancestors.remove(other_id)

  def get_ancestors(self):
    """Fully fetches all ancestors from the data store.
    """
    p_id = self.project.key().id()
    names = ['p.%s %s' % (p_id, i) for i in self.ancestors]
    return [r for r in RevisionId.get_by_key_name(names) if r]

  def get_children(self):
    """Obtain the revisions that depend upon this one.
    """
    return gql(RevisionId,
               'WHERE project = :1 AND ancestors = :2',
               self.project, self.id)

  def link_patchset(self, new_patchset):
    """Uniquely connect one patchset to this revision.

    Returns True if the passed patchset is the single patchset;
    False if another patchset has already been linked onto it.
    """
    def trans(self_key):
      c = db.get(self_key)
      if c.patchset is None:
        c.patchset = new_patchset
        c.put()
        return True
      return False
    return db.run_in_transaction(trans, self.key())


class BuildAttempt(BackedUpModel):
  """A specific build attempt."""

  branch = db.ReferenceProperty(Branch, required=True)
  revision_id = db.StringProperty(required=True)
  new_changes = db.ListProperty(db.Key) # PatchSet

  started = db.DateTimeProperty(auto_now_add=True)
  finished = db.BooleanProperty(default=False)
  success = db.BooleanProperty()


### Changes, PatchSets, Patches, DeltaContents, Comments, Messages ###

class Change(BackedUpModel):
  """The major top-level entity.

  It has one or more PatchSets as its descendants.
  """

  subject = db.StringProperty(required=True)
  description = db.TextProperty()
  owner = db.UserProperty(required=True)
  created = db.DateTimeProperty(auto_now_add=True)
  modified = db.DateTimeProperty(auto_now=True)
  reviewers = db.ListProperty(db.Email)
  claimed = db.BooleanProperty(default=False)
  cc = db.ListProperty(db.Email)
  closed = db.BooleanProperty(default=False)
  n_comments = db.IntegerProperty(default=0)
  n_patchsets = db.IntegerProperty(default=0)

  dest_project = db.ReferenceProperty(Project, required=True)
  dest_branch = db.ReferenceProperty(Branch, required=True)

  merge_submitted = db.DateTimeProperty()
  merged = db.BooleanProperty(default=False)

  emailed_clean_merge = db.BooleanProperty(default=False)
  emailed_missing_dependency = db.BooleanProperty(default=False)
  emailed_path_conflict = db.BooleanProperty(default=False)

  merge_patchset_key = db.StringProperty()
  def _get_merge_patchset(self):
    try:
      return self._merge_patchset_obj
    except AttributeError:
      k_str = self._merge_patchset_key
      if k_str:
        self._merge_patchset_obj = db.get(db.Key(k_str))
      else:
        self._merge_patchset_obj = None
    return self._merge_patchset_obj

  def _set_merge_patchset(self, p):
    if p is None:
      self._merge_patchset_key = None
      self._merge_patchset_obj = None
    else:
      self._merge_patchset_key = str(p.key())
      self._merge_patchset_obj = p
  merge_patchset = property(_get_merge_patchset, _set_merge_patchset)

  _is_starred = None

  @property
  def is_starred(self):
    """Whether the current user has this change starred."""
    if self._is_starred is not None:
      return self._is_starred
    account = Account.current_user_account
    self._is_starred = account is not None and self.key().id() in account.stars
    return self._is_starred

  def update_comment_count(self, n):
    """Increment the n_comments property by n.
    """
    self.n_comments += n

  @property
  def num_comments(self):
    """The number of non-draft comments for this change.

    This is almost an alias for self.n_comments, except that if
    n_comments is None, it is computed through a query, and stored,
    using n_comments as a cache.
    """
    return self.n_comments

  _num_drafts = None

  @property
  def num_drafts(self):
    """The number of draft comments on this change for the current user.

    The value is expensive to compute, so it is cached.
    """
    if self._num_drafts is None:
      account = Account.current_user_account
      if account is None:
        self._num_drafts = 0
      else:
        query = gql(Comment,
            'WHERE ANCESTOR IS :1 AND author = :2 AND draft = TRUE',
            self, account.user)
        self._num_drafts = query.count()
    return self._num_drafts

  def new_patchset(self, **kw):
    """Construct a new patchset for this change.
    """
    def trans(change_key):
      change = db.get(change_key)
      change.n_patchsets += 1
      id = change.n_patchsets
      change.put()

      patchset = PatchSet(change=change, parent=change, id=id, **kw)
      patchset.put()
      return patchset
    return db.run_in_transaction(trans, self.key())

  def set_review_status(self, user):
    """Gets or inserts the ReviewStatus object for the suppiled user."""
    return ReviewStatus.get_or_insert_status(self, user)

  def get_review_status(self, user=None):
    """Return the lgtm status for the given user if supplied.  All for this 
    change otherwise."""
    if user:
      # The owner must be checked separately because she automatically
      # approves / verifies her own change and there is no ReviewStatus
      # for that one.
      if user == self.owner:
        return []
      return ReviewStatus.get_status_for_user(self, user)
    else:
      return ReviewStatus.all_for_change(self)

  @classmethod
  def get_reviewer_status(cls, reviews):
    """Return a tuple of who has commented on the changes.

    The owner of the change is automatically added to the list

    Args:
      reviews  a list of ReviewStatus objects are returned from
               get_review_status().

    Returns:
      A map of the LGTM_CHOICES keys to users, plus the mapping
          verified_by --> the uesrs who verified it
    """
    result = {}
    for (k,v) in LGTM_CHOICES:
      result[k] = [r.user for r in reviews if r.lgtm == k]
    result["verified_by"] = [r.user for r in reviews if r.verified]
    return result

  @property
  def is_submitted(self):
    """Return true if the change has been submitted for merge.
    """
    return self.merge_submitted is not None

  def submit_merge(self, patchset):
    """Schedule a specific patchset of the change to be merged.
    """
    branch = self.dest_branch
    if not branch:
      raise InvalidSubmitMergeException, 'No branch defined'

    if self.merged:
      raise InvalidSubmitMergeException, 'Already merged'

    if self.is_submitted:
      raise InvalidSubmitMergeException, \
        "Already merging patch set %s" % self.merge_patchset.id

    branch.merge_patchset(patchset)
    self.merge_submitted = datetime.datetime.now()
    self.merge_patchset = patchset
    self.emailed_clean_merge = False
    self.emailed_missing_dependency = False
    self.emailed_path_conflict = False

  def unsubmit_merge(self):
    """Unschedule a merge of this change.
    """
    if self.merged:
      raise InvalidSubmitMergeException, 'Already merged'

    self.merge_submitted = None
    self.merge_patchset = None

  def set_reviewers(self, reviewers):
    self.reviewers = reviewers
    self.claimed = len(reviewers) != 0


class PatchSetFilenames(BackedUpModel):
  """A list of the file names in a PatchSet.

  This is a descendant of a PatchSet.
  """

  compressed_filenames = db.BlobProperty()

  @classmethod
  def _mc(cls, patchset):
    return MemCacheKey("PatchSet %s filenames" % patchset.key())

  @classmethod
  def store_compressed(cls, patchset, bin):
    cls(key_name = 'filenames',
        compressed_filenames = db.Blob(bin),
        parent = patchset).put()
    cls._mc(patchset).set(cls._split(bin))

  @classmethod
  def get_list(cls, patchset):
    def read():
      c = cls.get_by_key_name('filenames', parent = patchset)
      if c:
        return cls._split(c.compressed_filenames)
      names = patchset._all_filenames()
      bin = zlib.compress("\0".join(names).encode('utf_8'), 9)
      cls(key_name = 'filenames',
          compressed_filenames = db.Blob(bin),
          parent = patchset).put()
      return names
    return cls._mc(patchset).get(read)

  @classmethod
  def _split(cls, bin):
    tmp = zlib.decompress(bin).split("\0")
    return [s.decode('utf_8') for s in tmp]


class PatchSet(BackedUpModel):
  """A set of patchset uploaded together.

  This is a descendant of an Change and has Patches as descendants.
  """

  id = db.IntegerProperty(required=True)
  change = db.ReferenceProperty(Change, required=True) # == parent
  message = db.StringProperty()
  owner = db.UserProperty(required=True)
  created = db.DateTimeProperty(auto_now_add=True)
  modified = db.DateTimeProperty(auto_now=True)
  revision = db.ReferenceProperty(RevisionId, required=True)
  complete = db.BooleanProperty(default=False)

  _filenames = None

  @property
  def filenames(self):
    if self._filenames is None:
      self._filenames = PatchSetFilenames.get_list(self)
    return self._filenames

  def _all_filenames(self):
    last = ''
    names = []
    while True:
      list = gql(Patch,
                 'WHERE patchset = :1 AND filename > :2'
                 ' ORDER BY filename',
                 self, last).fetch(500)
      if not list:
        break
      for p in list:
        names.append(p.filename)
      last = list[-1].filename
    return names


class Message(BackedUpModel):
  """A copy of a message sent out in email.

  This is a descendant of an Change.
  """

  change = db.ReferenceProperty(Change, required=True)  # == parent
  subject = db.StringProperty()
  sender = db.EmailProperty()
  recipients = db.ListProperty(db.Email)
  date = db.DateTimeProperty(auto_now_add=True)
  text = db.TextProperty()


class CachedDeltaContent(object):
  """A fully inflated DeltaContent stored in memcache.
  """
  def __init__(self, dc):
    self.data_lines = dc.data_lines
    self.patch_lines = dc.patch_lines
    self.is_patch = dc.is_patch
    self.is_data = dc.is_data

  @property
  def data_text(self):
    if self.data_lines is None:
      return None
    return ''.join(self.data_lines)

  @property
  def patch_text(self):
    if self.patch_lines is None:
      return None
    return ''.join(self.patch_lines)

  @classmethod
  def get(cls, key):
    def load():
      dc = db.get(key)
      if dc:
        return cls(dc)
      return None
    return MemCacheKey('DeltaContent:%s' % key.name(),
                       compress = True).get(load)


def _apply_patch(old_lines, patch_name, dif_lines):
  new_lines = []
  chunks = patching.ParsePatchToChunks(dif_lines, patch_name)
  for tag, old, new in patching.PatchChunks(old_lines, chunks):
    new_lines.extend(new)
  return ''.join(new_lines)

def _blob_hash(data):
  m = hashlib.sha1()
  m.update("blob %d\0" % len(data))
  m.update(data)
  return m.hexdigest()


class DeltaContent(BackedUpModel):
  """Any content, such as for the old or new image of a Patch,
     or the patch data itself.

     These are stored as top-level entities.

     Key:
        Git blob SHA-1 of inflate(text)
      -or-
        Randomly generated name if this is a patch
  """

  text_z = db.BlobProperty(required=True)
  depth = db.IntegerProperty(default=0, required=True)
  base = db.SelfReferenceProperty()

  _data_lines = None
  _data_text = None
  _patch_text = None
  _patch_lines = None

  @classmethod
  def create_patch(cls, id, text_z):
    key_name = 'patch:%s' % id
    return cls.get_or_insert(key_name,
                             text_z = db.Blob(text_z),
                             depth = 0,
                             base = None)

  @classmethod
  def create_content(cls, id, text_z, base = None):
    """Create (or lookup and return an existing) content instance.

       Arguments:
        id:
          Git blob SHA-1 hash of the fully inflated content.
        text_z:
          If base is None this is the deflated content whose hash
          is id.

          If base is supplied this is a patch which when applied to
          base yields the content whose hash is id.
        base:
          The base content if text_z is a patch.
    """
    key_name = 'content:%s' % id
    r = cls.get_by_key_name(key_name)
    if r:
      return r

    if base is None:
      return cls.get_or_insert(key_name,
                               text_z = db.Blob(text_z),
                               depth = 0,
                               base = None)

    my_text = _apply_patch(base.data_lines,
                           id,
                           zlib.decompress(text_z).splitlines(True))
    cmp_id = _blob_hash(my_text)
    if id != cmp_id:
      raise DeltaPatchingException()

    if base.depth < MAX_DELTA_DEPTH:
      return cls.get_or_insert(key_name,
                               text_z = db.Blob(text_z),
                               depth = base.depth + 1,
                               base = base)
    return cls.get_or_insert(key_name,
                             text_z = db.Blob(zlib.compress(my_text)),
                             depth = 0,
                             base = None)

  @property
  def is_patch(self):
    return self._base or self.key().name().startswith('patch:')

  @property
  def is_data(self):
    return self.key().name().startswith('content:')

  @property
  def data_text(self):
    if self._data_text is None:
      if self._base:
        base = CachedDeltaContent.get(self._base)
        raw = _apply_patch(base.data_lines,
                           self.key().name(),
                           self.patch_lines)
      else:
        raw = zlib.decompress(self.text_z)
      self._data_text = raw
    return self._data_text

  @property
  def data_lines(self):
    if self._data_lines is None:
      self._data_lines = self.data_text.splitlines(True)
    return self._data_lines

  @property
  def patch_text(self):
    if not self.is_patch:
      return None
    if self._patch_text is None:
      self._patch_text = zlib.decompress(self.text_z)
    return self._patch_text

  @property
  def patch_lines(self):
    if not self.is_patch:
      return None
    if self._patch_lines is None:
      self._patch_lines = self.patch_text.splitlines(True)
    return self._patch_lines


class Patch(BackedUpModel):
  """A single patch, i.e. a set of changes to a single file.

  This is a descendant of a PatchSet.
  """

  patchset = db.ReferenceProperty(PatchSet, required=True)  # == parent
  filename = db.StringProperty(required=True)
  status = db.StringProperty(required=True)  # 'A', 'M', 'D'
  n_comments = db.IntegerProperty()

  old_data = db.ReferenceProperty(DeltaContent, collection_name='olddata_set')
  new_data = db.ReferenceProperty(DeltaContent, collection_name='newdata_set')
  diff_data = db.ReferenceProperty(DeltaContent, collection_name='diffdata_set')

  @classmethod
  def get_or_insert_patch(cls, patchset, filename, **kw):
    """Get or insert the patch for a specific file path.

    This method runs in an independent transaction.
    """
    m = hashlib.sha1()
    m.update(filename)
    key = 'z%s' % m.hexdigest()
    return cls.get_or_insert(key,
                             parent = patchset,
                             patchset = patchset,
                             filename = filename,
                             **kw)

  @classmethod
  def get_patch(cls, parent, id_str):
    if id_str.startswith('z'):
      return cls.get_by_key_name(id_str, parent=parent);
    else:
      return cls.get_by_id(int(id_str), parent=parent);

  @property
  def id(self):
    return str(self.key().id_or_name())

  @property
  def num_comments(self):
    """The number of non-draft comments for this patch.
    """
    return self.n_comments

  def update_comment_count(self, n):
    """Increment the n_comments property by n.
    """
    self.n_comments += n

  _num_drafts = None

  @property
  def num_drafts(self):
    """The number of draft comments on this patch for the current user.

    The value is expensive to compute, so it is cached.
    """
    if self._num_drafts is None:
      user = Account.current_user_account
      if user is None:
        self._num_drafts = 0
      else:
        query = gql(Comment,
                    'WHERE patch = :1 AND draft = TRUE AND author = :2',
                    self, user.user)
        self._num_drafts = query.count()
    return self._num_drafts

  def _data(self, name):
    prop = '_%s_CachedDeltaContent' % name
    try:
      c = getattr(self, prop)
    except AttributeError:
      # XXX Using internal knowledge about db package:
      # Key for ReferenceProperty 'foo' is '_foo'.

      data_key = getattr(self, '_%s_data' % name, None)
      if data_key:
        c = CachedDeltaContent.get(data_key)
        if data_key in ('diff', 'new') \
           and self._diff_data == self._new_data:
          self._diff_CachedDeltaContent = c
          self._new_CachedDeltaContent = c
        else:
          setattr(self, prop, c)
      else:
        c = None
        setattr(self, prop, c)
    return c

  @property
  def patch_text(self):
    """Get the patch converting old_text to new_text.
    """
    return self._data('diff').patch_text

  @property
  def patch_lines(self):
    """The patch_text split into lines, retaining line endings.
    """
    return self._data('diff').patch_lines

  @property
  def old_text(self):
    """Original version of the file text.
    """
    d = self._data('old')
    if d:
      return d.data_text
    return ''

  @property
  def old_lines(self):
    """The old_text split into lines, retaining line endings.
    """
    d = self._data('old')
    if d:
      return d.data_lines
    return []

  @property
  def new_text(self):
    """Get self.new_content
    """
    d = self._data('new')
    if d:
      return d.data_text
    return ''

  @property
  def new_lines(self):
    """The new_text split into lines, retaining line endings.
    """
    d = self._data('new')
    if d:
      return d.data_lines
    return []


class Comment(BackedUpModel):
  """A Comment for a specific line of a specific file.

  This is a descendant of a Patch.
  """

  patch = db.ReferenceProperty(Patch)  # == parent
  message_id = db.StringProperty()  # == key_name
  author = db.UserProperty()
  date = db.DateTimeProperty(auto_now=True)
  lineno = db.IntegerProperty()
  text = db.TextProperty()
  left = db.BooleanProperty()
  draft = db.BooleanProperty(required=True, default=True)

  def complete(self, patch):
    """Set the shorttext and buckets attributes."""
    # TODO(guido): Turn these into caching proprties instead.
    # TODO(guido): Properly parse the text into quoted and unquoted buckets.
    self.shorttext = self.text.lstrip()[:50].rstrip()
    self.buckets = [Bucket(text=self.text)]


class Bucket(BackedUpModel):
  """A 'Bucket' of text.

  A comment may consist of multiple text buckets, some of which may be
  collapsed by default (when they represent quoted text).

  NOTE: This entity is never written to the database.  See Comment.complete().
  """
  # TODO(guido): Flesh this out.

  text = db.TextProperty()


class ReviewStatus(BackedUpModel):
  """The information for whether a user has LGTMed or verified a change."""
  change = db.ReferenceProperty(Change, required=True)  # == parent
  user = db.UserProperty(required=True)
  lgtm = db.StringProperty()
  verified = db.BooleanProperty()

  @classmethod
  def get_or_insert_status(cls, change, user):
    key = '<%s>' % user.email
    return cls.get_or_insert(key,
                             change=change,
                             user=user,
                             parent=change)

  @classmethod
  def get_status_for_user(cls, change, user):
    key = '<%s>' % user.email
    return cls.get_by_key_name(key, parent=change)

  @classmethod
  def all_for_change(cls, change):
    return gql(ReviewStatus,
               'WHERE ANCESTOR IS :1',
               change).fetch(FETCH_MAX)


### Contributor License Agreements ###

class IndividualCLA:
  NONE = 0


### Accounts ###


class Account(BackedUpModel):
  """Maps a user or email address to a user-selected real_name, and more.

  Nicknames do not have to be unique.

  The default real_name is generated from the email address by
  stripping the first '@' sign and everything after it.  The email
  should not be empty nor should it start with '@' (AssertionError
  error is raised if either of these happens).

  Holds a list of ids of starred changes.  The expectation
  that you won't have more than a dozen or so starred changes (a few
  hundred in extreme cases) and the memory used up by a list of
  integers of that size is very modest, so this is an efficient
  solution.  (If someone found a use case for having thousands of
  starred changes we'd have to think of a different approach.)

  Returns whether a user is authorized to do lgtm or verify.
  For now, these authorization check methods do not test which repository
  the change is in.  This will change.
  """

  user = db.UserProperty(required=True)
  email = db.EmailProperty(required=True)  # key == <email>
  preferred_email = db.EmailProperty()

  created = db.DateTimeProperty(auto_now_add=True)
  modified = db.DateTimeProperty(auto_now=True)

  welcomed = db.BooleanProperty(default=False)
  real_name_entered = db.BooleanProperty(default=False)
  real_name = db.StringProperty()
  mailing_address = db.TextProperty()
  mailing_address_country = db.StringProperty()
  phone_number = db.StringProperty()
  fax_number = db.StringProperty()

  cla_verified = db.BooleanProperty(default=False)
  cla_verified_by = db.UserProperty()
  cla_verified_timestamp = db.DateTimeProperty() # the first time it's set
  individual_cla_version = db.IntegerProperty(default=IndividualCLA.NONE)
  individual_cla_timestamp = db.DateTimeProperty()
  cla_comments = db.TextProperty()

  default_context = db.IntegerProperty(default=DEFAULT_CONTEXT,
                                       choices=CONTEXT_CHOICES)
  stars = db.ListProperty(int)  # Change ids of all starred changes
  unclaimed_changes_projects = db.ListProperty(db.Key)

  # Current user's Account.  Updated by middleware.AddUserToRequestMiddleware.
  current_user_account = None

  def get_email(self):
    "Gets the email that this person wants us to use -- separate from login."
    if self.preferred_email:
      return self.preferred_email
    else:
      return self.email

  def get_email_formatted(self):
    return '"%s" <%s>' % (self.real_name, self.get_email())

  @classmethod
  def get_account_for_user(cls, user):
    """Get the Account for a user, creating a default one if needed."""
    email = user.email()
    assert email
    key = '<%s>' % email
    # Since usually the account already exists, first try getting it
    # without the transaction implied by get_or_insert().
    account = cls.get_by_key_name(key)
    if account is not None:
      return account
    real_name = user.nickname()
    if '@' in real_name:
      real_name = real_name.split('@', 1)[0]
    assert real_name
    return cls.get_or_insert(key, user=user, email=email, real_name=real_name)

  @classmethod
  def get_account_for_email(cls, email):
    """Get the Account for an email address, or return None."""
    assert email
    key = '<%s>' % email
    return cls.get_by_key_name(key)

  @classmethod
  def get_accounts_for_emails(cls, emails):
    """Get the Accounts for all email address.
    """
    return cls.get_by_key_name(map(lambda x: '<%s>' % x, emails))

  @classmethod
  def get_real_name_for_email(cls, email):
    """Get the real_name for an email address, possibly a default."""
    account = cls.get_account_for_email(email)
    if account is not None and account.real_name:
      return account.real_name
    real_name = email
    if '@' in real_name:
      real_name = real_name.split('@', 1)[0]
    assert real_name
    return real_name

  @classmethod
  def get_accounts_for_real_name(cls, real_name):
    """Get the list of Accounts that have this real_name."""
    assert real_name
    assert '@' not in real_name
    return list(gql(cls, 'WHERE real_name = :1', real_name))

  @classmethod
  def get_email_for_real_name(cls, real_name):
    """Turn a real_name into an email address.

    If the real_name is not unique or does not exist, this returns None.
    """
    accounts = cls.get_accounts_for_real_name(real_name)
    if len(accounts) != 1:
      return None
    return accounts[0].email

  _drafts = None

  @property
  def drafts(self):
    """A list of change ids that have drafts by this user.

    This is cached in memcache.
    """
    if self._drafts is None:
      if self._initialize_drafts():
        self._save_drafts()
    return self._drafts

  def update_drafts(self, change, have_drafts=None):
    """Update the user's draft status for this change.

    Args:
      change: an Change instance.
      have_drafts: optional bool forcing the draft status.  By default,
          change.num_drafts is inspected (which may query the datastore).

    The Account is written to the datastore if necessary.
    """
    dirty = False
    if self._drafts is None:
      dirty = self._initialize_drafts()
    id = change.key().id()
    if have_drafts is None:
      have_drafts = bool(change.num_drafts)  # Beware, this may do a query.
    if have_drafts:
      if id not in self._drafts:
        self._drafts.append(id)
        dirty = True
    else:
      if id in self._drafts:
        self._drafts.remove(id)
        dirty = True
    if dirty:
      self._save_drafts()

  def _initialize_drafts(self):
    """Initialize self._drafts from scratch.

    This mostly exists as a schema conversion utility.

    Returns:
      True if the user should call self._save_drafts(), False if not.
    """
    drafts = memcache.get('user_drafts:' + self.email)
    if drafts is not None:
      self._drafts = drafts
      return False
    # We're looking for the Change key id.  The ancestry of comments goes:
    # Change -> PatchSet -> Patch -> Comment.
    change_ids = set(comment.key().parent().parent().parent().id()
                    for comment in gql(Comment,
                                       'WHERE author = :1 AND draft = TRUE',
                                       self.user))
    self._drafts = list(change_ids)
    return True

  def _save_drafts(self):
    """Save self._drafts to memcache."""
    memcache.set('user_drafts:' + self.email, self._drafts, 3600)

  def can_lgtm(self):
    """Returns whether the user can lgtm a given change.
    
    For now returns true and doesn't take the change to check.
    """
    return True

  def can_verify(self):
    """Returns whether the user can verify a given change.

    For now returns true and doesn't take the change to check.
    """
    return True

  @classmethod
  def get_all_accounts(cls):
    """Return all accounts"""
    all = cls.all()
    all.order('real_name')
    return list(all)


### Group ###

AUTO_GROUPS = ['admin', 'submitters']

class AccountGroup(BackedUpModel):
  """A set of users.  Permissions are assigned to groups.
  
  There are some groups that can't be deleted -- like admin and all
  """
  
  name = db.StringProperty(required=True)
  comment = db.TextProperty(required=False)
  members = db.ListProperty(users.User)

  @classmethod
  def get_all_groups(cls):
    """Return all groups"""
    all = cls.all()
    all.order('name')
    return list(all)

  @property
  def is_auto_group(self):
    """These groups can't be deleted."""
    return self.name in AUTO_GROUPS

  @classmethod
  def create_groups(cls):
    for group_name in AUTO_GROUPS:
      def trans():
        g = cls(name=group_name, comment=(
            'Auto created %s group' % group_name))
        g.put()
      q = cls.gql('WHERE name=:name', name=group_name)
      if q.get() is None:
        db.run_in_transaction(trans)

  @classmethod
  def get_group_for_name(cls, name):
    return cls.gql('WHERE name=:name', name=name).get()

  def remove(self):
    """delete this group"""
    def trans(group):
      group.delete()
      # this will do the ON DELETE CASCADE once the users are in there
    db.run_in_transaction(trans, self)

  def put(self):
    if self.name in ['admin', 'submitters']:
      memcache.delete('group_members:%s' % self.name)
    BackedUpModel.put(self)

  @classmethod
  def _is_in_cached_group(cls, user, group):
    if not user:
      return False
    cache_key = 'group_members:%s' % group
    users = memcache.get(cache_key)
    if not users:
      g = AccountGroup.get_group_for_name(group)
      if not g:
        AccountGroup.create_groups()
        g = AccountGroup.get_group_for_name(group)
      if len(g.members) == 0:
        # if there are no users in this group, everyone is in this group
        # (helps with testing, upgrading and bootstrapping)
        # In prod this never really happens, so don't bother caching it
        return True
      users = [u.email() for u in g.members]
      memcache.set(cache_key, users)
    return user.email() in users

  @classmethod
  def is_user_admin(cls, user):
    return AccountGroup._is_in_cached_group(user, 'admin')

  @classmethod
  def is_user_submitter(cls, user):
    return AccountGroup._is_in_cached_group(user, 'submitters')
