text:
package org.pixmob.freemobile.netstat.gae.web.v1;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletResponse;

import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.util.Closeable;
import org.apache.commons.lang3.StringUtils;
import org.pixmob.freemobile.netstat.gae.repo.DeviceException;
import org.pixmob.freemobile.netstat.gae.repo.DeviceRepository;

import com.google.inject.Inject;
import com.google.inject.name.Named;
import com.google.sitebricks.client.transport.Json;
import com.google.sitebricks.headless.Reply;
import com.google.sitebricks.headless.Request;
import com.google.sitebricks.headless.Service;
import com.google.sitebricks.http.Delete;
import com.google.sitebricks.http.Put;

@Service
/**
 * REST service handling device resources.
 * @author Pixmob
 */
public class DeviceService {
    private final Logger logger = Logger.getLogger(DeviceService.class.getName());
    private final DeviceRepository dr;

    @Inject
    DeviceService(final DeviceRepository dr) {
        this.dr = dr;
    }

    @Put
    public Reply register(Request<String> req, @Named("id") String deviceId) {
        try (Closeable service = ObjectifyService.begin()) {
            final DeviceReg devReg = req.read(DeviceReg.class).as(Json.class);
            devReg.brand = StringUtils.trimToNull(devReg.brand);
            devReg.model = StringUtils.trimToNull(devReg.model);

            logger.fine("Trying to register device: " + devReg);

            try {
                dr.create(deviceId, devReg.brand, devReg.model);
            } catch (DeviceException e) {
                logger.log(Level.WARNING, "Failed to register device " + deviceId, e);
                return Reply.with(e.getMessage()).status(HttpServletResponse.SC_CONFLICT);
            }

            logger.info("Device registered");

            return Reply.saying().status(HttpServletResponse.SC_CREATED);
        }
    }

    @Delete
    public Reply unregister(@Named("id") String deviceId) {
        try (Closeable service = ObjectifyService.begin()) {
            logger.fine("Trying to unregister device");
            dr.delete(deviceId);
            logger.info("Device unregistered");

            return Reply.saying().ok();
        }
    }

    private static class DeviceReg {
        public String brand;
        public String model;

        @Override
        public String toString() {
            return "brand=" + brand + ", model=" + model;
        }
    }
}


text:
_Use this issue template for filing CVE placeholder issues._

TITLE: PLACEHOLDER ISSUE

---

/triage accepted
/lifecycle frozen
/area security
/kind bug
/committee security-response

redpajama_set_name: RedPajamaGithub


text:
package org.eclipse.deeplearning4j.dl4jcore.gradientcheck;

import lombok.extern.slf4j.Slf4j;
import org.deeplearning4j.BaseDL4JTest;
import org.eclipse.deeplearning4j.dl4jcore.TestUtils;
import org.deeplearning4j.gradientcheck.GradientCheckUtil;
import org.deeplearning4j.nn.conf.ComputationGraphConfiguration;
import org.deeplearning4j.nn.conf.ConvolutionMode;
import org.deeplearning4j.nn.conf.MultiLayerConfiguration;
import org.deeplearning4j.nn.conf.NeuralNetConfiguration;
import org.deeplearning4j.nn.conf.distribution.NormalDistribution;
import org.deeplearning4j.nn.conf.dropout.*;
import org.deeplearning4j.nn.conf.inputs.InputType;
import org.deeplearning4j.nn.conf.layers.ConvolutionLayer;
import org.deeplearning4j.nn.conf.layers.DenseLayer;
import org.deeplearning4j.nn.conf.layers.OutputLayer;
import org.deeplearning4j.nn.graph.ComputationGraph;
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.nd4j.common.tests.tags.NativeTag;
import org.nd4j.common.tests.tags.TagNames;
import org.nd4j.linalg.activations.Activation;
import org.nd4j.linalg.api.buffer.DataType;
import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.factory.Nd4j;
import org.nd4j.common.function.Consumer;
import org.nd4j.linalg.learning.config.NoOp;
import org.nd4j.linalg.lossfunctions.LossFunctions.LossFunction;

import static org.junit.jupiter.api.Assertions.assertTrue;

@Slf4j
@Tag(TagNames.NDARRAY_ETL)
@Tag(TagNames.TRAINING)
@Tag(TagNames.DL4J_OLD_API)
@NativeTag
public class TestDropoutGradientCheck extends BaseDL4JTest {

    private static final boolean PRINT_RESULTS = true;
    private static final boolean RETURN_ON_FIRST_FAILURE = false;
    private static final double DEFAULT_EPS = 1e-6;
    private static final double DEFAULT_MAX_REL_ERROR = 1e-3;
    private static final double DEFAULT_MIN_ABS_ERROR = 1e-8;

    static {
        Nd4j.setDataType(DataType.DOUBLE);
    }

    @Override
    public long getTimeoutMilliseconds() {
        return 90000L;
    }

    @Test
    public void testDropoutGradient() {
        int minibatch = 3;

        for(boolean cnn : new boolean[]{false, true}) {
            for (int i = 0; i < 5; i++) {

                IDropout dropout;
                switch (i){
                    case 0:
                        dropout = new Dropout(0.6);
                        break;
                    case 1:
                        dropout = new AlphaDropout(0.6);
                        break;
                    case 2:
                        dropout = new GaussianDropout(0.1);    //0.01 rate -> stdev 0.1; 0.1 rate -> stdev 0.333
                        break;
                    case 3:
                        dropout = new GaussianNoise(0.3);
                        break;
                    case 4:
                        dropout = new SpatialDropout(0.6);
                        break;
                    default:
                        throw new RuntimeException();
                }

                if(!cnn && i == 4){
                    //Skip spatial dropout for dense layer (not applicable)
                    continue;
                }

                NeuralNetConfiguration.ListBuilder builder = new NeuralNetConfiguration.Builder()
                        .dataType(DataType.DOUBLE)
                        .dist(new NormalDistribution(0,1))
                        .convolutionMode(ConvolutionMode.Same)
                        .dropOut(dropout)
                        .activation(Activation.TANH)
                        .updater(new NoOp())
                        .list();

                if(cnn){
                    builder.layer(new ConvolutionLayer.Builder().kernelSize(3,3).stride(2,2).nOut(2).build());
                    builder.layer(new ConvolutionLayer.Builder().kernelSize(3,3).stride(2,2).nOut(2).build());
                    builder.setInputType(InputType.convolutional(6,6,2));
                } else {
                    builder.layer(new DenseLayer.Builder().nOut(3).build());
                    builder.layer(new DenseLayer.Builder().nOut(3).build());
                    builder.setInputType(InputType.feedForward(6));
                }
                builder.layer(new OutputLayer.Builder().nOut(3).activation(Activation.SOFTMAX).lossFunction(LossFunction.MCXENT).build());

                MultiLayerConfiguration conf = builder.build();
                //Remove spatial dropout from output layer - can't be used for 2d input
                if(i == 4){
                   conf.getConf(2).getLayer().setIDropout(null);
                }

                MultiLayerNetwork mln = new MultiLayerNetwork(conf);
                mln.init();

                String msg = (cnn ? "CNN" : "Dense") + ": " + dropout.getClass().getSimpleName();

                INDArray f;
                if(cnn){
                    f = Nd4j.rand(new int[]{minibatch, 2, 6, 6}).muli(10).subi(5);
                } else {
                    f = Nd4j.rand(minibatch, 6).muli(10).subi(5);
                }
                INDArray l = TestUtils.randomOneHot(minibatch, 3);

                log.info("*** Starting test: " + msg + " ***");
                boolean gradOK = GradientCheckUtil.checkGradients(mln, DEFAULT_EPS, DEFAULT_MAX_REL_ERROR,
                        DEFAULT_MIN_ABS_ERROR, PRINT_RESULTS, RETURN_ON_FIRST_FAILURE, f, l, null, null,
                        false, -1, null, 12345);    //Last arg: ensures RNG is reset at each iter... otherwise will fail due to randomness!

                assertTrue(gradOK, msg);
                TestUtils.testModelSerialization(mln);
            }
        }
    }

    @Test
    public void testCompGraphMultiInput(){
        //Validate nets where the one output array is used as the input to multiple layers...
        Nd4j.getRandom().setSeed(12345);
        int mb = 3;

        ComputationGraphConfiguration conf = new NeuralNetConfiguration.Builder()
                .dataType(DataType.DOUBLE)
                .dist(new NormalDistribution(0,1))
                .convolutionMode(ConvolutionMode.Same)
                .dropOut(new GaussianDropout(0.1))  //0.33 stdev. Gaussian dropout: out = in * N(1,stdev)
                .activation(Activation.TANH)
                .updater(new NoOp())
                .graphBuilder()
                .addInputs("in")
                .addLayer("0", new DenseLayer.Builder().nIn(5).nOut(5).build(), "in")
                .addLayer("1", new DenseLayer.Builder().nIn(5).nOut(5).build(), "0")
                .addLayer("2", new DenseLayer.Builder().nIn(5).nOut(5).build(), "0")
                .addLayer("3", new DenseLayer.Builder().nIn(5).nOut(5).build(), "0")
                .addLayer("out", new OutputLayer.Builder().nIn(15).nOut(5).activation(Activation.SOFTMAX)
                        .lossFunction(LossFunction.MCXENT).build(), "1", "2", "3")
                .setOutputs("out")
                .build();

        ComputationGraph cg = new ComputationGraph(conf);
        cg.init();

        INDArray[] in = new INDArray[]{Nd4j.rand(mb, 5)};
        INDArray[] l = new INDArray[]{TestUtils.randomOneHot(mb, 5)};

        boolean gradOK = GradientCheckUtil.checkGradients(new GradientCheckUtil.GraphConfig().net(cg).inputs(in)
                .labels(l).callEachIter(new Consumer<ComputationGraph>() {
                    @Override
                    public void accept(ComputationGraph net) {
                        Nd4j.getRandom().setSeed(12345);
                    }
                }));

        assertTrue(gradOK);
    }

}


text:
#ifndef EIGEN_SPARSEREDUX_H
#define EIGEN_SPARSEREDUX_H

namespace Eigen {

template<typename Derived>
typename internal::traits<Derived>::Scalar
SparseMatrixBase<Derived>::sum() const
{
  eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
  Scalar res(0);
  for (Index j=0; j<outerSize(); ++j)
    for (typename Derived::InnerIterator iter(derived(),j); iter; ++iter)
      res += iter.value();
  return res;
}

template<typename _Scalar, int _Options, typename _Index>
typename internal::traits<SparseMatrix<_Scalar,_Options,_Index> >::Scalar
SparseMatrix<_Scalar,_Options,_Index>::sum() const
{
  eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
  if(this->isCompressed())
    return Matrix<Scalar,1,Dynamic>::Map(m_data.valuePtr(), m_data.size()).sum();
  else
    return Base::sum();
}

template<typename _Scalar, int _Options, typename _Index>
typename internal::traits<SparseVector<_Scalar,_Options, _Index> >::Scalar
SparseVector<_Scalar,_Options,_Index>::sum() const
{
  eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
  return Matrix<Scalar,1,Dynamic>::Map(m_data.valuePtr(), m_data.size()).sum();
}

} // end namespace Eigen

#endif // EIGEN_SPARSEREDUX_H


text:
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System.Linq.Tests.Helpers
{
    public class TestEnumerable<T> : IEnumerable<T>
    {
        public T[] Items = new T[0];
        public TestEnumerable(T[] items) { Items = items; }

        public IEnumerator<T> GetEnumerator() { return ((IEnumerable<T>)Items).GetEnumerator(); }
        IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); }
    }
}


