/*
 * Copyright 2018 Bloomberg Finance LP
 *
 * 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.
 */

#include <buildboxrun_hosttools_pathprefixutils.h>

namespace buildboxcommon {
namespace buildboxrun {
namespace hosttools {

std::vector<std::string> PathPrefixUtils::prefixAbspathsWithStagedDir(
    const std::vector<std::string> &command,
    const std::string &staged_directory)
{
    std::vector<std::string> prefixed_command;
    prefixed_command.reserve(command.size());

    // Skip the first argument in the command vector. It's expected
    // that the binary to run has the correct path already
    bool first = true;
    for (const std::string &arg : command) {
        if (first) {
            first = false;
            prefixed_command.push_back(arg);
            continue;
        }
        prefixed_command.push_back(
            prefixArgWithStagedDir(arg, staged_directory));
    }
    return prefixed_command;
}

const std::string
PathPrefixUtils::prefixArgWithStagedDir(const std::string &command,
                                        const std::string &staged_dir)
{
    // If this is an absolute path, prefix it right away
    if (command[0] == '/') {
        return staged_dir + command;
    }

    static const std::vector<std::string> INCLUDE_PREFIXES = {
        "-include",   "-imacros", "-I",        "-iquote",   "-isystem",
        "-idirafter", "-iprefix", "-isysroot", "--sysroot="};

    // Check if this is a special compile command that has
    // paths inline. If so split it up and prefix it if necessary
    for (const std::string &prefix : INCLUDE_PREFIXES) {
        if (command.compare(0, prefix.length(), prefix) == 0 &&
            command.length() > prefix.length()) {
            const std::string stripped = command.substr(prefix.length());
            if (stripped[0] == '/') {
                return prefix + staged_dir + stripped;
            }
            break;
        }
    }
    return command;
}

} // namespace hosttools
} // namespace buildboxrun
} // namespace buildboxcommon
