Unify the user image building code

Bug: 5398808

Before this change we have duplicate code in the Makefile and the
python-based releasetool. That's a real headache to maintain.

Change-Id: I8ddf04a79c6886540e89d990f723d8f77c9dd883
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
new file mode 100755
index 0000000..b5140a9
--- /dev/null
+++ b/tools/releasetools/build_image.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 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.
+
+"""
+Build image output_image_file from input_directory and properties_file.
+
+Usage:  build_image input_directory properties_file output_image_file
+
+"""
+import os
+import subprocess
+import sys
+
+
+def BuildImage(in_dir, prop_dict, out_file):
+  """Build an image to out_file from in_dir with property prop_dict.
+
+  Args:
+    in_dir: path of input directory.
+    prop_dict: property dictionary.
+    out_file: path of the output image file.
+
+  Returns:
+    True iff the image is built successfully.
+  """
+  build_command = []
+  fs_type = prop_dict.get("fs_type", "")
+  if fs_type.startswith("ext"):
+    build_command = ["mkuserimg.sh"]
+    if "extfs_sparse_flag" in prop_dict:
+      build_command.append(prop_dict["extfs_sparse_flag"])
+    build_command.extend([in_dir, out_file, fs_type,
+                          prop_dict["mount_point"]])
+    if "partition_size" in prop_dict:
+      build_command.append(prop_dict["partition_size"])
+  else:
+    build_command = ["mkyaffs2image", "-f"]
+    if prop_dict.get("mkyaffs2_extra_flags", None):
+      build_command.extend(prop_dict["mkyaffs2_extra_flags"].split())
+    build_command.append(in_dir)
+    build_command.append(out_file)
+
+  print "Running: ", " ".join(build_command)
+  p = subprocess.Popen(build_command);
+  p.communicate()
+  return p.returncode == 0
+
+
+def ImagePropFromGlobalDict(glob_dict, mount_point):
+  """Build an image property dictionary from the global dictionary.
+
+  Args:
+    glob_dict: the global dictionary from the build system.
+    mount_point: such as "system", "data" etc.
+  """
+  d = {}
+  common_props = (
+      "fs_type",
+      "extfs_sparse_flag",
+      "mkyaffs2_extra_flags",
+      )
+  for p in common_props:
+    if p in glob_dict:
+      d[p] = glob_dict[p]
+
+  d["mount_point"] = mount_point
+  if mount_point == "system":
+    if "system_size" in glob_dict:
+      d["partition_size"] = str(glob_dict["system_size"])
+  elif mount_point == "data":
+    if "userdata_size" in glob_dict:
+      d["partition_size"] = str(glob_dict["userdata_size"])
+
+  return d
+
+
+def LoadGlobalDict(filename):
+  """Load "name=value" pairs from filename"""
+  d = {}
+  f = open(filename)
+  for line in f:
+    line = line.strip()
+    if not line or line.startswith("#"):
+      continue
+    k, v = line.split("=", 1)
+    d[k] = v
+  f.close()
+  return d
+
+
+def main(argv):
+  if len(argv) != 3:
+    print __doc__
+    sys.exit(1)
+
+  in_dir = argv[0]
+  glob_dict_file = argv[1]
+  out_file = argv[2]
+
+  glob_dict = LoadGlobalDict(glob_dict_file)
+  image_filename = os.path.basename(out_file)
+  mount_point = ""
+  if image_filename == "system.img":
+    mount_point = "system"
+  elif image_filename == "userdata.img":
+    mount_point = "data"
+
+  image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
+  if not BuildImage(in_dir, image_properties, out_file):
+    print >> sys.stderr, "error: failed to build %s from %s" % (out_file, in_dir)
+    exit(1)
+
+
+if __name__ == '__main__':
+  main(sys.argv[1:])