text:
import sbt._
import Keys._
import Status.{ publishStatus }
import com.typesafe.sbt.{ SbtGhPages, SbtGit, SbtSite, site => sbtsite }
import SbtSite.{ site, SiteKeys }
import SbtGhPages.{ ghpages, GhPagesKeys => ghkeys }
import SbtGit.{ git, GitKeys }
import sbtsite.SphinxSupport
import SiteKeys.{ makeSite, siteMappings }
import Sxr.sxr
import SiteMap.Entry

object Docs {
  val rootFiles = SettingKey[Seq[File]]("root-files", "Location of file that will be copied to the website root.")
  val latestRelease = SettingKey[Boolean]("latest-release")

  val siteExcludes = Set(".buildinfo", "objects.inv")
  def siteInclude(f: File) = !siteExcludes.contains(f.getName)
  def siteSourceBase(siteSourceVersion: String) = s"https://github.com/sbt/sbt/raw/$siteSourceVersion/src/sphinx/"
  val sbtSiteBase = uri("http://www.scala-sbt.org/")

  val SnapshotPath = "snapshot"
  val ReleasePath = "release"
  val DocsPath = "docs"
  val IndexHtml = "index.html"
  val HomeHtml = "home.html"
  val VersionPattern = """(\d+)\.(\d+)\.(\d+)(-.+)?""".r.pattern

  def settings: Seq[Setting[_]] =
    site.settings ++
      site.sphinxSupport(DocsPath) ++
      site.includeScaladoc("api") ++
      siteIncludeSxr("sxr") ++
      ghPagesSettings ++
      Seq(
        SphinxSupport.sphinxEnv in SphinxSupport.Sphinx <<= sphinxEnvironmentVariables,
        SphinxSupport.sphinxIncremental in SphinxSupport.Sphinx := true,
        // TODO: set to true with newer sphinx plugin release
        SphinxSupport.enableOutput in SphinxSupport.generatePdf := false
      )

  def ghPagesSettings = ghpages.settings ++ Seq(
    git.remoteRepo := "git@github.com:sbt/sbt.github.com.git",
    localRepoDirectory,
    ghkeys.synchLocal <<= synchLocalImpl,
    rootFiles := {
      val base = (sourceDirectory in SphinxSupport.Sphinx).value
      Seq("CNAME", "robots.txt").map(base / _)
    },
    latestRelease in ThisBuild := false,
    commands += setLatestRelease,
    GitKeys.gitBranch in ghkeys.updatedRepository := Some("master")
  )

  def localRepoDirectory = ghkeys.repository := {
    // distinguish between building to update the site or not so that CI jobs
    //  that don't commit+publish don't leave uncommitted changes in the working directory
    val status = if (isSnapshot.value) "snapshot" else "public"
    Path.userHome / ".sbt" / "ghpages" / status / organization.value / name.value
  }

  def siteIncludeSxr(prefix: String) = Seq(
    mappings in sxr <<= sxr.map(dir => Path.allSubpaths(dir).toSeq),
    site.addMappingsToSiteDir(mappings in sxr, prefix)
  )

  def sphinxEnvironmentVariables = (scalaVersion, version, isSnapshot) map { (scalaV, sbtV, snap) =>
    // sphinx's terminology: major.minor
    def release(v: String): String = CrossVersion.partialVersion(v) match {
      case Some((major, minor)) => major + "." + minor
      case None                 => v
    }
    val siteVersion = sbtV.takeWhile(_ != '-')
    val siteSourceVersion = if (snap) release(siteVersion) else siteVersion
    Map[String, String](
      "sbt.full.version" -> sbtV,
      "sbt.partial.version" -> release(sbtV),
      "sbt.site.version" -> siteVersion,
      "sbt.site.source.base" -> siteSourceBase(siteSourceVersion),
      "sbt.binary.version" -> CrossVersion.binarySbtVersion(sbtV),
      "scala.full.version" -> scalaV,
      "scala.partial.version" -> release(scalaV),
      "scala.binary.version" -> CrossVersion.binaryScalaVersion(scalaV)
    )
  }

  def synchLocalImpl = (ghkeys.privateMappings, ghkeys.updatedRepository, version, isSnapshot, latestRelease, streams, rootFiles) map {
    (mappings, repo, v, snap, latest, s, roots) =>
      val versioned = repo / v
      IO.delete(versioned)
      val toCopy = for ((file, target) <- mappings if siteInclude(file)) yield (file, versioned / target)
      IO.copy(toCopy)
      for (f <- roots)
        IO.copyFile(f, repo / f.getName)
      IO.touch(repo / ".nojekyll")
      IO.write(repo / "versions.js", versionsJs(sortVersions(collectVersions(repo))))
      if (!snap && latest)
        RootIndex(versioned / DocsPath / "home.html", repo / IndexHtml)
      if (snap || latest)
        linkSite(repo, v, if (snap) SnapshotPath else ReleasePath, s.log)
      s.log.info("Copied site to " + versioned)

      if (latest) {
        val (index, siteMaps) = SiteMap.generate(repo, sbtSiteBase, gzip = true, siteEntry(v), s.log)
        s.log.info(s"Generated site map index: $index")
        s.log.debug(s"Generated site maps: ${siteMaps.mkString("\n\t", "\n\t", "")}")
      }

      repo
  }
  def siteEntry(CurrentVersion: String)(file: File, relPath: String): Option[Entry] =
    {
      val apiOrSxr = """([^/]+)/(api|sxr)/.*""".r
      val docs = """([^/]+)/docs/.*""".r
      val old077 = """0\.7\.7/.*""".r
      val manualRedirects = """[^/]+\.html""".r
      val snapshot = """(.+-SNAPSHOT|snapshot)/.+/.*""".r
      // highest priority is the home page
      // X/docs/ are higher priority than X/(api|sxr)/
      // release/ is slighty higher priority than <releaseVersion>/
      // non-current releases are low priority
      // 0.7.7 documentation is very low priority
      // snapshots docs are very low priority
      // the manual redirects from the old version of the site have no priority at all
      relPath match {
        case "index.html"                => Some(Entry("weekly", 1.0))
        case docs(ReleasePath)           => Some(Entry("weekly", 0.9))
        case docs(CurrentVersion)        => Some(Entry("weekly", 0.8))
        case apiOrSxr(ReleasePath, _)    => Some(Entry("weekly", 0.6))
        case apiOrSxr(CurrentVersion, _) => Some(Entry("weekly", 0.5))
        case snapshot(_)                 => Some(Entry("weekly", 0.02))
        case old077()                    => Some(Entry("never", 0.01))
        case docs(_)                     => Some(Entry("never", 0.2))
        case apiOrSxr(_, _)              => Some(Entry("never", 0.1))
        case x                           => Some(Entry("never", 0.0))
      }
    }

  def versionsJs(vs: Seq[String]): String = "var availableDocumentationVersions = " + vs.mkString("['", "', '", "']")
  // names of all directories that are explicit versions
  def collectVersions(base: File): Seq[String] = (base * versionFilter).get.map(_.getName)
  def sortVersions(vs: Seq[String]): Seq[String] = vs.sortBy(versionComponents).reverse
  def versionComponents(v: String): Option[(Int, Int, Int, Option[String])] = {
    val m = VersionPattern.matcher(v)
    if (m.matches())
      Some((m.group(1).toInt, m.group(2).toInt, m.group(3).toInt, Option(m.group(4))))
    else
      None
  }
  def versionFilter = new PatternFilter(VersionPattern) && DirectoryFilter

  def linkSite(base: File, to: String, from: String, log: Logger) {
    val current = base / to
    assert(current.isDirectory, "Versioned site not present at " + current.getAbsolutePath)
    val symlinkDir = base / from
    symlinkDir.delete()
    symlink(path = to, file = symlinkDir, log = log)
  }

  // TODO: platform independence/use symlink from Java 7
  def symlink(path: String, file: File, log: Logger): Unit =
    "ln" :: "-s" :: path :: file.getAbsolutePath :: Nil ! log match {
      case 0    => ()
      case code => error("Could not create symbolic link '" + file.getAbsolutePath + "' with path " + path)
    }

  def setLatestRelease = Command.command("latest-release-docs") { state =>
    Project.extract(state).append((latestRelease in ThisBuild := true) :: Nil, state)
  }

}
object RootIndex {
  import Docs._
  import org.jsoup._

  def apply(versionIndex: File, to: File) {
    val doc = Jsoup.parse(versionIndex, "UTF-8")
    rewriteLinks(doc)
    removeSearch(doc)
    IO.write(to, doc.outerHtml)
  }
  def retargetIndexLink(original: String): String =
    if (isAbsolute(original) || original.startsWith("#"))
      original
    else
      ReleasePath + "/docs/" + original

  def isAbsolute(s: String): Boolean = (new java.net.URI(s)).isAbsolute

  def rewriteLinks(doc: nodes.Document) {
    rewriteLinks(doc, "*", "href")
    rewriteLinks(doc, "script", "src")
  }
  def rewriteLinks(doc: nodes.Document, elemName: String, attrName: String): Unit =
    for (elem <- select(doc, elemName + "[" + attrName + "]"))
      elem.attr(attrName, retargetIndexLink(elem.attr(attrName)))

  def removeSearch(doc: nodes.Document): Unit =
    doc.select(".search").remove()

  def select(doc: nodes.Document, s: String) =
    {
      import collection.JavaConverters._
      doc.select(s).iterator.asScala
    }
}


text:
"""Views for Gerrit.

This requires Django 0.97.pre.
"""

### Imports ###

# Python imports
import os
import cgi
import random
import re
import logging
import binascii
import datetime
import hashlib
import zlib
from xml.etree import ElementTree
from cStringIO import StringIO

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

# Django imports
# TODO(guido): Don't import classes/functions directly.
from django import forms
from django import http
from django.http import HttpResponse, HttpResponseRedirect
from django.http import HttpResponseForbidden, HttpResponseNotFound
from django.shortcuts import render_to_response
import django.template
from django.utils import simplejson
from django.forms import formsets

# Local imports
import changetable
from memcache import Key as MemCacheKey
import models
import email
import engine
import library
import patching
import fields
import project
import git_models
from view_util import *

### Constants ###

MAX_ROWS = 1000

CHANGE_TABLE_FIELDS = (changetable.FIELD_ID,
          changetable.FIELD_SUBJECT,
          changetable.FIELD_OWNER,
          changetable.FIELD_REVIEWERS,
          changetable.FIELD_PROJECT,
#            changetable.FIELD_BRANCH,
          changetable.FIELD_MODIFIED,
         )

CHANGE_TABLE_FIELDS_NO_PROJECT = (changetable.FIELD_ID,
          changetable.FIELD_SUBJECT,
          changetable.FIELD_OWNER,
          changetable.FIELD_REVIEWERS,
#            changetable.FIELD_BRANCH,
          changetable.FIELD_MODIFIED,
         )

### Helper functions ###

def _random_bytes(n):
  """Helper returning a string of random bytes of given length."""
  return ''.join(map(chr, (random.randrange(256) for i in xrange(n))))

### Request handlers ###

def index(request):
  """/ - Show a list of patches."""
  if request.user is None:
    return open_changes(request)
  else:
    return mine(request)

def hello(request):
  """/hello"""
  return HttpResponseRedirect('/settings/welcome?dest=/')
  #return respond(request, 'hello.html', {})

def all_changes(request):
    """Show all changes"""
    return _list_changes(request, 'SELECT * FROM Change'
                      ' ORDER BY modified DESC', 'All Changes')

def open_changes(request):
    """Show open changes"""
    return _list_changes(request, 'SELECT * FROM Change'
                      ' WHERE closed = FALSE'
                      ' ORDER BY modified DESC', 'Open Changes')

DEFAULT_LIMIT = 10

