mirror of
https://github.com/RPCS3/llvm.git
synced 2026-07-01 21:04:04 -04:00
[llvm-ar] Make paths case insensitive when on windows
When on windows gnu-ar treats member names as case insensitive. This commit implements the same behaviour. Differential Revision: https://reviews.llvm.org/D68033 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@375002 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -35,6 +35,12 @@ Here's where **llvm-ar** departs from previous ``ar`` implementations:
|
||||
|
||||
Currently **llvm-ar** can read GNU and BSD long file names, but only writes
|
||||
archives with the GNU format.
|
||||
|
||||
*Windows Paths*
|
||||
|
||||
When on Windows **llvm-ar** treats the names of archived *files* in the same
|
||||
case sensitive manner as the operating system. When on a non-Windows machine
|
||||
**llvm-ar** does not consider character case.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
!<arch>
|
||||
// 22 `
|
||||
a/foo.txt/
|
||||
b/foo.txt/
|
||||
/0 0 0 0 644 8 `
|
||||
hello-a
|
||||
/11 0 0 0 644 8 `
|
||||
hello-b
|
||||
@@ -0,0 +1,27 @@
|
||||
## Test that on windows, members are case insensitive.
|
||||
# UNSUPPORTED: system-windows
|
||||
|
||||
# RUN: mkdir -p %t
|
||||
# RUN: rm -rf %t/lowerCase %t/UPPERCASE && mkdir %t/lowerCase %t/UPPERCASE
|
||||
# RUN: echo lowerCase > %t/lowerCase/file.txt
|
||||
# RUN: echo UPPERCASE > %t/UPPERCASE/FILE.TXT
|
||||
|
||||
# RUN: rm -f %t/archive.a
|
||||
# RUN: llvm-ar rc %t/archive.a %t/lowerCase/file.txt
|
||||
# RUN: llvm-ar rc %t/archive.a %t/UPPERCASE/FILE.TXT
|
||||
# RUN: FileCheck %s -input-file=%t/archive.a --check-prefix=ARCHIVE
|
||||
|
||||
# ARCHIVE: file.txt
|
||||
# ARCHIVE: FILE.TXT
|
||||
|
||||
# RUN: rm -f %t/thin-archive.a
|
||||
# RUN: llvm-ar Trc %t/thin-archive.a %t/lowerCase/file.txt %t/UPPERCASE/FILE.TXT
|
||||
# RUN: llvm-ar dTP %t/thin-archive.a %t/uppercase/file.txt
|
||||
|
||||
# RUN: FileCheck %s -input-file=%t/thin-archive.a --check-prefix=THIN-ARCHIVE -DPATH=%/t
|
||||
|
||||
# RUN: llvm-ar dTP %t/thin-archive.a %t/LOWERCASE/FILE.TXT
|
||||
# RUN: FileCheck %s -input-file=%t/thin-archive.a --check-prefix=THIN-ARCHIVE -DPATH=%/t
|
||||
|
||||
# THIN-ARCHIVE: [[PATH]]/lowerCase/file.txt
|
||||
# THIN-ARCHIVE: [[PATH]]/UPPERCASE/FILE.TXT
|
||||
@@ -0,0 +1,9 @@
|
||||
RUN: llvm-ar t %S/Inputs/path-names.a | FileCheck %s --check-prefix=CONTENTS --implicit-check-not {{.}}
|
||||
CONTENTS: a/foo.txt
|
||||
CONTENTS-NEXT: b/foo.txt
|
||||
|
||||
RUN: llvm-ar p %S/Inputs/path-names.a b/foo.txt | FileCheck %s --check-prefix=NO-FULL-PATH --implicit-check-not {{.}}
|
||||
NO-FULL-PATH: hello-a
|
||||
|
||||
RUN: llvm-ar Pp %S/Inputs/path-names.a b/foo.txt | FileCheck %s --check-prefix=FULL-PATH --implicit-check-not {{.}}
|
||||
FULL-PATH: hello-b
|
||||
@@ -0,0 +1,29 @@
|
||||
## Test that on windows, members are case insensitive.
|
||||
# REQUIRES: system-windows
|
||||
|
||||
# RUN: mkdir -p %t
|
||||
# RUN: rm -rf %t/lowerCase %t/UPPERCASE && mkdir %t/lowerCase %t/UPPERCASE
|
||||
# RUN: echo lowerCase > %t/lowerCase/file.txt
|
||||
# RUN: echo UPPERCASE > %t/UPPERCASE/FILE.TXT
|
||||
|
||||
# RUN: rm -f %t/archive.a
|
||||
# RUN: llvm-ar rc %t/archive.a %t/lowerCase/file.txt
|
||||
# RUN: FileCheck %s -input-file=%t/archive.a --check-prefix=LOWER --implicit-check-not=FILE.TXT
|
||||
# RUN: llvm-ar rc %t/archive.a %t/UPPERCASE/FILE.TXT
|
||||
# RUN: FileCheck %s -input-file=%t/archive.a --check-prefix=UPPER --implicit-check-not=file.txt
|
||||
|
||||
# LOWER: file.txt
|
||||
# UPPER: FILE.TXT
|
||||
|
||||
# RUN: rm -f %t/thin-archive.a
|
||||
# RUN: llvm-ar Trc %t/thin-archive.a %t/lowerCase/file.txt %t/UPPERCASE/FILE.txt
|
||||
# RUN: llvm-ar dTP %t/thin-archive.a %t/uppercase/file.txt
|
||||
|
||||
# RUN: FileCheck %s -input-file=%t/thin-archive.a --check-prefix=THIN-ARCHIVE -DPATH=%/t
|
||||
# THIN-ARCHIVE-NOT: [[PATH]]/UPPERCASE/FILE.TXT
|
||||
# THIN-ARCHIVE: [[PATH]]/lowerCase/file.txt
|
||||
|
||||
# RUN: llvm-ar dTP %t/thin-archive.a %t/LOWERCASE/FILE.TXT
|
||||
# RUN: FileCheck %s -input-file=%t/thin-archive.a --check-prefix=EMPTY --implicit-check-not {{.}}
|
||||
|
||||
EMPTY: !<thin>
|
||||
@@ -43,6 +43,11 @@
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// The name this program was invoked as.
|
||||
@@ -488,6 +493,23 @@ static std::string normalizePath(StringRef Path) {
|
||||
: std::string(sys::path::filename(Path));
|
||||
}
|
||||
|
||||
static bool comparePaths(StringRef Path1, StringRef Path2) {
|
||||
// When on Windows this function calls CompareStringOrdinal
|
||||
// as Windows file paths are case-insensitive.
|
||||
// CompareStringOrdinal compares two Unicode strings for
|
||||
// binary equivalence and allows for case insensitivity.
|
||||
#ifdef _WIN32
|
||||
SmallVector<wchar_t, 128> WPath1, WPath2;
|
||||
failIfError(sys::path::widenPath(normalizePath(Path1), WPath1));
|
||||
failIfError(sys::path::widenPath(normalizePath(Path2), WPath2));
|
||||
|
||||
return CompareStringOrdinal(WPath1.data(), WPath1.size(), WPath2.data(),
|
||||
WPath2.size(), true) == CSTR_EQUAL;
|
||||
#else
|
||||
return normalizePath(Path1) == normalizePath(Path2);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Implement the 'x' operation. This function extracts files back to the file
|
||||
// system.
|
||||
static void doExtract(StringRef Name, const object::Archive::Child &C) {
|
||||
@@ -561,7 +583,7 @@ static void performReadOperation(ArchiveOperation Operation,
|
||||
|
||||
if (Filter) {
|
||||
auto I = find_if(Members, [Name](StringRef Path) {
|
||||
return Name == normalizePath(Path);
|
||||
return comparePaths(Name, Path);
|
||||
});
|
||||
if (I == Members.end())
|
||||
continue;
|
||||
@@ -691,7 +713,7 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,
|
||||
if (Operation == QuickAppend || Members.empty())
|
||||
return IA_AddOldMember;
|
||||
auto MI = find_if(
|
||||
Members, [Name](StringRef Path) { return Name == normalizePath(Path); });
|
||||
Members, [Name](StringRef Path) { return comparePaths(Name, Path); });
|
||||
|
||||
if (MI == Members.end())
|
||||
return IA_AddOldMember;
|
||||
@@ -742,15 +764,14 @@ computeNewArchiveMembers(ArchiveOperation Operation,
|
||||
std::vector<NewArchiveMember> Moved;
|
||||
int InsertPos = -1;
|
||||
if (OldArchive) {
|
||||
std::string PosName = normalizePath(RelPos);
|
||||
Error Err = Error::success();
|
||||
StringMap<int> MemberCount;
|
||||
for (auto &Child : OldArchive->children(Err)) {
|
||||
int Pos = Ret.size();
|
||||
Expected<StringRef> NameOrErr = Child.getName();
|
||||
failIfError(NameOrErr.takeError());
|
||||
StringRef Name = NameOrErr.get();
|
||||
if (Name == PosName) {
|
||||
std::string Name = NameOrErr.get();
|
||||
if (comparePaths(Name, RelPos)) {
|
||||
assert(AddAfter || AddBefore);
|
||||
if (AddBefore)
|
||||
InsertPos = Pos;
|
||||
@@ -1018,9 +1039,9 @@ static void runMRIScript() {
|
||||
ArchiveName = Rest;
|
||||
break;
|
||||
case MRICommand::Delete: {
|
||||
std::string Name = normalizePath(Rest);
|
||||
llvm::erase_if(NewMembers,
|
||||
[=](NewArchiveMember &M) { return M.MemberName == Name; });
|
||||
llvm::erase_if(NewMembers, [=](NewArchiveMember &M) {
|
||||
return comparePaths(M.MemberName, Rest);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case MRICommand::Save:
|
||||
|
||||
Reference in New Issue
Block a user