Skip to content

Commit 820e609

Browse files
authored
Merge pull request #937 from bobeff/bugfix/symlinks-checksums
Fix a bug when including symbolic link files to the package's checksum.
2 parents 7957048 + 7a2f2fd commit 820e609

File tree

3 files changed

+56
-19
lines changed

3 files changed

+56
-19
lines changed

src/nimblepkg/checksums.nim

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,36 @@ proc updateSha1Checksum(checksum: var Sha1State, fileName, filePath: string) =
2525
# directory from which no files are being installed.
2626
return
2727
checksum.update(fileName)
28-
var file: File
29-
try:
30-
file = filePath.open(fmRead)
31-
except IOError:
32-
## If the file cannot be open for reading do not count its content in the
33-
## checksum.
34-
displayWarning(&"The file \"{filePath}\" cannot be open for reading.\n" &
35-
"Skipping it in the calculation of the checksum.")
36-
return
37-
defer: close(file)
38-
const bufferSize = 8192
39-
var buffer = newString(bufferSize)
40-
while true:
41-
var bytesRead = readChars(file, buffer)
42-
if bytesRead == 0: break
43-
checksum.update(buffer.toOpenArray(0, bytesRead - 1))
28+
if symlinkExists(filePath):
29+
# Check whether a file is a symbolic link and if so update the checksum with
30+
# the path to the file that the link points to.
31+
var linkPath: string
32+
try:
33+
linkPath = expandSymlink(filePath)
34+
except OSError:
35+
displayWarning(&"Cannot expand symbolic link \"{filePath}\".\n" &
36+
"Skipping it in the calculation of the checksum.")
37+
return
38+
checksum.update(linkPath)
39+
else:
40+
# Otherwise this is an ordinary file and we are adding its content to the
41+
# checksum.
42+
var file: File
43+
try:
44+
file = filePath.open(fmRead)
45+
except IOError:
46+
## If the file cannot be open for reading do not count its content in the
47+
## checksum.
48+
displayWarning(&"The file \"{filePath}\" cannot be open for reading.\n" &
49+
"Skipping it in the calculation of the checksum.")
50+
return
51+
defer: close(file)
52+
const bufferSize = 8192
53+
var buffer = newString(bufferSize)
54+
while true:
55+
var bytesRead = readChars(file, buffer)
56+
if bytesRead == 0: break
57+
checksum.update(buffer.toOpenArray(0, bytesRead - 1))
4458

4559
proc calculateDirSha1Checksum*(dir: string): Sha1Hash =
4660
## Recursively calculates the sha1 checksum of the contents of the directory

src/nimblepkg/download.nim

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,25 @@ 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+
for line in cmdOutput.splitLines():
324+
if line.contains(" -> "):
325+
let parts = line.split
326+
let linkPath = parts[^1]
327+
let linkNameParts = parts[^3].split('/')
328+
let linkName = linkNameParts[1 .. ^1].foldl(a / b)
329+
writeFile(downloadDir / linkName, linkPath)
330+
312331
filePath.removeFile
313332
return if queryRevision: getRevision(url, version) else: notSetSha1Hash
314333

src/nimblepkg/vcstools.nim

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,12 @@ proc getVcsRevision*(dir: Path): Sha1Hash =
203203
proc getPackageFileListWithoutVcs(dir: Path): seq[string] =
204204
## Recursively walks the directory `dir` and returns a list of files in it and
205205
## its subdirectories.
206-
for file in walkDirRec($dir, relative = true):
206+
for file in walkDirRec($dir, yieldFilter = {pcFile, pcLinkToFile},
207+
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('\\', '/')
207212
result.add file
208213

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

10621067
test "getPackageFileList":
1063-
check getPackageFileList(testNoVcsDir) ==
1064-
@[testFile, testSubDirFile.normalizedPath]
1068+
check getPackageFileList(testNoVcsDir) == @[testFile, testSubDirFile]
10651069

10661070
tearDownSuite(testNoVcsDir)

0 commit comments

Comments
 (0)