def _list_changes(request,query,title):
  """Show a list of changes specified by the query.
     DEFAULT_LIMIT changes are displayed per page unless
     the limit parameter is passed."""
  offset = request.GET.get('offset')
  if offset:
    try:
      offset = int(offset)
    except:
      offset = 0
    else:
      offset = max(0, offset)
  else:
    offset = 0
  limit = request.GET.get('limit')
  if limit:
    try:
      limit = int(limit)
    except:
      limit = DEFAULT_LIMIT
    else:
      limit = max(1, min(limit, 100))
  else:
    limit = DEFAULT_LIMIT
  query = db.GqlQuery(query)
  # Fetch one more to see if there should be a 'next' link
  changes = query.fetch(limit+1, offset)
  more = bool(changes[limit:])
  if more:
    del changes[limit:]
  if more:
    next = '?offset=%d&limit=%d' % (offset+limit, limit)
  else:
    next = ''
  if offset > 0:
    prev = '?offset=%d&limit=%d' % (max(0, offset-limit), limit)
  else:
    prev = ''
  newest = ''
  if offset > limit:
    newest = '?limit=%d' % limit

  _optimize_draft_counts(changes)
  _prefetch_names(changes)

  table = changetable.ChangeTable(request.user, CHANGE_TABLE_FIELDS)
  table.add_section(None, changes)

  return respond(request, 'list_changes.html', {
                    'changes': table.render(),
                    'title': title,
                    'limit': limit,
                    'newest': newest,
                    'prev': prev,
                    'next': next,
                    'first': offset+1,
                    'last': len(changes) > 1 and offset+len(changes) or None
                  })

def _optimize_draft_counts(changes):
  """Force _num_drafts to zero for changes that are known to have no drafts.

  Args:
    changes: list of model.Change instances.

  This inspects the drafts attribute of the current user's Account
  instance, and forces the draft count to zero of those changes in the
  list that aren't mentioned there.

  If there is no current user, all draft counts are forced to 0.
  """
  account = models.Account.current_user_account
  if account is None:
    change_ids = None
  else:
    change_ids = account.drafts
  for change in changes:
    if change_ids is None or change.key().id() not in change_ids:
      change._num_drafts = 0

def _prefetch_names(changes):
  for c in changes:
    library.prefetch_names([c.owner])
    library.prefetch_names(c.reviewers)
    library.prefetch_names(c.cc)

@login_required
def mine(request):
  """/mine - Show a list of changes created by the current user."""
  request.user_to_show = request.user
  return _show_user(request)

def all_unclaimed(request):
  flat_changes = models.gql(models.Change,
                          ' WHERE closed = FALSE'
                          '   AND claimed = FALSE'
                          ' ORDER BY dest_project DESC,'
                          '   modified DESC').fetch(1000)
  changes = changetable.ChangeTable(request.user,
      CHANGE_TABLE_FIELDS_NO_PROJECT)
  c_list = []
  last_project_key = None

  for c in flat_changes:
    k = c.dest_project.key()
    if k != last_project_key:
      if c_list:
        _optimize_draft_counts(c_list)
        _prefetch_names(c_list)
        changes.add_section(c_list[0].dest_project.name, c_list)
      last_project_key = k
      c_list = []
    c_list.append(c)

  if c_list:
    _optimize_draft_counts(c_list)
    _prefetch_names(c_list)
    changes.add_section(c_list[0].dest_project.name, c_list)
  vars = {
      'changes': changes.render(),
    }

  return respond(request, 'unclaimed.html', vars)

@login_required
def unclaimed(request):
  """/unclaimed - Show changes with no reviewer listed for
     user's selected projects.
  """
  changes = changetable.ChangeTable(request.user,
      CHANGE_TABLE_FIELDS_NO_PROJECT)

  for project in db.get(request.account.unclaimed_changes_projects):
    if project is None:
      continue
    c = models.gql(models.Change,
                          ' WHERE closed = FALSE'
                          '   AND claimed = FALSE'
                          '   AND dest_project = :dest_project'
                          ' ORDER BY modified DESC',
                          dest_project=project.key()).fetch(1000)
    if len(c) > 0:
      _optimize_draft_counts(c)
      _prefetch_names(c)
      changes.add_section(project.name, c)

  vars = {
      'changes': changes.render(),
    }

  return respond(request, 'unclaimed.html', vars)

@login_required
def starred(request):
  """/starred - Show a list of changes starred by the current user."""
  stars = models.Account.current_user_account.stars
  table = changetable.ChangeTable(request.user, CHANGE_TABLE_FIELDS)
  if stars:
    changes = [change for change in models.Change.get_by_id(stars)
                    if change is not None]
    _optimize_draft_counts(changes)
    _prefetch_names(changes)
    table.add_section(None, changes)
  return respond(request, 'starred.html', {'changes': table.render()})

@user_key_required
def show_user(request):
  """/user - Show the user's dashboard"""
  return _show_user(request)

def _respond_paged(request, template, new_pfx, old_pfx, vars):
  return respond(request, template, {
                 new_pfx + '_list': vars[old_pfx + '_list'],
                 new_pfx + '_opos': vars[old_pfx + '_opos'],
                 new_pfx + '_oend': vars[old_pfx + '_oend'],
                 new_pfx + '_prev': vars[old_pfx + '_prev'],
                 new_pfx + '_next': vars[old_pfx + '_next']
                 })

def _paginate(prefix, n, offset, q):
  list = q.fetch(n + 1, offset - 1)
  have = len(list)

  if have == n + 1:
    list = list[0:-1]
    have = n
    next = offset + n
    if next >= 1000:
      next = None
  else:
    next = None

  if offset == 0:
    prev = None
  else:
    prev = offset - n
    if prev < 0:
      prev = 0

  if next:
    last = next - 1
  else:
    last = offset + have - 1

  for i in list:
    i.paginate_row_type = prefix

  return {prefix + '_list': list,
          prefix + '_opos': offset,
          prefix + '_oend': last,
          prefix + '_prev': prev,
          prefix + '_next': next}

def _user_mine(user):
  r = models.gql(models.Change,
      'WHERE closed = FALSE AND owner = :1'
      ' ORDER BY modified DESC',
      user).fetch(1000)
  _optimize_draft_counts(r)
  _prefetch_names(r)
  return r

def _user_review(user):
  r = models.gql(models.Change,
      'WHERE closed = FALSE AND reviewers = :1'
      ' ORDER BY modified DESC',
      user.email()).fetch(1000)
  _optimize_draft_counts(r)
  _prefetch_names(r)
  return r

def _user_closed(user):
  r = models.gql(models.Change,
      'WHERE closed = TRUE AND owner = :1 AND modified > :2'
      ' ORDER BY modified DESC',
      user,
      datetime.datetime.now() - datetime.timedelta(days=7)
      ).fetch(15)
  _optimize_draft_counts(r)
  _prefetch_names(r)
  return r

def _show_user(request):
  user = request.user_to_show
  real_name = library.real_name(user)

  mine = _user_mine(user)
  review = _user_review(user)
  closed = _user_closed(user)

  changes = changetable.ChangeTable(request.user, CHANGE_TABLE_FIELDS)

  changes.add_section('Changes uploaded by %s' % real_name, mine)
  changes.add_section('Changes reviewable by %s' % real_name, review)
  changes.add_section('Recently closed changes', closed)

  vars = {
      'email': user.email(),
      'changes': changes.render(),
    }

  return respond(request, 'user.html', vars)

def _get_emails(form, label):
  """Helper to return the list of reviewers, or None for error."""
  emails = []
  raw_emails = form.cleaned_data.get(label)
  if raw_emails:
    for email in raw_emails.split(','):
      email = email.strip().lower()
      if email and email not in emails:
        try:
          email = db.Email(email)
          if email.count('@') != 1:
            raise db.BadValueError('Invalid email address: %s' % email)
          head, tail = email.split('@')
          if '.' not in tail:
            raise db.BadValueError('Invalid email address: %s' % email)
        except db.BadValueError, err:
          form.errors[label] = [unicode(err)]
          continue
        emails.append(email)
  return emails

def _prepare_show_patchset(user, patchset):
  if user:
    drafts = list(models.gql(models.Comment,
             'WHERE ANCESTOR IS :1'
             ' AND draft = TRUE'
             ' AND author = :2',
             patchset, user))
  else:
    drafts = []

  max_rows = 250
  if len(patchset.filenames) < max_rows:
    files = models.gql(models.Patch,
                       'WHERE patchset = :1 ORDER BY filename',
                        patchset).fetch(max_rows)
    patchset.n_comments = 0
    patchset.n_drafts = len(drafts)
    patchset.patches = files

    if drafts:
      p_bykey = dict()
      for p in patchset.patches:
        p_bykey[p.key()] = p
        p._num_drafts = 0
        patchset.n_comments += p.num_comments

      for d in drafts:
        if d.parent_key() in p_bykey:
          p = p_bykey[d.parent_key()]
          p._num_drafts += 1
    else:
      for p in patchset.patches:
          p._num_drafts = 0
  else:
    patchset.freaking_huge = True
    patchset.patches = []

def _restrict_lgtm(lgtm, can_approve):
  if not can_approve:
    if lgtm == 'lgtm':
      return 'yes'
    elif lgtm == 'reject':
      return 'no'
  return lgtm

def _restrict_verified(verified, can_verify):
  if can_verify:
    return verified
  else:
    return False

def _map_status(rs, real_approvers,
                    real_deniers,
                    real_verifiers,
                    known_owners,
                    known_approvers,
                    known_verifiers):
  email = rs.user.email()
  lgtm = _restrict_lgtm(rs.lgtm,
      (email in real_approvers) or (email in real_deniers))
  verified = _restrict_verified(rs.verified, email in real_verifiers)

  if email in known_owners:
    user_type = 'Project Lead'
  elif email in known_approvers:
    user_type = 'Approver'
  elif email in known_verifiers:
    user_type = 'Verifier'
  else:
    user_type = 'Contributor'

  return {
      'user': rs.user,
      'user_type' : user_type,
      'lgtm': lgtm,
      'verified': verified,
    }

