Beispiel #1
0
    static StatusParagraphs load_current_database(Files::Filesystem& fs,
                                                  const fs::path& vcpkg_dir_status_file,
                                                  const fs::path& vcpkg_dir_status_file_old)
    {
        if (!fs.exists(vcpkg_dir_status_file))
        {
            if (!fs.exists(vcpkg_dir_status_file_old))
            {
                // no status file, use empty db
                return StatusParagraphs();
            }

            fs.rename(vcpkg_dir_status_file_old, vcpkg_dir_status_file);
        }

        auto pghs = Paragraphs::get_paragraphs(fs, vcpkg_dir_status_file).value_or_exit(VCPKG_LINE_INFO);

        std::vector<std::unique_ptr<StatusParagraph>> status_pghs;
        for (auto&& p : pghs)
        {
            status_pghs.push_back(std::make_unique<StatusParagraph>(std::move(p)));
        }

        return StatusParagraphs(std::move(status_pghs));
    }
Beispiel #2
0
    std::string get_file_hash(const Files::Filesystem& fs, const fs::path& path, const std::string& hash_type)
    {
        const std::string digest_size = get_digest_size(hash_type);
        Checks::check_exit(VCPKG_LINE_INFO, fs.exists(path), "File %s does not exist", path.u8string());

        // Try hash-specific tools, like sha512sum
        {
            const auto ec_data = System::cmd_execute_and_capture_output(
                Strings::format(R"(sha%ssum "%s")", digest_size, path.u8string()));
            if (ec_data.exit_code == 0)
            {
                return parse_shasum_output(ec_data.output);
            }
        }

        // Try shasum
        {
            const auto ec_data = System::cmd_execute_and_capture_output(
                Strings::format(R"(shasum -a %s "%s")", digest_size, path.u8string()));
            if (ec_data.exit_code == 0)
            {
                return parse_shasum_output(ec_data.output);
            }
        }

        Checks::exit_with_message(VCPKG_LINE_INFO, "Could not hash file %s with %s", path.u8string(), hash_type);
    }

    std::string get_string_hash(const std::string& s, const std::string& hash_type)
    {
        const std::string digest_size = get_digest_size(hash_type);
        verify_has_only_allowed_chars(s);

        // Try hash-specific tools, like sha512sum
        {
            const auto ec_data =
                System::cmd_execute_and_capture_output(Strings::format(R"(echo -n "%s" | sha%ssum)", s, digest_size));
            if (ec_data.exit_code == 0)
            {
                return parse_shasum_output(ec_data.output);
            }
        }

        // Try shasum
        {
            const auto ec_data = System::cmd_execute_and_capture_output(
                Strings::format(R"(echo -n "%s" | shasum -a %s)", s, digest_size));
            if (ec_data.exit_code == 0)
            {
                return parse_shasum_output(ec_data.output);
            }
        }

        Checks::exit_with_message(VCPKG_LINE_INFO, "Could not hash input string with %s", hash_type);
    }
#endif
}
Beispiel #3
0
 void UserConfig::try_write_data(Files::Filesystem& fs) const
 {
     try
     {
         auto config_path = get_config_path();
         auto config_dir = config_path.parent_path();
         std::error_code ec;
         fs.create_directory(config_dir, ec);
         fs.write_contents(config_path,
                           Strings::format("User-Id: %s\n"
                                           "User-Since: %s\n"
                                           "Mac-Hash: %s\n"
                                           "Survey-Completed: %s\n",
                                           user_id,
                                           user_time,
                                           user_mac,
                                           last_completed_survey),
                           ec);
     }
     catch (...)
     {
     }
 }
Beispiel #4
0
 LoadResults try_load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir)
 {
     LoadResults ret;
     for (auto&& path : fs.get_files_non_recursive(ports_dir))
     {
         auto maybe_spgh = try_load_port(fs, path);
         if (auto spgh = maybe_spgh.get())
         {
             ret.paragraphs.emplace_back(std::move(*spgh));
         }
         else
         {
             ret.errors.emplace_back(std::move(maybe_spgh).error());
         }
     }
     return ret;
 }
