#!/usr/bin/env python2.7
# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
This script allows for the conversion between ids.txt and .build-id formats.
"""

import os
import sys
import argparse

# rel_to is expected to be absolute
def abs_path(path, rel_to):
    if os.path.isabs(path):
        return path
    else:
        return os.path.abspath(os.path.join(rel_to, path))

# rel_to is assumed to be absolute
def read_ids_txt(ids_path, rel_to):
    with open(ids_path) as f:
        return {build_id:abs_path(path, rel_to) for (build_id, path) in (x.split() for x in f.readlines())}

# build_id_dir is assumed to be absolute
def read_build_id_dir(build_id_dir):
    out = {}
    for root, dirs, files in os.walk(build_id_dir):
        if len(files) != 0 and len(dirs) != 0:
            raise Exception("%s is not a valid .build-id directory" % build_id_dir)
        for f in files:
            suffix = ".debug"
            if f.endswith(suffix):
                out[os.path.basename(root) + f[:-len(suffix)]] = os.path.join(root, f)
    return out

def link(src, dst):
    src = os.path.realpath(src)
    if os.path.exists(dst):
        os.remove(dst)
    os.link(src, dst)

def mkdir(path):
    try:
        os.makedirs(path)
    except OSError as e:
        if e.errno != os.errno.EEXIST:
            raise e

def touch(path):
    if os.path.exists(path):
        os.utime(path, None)
    else:
        with open(path, 'w'):
            return

def write_build_id_dir(build_id_dir, mods):
    for build_id, path in mods.iteritems():
        mkdir(os.path.join(build_id_dir, build_id[:2]))
        link(path, os.path.join(build_id_dir, build_id[:2], build_id[2:] + ".debug"))

# rel_to and path are assumed to be absolute
# if rel_to is None fix_path returns the absolute path. If rel_to
# is not None it turns the path into a relative path.
def fix_path(path, rel_to):
    if rel_to is None:
        return path
    return os.path.relpath(path, rel_to)

# rel_to is assumed to be an absolute path
def write_ids_txt(ids_path, rel_to, mods):
    with open(ids_path, "w") as f:
        for build_id, path in sorted(mods.iteritems()):
            path = fix_path(mods[build_id], rel_to)
            f.write("%s %s\n" % (build_id, path))

def main():
    ids_fmt = "ids.txt"
    build_id_fmt = ".build-id"

    parser = argparse.ArgumentParser(description="Convert between ids.txt and .build-id")
    parser.add_argument("-O", "--output-format", help="Sets the output format.",
                        metavar="FMT",
                        choices=[ids_fmt, build_id_fmt])
    parser.add_argument("--ids-rel-to-in",
                        help="When reading ids.txt use paths relative to DIR",
                        metavar="DIR")
    parser.add_argument("--ids-rel-to-out",
                        help="When writing ids.txt use paths relative to DIR",
                        metavar="DIR")
    parser.add_argument("--stamp",
                        help="Touch STAMP after finishing",
                        metavar="STAMP")
    parser.add_argument("--input", action="append",
                        help=".build-id directories or ids.txt files depending on the output format")
    parser.add_argument("output")

    args = parser.parse_args()

        
    input_paths = map(os.path.abspath, args.input)
    input_paths = filter(os.path.exists, input_paths) # conventionally ignore empty inputs
    input_dirs = map(os.path.isdir, input_paths)
    if len(input_dirs) > 0:
        assert len(input_dirs) == len(input_paths), "input formats cannot be mixed"
        in_fmt = build_id_fmt
    else:
        in_fmt = ids_fmt

    output_path = args.output
    rel_to_in = os.path.abspath(args.ids_rel_to_in) if args.ids_rel_to_in is not None else None
    rel_to_out = os.path.abspath(args.ids_rel_to_out) if args.ids_rel_to_out is not None else None

    mods = {}
    for input_path in input_paths:
        if in_fmt == ids_fmt:
            if rel_to_in is None:
                rel_to_in = os.path.abspath(os.path.dirname(input_path))
            mods.update(read_ids_txt(input_path, rel_to_in))
        else:
            mods.update(read_build_id_dir(input_path))

    if args.output_format == None:
        if in_fmt == ids_fmt:
            out_fmt = build_id_fmt
        else:
            out_fmt = ids_fmt
    else:
        out_fmt = args.output_format

    if out_fmt == ids_fmt:
        write_ids_txt(output_path, rel_to_out, mods)
    else:
        write_build_id_dir(output_path, mods)

    if args.stamp is not None:
        touch(args.stamp)

if __name__ == "__main__":
    main()