@change_required
def show(request, form=None):
  """/<change> - Show a change."""
  change = request.change

  messages = list(change.message_set.order('date'))
  patchsets = list(change.patchset_set.order('id'))
  if not patchsets:
    return HttpResponse('No patchset available.')

  last_patchset = patchsets[-1]
  _prepare_show_patchset(request.user, last_patchset)

  if last_patchset.patches:
    first_patch = last_patchset.patches[0]
  else:
    first_patch = None

  dependencies_table = changetable.ChangeTable(request.user,
      CHANGE_TABLE_FIELDS_NO_PROJECT)
  depends_on = [ r.patchset.change
                 for r in last_patchset.revision.get_ancestors()
                 if r.patchset ]
  dependencies_table.add_section("Depends On", depends_on)
  needed_by  = [ r.patchset.change
                 for r in last_patchset.revision.get_children()
                 if r.patchset ]
  dependencies_table.add_section("Needed By", needed_by)

  # approvals
  review_status = change.get_review_status()
  reviewer_status = models.Change.get_reviewer_status(review_status)
  ready_to_submit = project.ready_to_submit(
      change.dest_branch,
      change.owner,
      reviewer_status,
      last_patchset.filenames,
      request.user)

  # if the owner can lgtm or verify, show her too
  author_status = {
      'lgtm': 'lgtm' if ready_to_submit['owner_auto_lgtm'] else 'abstain',
      'verified': ready_to_submit['owner_auto_verify']
    }

  show_dependencies = len(needed_by) > 0
  for c in depends_on:
    if not c.closed:
      show_dependencies = True
  if change.closed:
    show_dependencies = False

  can_submit = ready_to_submit['can_submit']
  if not last_patchset.complete:
    can_submit = False

  project_owners = set([u.email() for u in change.dest_project.leads()])
  project_approvers = set()
  project_verifiers = set()

  for ar in change.dest_project.get_code_reviews():
    for u in ar.approvers():
      project_approvers.add(u.email())
    for u in ar.verifiers():
      project_verifiers.add(u.email())

  real_approvers = ready_to_submit['real_approvers']
  real_deniers = ready_to_submit['real_deniers']
  real_verifiers = ready_to_submit['real_verifiers']

  real_review_status = [
      _map_status(rs,
                  real_approvers,
                  real_deniers,
                  real_verifiers,
                  project_owners,
                  project_approvers,
                  project_verifiers)
      for rs in review_status]
  reviewers = [rs.user.email() for rs in review_status]

  show_submit_button = (not change.is_submitted) and can_submit

  show_edit_reviewers_button = (request.user
          and (request.user_is_admin or request.user.email() in project_owners))
  show_add_reviewers_button = request.user and not show_edit_reviewers_button
  reviewers_url = '/%s/reviewers' % change.key().id()
  show_remove_self_button = request.user and request.user.email() in reviewers
  remove_self_url = '/%s/remove_me' % change.key().id()
  show_delete_button = change.user_can_edit()
  delete_url = '/%s/delete' % change.key().id()
  show_more_options = (show_remove_self_button or show_delete_button
                       or show_edit_reviewers_button
                       or show_add_reviewers_button)

  _prefetch_names([change])
  _prefetch_names(depends_on)
  _prefetch_names(needed_by)
  library.prefetch_names(map(lambda s: s.user, review_status))

  return respond(request, 'change.html', {
                  'change': change,
                  'ready_to_submit': can_submit,
                  'show_submit_button': show_submit_button,
                  'is_approved': ready_to_submit['approved'],
                  'is_rejected': ready_to_submit['denied'],
                  'is_verified': ready_to_submit['verified'],
                  'author_status': author_status,
                  'review_status': real_review_status,
                  'dependencies_table': dependencies_table.render(),
                  'show_dependencies': show_dependencies,
                  'patchsets': patchsets,
                  'messages': messages,
                  'last_patchset': last_patchset,
                  'first_patch': first_patch,
                  'reply_url': '/%s/publish' % change.key().id(),
                  'merge_url': '/%s/merge/%s' % (change.key().id(),
                                                 last_patchset.key().id()),
                  'show_remove_self_button': show_remove_self_button,
                  'remove_self_url': remove_self_url,
                  'show_edit_reviewers_button': show_edit_reviewers_button,
                  'show_add_reviewers_button': show_add_reviewers_button,
                  'reviewers_url': reviewers_url,
                  'show_delete_button': show_delete_button,
                  'delete_url': delete_url,
                  'show_more_options': show_more_options,
                })

@patchset_required
def ajax_patchset(request):
  """/<change>/ajax_patchset/<ps> - Format one patchset."""
  change = request.change
  patchset = request.patchset

  _prepare_show_patchset(request.user, patchset)
  return respond(request, 'patchset.html',
                 {'change' : request.change,
                  'patchset' : request.patchset
                 })

def revision_redirect(request, hash):
  """/r/<hash> - Redirect to a Change for this git revision, if we can."""
  hash = hash.lower()
  if len(hash) < 40:
    q = models.gql(models.RevisionId,
                   "WHERE id > :1 AND id < :2",
                   hash, hash.ljust(40, 'z'))
  else:
    q = models.gql(models.RevisionId, "WHERE id=:1", hash)
  revs = q.fetch(2)
  count = len(revs)

  if count == 1:
    rev_id = revs[0]
    if rev_id.patchset:
      return HttpResponseRedirect('/%s' % rev_id.patchset.change.key().id())
    else:
      return respond(request, 'change_revision_unknown.html', { 'hash': hash })

  if count > 0:
    return http.HttpResponseServerError("error 500: multiple matches for hash")

  if len(hash) < 40:
    q = models.gql(git_models.ReceivedBundle,
                   "WHERE contained_objects > :1"
                   "  AND contained_objects < :2",
                   hash, hash.ljust(40, 'z'))
  else:
    q = models.gql(git_models.ReceivedBundle,
                   "WHERE contained_objects=:1",
                   hash)
  rb = q.get()
  if rb:
    return respond(request, 'change_revision_uploading.html',
                   { 'hash': hash })
  else:
    return respond(request, 'change_revision_unknown.html',
                   { 'hash': hash },
                   status = 404)

@user_required
@change_required
@xsrf_required
def remove_me(request):
  change = request.change
  change.remove_reviewer(request.user)
  return HttpResponseRedirect('/%s' % change.key().id())

class ReviewersForm(BaseForm):
  _template = 'reviewers.html'

  reviewers = fields.UserGroupField(allow_users=True, allow_groups=False,
                                      sorted=False)
  message = forms.CharField(required=False,
                            max_length=10000,
                            widget=forms.Textarea(attrs={'cols': 60}))
  send_mail = forms.BooleanField(required=False)

  @classmethod
  def _get_reviewers(cls, change):
    rev = [users.User(email) for email in change.reviewers]
    reviewers = fields.UserGroupField.field_value_for_keys(users=rev)
    return reviewers

  @classmethod
  def _init(cls, state):
    (request,user,change,can_edit) = state
    if can_edit:
      reviewers = ReviewersForm._get_reviewers(change)
    else:
      reviewers = []
    return {
            'initial': {
              'send_mail': True,
              'reviewers': reviewers,
            },
          }

  def _post_init(self, state):
    (request,user,change,can_edit) = state
    read_only = [models.Account.get_account_for_user(change.owner)]
    if not can_edit:
      read_only = read_only +  ReviewersForm._get_reviewers(change)
    self.fields['reviewers'].widget.read_only = read_only

  def _save(self, cd, state):
    (request,user,change,can_edit) = state

    users = fields.UserGroupField.get_users(cd['reviewers'])
    old_review_status = change.get_review_status()

    def trans():
      if can_edit:
        new_users = set(users)
      else:
        new_users = set([rs.user for rs in old_review_status] + users)

      (added_review_status, deleted_review_status, new_review_status) = \
          library.update_reviewers(change, old_review_status, new_users)

      for rs in added_review_status:
        rs.put()
      for rs in deleted_review_status:
        rs.delete()
      change.put()

      return (added_review_status, deleted_review_status, new_review_status)

    (added_review_status,deleted_review_status,new_review_status) = \
        db.run_in_transaction(trans)

    if cd['send_mail']:
      to_users = [rs.user for rs in added_review_status if rs.user != user]
      library.send_new_change_emails(change, user, to_users, [],
          cd['message'] + '\n')

@login_required
@change_required
def reviewers(request):
  user = request.user
  change = request.change
  def done():
    return HttpResponseRedirect('/%s' % change.key().id())
  project_owners = set([u.email() for u in change.dest_project.leads()])
  can_edit = user and (request.user_is_admin or user.email() in project_owners)
  fixed_message = library.make_please_review_message(change,
      models.Account.current_user_account)
  return process_form(request, ReviewersForm, (request,user,change,can_edit),
      done, {
        'change': change,
        'can_edit': can_edit,
        'fixed_message': fixed_message,
      })

@change_owner_required
@xsrf_required
def delete(request):
  """/<change>/delete - Delete a change.  There is no way back."""
  change = request.change

  for ps in models.PatchSet.gql('WHERE ANCESTOR IS :1', change):
    for rev in models.RevisionId.get_for_patchset(ps):
      rev.patchset = None
      rev.put()

  tbd = []
  for cls in [models.Patch,
              models.PatchSet,
              models.PatchSetFilenames,
              models.Comment,
              models.Message,
              models.ReviewStatus]:
    tbd += cls.gql('WHERE ANCESTOR IS :1', change).fetch(50)
    if len(tbd) > 100:
      db.delete(tbd)
      return respond(request, 'delete_loop.html',
                     {'change': change,
                      'del_url': '/%s/delete' % id})

  tbd += [change]
  db.delete(tbd)
  return HttpResponseRedirect('/mine')

@xsrf_required
@patchset_required
def merge(request):
  """/<change>/merge/<patchset> - Submit a change for merge."""
  change = request.change
  patchset = request.patchset
  patchset.patches = list(patchset.patch_set.order('filename'))

  reviewer_status = models.Change.get_reviewer_status(
      change.get_review_status())
  ready_to_submit = project.ready_to_submit(
      change.dest_branch,
      change.owner,
      reviewer_status,
      patchset.filenames,
      request.user)

  if not ready_to_submit['can_submit']:
    # Again, the button shouldn't have been there in this case.
    # Just send 'em back to the change page.
    return HttpResponseRedirect('/%d' % change.key().id())

  try:
    change.submit_merge(patchset)
    change.put()
  except models.InvalidSubmitMergeException, why:
    return HttpResponseForbidden(str(why))
  return HttpResponseRedirect('/mine')

@patch_required
def patch(request):
  """/<change>/patch/<patchset>/<patch> - View a raw patch."""
  return patch_helper(request)

def patch_helper(request, nav_type='patch'):
  """Returns a unified diff.

  Args:
    request: Django Request object.
    nav_type: the navigation used in the url (i.e. patch/diff/diff2).  Normally
      the user looks at either unified or side-by-side diffs at one time, going
      through all the files in the same mode.  However, if side-by-side is not
      available for some files, we temporarly switch them to unified view, then
      switch them back when we can.  This way they don't miss any files.

  Returns:
    Whatever respond() returns.
  """
  _add_next_prev(request.patchset, request.patch)
  request.patch.nav_type = nav_type
  parsed_lines = patching.ParsePatchToLines(request.patch.patch_lines,
                                            request.patch.multi_way_diff)
  if parsed_lines is None:
    return HttpResponseNotFound('Can\'t parse the patch')
  rows = engine.RenderUnifiedTableRows(request, parsed_lines)
  return respond(request, 'patch.html',
                 {'patch': request.patch,
                  'patchset': request.patchset,
                  'rows': rows,
                  'change': request.change})

def _get_context_for_user(request):
  """Returns the context setting for a user.

  The value is validated against models.CONTEXT_CHOICES.
  If an invalid value is found, the value is overwritten with
  models.DEFAULT_CONTEXT.
  """
  if request.user:
    account = models.Account.current_user_account
    default_context = account.default_context
  else:
    default_context = models.DEFAULT_CONTEXT
  try:
    context = int(request.GET.get("context", default_context))
  except ValueError:
    context = default_context
  if context not in models.CONTEXT_CHOICES:
    context = models.DEFAULT_CONTEXT
  return context

@patch_required
def diff(request):
  """/<change>/diff/<patchset>/<patch> - View a patch as a side-by-side diff"""
  patchset = request.patchset
  patch = request.patch

  context = _get_context_for_user(request)
  rows = _get_diff_table_rows(request, patch, context)
  if isinstance(rows, HttpResponse):
    return rows

  _add_next_prev(patchset, patch)
  return respond(request, 'diff.html',
                 {'change': request.change, 'patchset': patchset,
                  'patch': patch, 'rows': rows,
                  'context': context, 'context_values': models.CONTEXT_CHOICES})

def _get_diff_table_rows(request, patch, context):
  """Helper function that returns rendered rows for a patch"""
  chunks = patching.ParsePatchToChunks(patch.patch_lines,
                                       patch.filename)
  if chunks is None:
    # If the patch has nothing in it, try using the
    # unified diff patch view instead as then we can
    # at least see the patch in the UI.
    #
    return HttpResponseRedirect('/%d/patch/%d/%s' % (
             patch.patchset.change.key().id(),
             patch.patchset.key().id(),
             patch.id))

  return list(engine.RenderDiffTableRows(request, patch.old_lines,
                                         chunks, patch,
                                         context=context))

