# Copyright 2015 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""This script installs users and groups into sysroots."""

import os

from chromite.lib import accounts_lib
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import osutils
from chromite.lib import sysroot_lib
from chromite.lib import user_db


ACCOUNT_DB_FILENAME = "accounts.json"

ACTION_GET_ENTRY = "get_entry"
ACTION_INSTALL_USER = "install_user"
ACTION_INSTALL_GROUP = "install_group"

USER_DB = "passwd"
GROUP_DB = "group"


def GetOptions(argv):
    """Returns the parsed command line arguments in |argv|."""
    parser = commandline.ArgumentParser(description=__doc__)
    command_parsers = parser.add_subparsers(dest="action")

    get_ent_parser = command_parsers.add_parser(
        ACTION_GET_ENTRY, help="Get an entry from an account database."
    )
    get_ent_parser.add_argument(
        "--nolock",
        action="store_true",
        default=False,
        help="Skip locking the database before reading it.",
    )
    get_ent_parser.add_argument(
        "sysroot", type="path", help="Path to sysroot containing the database"
    )
    get_ent_parser.add_argument(
        "database", choices=(USER_DB, GROUP_DB), help="Name of database to get"
    )
    get_ent_parser.add_argument("name", type=str, help="Name of account to get")

    user_parser = command_parsers.add_parser(
        ACTION_INSTALL_USER, help="Install a user to a sysroot"
    )
    user_parser.add_argument("name", type=str, help="Name of user to install")
    user_parser.add_argument("--uid", type=int, help="UID of the user")
    user_parser.add_argument("--shell", type="path", help="Shell of user")
    user_parser.add_argument(
        "--home", type="path", help="Home directory of user"
    )
    user_parser.add_argument(
        "--primary_group", type=str, help="Name of primary group for user"
    )

    group_parser = command_parsers.add_parser(
        ACTION_INSTALL_GROUP, help="Install a group to a sysroot"
    )
    group_parser.add_argument(
        "name", type=str, help="Name of group to install."
    )
    group_parser.add_argument("--gid", type=int, help="GID of the group")

    # Both group and user parsers need to understand the target sysroot.
    for sub_parser in (user_parser, group_parser):
        sub_parser.add_argument(
            "sysroot", type="path", help="The sysroot to install the user into"
        )

    options = parser.parse_args(argv)
    options.Freeze()
    return options


def main(argv):
    cros_build_lib.AssertInsideChroot()
    options = GetOptions(argv)

    if options.action == ACTION_GET_ENTRY:
        db = user_db.UserDB(options.sysroot)
        if options.database == USER_DB:
            print(db.GetUserEntry(options.name, skip_lock=options.nolock))
        else:
            print(db.GetGroupEntry(options.name, skip_lock=options.nolock))
        return 0

    overlays = (
        sysroot_lib.Sysroot(options.sysroot)
        .GetStandardField(sysroot_lib.STANDARD_FIELD_PORTDIR_OVERLAY)
        .split()
    )

    # TODO(wiley) This process could be optimized to avoid reparsing these
    #             overlay databases each time.
    account_db = accounts_lib.AccountDatabase()
    for overlay_path in overlays:
        database_path = os.path.join(overlay_path, ACCOUNT_DB_FILENAME)
        if os.path.exists(database_path):
            account_db.AddAccountsFromDatabase(database_path)

    installed_users = user_db.UserDB(options.sysroot)

    if options.action == ACTION_INSTALL_USER:
        account_db.InstallUser(
            options.name,
            installed_users,
            uid=options.uid,
            shell=options.shell,
            homedir=options.home,
            primary_group=options.primary_group,
        )

        homedir = account_db.users[options.name].home
        homedir_path = os.path.join(options.sysroot, homedir)

        if homedir != "/dev/null" and not os.path.exists(homedir_path):
            osutils.SafeMakedirs(homedir_path, sudo=True)
            uid = account_db.users[options.name].uid
            cros_build_lib.sudo_run(
                ["chown", "%d:%d" % (uid, uid), homedir_path], print_cmd=False
            )

    elif options.action == ACTION_INSTALL_GROUP:
        account_db.InstallGroup(options.name, installed_users, gid=options.gid)
    else:
        cros_build_lib.Die(
            "Unsupported account type: %s" % options.account_type
        )
