Skip to content

Commit 691188b

Browse files
authored
Merge pull request github#11523 from github/alexdenisov/preserve-symlinks
Swift: resolve symlinks conditionally
2 parents d3e06ee + 7a3beac commit 691188b

File tree

13 files changed

+124
-22
lines changed

13 files changed

+124
-22
lines changed

swift/extractor/SwiftExtractor.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,12 @@
1212
#include "swift/extractor/translators/SwiftVisitor.h"
1313
#include "swift/extractor/TargetTrapFile.h"
1414
#include "swift/extractor/SwiftBuiltinSymbols.h"
15+
#include "swift/extractor/infra/Path.h"
1516

1617
using namespace codeql;
1718
using namespace std::string_literals;
1819
namespace fs = std::filesystem;
1920

20-
static fs::path toPath(llvm::StringRef s) {
21-
return {static_cast<std::string_view>(s)};
22-
}
23-
2421
static void ensureDirectory(const char* label, const fs::path& dir) {
2522
std::error_code ec;
2623
fs::create_directories(dir, ec);
@@ -34,7 +31,7 @@ static void archiveFile(const SwiftExtractorConfiguration& config, swift::Source
3431
ensureDirectory("TRAP", config.trapDir);
3532
ensureDirectory("source archive", config.sourceArchiveDir);
3633

37-
fs::path srcFilePath = fs::absolute(toPath(file.getFilename()));
34+
fs::path srcFilePath = codeql::getCodeQLPath(file.getFilename());
3835
auto dstFilePath = config.sourceArchiveDir;
3936
dstFilePath += srcFilePath;
4037

@@ -60,7 +57,7 @@ static fs::path getFilename(swift::ModuleDecl& module, swift::SourceFile* primar
6057
// Moreover, pcm files may come from caches located in different directories, but are
6158
// unambiguously identified by the base file name, so we can discard the absolute directory
6259
fs::path filename = "/pcms";
63-
filename /= toPath(module.getModuleFilename()).filename();
60+
filename /= getCodeQLPath(module.getModuleFilename()).filename();
6461
filename += "-";
6562
filename += module.getName().str();
6663
return filename;
@@ -69,7 +66,7 @@ static fs::path getFilename(swift::ModuleDecl& module, swift::SourceFile* primar
6966
// The Builtin module has an empty filename, let's fix that
7067
return "/__Builtin__";
7168
}
72-
auto filename = toPath(module.getModuleFilename());
69+
auto filename = getCodeQLPath(module.getModuleFilename());
7370
// there is a special case of a module without an actual filename reporting `<imports>`: in this
7471
// case we want to avoid the `<>` characters, in case a dirty DB is imported on Windows
7572
if (filename == "<imports>") {

swift/extractor/infra/Path.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include "swift/extractor/infra/Path.h"
2+
#include <iostream>
3+
#include <unistd.h>
4+
5+
namespace codeql {
6+
7+
static bool shouldCanonicalize() {
8+
auto preserve = getenv("CODEQL_PRESERVE_SYMLINKS");
9+
if (preserve && std::string(preserve) == "true") {
10+
return false;
11+
}
12+
preserve = getenv("SEMMLE_PRESERVE_SYMLINKS");
13+
if (preserve && std::string(preserve) == "true") {
14+
return false;
15+
}
16+
return true;
17+
}
18+
19+
std::filesystem::path getCodeQLPath(std::string_view path) {
20+
// TODO: this needs more testing
21+
// TODO: check canonicalization of names on a case insensitive filesystems
22+
std::error_code ec;
23+
std::filesystem::path ret = {};
24+
static const auto canonicalize = shouldCanonicalize();
25+
if (canonicalize) {
26+
ret = std::filesystem::canonical(path, ec);
27+
} else {
28+
ret = std::filesystem::absolute(path, ec);
29+
}
30+
if (ec) {
31+
std::cerr << "Cannot get " << (canonicalize ? "canonical" : "absolute")
32+
<< " path: " << std::quoted(path) << ": " << ec.message() << "\n";
33+
return {};
34+
}
35+
return ret;
36+
}
37+
38+
} // namespace codeql

swift/extractor/infra/Path.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
3+
#include <filesystem>
4+
5+
namespace codeql {
6+
std::filesystem::path getCodeQLPath(std::string_view path);
7+
}

swift/extractor/infra/SwiftLocationExtractor.cpp

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,10 @@
55
#include "swift/extractor/trap/generated/TrapEntries.h"
66
#include "swift/extractor/trap/generated/TrapClasses.h"
77
#include "swift/extractor/infra/SwiftLocationExtractor.h"
8+
#include "swift/extractor/infra/Path.h"
89

910
using namespace codeql;
1011

11-
static std::filesystem::path getFilePath(std::string_view path) {
12-
// TODO: this needs more testing
13-
// TODO: check canonicalization of names on a case insensitive filesystems
14-
// TODO: make symlink resolution conditional on CODEQL_PRESERVE_SYMLINKS=true
15-
std::error_code ec;
16-
auto ret = std::filesystem::canonical(path, ec);
17-
if (ec) {
18-
std::cerr << "Cannot get real path: " << std::quoted(path) << ": " << ec.message() << "\n";
19-
return {};
20-
}
21-
return ret;
22-
}
23-
2412
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
2513
swift::SourceLoc start,
2614
swift::SourceLoc end,
@@ -29,7 +17,7 @@ void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceMa
2917
// invalid locations seem to come from entities synthesized by the compiler
3018
return;
3119
}
32-
auto file = getFilePath(sourceManager.getDisplayNameForLoc(start));
20+
auto file = getCodeQLPath(sourceManager.getDisplayNameForLoc(start));
3321
DbLocation entry{{}};
3422
entry.file = fetchFileLabel(file);
3523
std::tie(entry.start_line, entry.start_column) = sourceManager.getLineAndColumnInBuffer(start);
@@ -42,7 +30,7 @@ void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceMa
4230
}
4331

4432
void SwiftLocationExtractor::emitFile(llvm::StringRef path) {
45-
fetchFileLabel(getFilePath(path));
33+
fetchFileLabel(getCodeQLPath(path));
4634
}
4735

4836
TrapLabel<FileTag> SwiftLocationExtractor::fetchFileLabel(const std::filesystem::path& file) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*/Sources/A.swift
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
| file://:0:0:0:0 | |
2+
| main.swift:0:0:0:0 | main.swift |
3+
| preserve/Package.swift:0:0:0:0 | preserve/Package.swift |
4+
| preserve/Sources/A.swift:0:0:0:0 | preserve/Sources/A.swift |
5+
| resolve/Package.swift:0:0:0:0 | resolve/Package.swift |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import swift
2+
3+
from File f
4+
select f
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
public struct preserve {
2+
public private(set) var text = "Hello, World!"
3+
4+
public init() {
5+
}
6+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// swift-tools-version: 5.7
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "preserve",
8+
products: [
9+
.library(
10+
name: "preserve",
11+
targets: ["preserve"]),
12+
],
13+
targets: [
14+
.target(
15+
name: "preserve",
16+
path: "Sources"),
17+
]
18+
)

swift/integration-tests/posix-only/symlinks/preserve/Sources/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)