# 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
try:
  import hashlib
except ImportError:
  pass
import logging
import random
import re
import zlib

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

# Local imports
from memcache import Key as MemCacheKey
from memcache import CachedDict
import patching


CUR_SCHEMA_VERSION = 1
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()
  canonical_url = db.StringProperty(default='')
  source_browser_url = db.StringProperty(default='')
  merge_log_email = db.StringProperty()
  schema_version = db.IntegerProperty(default=0)

  _Key = MemCacheKey('Settings_Singleton')
  _LocalCache = None

  @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.
    """
    if Settings._LocalCache is None:
      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),
                                    schema_version = CUR_SCHEMA_VERSION)
      Settings._LocalCache = Settings._Key.get(read)
    return Settings._LocalCache

  def put(self):
    BackedUpModel.put(self)
    self._Key.clear()
    Settings._LocalCache = None


### 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)
  submitters_users = db.ListProperty(users.User)
  submitters_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)

  def submitters(self):
    """Returns a set of the users who are submitters."""
    return _flatten_users_and_groups(self.submitters_users,
        self.submitters_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 leads(self):
    """Returns a set of the users who are leads."""
    return _flatten_users_and_groups(self.owners_users,
                                     self.owners_groups)

  def is_user_lead(self, user):
    if user in self.owners_users:
      return True
    for group in AccountGroup.get(self.owners_groups):
      if group and user in group.members:
        return True
    return False

def _get_owned_projects(email):
  u = users.User(email)
  projects = set(gql(Project,
                     'WHERE owners_users = :1',
                     u).fetch(1000))

  groups = gql(AccountGroup, 'WHERE members = :1', u).fetch(1000)
  if groups:
    projects.update(gql(Project,
                        'WHERE owners_groups IN :1',
                        [g.key() for g in groups]).fetch(1000))
  return [p.key() for p in projects]

OwnedProjects = CachedDict(prefix = 'OwnedProject:',
                           compute_one = _get_owned_projects)

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 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, ps in zip(keys, objs):
      if ps and not ps.change.closed:
        good.append(ps)
      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

  _user_can_edit = None
  def user_can_edit(self):
    """Can the current account edit this change?
    """
    if self._user_can_edit is None:
      a = Account.current_user_account
      if not a:
        e = False
      elif a.is_admin:
        e = True
      elif self.owner == a.user:
        e = True
      elif self.dest_project.is_user_lead(a.user):
        e = True
      else:
        e = False
      self._user_can_edit = e
    return self._user_can_edit

  def remove_reviewer(self, user):
    """Removes a user from the list of reviewers, and removes the ReviewStatus
    object."""
    def trans():
      email = user.email()
      reviewers = [e for e in self.reviewers if e != email]
      self.set_reviewers(reviewers)
      rs = ReviewStatus.get_status_for_user(self, user)
      if rs:
        rs.delete()
      self.put()
    db.run_in_transaction(trans)



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

  def revision_hash(self):
    return self.revision.id


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 PatchOtherVersion(object):
  """A reference to a prior version of a patch
  """
  def __init__(self, patchset_id, patchset_name, patch_id):
    self.patchset_id = patchset_id
    self.patchset_name = patchset_name
    self.patch_id = patch_id

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'
  multi_way_diff = db.BooleanProperty(default=False)
  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')

  # Note: Each entry is a triple:
  #   "${patchset.key().id} ${patchset.id} ${patch.id}"
  #
  other_versions = db.StringListProperty()

  @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_by_filename(cls, parent, filename):
    m = hashlib.sha1()
    m.update(filename)
    key = 'z%s' % m.hexdigest()
    return cls.get_by_key_name(key, parent=parent);

  @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

  @property
  def other_patch_versions(self):
    return [PatchOtherVersion(*t)
            for t
            in [line.split(' ', 3)
                for line
                in self.other_versions]]

  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

  def patch_equals(self, other_delta):
    """Does this patch use the given DeltaContent as its patch body?
    """
    return self._diff_data == other_delta.key()

  @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 ReviewStatus.get_or_insert(key,
                             change=change,
                             user=user,
                             parent=change)

  @classmethod
  def insert_status(cls, change, user):
    key = '<%s>' % user.email
    return ReviewStatus(key_name=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)

  is_admin = db.BooleanProperty(default=False)
  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

  _draft_key = None

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

    This is cached in memcache.
    """
    if self._draft_key is None:
      self._draft_key = MemCacheKey(
          key = 'user_drafts:%s' % self.email,
          incore = True,
          timeout = 3600)

    def query_store():
      # 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))
      return list(change_ids)
    return self._draft_key.get(query_store)

  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.
    """
    my_drafts = self.drafts
    id = change.key().id()
    if have_drafts is None:
      have_drafts = bool(change.num_drafts)  # this may do a query

    if have_drafts:
      if id not in my_drafts:
        my_drafts.append(id)
        self._draft_key.set(my_drafts)
    else:
      if id in my_drafts:
        my_drafts.remove(id)
        self._draft_key.set(my_drafts)


### Group ###

AUTO_GROUPS = ['admin']

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()
      if not cls.get_group_for_name(group_name):
        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)
