def ParsePatchToChunks(lines, name="<patch>"):
  lineno = 0
  raw_chunk = []
  chunks = []
  old_range = new_range = None
  old_last = new_last = 0
  in_prelude = True
  for line in lines:
    lineno += 1
    if in_prelude:
      # Skip leading lines until after we've seen one starting with '+++'
      if line.startswith("+++"):
        in_prelude = False
      continue
    match = _CHUNK_RE.match(line)
    if match:
      if raw_chunk:
        # Process the lines in the previous chunk
        old_chunk = []
        new_chunk = []
        for tag, rest in raw_chunk:
          if tag in (" ", "-"):
            old_chunk.append(rest)
          if tag in (" ", "+"):
            new_chunk.append(rest)
        # Check consistency
        old_i, old_j = old_range
        new_i, new_j = new_range
        if len(old_chunk) != old_j - old_i or len(new_chunk) != new_j - new_i:
          logging.warn("%s:%s: previous chunk has incorrect length",
                       name, lineno)
          return None
        chunks.append((old_range, new_range, old_chunk, new_chunk))
        raw_chunk = []
      # Parse the @@ header
      old_ln, old_n, new_ln, new_n = match.groups()
      old_ln, old_n, new_ln, new_n = map(long,
                                         (old_ln, old_n or 1,
                                          new_ln, new_n or 1))
      # Convert the numbers to list indices we can use
      if old_n == 0:
        old_i = old_ln
      else:
        old_i = old_ln - 1
      old_j = old_i + old_n
      old_range = old_i, old_j
      if new_n == 0:
        new_i = new_ln
      else:
        new_i = new_ln - 1
      new_j = new_i + new_n
      new_range = new_i, new_j
      # Check header consistency with previous header
      if old_i < old_last or new_i < new_last:
        logging.warn("%s:%s: chunk header out of order: %r",
                     name, lineno, line)
        return None
      if old_i - old_last != new_i - new_last:
        logging.warn("%s:%s: inconsistent chunk header: %r",
                     name, lineno, line)
        return None
      old_last = old_j
      new_last = new_j
    else:
      tag, rest = line[0], line[1:]
      if tag in (" ", "-", "+"):
        raw_chunk.append((tag, rest))
      elif line.startswith(_NO_NEWLINE_MESSAGE):
        # TODO(guido): need to check that no more lines follow for this file
        if raw_chunk:
          last_tag, last_rest = raw_chunk[-1]
          if last_rest.endswith("\n"):
            raw_chunk[-1] = (last_tag, last_rest[:-1])
      else:
        # Only log if it's a non-blank line.  Blank lines we see a lot.
        if line and line.strip():
          logging.warn("%s:%d: indecypherable input: %r", name, lineno, line)
        if chunks or raw_chunk:
          break  # Trailing garbage isn't so bad
        return None
  if raw_chunk:
    # Process the lines in the last chunk
    old_chunk = []
    new_chunk = []
    for tag, rest in raw_chunk:
      if tag in (" ", "-"):
        old_chunk.append(rest)
      if tag in (" ", "+"):
        new_chunk.append(rest)
    # Check consistency
    old_i, old_j = old_range
    new_i, new_j = new_range
    if len(old_chunk) != old_j - old_i or len(new_chunk) != new_j - new_i:
      print >> sys.stderr, ("%s:%s: last chunk has incorrect length" %
                            (name, lineno))
      return None
    chunks.append((old_range, new_range, old_chunk, new_chunk))
    raw_chunk = []
  return chunks
REMOTE_USER user Authentication
dataset/ETHPy150Open rietveld-codereview/rietveld/codereview/patching.py/ParsePatchToChunks--crossover with--dataset/ETHPy150Open dpgaspar/Flask-AppBuilder/flask_appbuilder/security/manager.py/BaseSecurityManager.auth_user_remote_user