@patch_required
def diff_skipped_lines(request, id_before, id_after, where):
  """/<change>/diff/<patchset>/<patch> - Returns a fragment of skipped lines"""
  patchset = request.patchset
  patch = request.patch

  # TODO: allow context = None?
  rows = _get_diff_table_rows(request, patch, 10000)
  if isinstance(rows, HttpResponse):
    return rows
  return _get_skipped_lines_response(rows, id_before, id_after, where)

def _get_skipped_lines_response(rows, id_before, id_after, where):
  """Helper function that creates a Response object for skipped lines"""
  response_rows = []
  id_before = int(id_before)
  id_after = int(id_after)

  if where == "b":
    rows.reverse()

  for row in rows:
    m = re.match('^<tr( name="hook")? id="pair-(?P<rowcount>\d+)">', row)
    if m:
      curr_id = int(m.groupdict().get("rowcount"))
      if curr_id < id_before or curr_id > id_after:
        continue
      if where  == "b" and curr_id <= id_after:
        response_rows.append(row)
      elif where == "t" and curr_id >= id_before:
        response_rows.append(row)
      if len(response_rows) >= 10:
        break

  # Create a usable structure for the JS part
  response = []
  content = '<div>%s</div>' % "".join(response_rows)
  content = content.replace('»', '&raquo;')
  dom = ElementTree.parse(StringIO(content))
  for node in dom.getroot().getchildren():
    content = "\n".join([ElementTree.tostring(x) for x in node.getchildren()])
    content = content.replace('&raquo;', '»')
    response.append([node.items(), content])
  return HttpResponse(simplejson.dumps(response))

def _get_diff2_data(request, ps_left_id, ps_right_id, patch_id, context):
  """Helper function that returns objects for diff2 views"""
  ps_left = models.PatchSet.get_by_id(int(ps_left_id), parent=request.change)
  if ps_left is None:
    return HttpResponseNotFound('No patch set exists with that id (%s)' %
                                ps_left_id)
  ps_left.change = request.change
  ps_right = models.PatchSet.get_by_id(int(ps_right_id), parent=request.change)
  if ps_right is None:
    return HttpResponseNotFound('No patch set exists with that id (%s)' %
                                ps_right_id)
  ps_right.change = request.change
  patch_right = models.Patch.get_patch(ps_right, patch_id)
  if patch_right is None:
    return HttpResponseNotFound('No patch exists with that id (%s/%s)' %
                                (ps_right_id, patch_id))
  patch_right.patchset = ps_right
  # Now find the corresponding patch in ps_left
  patch_left = models.Patch.gql('WHERE patchset = :1 AND filename = :2',
                                ps_left, patch_right.filename).get()
  if patch_left is None:
    return HttpResponseNotFound(
        "Patch set %s doesn't have a patch with filename %s" %
        (ps_left_id, patch_right.filename))

  rows = engine.RenderDiff2TableRows(request,
                                     patch_left.new_lines, patch_left,
                                     patch_right.new_lines, patch_right,
                                     context=context)
  rows = list(rows)
  if rows and rows[-1] is None:
    del rows[-1]

  return dict(patch_left=patch_left, ps_left=ps_left,
              patch_right=patch_right, ps_right=ps_right,
              rows=rows)

@change_required
def diff2(request, ps_left_id, ps_right_id, patch_id):
  """/<change>/diff2/... - View the delta between two different patch sets."""
  context = _get_context_for_user(request)
  data = _get_diff2_data(request, ps_left_id, ps_right_id, patch_id, context)
  if isinstance(data, HttpResponseNotFound):
    return data

  _add_next_prev(data["ps_right"], data["patch_right"])
  return respond(request, 'diff2.html',
                 {'change': request.change,
                  'ps_left': data["ps_left"],
                  'patch_left': data["patch_left"],
                  'ps_right': data["ps_right"],
                  'patch_right': data["patch_right"],
                  'rows': data["rows"],
                  'patch_id': patch_id,
                  'context': context,
                  'context_values': models.CONTEXT_CHOICES,
                  })

@change_required
def diff2_skipped_lines(request, ps_left_id, ps_right_id, patch_id,
                        id_before, id_after, where):
  """/<change>/diff2/... - Returns a fragment of skipped lines"""
  data = _get_diff2_data(request, ps_left_id, ps_right_id, patch_id, 10000)
  if isinstance(data, HttpResponseNotFound):
    return data
  return _get_skipped_lines_response(data["rows"], id_before, id_after, where)

def _add_next_prev(patchset, patch):
  """Helper to add .next and .prev attributes to a patch object."""
  patch.prev = patch.next = None
  patches = list(models.Patch.gql("WHERE patchset = :1 ORDER BY filename",
                                  patchset))
  patchset.patches = patches  # Required to render the jump to select.
  last = None
  for p in patches:
    if last is not None:
      if p.filename == patch.filename:
        patch.prev = last
      elif last.filename == patch.filename:
        patch.next = p
        break
    last = p

def inline_draft(request):
  """/inline_draft - Ajax handler to submit an in-line draft comment.

  This wraps _inline_draft(); all exceptions are logged and cause an
  abbreviated response indicating something went wrong.
  """
  if request.method != 'POST':
    return HttpResponse("POST request required.", status=405)
  try:
    return _inline_draft(request)
  except Exception, err:
    s = ''
    for k,v in request.POST.iteritems():
      s += '\n%s=%s' % (k, v)
    return HttpResponse('<font color="red">'
                        'Please report error "%s".'
                        '</font>'
                        % err.__class__.__name__)

def _inline_draft(request):
  """Helper to submit an in-line draft comment.
  """
  # Don't use @login_required; JS doesn't understand redirects.
  if not request.user:
    return HttpResponse('<font color="red">Not logged in</font>')

  if not is_xsrf_ok(request):
    return HttpResponse('<font color="red">'
                        'Stale xsrf signature.<br />'
                        'Please reload the page and try again.'
                        '</font>')

  snapshot = request.POST.get('snapshot')
  assert snapshot in ('old', 'new'), repr(snapshot)
  left = (snapshot == 'old')
  side = request.POST.get('side')
  assert side in ('a', 'b'), repr(side)  # Display left (a) or right (b)
  change_id = int(request.POST['change'])
  change = models.Change.get_by_id(change_id)
  assert change  # XXX
  patchset_id = request.POST.get('patchset') or request.POST[side == 'a' and 'ps_left' or 'ps_right']
  patchset = models.PatchSet.get_by_id(int(patchset_id), parent=change)
  assert patchset  # XXX
  patch_id = request.POST.get('patch') or request.POST[side == 'a' and 'patch_left' or 'patch_right']
  patch = models.Patch.get_patch(patchset, patch_id)
  assert patch  # XXX
  text = request.POST.get('text')
  lineno = int(request.POST['lineno'])
  message_id = request.POST.get('message_id')
  comment = None
  if message_id:
    comment = models.Comment.get_by_key_name(message_id, parent=patch)
    if comment is None or not comment.draft or comment.author != request.user:
      comment = None
      message_id = None
  if not message_id:
    # Prefix with 'z' to avoid key names starting with digits.
    message_id = 'z' + binascii.hexlify(_random_bytes(16))

  if not text.rstrip():
    if comment is not None:
      assert comment.draft and comment.author == request.user
      comment.delete()  # Deletion
      comment = None
      # Re-query the comment count.
      models.Account.current_user_account.update_drafts(change)
  else:
    if comment is None:
      comment = models.Comment(
                  patch=patch,
                  key_name=message_id,
                  parent=patch)
    comment.lineno = lineno
    comment.left = left
    comment.author = request.user
    comment.text = db.Text(text)
    comment.message_id = message_id
    comment.put()
    # The actual count doesn't matter, just that there's at least one.
    models.Account.current_user_account.update_drafts(change, 1)

  query = models.Comment.gql(
      'WHERE patch = :patch AND lineno = :lineno AND left = :left '
      'ORDER BY date',
      patch=patch, lineno=lineno, left=left)
  comments = list(c for c in query if not c.draft or c.author == request.user)
  if comment is not None and comment.author is None:
    # Show anonymous draft even though we don't save it
    comments.append(comment)
  if not comments:
    return HttpResponse(' ')
  for c in comments:
    c.complete(patch)
  return render_to_response('inline_comment.html',
                            {'inline_draft_url': '/inline_draft',
                             'user': request.user,
                             'patch': patch,
                             'patchset': patchset,
                             'change': change,
                             'comments': comments,
                             'lineno': lineno,
                             'snapshot': snapshot,
                             'side': side})

class PublishCommentsForm(BaseForm):
  _template = 'publish.html'

  reviewers = forms.CharField(required=False,
                              max_length=1000,
                              widget=fields.ReadOnlyTextWidget())
  cc = forms.CharField(required=False,
                       max_length=1000,
                       label = 'CC',
                       widget=forms.TextInput(attrs={'size': 60}))
  send_mail = forms.BooleanField(required=False)
  message = forms.CharField(required=False,
                            max_length=10000,
                            widget=forms.Textarea(attrs={'cols': 60}))

  lgtm = forms.CharField(required=False, label='Code review')
  verified = forms.BooleanField(required=False,
                                label='Verified')
  abandoned = forms.BooleanField(required=False,
                                label='Abandoned')

  def __init__(self, *args, **kwargs):
    is_initial = kwargs.pop('is_initial', False)
    self.user_can_approve = kwargs.pop('user_can_approve', False)
    self.user_can_verify = kwargs.pop('user_can_verify', False)
    self.user_is_owner = kwargs.pop('user_is_owner', False)
    self.user_can_abandon = kwargs.pop('user_can_abandon', False)

    BaseForm.__init__(self, *args, **kwargs)

    if is_initial:
      # only show the available lgtm options
      lgtm_field = self.fields.get("lgtm")
      if lgtm_field:
        if self.user_can_approve:
          lgtm_field.widget = forms.RadioSelect(choices=models.LGTM_CHOICES)
        else:
          lgtm_field.widget = forms.RadioSelect(
                 choices=models.LIMITED_LGTM_CHOICES)
      # only show verified if the user can do it
      if not self.user_can_verify:
        del self.fields['verified']

      # disable the abandon button if the user can't change it
      if not self.user_can_abandon:
        del self.fields['abandoned']
      self.is_abandoned = kwargs['initial'].get('is_abandoned', False)

  @classmethod
  def _init(cls, state):
    request, change = state
    user = request.user

    cc = list(change.cc)

    (user_can_approve,user_can_verify) = project.user_can_approve(
          request.user, change)

    # Pick the proper review / verify status
    review = change.get_review_status(user)
    if review:
      lgtm = _restrict_lgtm(review.lgtm, user_can_approve)
      verified = review.verified
    else:
      lgtm = 'abstain'
      verified = False

    user_can_abandon = change.user_can_edit() and not change.merged
    is_abandoned = change.closed and not change.merged

    reviewers = ', '.join(change.reviewers)

    return {'initial': {
              'cc': ', '.join(cc),
              'send_mail': True,
              'lgtm': lgtm,
              'verified': verified,
              'abandoned': is_abandoned,
              'reviewers': reviewers,
              },
            'user_can_approve': user_can_approve,
            'user_can_verify': user_can_verify,
            'user_is_owner': user == change.owner,
            'user_can_abandon': user_can_abandon,
            'is_initial': True,
          }

  def _save(self, cd, state):
    request, change = state
    user = request.user

    tbd, comments = _get_draft_comments(request, change)
    cc = _get_emails(self, 'cc')
    (self.user_can_approve,self.user_can_verify) = project.user_can_approve(
          request.user, change)
    lgtm = _restrict_lgtm(cd.get('lgtm', 'abstain'), self.user_can_approve)
    verified = _restrict_verified(cd.get('verified', False),
          self.user_can_verify)

    if change.user_can_edit():
      if not change.merged:
        change.closed = cd['abandoned']

    if user != change.owner:
      # Owners shouldn't have their own review status as it
      # is implied that 'lgtm' and verified by them.
      review_status = _update_review_status(change,
                                            user,
                                            lgtm,
                                            verified)
      tbd.append(review_status)

    change.cc = cc
    change.update_comment_count(len(comments))

    msg = _make_comment_message(request, change, lgtm, verified,
                        cd['message'],
                        comments,
                        cd['send_mail'])
    if msg:
      tbd.append(msg)
    tbd.append(change)

    while tbd:
      db.put(tbd[:50])
      tbd = tbd[50:]
    models.Account.current_user_account.update_drafts(change, 0)

