Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make comparison of installed files case-insensitive #1483

Merged
merged 5 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions azure-pipelines/e2e-ports/duplicate-file-a/portfile.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
set(VCPKG_BUILD_TYPE release)

file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/include/")
file(WRITE "${CURRENT_PACKAGES_DIR}/include/COMMON.H" "// THIS IS A HEADER FILE")
4 changes: 4 additions & 0 deletions azure-pipelines/e2e-ports/duplicate-file-a/vcpkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "duplicate-file-a",
"version": "0.0.1"
}
4 changes: 4 additions & 0 deletions azure-pipelines/e2e-ports/duplicate-file-b/portfile.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
set(VCPKG_BUILD_TYPE release)

file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/include/")
file(WRITE "${CURRENT_PACKAGES_DIR}/include/common.h" "// THIS IS A HEADER FILE")
4 changes: 4 additions & 0 deletions azure-pipelines/e2e-ports/duplicate-file-b/vcpkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "duplicate-file-b",
"version": "0.0.1"
}
8 changes: 8 additions & 0 deletions azure-pipelines/end-to-end-tests-dir/post-build-checks.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ if ($IsWindows) {
$NativeSlash = '\'
}

# Fail if installed files exist
Refresh-TestRoot
[string]$dupOutput = Run-VcpkgAndCaptureOutput install @commonArgs "--overlay-ports=$PSScriptRoot/../e2e-ports" duplicate-file-a duplicate-file-b
Throw-IfNotFailed
if (-not $dupOutput.Contains('The following files are already installed')) {
throw ('Incorrect error message for due to duplicate files; output was ' + $dupOutput)
}

# Empty package / disable all checks
Refresh-TestRoot
[string]$buildOutput = Run-VcpkgAndCaptureStderr install @commonArgs --overlay-ports="$PSScriptRoot/../e2e-ports" vcpkg-policy-set-incorrectly
Expand Down
1 change: 1 addition & 0 deletions include/vcpkg/base/strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ namespace vcpkg::Strings
const char* case_insensitive_ascii_search(StringView s, StringView pattern);
bool case_insensitive_ascii_contains(StringView s, StringView pattern);
bool case_insensitive_ascii_equals(StringView left, StringView right);
bool case_insensitive_ascii_less(StringView left, StringView right);

void inplace_ascii_to_lowercase(char* first, char* last);
void inplace_ascii_to_lowercase(std::string& s);
Expand Down
20 changes: 20 additions & 0 deletions src/vcpkg-test/strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,26 @@ TEST_CASE ("api_stable_format(sv,append_f)", "[strings]")
REQUIRE(*res.get() == "123hello456");
}

TEST_CASE ("lex compare less", "[strings]")
{
REQUIRE(Strings::case_insensitive_ascii_less("a", "b"));
REQUIRE(Strings::case_insensitive_ascii_less("a", "B"));
REQUIRE(Strings::case_insensitive_ascii_less("A", "b"));
REQUIRE(Strings::case_insensitive_ascii_less("A", "B"));

REQUIRE_FALSE(Strings::case_insensitive_ascii_less("b", "a"));
REQUIRE_FALSE(Strings::case_insensitive_ascii_less("B", "a"));
REQUIRE_FALSE(Strings::case_insensitive_ascii_less("b", "A"));
REQUIRE_FALSE(Strings::case_insensitive_ascii_less("B", "A"));

REQUIRE_FALSE(Strings::case_insensitive_ascii_less("b", "b"));
REQUIRE_FALSE(Strings::case_insensitive_ascii_less("b", "B"));
REQUIRE_FALSE(Strings::case_insensitive_ascii_less("B", "b"));

REQUIRE(Strings::case_insensitive_ascii_less("a", "aa"));
REQUIRE_FALSE(Strings::case_insensitive_ascii_less("aa", "a"));
}

#if defined(_WIN32)
TEST_CASE ("ascii to utf16", "[utf16]")
{
Expand Down
10 changes: 10 additions & 0 deletions src/vcpkg/base/strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ namespace
bool operator()(char a, char b) const noexcept { return tolower_char(a) == tolower_char(b); }
} icase_eq;

constexpr struct
{
bool operator()(char a, char b) const noexcept { return tolower_char(a) < tolower_char(b); }
} icase_less;

}

#if defined(_WIN32)
Expand Down Expand Up @@ -173,6 +178,11 @@ bool Strings::case_insensitive_ascii_equals(StringView left, StringView right)
return std::equal(left.begin(), left.end(), right.begin(), right.end(), icase_eq);
}

bool Strings::case_insensitive_ascii_less(StringView left, StringView right)
{
return std::lexicographical_compare(left.begin(), left.end(), right.begin(), right.end(), icase_less);
}

void Strings::inplace_ascii_to_lowercase(char* first, char* last) { std::transform(first, last, first, tolower_char); }

void Strings::inplace_ascii_to_lowercase(std::string& s)
Expand Down
16 changes: 8 additions & 8 deletions src/vcpkg/commands.install.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,14 @@ namespace vcpkg

struct intersection_compare
{
// The VS2015 standard library requires comparison operators of T and U
// to also support comparison of T and T, and of U and U, due to debug checks.
#if _MSC_VER <= 1910
bool operator()(const std::string& lhs, const std::string& rhs) const { return lhs < rhs; }
bool operator()(const file_pack& lhs, const file_pack& rhs) const { return lhs.first < rhs.first; }
#endif
bool operator()(const std::string& lhs, const file_pack& rhs) const { return lhs < rhs.first; }
bool operator()(const file_pack& lhs, const std::string& rhs) const { return lhs.first < rhs; }
bool operator()(const std::string& lhs, const file_pack& rhs) const
{
return Strings::case_insensitive_ascii_less(lhs, rhs.first);
}
bool operator()(const file_pack& lhs, const std::string& rhs) const
{
return Strings::case_insensitive_ascii_less(lhs.first, rhs);
}
};

std::vector<file_pack> intersection;
Expand Down
Loading