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

import argparse
import sys

# Usage: post_process_props.py file.prop [disallowed_key, ...]
# Disallowed keys are removed from the property file, if present

# See PROP_VALUE_MAX in system_properties.h.
# The constant in system_properties.h includes the terminating NUL,
# so we decrease the value by 1 here.
PROP_VALUE_MAX = 91

# Put the modifications that you need to make into the */build.prop into this
# function.
def mangle_build_prop(prop_list):
  # If ro.debuggable is 1, then enable adb on USB by default
  # (this is for userdebug builds)
  if prop_list.get_value("ro.debuggable") == "1":
    val = prop_list.get_value("persist.sys.usb.config")
    if "adb" not in val:
      if val == "":
        val = "adb"
      else:
        val = val + ",adb"
      prop_list.put("persist.sys.usb.config", val)
  # UsbDeviceManager expects a value here.  If it doesn't get it, it will
  # default to "adb". That might not the right policy there, but it's better
  # to be explicit.
  if not prop_list.get_value("persist.sys.usb.config"):
    prop_list.put("persist.sys.usb.config", "none");

def validate(prop_list):
  """Validate the properties.

  If the value of a sysprop exceeds the max limit (91), it's an error, unless
  the sysprop is a read-only one.

  Checks if there is no optional prop assignments.

  Returns:
    True if nothing is wrong.
  """
  check_pass = True
  for p in prop_list.get_all_props():
    if len(p.value) > PROP_VALUE_MAX and not p.name.startswith("ro."):
      check_pass = False
      sys.stderr.write("error: %s cannot exceed %d bytes: " %
                       (p.name, PROP_VALUE_MAX))
      sys.stderr.write("%s (%d)\n" % (p.value, len(p.value)))

    if p.is_optional():
      check_pass = False
      sys.stderr.write("error: found unresolved optional prop assignment:\n")
      sys.stderr.write(str(p) + "\n")

  return check_pass

def override_optional_props(prop_list, allow_dup=False):
  """Override a?=b with a=c, if the latter exists

  Overriding is done by deleting a?=b
  When there are a?=b and a?=c, then only the last one survives
  When there are a=b and a=c, then it's an error.

  Returns:
    True if the override was successful
  """
  success = True
  for name in prop_list.get_all_names():
    props = prop_list.get_props(name)
    optional_props = [p for p in props if p.is_optional()]
    overriding_props = [p for p in props if not p.is_optional()]
    if len(overriding_props) > 1:
      # duplicated props are allowed when the all have the same value
      if all(overriding_props[0].value == p.value for p in overriding_props):
        for p in optional_props:
          p.delete("overridden by %s" % str(overriding_props[0]))
        continue
      # or if dup is explicitly allowed for compat reason
      if allow_dup:
        # this could left one or more optional props unresolved.
        # Convert them into non-optional because init doesn't understand ?=
        # syntax
        for p in optional_props:
          p.optional = False
        continue

      success = False
      sys.stderr.write("error: found duplicate sysprop assignments:\n")
      for p in overriding_props:
        sys.stderr.write("%s\n" % str(p))
    elif len(overriding_props) == 1:
      for p in optional_props:
        p.delete("overridden by %s" % str(overriding_props[0]))
    else:
      if len(optional_props) > 1:
        for p in optional_props[:-1]:
          p.delete("overridden by %s" % str(optional_props[-1]))
      # Make the last optional one as non-optional
      optional_props[-1].optional = False

  return success

class Prop:

  def __init__(self, name, value, optional=False, comment=None):
    self.name = name.strip()
    self.value = value.strip()
    if comment != None:
      self.comments = [comment]
    else:
      self.comments = []
    self.optional = optional

  @staticmethod
  def from_line(line):
    line = line.rstrip('\n')
    if line.startswith("#"):
      return Prop("", "", comment=line)
    elif "?=" in line:
      name, value = line.split("?=", 1)
      return Prop(name, value, optional=True)
    elif "=" in line:
      name, value = line.split("=", 1)
      return Prop(name, value, optional=False)
    else:
      # don't fail on invalid line
      # TODO(jiyong) make this a hard error
      return Prop("", "", comment=line)

  def is_comment(self):
    return bool(self.comments and not self.name)

  def is_optional(self):
    return (not self.is_comment()) and self.optional

  def make_as_comment(self):
    # Prepend "#" to the last line which is the prop assignment
    if not self.is_comment():
      assignment = str(self).rsplit("\n", 1)[-1]
      self.comments.append("#" + assignment)
      self.name = ""
      self.value = ""

  def delete(self, reason):
    self.comments.append("# Removed by post_process_props.py because " + reason)
    self.make_as_comment()

  def __str__(self):
    assignment = []
    if not self.is_comment():
      operator = "?=" if self.is_optional() else "="
      assignment.append(self.name + operator + self.value)
    return "\n".join(self.comments + assignment)

class PropList:

  def __init__(self, filename):
    with open(filename) as f:
      self.props = [Prop.from_line(l)
                    for l in f.readlines() if l.strip() != ""]

  def get_all_props(self):
    return [p for p in self.props if not p.is_comment()]

  def get_all_names(self):
    return set([p.name for p in self.get_all_props()])

  def get_props(self, name):
    return [p for p in self.get_all_props() if p.name == name]

  def get_value(self, name):
    # Caution: only the value of the first sysprop having the name is returned.
    return next((p.value for p in self.props if p.name == name), "")

  def put(self, name, value):
    # Note: when there is an optional prop for the name, its value isn't changed.
    # Instead a new non-optional prop is appended, which will override the
    # optional prop. Otherwise, the new value might be overridden by an existing
    # non-optional prop of the same name.
    index = next((i for i,p in enumerate(self.props)
                  if p.name == name and not p.is_optional()), -1)
    if index == -1:
      self.props.append(Prop(name, value,
                             comment="# Auto-added by post_process_props.py"))
    else:
      self.props[index].comments.append(
          "# Value overridden by post_process_props.py. Original value: %s" %
          self.props[index].value)
      self.props[index].value = value

  def write(self, filename):
    with open(filename, 'w+') as f:
      for p in self.props:
        f.write(str(p) + "\n")

def main(argv):
  parser = argparse.ArgumentParser(description="Post-process build.prop file")
  parser.add_argument("--allow-dup", dest="allow_dup", action="store_true",
                      default=False)
  parser.add_argument("filename")
  parser.add_argument("disallowed_keys", metavar="KEY", type=str, nargs="*")
  args = parser.parse_args()

  if not args.filename.endswith("/build.prop"):
    sys.stderr.write("bad command line: " + str(argv) + "\n")
    sys.exit(1)

  props = PropList(args.filename)
  mangle_build_prop(props)
  if not override_optional_props(props, args.allow_dup):
    sys.exit(1)
  if not validate(props):
    sys.exit(1)

  # Drop any disallowed keys
  for key in args.disallowed_keys:
    for p in props.get_props(key):
      p.delete("%s is a disallowed key" % key)

  props.write(args.filename)

if __name__ == "__main__":
  main(sys.argv)