@change_required
@login_required
def publish(request):

  """ /<change>/publish - Publish draft comments and send mail."""
  change = request.change

  tbd, comments = _get_draft_comments(request, change, True)
  preview = _get_draft_details(request, comments)

  def done():
    return HttpResponseRedirect('/%s' % change.key().id())
  return process_form(request, PublishCommentsForm, (request, change), done,
                      {'change': change,
                       'preview' : preview})

def _update_review_status(change, user, lgtm, verified):
  """Creates / updates the ReviewStatus for a user, returns that object."""
  review = change.set_review_status(user)
  review.lgtm = lgtm
  review.verified = verified
  return review

def _encode_safely(s):
  """Helper to turn a unicode string into 8-bit bytes."""
  if isinstance(s, unicode):
    s = s.encode('utf-8')
  return s

def _get_draft_comments(request, change, preview=False):
  """Helper to return objects to put() and a list of draft comments.

  If preview is True, the list of objects to put() is empty to avoid changes
  to the datastore.

  Args:
    request: Django Request object.
    change: Change instance.
    preview: Preview flag (default: False).

  Returns:
    2-tuple (put_objects, comments).
  """
  comments = []
  tbd = []
  dps = dict()

  # XXX Should request all drafts for this change once, now we can.
  for patchset in change.patchset_set.order('id'):
    ps_comments = list(models.Comment.gql(
        'WHERE ANCESTOR IS :1 AND author = :2 AND draft = TRUE',
        patchset, request.user))
    if ps_comments:
      patches = dict((p.key(), p) for p in patchset.patch_set)
      for p in patches.itervalues():
        p.patchset = patchset
      for c in ps_comments:
        c.draft = False
        # XXX Using internal knowledge about db package: the key for
        # reference property foo is stored as _foo.
        pkey = getattr(c, '_patch', None)
        if pkey in patches:
          patch = patches[pkey]
          c.patch = patch
        if pkey not in dps:
          dps[pkey] = c.patch
        c.patch.update_comment_count(1)
      if not preview:
        tbd += ps_comments
      ps_comments.sort(key=lambda c: (c.patch.filename, not c.left,
                                      c.lineno, c.date))
      comments += ps_comments
  if not preview:
    tbd += dps.values()
  return tbd, comments

FILE_LINE = '======================================================================'
COMMENT_LINE = '------------------------------'

def _get_draft_details(request, comments):
  """Helper to display comments with context in the email message."""
  last_key = None
  output = []
  linecache = {}  # Maps (c.patch.filename, c.left) to list of lines
  for c in comments:
    if (c.patch.filename, c.left) != last_key:
      if not last_key is None:
        output.append('%s\n' % FILE_LINE)
      url = request.build_absolute_uri('/%d/diff/%d/%s' %
                                       (request.change.key().id(),
                                        c.patch.patchset.key().id(),
                                        c.patch.id))
      output.append('\n%s\n%s\nFile %s:' % (FILE_LINE, url, c.patch.filename))
      last_key = (c.patch.filename, c.left)
      patch = c.patch
      if c.left:
        linecache[last_key] = patch.old_lines
      else:
        linecache[last_key] = patch.new_lines
    file_lines = linecache.get(last_key, ())
    context = ''
    if 1 <= c.lineno <= len(file_lines):
      context = file_lines[c.lineno - 1].strip()
    url = request.build_absolute_uri('/%d/diff/%d/%s#%scode%d' %
                                     (request.change.key().id(),
                                      c.patch.patchset.key().id(),
                                      c.patch.id,
                                      c.left and "old" or "new",
                                      c.lineno))
    output.append('%s\nLine %d: %s\n%s'  % (COMMENT_LINE, c.lineno,
                                                context, c.text.rstrip()))
  if not last_key is None:
    output.append('%s\n' % FILE_LINE)
  return '\n'.join(output)

def _make_comment_message(request, change, lgtm, verified, message,
                  comments=None, send_mail=False):
  """Helper to create a Message instance and optionally send an email."""

  prefix = ''
  if len(lgtm):
    prefix = prefix + [y for (x,y) in models.LGTM_CHOICES
                       if x == lgtm][0] + '\n'
  if verified:
    prefix = prefix + 'Verified.\n'
  if prefix:
    prefix = prefix + '\n'

  message = message.replace('\r\n', '\n')
  message = prefix + message

  if comments:
    details = _get_draft_details(request, comments)
  else:
    details = ''

  template_args = {
      'message': message,
      'details': details,
    }

  return email.send_change_message(
                              request, change,
                              'mails/comment.txt', template_args, request.user,
                              send_mail, 'mails/comment-email.txt')

@xsrf_required
@posted_change_required
def star(request):
  account = models.Account.current_user_account
  if account.stars is None:
    account.stars = []
  id = request.change.key().id()
  if id not in account.stars:
    account.stars.append(id)
    account.put()
  return respond(request, 'change_star.html', {'change': request.change})

@xsrf_required
@posted_change_required
def unstar(request):
  account = models.Account.current_user_account
  if account.stars is None:
    account.stars = []
  id = request.change.key().id()
  if id in account.stars:
    account.stars[:] = [i for i in account.stars if i != id]
    account.put()
  return respond(request, 'change_star.html', {'change': request.change})

@gae_admin_required
def download_bundle(request, bundle_id, segment_id):
  """/download/bundle(\d+)_(\d+) - get a bundle segment"""
  rb = git_models.ReceivedBundle.get_by_id(int(bundle_id))
  if not rb:
    return HttpResponseNotFound('No bundle exists with that id (%s)' % bundle_id)
  seg = rb.get_segment(int(segment_id))
  if not seg:
    return HttpResponseNotFound('No segment %s in bundle %s' % (segment_id,bundle_id))
  return HttpResponse(seg.bundle_data,
                      content_type='application/x-git-bundle-segment')

### Administration ###

@project_owner_or_admin_required
def admin(request):
  """/admin - user & other settings"""
  return respond(request, 'admin.html', {})

@gae_admin_required
def admin_settings(request):
  settings = models.Settings.get_settings()
  return respond(request, 'admin_settings.html', {
            'settings': settings,
            'CUR_SCHEMA_VERSION': models.CUR_SCHEMA_VERSION,
            'from_email_test_xsrf': xsrf_for('/admin/settings/from_email_test')
          })

class AdminSettingsAnalyticsForm(BaseForm):
  _template = 'admin_settings_analytics.html'

  analytics = forms.CharField(required=False, max_length=20,
                              widget=forms.TextInput(attrs={'size': 20}))

  @classmethod
  def _init(cls, state):
    settings = models.Settings.get_settings()
    return {'initial': {
                'analytics': settings.analytics,
              }
            }

  def _save(self, cd, change):
    settings = models.Settings.get_settings()
    settings.analytics = cd['analytics']
    settings.put()

@gae_admin_required
def admin_settings_analytics(request):
  def done():
    return HttpResponseRedirect('/admin/settings')
  return process_form(request, AdminSettingsAnalyticsForm, None, done)

class AdminSettingsFromEmailForm(BaseForm):
  _template = 'admin_settings_from_email.html'

  from_email = forms.CharField(required=False,
                              max_length=60,
                              widget=forms.TextInput(attrs={'size': 60}))

  @classmethod
  def _init(cls, state):
    settings = models.Settings.get_settings()
    return {'initial': {
                'from_email': settings.from_email,
              }
            }

  def _save(self, cd, change):
    settings = models.Settings.get_settings()
    settings.from_email = cd['from_email']
    settings.put()

@gae_admin_required
def admin_settings_from_email(request):
  def done():
    return HttpResponseRedirect('/admin/settings')
  return process_form(request, AdminSettingsFromEmailForm, None, done)

class AdminSettingsMergeLogEmailForm(BaseForm):
  _template = 'admin_settings_merge_log_email.html'

  merge_log_email = forms.CharField(required=False,
                                    max_length=60,
                                    widget=forms.TextInput(attrs={'size': 60}))

  @classmethod
  def _init(cls, state):
    settings = models.Settings.get_settings()
    return {'initial': {
                'merge_log_email': settings.merge_log_email,
              }
            }

  def _save(self, cd, change):
    settings = models.Settings.get_settings()
    settings.merge_log_email = cd['merge_log_email']
    settings.put()

@gae_admin_required
def admin_settings_merge_log_email(request):
  def done():
    return HttpResponseRedirect('/admin/settings')
  return process_form(request,
                      AdminSettingsMergeLogEmailForm,
                      None,
                      done)

class AdminSettingsCanonicalUrlForm(BaseForm):
  _template = 'admin_settings_canonical_url.html'

  url = forms.CharField(required=True)

  @classmethod
  def _init(cls, state):
    settings = models.Settings.get_settings()
    return {'initial': {
                'url': settings.canonical_url,
              }
            }

  def _save(self, cd, change):
    settings = models.Settings.get_settings()
    settings.canonical_url = cd['url']
    settings.put()

@gae_admin_required
def admin_settings_canonical_url(request):
  def done():
    return HttpResponseRedirect('/admin/settings')
  return process_form(request, AdminSettingsCanonicalUrlForm, None, done)

class AdminSettingsSourceBrowserUrlForm(BaseForm):
  _template = 'admin_settings_source_browser_url.html'

  url = forms.CharField(required=True,
                        widget=forms.TextInput(attrs={'size': 60}))

  @classmethod
  def _init(cls, state):
    settings = models.Settings.get_settings()
    return {'initial': {
                'url': settings.source_browser_url,
              }
            }

  def _save(self, cd, change):
    settings = models.Settings.get_settings()
    settings.source_browser_url = cd['url']
    settings.put()

@gae_admin_required
def admin_settings_source_browser_url(request):
  def done():
    return HttpResponseRedirect('/admin/settings')
  return process_form(request, AdminSettingsSourceBrowserUrlForm, None, done)

@gae_admin_required
def admin_settings_from_email_test(request):
  if request.method == 'POST':
    if is_xsrf_ok(request, xsrf=request.POST.get('xsrf')):
      address = email.get_default_sender()
      try:
        mail.check_email_valid(address, 'blah')
        email.send(None, [models.Account.current_user_account], 'test',
                              'mails/from_email_test.txt', None)
        status = 'email sent'
      except mail.InvalidEmailError:
        status = 'invalid email address'
      return respond(request, 'admin_settings_from_email_test.html', {
                  'status': status,
                  'address': address
                })
  return HttpResponse('<font color="red">Ich don\'t think so!</font>')

### User Profiles ###

def validate_real_name(real_name):
  """Returns None if real_name is fine and an error message otherwise."""
  if not real_name:
    return 'Name cannot be empty.'
  elif real_name == 'me':
    return 'Of course, you are what you are.  But \'me\' is for everyone.'
  else:
    return None

