Skip to content

Commit ef5edde

Browse files
committed
Fix handling of symbolic links on Windows
When cloning a Git repository on Windows Git puts the link file path as the content of an ordinary file. When downloading tarball the symbolic link files cannot be properly established and Tar writes empty files instead. This leads to different packages checksums compared to the case when the package is downloaded via Git or downloaded on Linux either via Git or via tarball. To fix the problem we parsed the content of the tarball and extract the link paths from there. After that, we write a link file with the link path in it overriding the empty file extracted by Tar. Additionally, the `getPackageFileListWithoutVcs` procedure is fixed to return relative paths to files with `/` character as directory separator even on Windows, because they are used in the package checksum calculation and we must have the same checksum for the same package regardless of the operating system or download method. Related to #127
1 parent 9e971a1 commit ef5edde

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/nimblepkg/download.nim

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,26 @@ proc doDownloadTarball(url, downloadDir, version: string, queryRevision: bool):
309309
raise nimbleError(tryDoCmdExErrorMessage(cmd, output, exitCode))
310310
display("Completed", "unpacking " & filePath)
311311

312+
when defined(windows):
313+
# On Windows symbolic link files are not being extracted properly by the
314+
# `tar` command. They are extracted as empty files, but when cloning the
315+
# repository with Git they are extracted as ordinary files with the link
316+
# path in them. For that reason here we parse the tar file content to
317+
# extract the symbolic links and add their paths manually to the content of
318+
# their files.
319+
let listCmd = &"{getTarExePath()} -ztvf {filePath} --force-local"
320+
let (cmdOutput, cmdExitCode) = doCmdEx(listCmd)
321+
if cmdExitCode != QuitSuccess:
322+
raise nimbleError(tryDoCmdExErrorMessage(listCmd, cmdOutput, cmdExitCode))
323+
let lines = cmdOutput.splitLines()
324+
for line in lines:
325+
if line.contains(" -> "):
326+
let parts = line.split
327+
let linkPath = parts[^1]
328+
let linkNameParts = parts[^3].split('/')
329+
let linkName = linkNameParts[1 .. ^1].foldl(a / b)
330+
writeFile(downloadDir / linkName, linkPath)
331+
312332
filePath.removeFile
313333
return if queryRevision: getRevision(url, version) else: notSetSha1Hash
314334

src/nimblepkg/vcstools.nim

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ proc getPackageFileListWithoutVcs(dir: Path): seq[string] =
205205
## its subdirectories.
206206
for file in walkDirRec($dir, yieldFilter = {pcFile, pcLinkToFile},
207207
relative = true):
208+
when defined(windows):
209+
# On windows relative paths to files which are included in the calculation
210+
# of the package checksum must be the same as on POSIX systems.
211+
let file = file.replace('\\', '/')
208212
result.add file
209213

210214
proc getPackageFileList*(dir: Path): seq[string] =
@@ -1061,7 +1065,6 @@ username = John Doe <[email protected]>
10611065
check not isValidSha1Hash($getVcsRevision(testNoVcsDir))
10621066

10631067
test "getPackageFileList":
1064-
check getPackageFileList(testNoVcsDir) ==
1065-
@[testFile, testSubDirFile.normalizedPath]
1068+
check getPackageFileList(testNoVcsDir) == @[testFile, testSubDirFile]
10661069

10671070
tearDownSuite(testNoVcsDir)

0 commit comments

Comments
 (0)