Beispiel #5
0
    static LintStatus check_bin_folders_are_not_present_in_static_build(const Files::Filesystem& fs,
                                                                        const fs::path& package_dir)
    {
        const fs::path bin = package_dir / "bin";
        const fs::path debug_bin = package_dir / "debug" / "bin";

        if (!fs.exists(bin) && !fs.exists(debug_bin))
        {
            return LintStatus::SUCCESS;
        }

        if (fs.exists(bin))
        {
            System::println(System::Color::warning,
                            R"(There should be no bin\ directory in a static build, but %s is present.)",
                            bin.u8string());
        }

        if (fs.exists(debug_bin))
        {
            System::println(System::Color::warning,
                            R"(There should be no debug\bin\ directory in a static build, but %s is present.)",
                            debug_bin.u8string());
        }

        System::println(
            System::Color::warning,
            R"(If the creation of bin\ and/or debug\bin\ cannot be disabled, use this in the portfile to remove them)"
            "\n"
            "\n"
            R"###(    if(VCPKG_LIBRARY_LINKAGE STREQUAL static))###"
            "\n"
            R"###(        file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/bin ${CURRENT_PACKAGES_DIR}/debug/bin))###"
            "\n"
            R"###(    endif())###"
            "\n");

        return LintStatus::ERROR_DETECTED;
    }

    static LintStatus check_no_empty_folders(const Files::Filesystem& fs, const fs::path& dir)
    {
        std::vector<fs::path> empty_directories = fs.get_files_recursive(dir);

        Util::erase_remove_if(empty_directories, [&fs](const fs::path& current) {
            return !fs.is_directory(current) || !fs.is_empty(current);
        });

        if (!empty_directories.empty())
        {
            System::println(System::Color::warning, "There should be no empty directories in %s", dir.generic_string());
            System::println("The following empty directories were found: ");
            Files::print_paths(empty_directories);
            System::println(
                System::Color::warning,
                "If a directory should be populated but is not, this might indicate an error in the portfile.\n"
                "If the directories are not needed and their creation cannot be disabled, use something like this in "
                "the portfile to remove them:\n"
                "\n"
                R"###(    file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/a/dir ${CURRENT_PACKAGES_DIR}/some/other/dir))###"
                "\n"
                "\n");
            return LintStatus::ERROR_DETECTED;
        }

        return LintStatus::SUCCESS;
    }

    struct BuildTypeAndFile
    {
        fs::path file;
        BuildType build_type;
    };

    static LintStatus check_crt_linkage_of_libs(const BuildType& expected_build_type,
                                                const std::vector<fs::path>& libs,
                                                const fs::path dumpbin_exe)
    {
        std::vector<BuildType> bad_build_types(BuildTypeC::VALUES.cbegin(), BuildTypeC::VALUES.cend());
        bad_build_types.erase(std::remove(bad_build_types.begin(), bad_build_types.end(), expected_build_type),
                              bad_build_types.end());

        std::vector<BuildTypeAndFile> libs_with_invalid_crt;

        for (const fs::path& lib : libs)
        {
            const std::string cmd_line =
                Strings::format(R"("%s" /directives "%s")", dumpbin_exe.u8string(), lib.u8string());
            System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line);
            Checks::check_exit(VCPKG_LINE_INFO,
                               ec_data.exit_code == 0,
                               "Running command:\n   %s\n failed with message:\n%s",
                               cmd_line,
                               ec_data.output);

            for (const BuildType& bad_build_type : bad_build_types)
            {
                if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), bad_build_type.crt_regex()))
                {
                    libs_with_invalid_crt.push_back({lib, bad_build_type});
                    break;
                }
            }
        }
Beispiel #6
0
 std::string get_file_hash(const Files::Filesystem& fs, const fs::path& path, const std::string& hash_type)
 {
     Checks::check_exit(VCPKG_LINE_INFO, fs.exists(path), "File %s does not exist", path.u8string());
     return BCryptHasher{hash_type}.hash_file(path);
 }
Beispiel #7
0
    static void upgrade_to_slash_terminated_sorted_format(Files::Filesystem& fs,
                                                          std::vector<std::string>* lines,
                                                          const fs::path& listfile_path)
    {
        static bool was_tracked = false;

        if (lines->empty())
        {
            return;
        }

        if (lines->at(0).back() == '/')
        {
            return; // File already in the new format
        }

        if (!was_tracked)
        {
            was_tracked = true;
            Metrics::track_property("listfile", "update to new format");
        }

        // The files are sorted such that directories are placed just before the files they contain
        // (They are not necessarily sorted alphabetically, e.g. libflac)
        // Therefore we can detect the entries that represent directories by comparing every element with the next one
        // and checking if the next has a slash immediately after the current one's length
        for (size_t i = 0; i < lines->size() - 1; i++)
        {
            std::string& current_string = lines->at(i);
            const std::string& next_string = lines->at(i + 1);

            const size_t potential_slash_char_index = current_string.length();
            // Make sure the index exists first
            if (next_string.size() > potential_slash_char_index && next_string.at(potential_slash_char_index) == '/')
            {
                current_string += '/'; // Mark as a directory
            }
        }

        // After suffixing the directories with a slash, we can now sort.
        // We cannot sort before adding the suffixes because the following (actual example):
        /*
            x86-windows/include/FLAC <<<<<< This would be separated from its group due to sorting
            x86-windows/include/FLAC/all.h
            x86-windows/include/FLAC/assert.h
            x86-windows/include/FLAC/callback.h
            x86-windows/include/FLAC++
            x86-windows/include/FLAC++/all.h
            x86-windows/include/FLAC++/decoder.h
            x86-windows/include/FLAC++/encoder.h
         *
            x86-windows/include/FLAC/ <<<<<< This will now be kept with its group when sorting
            x86-windows/include/FLAC/all.h
            x86-windows/include/FLAC/assert.h
            x86-windows/include/FLAC/callback.h
            x86-windows/include/FLAC++/
            x86-windows/include/FLAC++/all.h
            x86-windows/include/FLAC++/decoder.h
            x86-windows/include/FLAC++/encoder.h
        */
        // Note that after sorting, the FLAC++/ group will be placed before the FLAC/ group
        // The new format is lexicographically sorted
        std::sort(lines->begin(), lines->end());

        // Replace the listfile on disk
        const fs::path updated_listfile_path = listfile_path.generic_string() + "_updated";
        fs.write_lines(updated_listfile_path, *lines);
        fs.rename(updated_listfile_path, listfile_path);
    }