@user_key_required
def user_popup(request):
  """/user_popup - Pop up to show the user info."""
  try:
    user = request.user_to_show
    def gen():
      account = models.Account.get_account_for_user(user)
      return render_to_response('user_popup.html', {'account': account})
    return MemCacheKey('user_popup:' + user.email(), 300).get(gen)
  except Exception, err:
    return HttpResponse(
      '<font color="red">Error: %s; please report!</font>'
      % err.__class__.__name__)

class AdminDataStoreDeleteForm(BaseForm):
  _template = 'admin_datastore_delete.html'

  really = forms.CharField(required=True)

  def _save(self, cd, request):
    if cd['really'] != 'DELETE EVERYTHING':
      return self

    max_cnt = 50
    rm = []
    specials = []
    for cls in [models.ApprovalRight,
                models.Project,
                models.Branch,
                models.RevisionId,
                models.BuildAttempt,
                models.Change,
                models.PatchSetFilenames,
                models.PatchSet,
                models.Message,
                models.DeltaContent,
                models.Patch,
                models.Comment,
                models.Bucket,
                models.ReviewStatus,
                models.Account,
                models.AccountGroup,
                git_models.ReceivedBundleSegment,
                git_models.ReceivedBundle,
               ]:
      all = cls.all().fetch(max_cnt)
      if cls == models.Account:
        for a in all:
          if a.key() == request.account.key():
            specials.append(a)
          else:
            rm.append(a)
      elif cls == models.AccountGroup:
        for a in all:
          if a.is_auto_group:
            specials.append(a)
          else:
            rm.append(a)
      else:
        rm.extend(all)
      if len(rm) >= max_cnt:
        break

    if rm:
      # Delete this block of data and continue via
      # a JavaScript reload in the browser.
      #
      db.delete(rm)
      return self

    # We are done with the bulk of the content, but we need
    # to clean up a few special objects.
    #
    library._user_cache.clear()
    models.Settings._Key.clear()

    specials.extend(models.Settings.all().fetch(100))
    db.delete(specials)
    return None

@gae_admin_required
def admin_datastore_delete(request):
  def done():
    return HttpResponseRedirect('/')
  return process_form(request, AdminDataStoreDeleteForm, request, done)

class AdminDataStoreUpgradeForm(BaseForm):
  _template = 'admin_datastore_upgrade.html'

  really = forms.CharField(required=True)
  stage = forms.IntegerField(widget=forms.HiddenInput(), initial=1)

  def _save(self, cd, request):
    if cd['really'] != 'UPGRADE':
      return self

    stage = cd['stage']
    s = models.Settings.get_settings()
    name = '_upgrade%d_stage%d' % (s.schema_version, stage)
    try:
      f = getattr(self, name)
    except AttributeError:
      return http.HttpResponseServerError("no %s" % name)

    if not f():
      # This stage function needs to run again.
      #
      return self

    name = '_upgrade%d_stage%d' % (s.schema_version, stage + 1)
    if getattr(self, name, None):
      # There is another stage function in this version.
      #
      new_cd = dict(cd)
      new_cd['stage'] = stage + 1
      return self.__class__(initial=new_cd)

    # The current schema version is completely upgraded.
    #
    s.schema_version += 1
    s.put()

    name = '_upgrade%d_stage%d' % (s.schema_version, 1)
    if getattr(self, name, None):
      # There is another upgrade to execute.
      #
      new_cd = dict(cd)
      new_cd['stage'] = 1
      return self.__class__(initial=new_cd)

    # There are no further upgrades to process.
    #
    return None

  def _upgrade0_stage1(self):
    all = models.gql(models.ApprovalRight,
                     'WHERE last_backed_up = :1',
                     0).fetch(25)
    if not all:
      return True

    sb = models.AccountGroup.get_group_for_name('submitters')
    for ar in all:
      ar.last_backed_up = 1
      ar.submitters_groups.append(sb.key())
      ar.put()
    return False

  def _upgrade0_stage2(self):
    all = models.gql(models.ApprovalRight,
                     'WHERE last_backed_up = :1',
                     1).fetch(25)
    if not all:
      return True

    for ar in all:
      ar.last_backed_up = 0
      ar.put()
    return False

@gae_admin_required
def admin_datastore_upgrade(request):
  def done():
    return HttpResponseRedirect('/')
  return process_form(request, AdminDataStoreUpgradeForm, request, done)


text:
package io.rtr.alchemy.models;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;

/**
 * Represents a possible user experience in an experiment
 */

public class Treatment implements Named {
    private final String name;
    private String description;

    public Treatment(String name) {
        this(name, null);
    }

    public Treatment(String name, String description) {
        this.name = name;
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(name);
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Treatment)) {
            return false;
        }

        final Treatment other = (Treatment) obj;
        return
            Objects.equal(name, other.name);
    }

    @Override
    public String toString() {
        return
            MoreObjects
                .toStringHelper(this)
                .add("name", name)
                .add("description", description)
                .toString();
    }
}


text:
package magefortress.jobs.mining;

import magefortress.core.MFGameObjectFactory;
import magefortress.creatures.MFCreature;
import magefortress.creatures.behavior.instrumentable.MFEJob;
import magefortress.items.MFItem;
import magefortress.jobs.subtasks.MFSubtask;
import magefortress.jobs.subtasks.MFSubtaskCanceledException;
import magefortress.map.MFMap;
import magefortress.map.ground.MFGround;

/**
 * Mines for ore/stones/gems at the present location of the owner.
 */
public class MFMineSubtask extends MFSubtask
{
  public MFMineSubtask(MFCreature _owner, MFMap _map, MFGameObjectFactory _gameObjectFactory)
  {
    super(_owner);
    validateConstructorParams(_map, _owner, _gameObjectFactory);
    this.map = _map;
    this.ground = this.map.getTile(this.getOwner().getLocation()).getGround();
    this.gameObjectFactory = _gameObjectFactory;
  }

  //---vvv---     SUBTASK METHODS       ---vvv---
  @Override
  public boolean update() throws MFSubtaskCanceledException
  {
    boolean result = false;

    if (this.ticksLeft == 0) {
      this.ticksLeft = this.calculateMiningTime();
    } else if (this.ticksLeft == 1) {
      getStone();
      gainExperience();
      result = true;
    } else {
      --ticksLeft;
    }

    return result;
  }

  //---vvv---      PRIVATE METHODS      ---vvv---
  private static final MFEJob JOB_SKILL_USED = MFEJob.DIGGING;
  private static final int MIN_DIGGING_TIME  = 10;

  private final MFMap map;
  private final MFGround ground;
  private final MFGameObjectFactory gameObjectFactory;

  private int ticksLeft;

  /**
   * Calculates the time it will take the creature to dig out the tile. Takes
   * the stone's hardness and the miner's skill into account.
   * @return The time left in ticks until the tile is dug out
   */
  private int calculateMiningTime()
  {
    final int hardness = this.ground.getHardness();
    final int jobSkill = this.getOwner().getJobSkill(JOB_SKILL_USED);

    int result = MIN_DIGGING_TIME;
    result += Math.max(0, hardness-jobSkill);

    return result;
  }

  /**
   * Creates an item according to the blueprint received from the ground, puts
   * it on the floor, and lets the creature pick it up.
   */
  private void getStone()
  {
    MFItem stone = this.gameObjectFactory.createItem(this.ground.getBlueprint());
    this.map.getTile(this.getOwner().getLocation()).setObject(stone);
    this.getOwner().pickup();
  }

  /**
   * Awards the mining creature with experience. The harder the stone,
   * the higher the reward.
   */
  private void gainExperience()
  {
    final int xp = (int) Math.ceil(this.ground.getHardness() / 100);
    this.getOwner().gainJobExperience(JOB_SKILL_USED, xp);
  }

  private void validateConstructorParams(MFMap _map, MFCreature _owner,
                                         MFGameObjectFactory _gameObjectFactory)
  {
    if (_map == null) {
      String msg = this.getClass().getSimpleName() + ": Cannot create " +
                                                               "without a map.";
      logger.severe(msg);
      throw new IllegalArgumentException(msg);
    }
    if (!_owner.canHold()) {
      String msg = this.getClass().getSimpleName() + ": Cannot create " +
                                       "with a creature unable to carry items.";
      logger.severe(msg);
      throw new IllegalArgumentException(msg);
    }
    if (!_owner.canUseTools()) {
      String msg = this.getClass().getSimpleName() + ": Cannot create " +
                                         "with a creature unable to use tools.";
      logger.severe(msg);
      throw new IllegalArgumentException(msg);
    }
    if (_owner.getJobSkill(JOB_SKILL_USED) < 1) {
      String msg = this.getClass().getSimpleName() + ": Cannot create " +
                                              "with a creature unable to mine.";
      logger.severe(msg);
      throw new IllegalArgumentException(msg);
    }
    if (_gameObjectFactory == null) {
      String msg = this.getClass().getSimpleName() + ": Cannot create " +
                                               "without a game object factory.";
      logger.severe(msg);
      throw new IllegalArgumentException(msg);
    }
  }

}


text:
<?php

// abstract class

abstract class App_Model_Mapper_Abstract
{
    private $_dbTable;
    private $_dbModel;
    private $_model;

    public function __call($methodName, $args)
    {
        $className = get_class($this);

        try {
            if (method_exists($this->getModel(), $methodName)) {
                return call_user_func_array(array($this->getModel(), $methodName), $args);
            } else if (method_exists($this->getDbTable(), $methodName)) {
                return call_user_func_array(array($this->getDbTable(), $methodName), $args);
            } else {
                throw new Zend_Exception('The method ' . $methodName . '() was not implemented in <i>' . $className . '</i>');
            }
        } catch (Exception $e) {
            throw $e;
        }
    }

    public function setDbTable($dbTable)
    {
        if (is_string($dbTable)) {
            $dbTable = new $dbTable();
        }

        if (!$dbTable instanceof Zend_Db_Table_Abstract) {
            throw new Zend_Exception('Invalid table data gateway provided');
        }

        $this->_dbTable = $dbTable;
    }

    public function getDbTable()
    {
        if (null === $this->_dbTable) {
            $this->setDbTable('Application_Model_DbTable_' . $this->getModel());
        }

        return $this->_dbTable;
    }

    private function setDbModel($dbModel)
    {
        if (is_string($dbModel)) {
            $dbModel = new $dbModel();
        }

        $this->_dbModel = $dbModel;
    }

    private function getDbModel()
    {
        if (null === $this->_dbModel) {
            $this->setDbModel('Application_Model_' . $this->getModel());
        }

        return $this->_dbModel;
    }

    public function setModel($model)
    {
        $this->_model = $model;
    }

    public function getModel()
    {
        if (null === $this->_model) {
            $this->setModel('Abstract');
        }

        return $this->_model;
    }

    public function getDbPrimary()
    {
        $primaryKey = $this->getDbTable()->info('primary');

        return $primaryKey[1];
    }

    public function save($model)
    {
        $data = $model->toArray();

        if (0 == ($id = $model->getId())) {
            $this->insert($data);
        } else {
            $this->update($data, $id);
        }
    }

    public function insert($data)
    {
        $this->getDbTable()->insert($data);
    }

    public function update($data, $id)
    {
        $where = $this->getDbTable()->getAdapter()->quoteInto($this->getDbPrimary() . ' = ?', $id);

        $this->getDbTable()->update($data, $where);
    }

    public function delete($id)
    {
        $where = $this->getDbTable()->getAdapter()->quoteInto($this->getDbPrimary() . ' = ?', $id);

        $this->getDbTable()->delete($where);
    }

    public function find($id)
    {
        $result = $this->getDbTable()->find($id);
        if (count($result)) {
            return $this->getDbModel()->populate($result->current())->toArray();
        } else {
            throw new Zend_Controller_Action_Exception('This page does not exist', 404);
        }
    }

    public function fetchAll($select)
    {
        return $this->getDbTable()->fetchAll($select);
    }

}


text:
<?php

use SilverStripe\Dev\SapphireTest;

class CreatorLastEditorExtensionTest extends SapphireTest
{
    public function testOnBeforeWrite()
    {
        $this->markTestSkipped('TODO');
    }

    public function testUpdateCMSFields()
    {
        $this->markTestSkipped('TODO');
    }
}


text:
class RedirectOutputAppend : public Connector {
        string filename;
    public:
        RedirectOutputAppend();
        ~RedirectOutputAppend();
        RedirectOutputAppend(Cmd*, string);
        bool execute(bool);
        string getExecutable () {return "";};
};

#endif


text:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.UnitTests;
using Xunit;

namespace Microsoft.Build.Engine.UnitTests
{
    public sealed class WarningsAsMessagesAndErrorsTests
    {
        private const string ExpectedEventMessage = "03767942CDB147B98D0ECDBDE1436DA3";
        private const string ExpectedEventCode = "0BF68998";

        [Fact]
        public void TreatAllWarningsAsErrors()
        {
            MockLogger logger = ObjectModelHelpers.BuildProjectExpectFailure(GetTestProject(treatAllWarningsAsErrors: true));

            VerifyBuildErrorEvent(logger);

            ObjectModelHelpers.BuildProjectExpectSuccess(GetTestProject(treatAllWarningsAsErrors: false));
        }

        /// <summary>
        /// https://github.com/Microsoft/msbuild/issues/2667
        /// </summary>
        [Fact]
        public void TreatWarningsAsErrorsWhenBuildingSameProjectMultipleTimes()
        {
            using (TestEnvironment testEnvironment = TestEnvironment.Create())
            {
                TransientTestProjectWithFiles project2 = testEnvironment.CreateTestProjectWithFiles($@"
                <Project xmlns=""msbuildnamespace"">
                    <PropertyGroup>
                        <MSBuildWarningsAsErrors>{ExpectedEventCode}</MSBuildWarningsAsErrors>
                    </PropertyGroup>
                    <Target Name=""Build"">
                        <MSBuild Projects=""$(MSBuildThisFileFullPath)"" Targets=""AnotherTarget"" />
                    </Target>
                    <Target Name=""AnotherTarget"">
                        <Warning Text=""{ExpectedEventMessage}"" Code=""{ExpectedEventCode}"" />
                    </Target>
                </Project>");

                TransientTestProjectWithFiles project1 = testEnvironment.CreateTestProjectWithFiles($@"
                <Project xmlns=""msbuildnamespace"">
                    <Target Name=""Build"">
                        <MSBuild Projects=""{project2.ProjectFile}"" Targets=""Build"" />
                    </Target>
                </Project>");

                MockLogger logger = project1.BuildProjectExpectFailure();

                VerifyBuildErrorEvent(logger);
            }
        }

        [Fact]
        public void TreatWarningsAsErrorsWhenSpecified()
        {
            MockLogger logger = ObjectModelHelpers.BuildProjectExpectFailure(GetTestProject(warningsAsErrors: ExpectedEventCode));

            VerifyBuildErrorEvent(logger);
        }

        [Fact]
        public void TreatWarningsAsErrorsWhenSpecifiedIndirectly()
        {
            MockLogger logger = ObjectModelHelpers.BuildProjectExpectFailure(
                GetTestProject(
                    customProperties: new Dictionary<string, string>
                    {
                        {"Foo", "true"},
                        {"MSBuildTreatWarningsAsErrors", "$(Foo)"}
                    }));

            VerifyBuildErrorEvent(logger);
        }

        [Fact]
        public void TreatWarningsAsErrorsWhenSpecifiedThroughAdditiveProperty()
        {
            MockLogger logger = ObjectModelHelpers.BuildProjectExpectFailure(
                GetTestProject(
                    customProperties: new List<KeyValuePair<string, string>>
                    {
                        new KeyValuePair<string, string>("MSBuildWarningsAsErrors", "123"),
                        new KeyValuePair<string, string>("MSBuildWarningsAsErrors", $@"$(MSBuildWarningsAsErrors);
                                                                                {ExpectedEventCode.ToLowerInvariant()}"),
                        new KeyValuePair<string, string>("MSBuildWarningsAsErrors", "$(MSBuildWarningsAsErrors);ABC")
                    }));

            VerifyBuildErrorEvent(logger);
        }

        [Fact]
        public void NotTreatWarningsAsErrorsWhenCodeNotSpecified()
        {
            MockLogger logger = ObjectModelHelpers.BuildProjectExpectSuccess(
                GetTestProject(
                    customProperties: new List<KeyValuePair<string, string>>
                    {
                        new KeyValuePair<string, string>("MSBuildWarningsAsErrors", "123"),
                        new KeyValuePair<string, string>("MSBuildWarningsAsErrors", "$(MSBuildWarningsAsErrors);ABC")
                    }));

            VerifyBuildWarningEvent(logger);
        }

        [Fact]
        public void TreatWarningsAsMessagesWhenSpecified()
        {
            MockLogger logger = ObjectModelHelpers.BuildProjectExpectSuccess(GetTestProject(warningsAsMessages: ExpectedEventCode));

            VerifyBuildMessageEvent(logger);
        }

        /// <summary>
        /// https://github.com/Microsoft/msbuild/issues/2667
        /// </summary>
        [Fact]
        public void TreatWarningsAsMessagesWhenBuildingSameProjectMultipleTimes()
        {
            using (TestEnvironment testEnvironment = TestEnvironment.Create())
            {
                TransientTestProjectWithFiles project2 = testEnvironment.CreateTestProjectWithFiles($@"
                <Project xmlns=""msbuildnamespace"">
                    <PropertyGroup>
                        <MSBuildWarningsAsMessages>{ExpectedEventCode}</MSBuildWarningsAsMessages>
                    </PropertyGroup>
                    <Target Name=""Build"">
                        <MSBuild Projects=""$(MSBuildThisFileFullPath)"" Targets=""AnotherTarget"" />
                    </Target>
                    <Target Name=""AnotherTarget"">
                        <Warning Text=""{ExpectedEventMessage}"" Code=""{ExpectedEventCode}"" />
                    </Target>
                </Project>");

                TransientTestProjectWithFiles project1 = testEnvironment.CreateTestProjectWithFiles($@"
                <Project xmlns=""msbuildnamespace"">
                    <Target Name=""Build"">
                        <MSBuild Projects=""{project2.ProjectFile}"" Targets=""Build"" />
                    </Target>
                </Project>");

                MockLogger logger = project1.BuildProjectExpectSuccess();

                VerifyBuildMessageEvent(logger);
            }
        }

        [Fact]
        public void TreatWarningsAsMessagesWhenSpecifiedIndirectly()
        {
            MockLogger logger = ObjectModelHelpers.BuildProjectExpectSuccess(
                GetTestProject(
                    customProperties: new Dictionary<string, string>
                    {
                        {"Foo", ExpectedEventCode},
                    },
                    warningsAsMessages: "$(Foo)"
                )
            );

            VerifyBuildMessageEvent(logger);
        }

        [Fact]
        public void TreatWarningsAsMessagesWhenSpecifiedThroughAdditiveProperty()
        {
            MockLogger logger = ObjectModelHelpers.BuildProjectExpectSuccess(
                GetTestProject(
                    customProperties: new List<KeyValuePair<string, string>>
                    {
                        new KeyValuePair<string, string>("MSBuildWarningsAsMessages", "123"),
                        new KeyValuePair<string, string>("MSBuildWarningsAsMessages", $@"$(MSBuildWarningsAsMessages);
                                                                                {ExpectedEventCode.ToLowerInvariant()}"),
                        new KeyValuePair<string, string>("MSBuildWarningsAsMessages", "$(MSBuildWarningsAsMessages);ABC")
                    }));

            VerifyBuildMessageEvent(logger);
        }

        [Fact]
        public void NotTreatWarningsAsMessagesWhenCodeNotSpecified()
        {
            MockLogger logger = ObjectModelHelpers.BuildProjectExpectSuccess(
                GetTestProject(
                    customProperties: new List<KeyValuePair<string, string>>
                    {
                        new KeyValuePair<string, string>("MSBuildWarningsAsMessages", "123"),
                        new KeyValuePair<string, string>("MSBuildWarningsAsMessages", "$(MSBuildWarningsAsMessages);ABC")
                    }));

            VerifyBuildWarningEvent(logger);
        }

        [Fact]
        public void TreatWarningAsMessageOverridesTreatingItAsError()
        {
            MockLogger logger = ObjectModelHelpers.BuildProjectExpectSuccess(
                GetTestProject(
                    warningsAsMessages: ExpectedEventCode,
                    warningsAsErrors: ExpectedEventCode
                    ));

            VerifyBuildMessageEvent(logger);
        }

        private void VerifyBuildErrorEvent(MockLogger logger)
        {
            BuildErrorEventArgs actualEvent = logger.Errors.FirstOrDefault();

            Assert.NotNull(actualEvent);

            Assert.Equal(ExpectedEventMessage, actualEvent.Message);
            Assert.Equal(ExpectedEventCode, actualEvent.Code);

            logger.AssertNoWarnings();
        }

        private void VerifyBuildWarningEvent(MockLogger logger)
        {
            BuildWarningEventArgs actualEvent = logger.Warnings.FirstOrDefault();

            Assert.NotNull(actualEvent);

            Assert.Equal(ExpectedEventMessage, actualEvent.Message);
            Assert.Equal(ExpectedEventCode, actualEvent.Code);

            logger.AssertNoErrors();
        }

        private void VerifyBuildMessageEvent(MockLogger logger)
        {
            BuildMessageEventArgs actualEvent = logger.BuildMessageEvents.FirstOrDefault(i => i.Message.Equals(ExpectedEventMessage));

            Assert.NotNull(actualEvent);

            Assert.Equal(ExpectedEventCode, actualEvent.Code);

            logger.AssertNoErrors();
            logger.AssertNoWarnings();
        }

        private string GetTestProject(bool? treatAllWarningsAsErrors = null, string warningsAsErrors = null, string warningsAsMessages = null, ICollection<KeyValuePair<string, string>> customProperties = null)
        {
            return $@"
            <Project ToolsVersion=""msbuilddefaulttoolsversion"" xmlns=""msbuildnamespace"">
                <PropertyGroup>
                    {(customProperties != null ? String.Join(Environment.NewLine, customProperties.Select(i => $"<{i.Key}>{i.Value}</{i.Key}>")) : "")}
                    {(treatAllWarningsAsErrors.HasValue ? $"<MSBuildTreatWarningsAsErrors>{treatAllWarningsAsErrors.Value}</MSBuildTreatWarningsAsErrors>" : "")}
                    {(warningsAsErrors != null ? $"<MSBuildWarningsAsErrors>{warningsAsErrors}</MSBuildWarningsAsErrors>" : "")}
                    {(warningsAsMessages != null ? $"<MSBuildWarningsAsMessages>{warningsAsMessages}</MSBuildWarningsAsMessages>" : "")}
                </PropertyGroup>
                <Target Name='Build'>
                    <Message Text=""MSBuildTreatWarningsAsErrors: '$(MSBuildTreatWarningsAsErrors)' "" />
                    <Message Text=""MSBuildWarningsAsErrors: '$(MSBuildWarningsAsErrors)' "" />
                    <Message Text=""MSBuildWarningsAsMessages: '$(MSBuildWarningsAsMessages)' "" />
                    <Warning Text=""{ExpectedEventMessage}"" Code=""{ExpectedEventCode}"" />
                </Target>
            </Project>";
        }
    }
}