Skip to content

Commit

Permalink
Merge pull request nim-lang#937 from bobeff/bugfix/symlinks-checksums
Browse files Browse the repository at this point in the history
Fix a bug when including symbolic link files to the package's checksum.
  • Loading branch information
Araq authored Sep 10, 2021
2 parents 7957048 + 7a2f2fd commit 820e609
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 19 deletions.
46 changes: 30 additions & 16 deletions src/nimblepkg/checksums.nim
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,36 @@ proc updateSha1Checksum(checksum: var Sha1State, fileName, filePath: string) =
# directory from which no files are being installed.
return
checksum.update(fileName)
var file: File
try:
file = filePath.open(fmRead)
except IOError:
## If the file cannot be open for reading do not count its content in the
## checksum.
displayWarning(&"The file \"{filePath}\" cannot be open for reading.\n" &
"Skipping it in the calculation of the checksum.")
return
defer: close(file)
const bufferSize = 8192
var buffer = newString(bufferSize)
while true:
var bytesRead = readChars(file, buffer)
if bytesRead == 0: break
checksum.update(buffer.toOpenArray(0, bytesRead - 1))
if symlinkExists(filePath):
# Check whether a file is a symbolic link and if so update the checksum with
# the path to the file that the link points to.
var linkPath: string
try:
linkPath = expandSymlink(filePath)
except OSError:
displayWarning(&"Cannot expand symbolic link \"{filePath}\".\n" &
"Skipping it in the calculation of the checksum.")
return
checksum.update(linkPath)
else:
# Otherwise this is an ordinary file and we are adding its content to the
# checksum.
var file: File
try:
file = filePath.open(fmRead)
except IOError:
## If the file cannot be open for reading do not count its content in the
## checksum.
displayWarning(&"The file \"{filePath}\" cannot be open for reading.\n" &
"Skipping it in the calculation of the checksum.")
return
defer: close(file)
const bufferSize = 8192
var buffer = newString(bufferSize)
while true:
var bytesRead = readChars(file, buffer)
if bytesRead == 0: break
checksum.update(buffer.toOpenArray(0, bytesRead - 1))

proc calculateDirSha1Checksum*(dir: string): Sha1Hash =
## Recursively calculates the sha1 checksum of the contents of the directory
Expand Down
19 changes: 19 additions & 0 deletions src/nimblepkg/download.nim
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,25 @@ proc doDownloadTarball(url, downloadDir, version: string, queryRevision: bool):
raise nimbleError(tryDoCmdExErrorMessage(cmd, output, exitCode))
display("Completed", "unpacking " & filePath)

when defined(windows):
# On Windows symbolic link files are not being extracted properly by the
# `tar` command. They are extracted as empty files, but when cloning the
# repository with Git they are extracted as ordinary files with the link
# path in them. For that reason here we parse the tar file content to
# extract the symbolic links and add their paths manually to the content of
# their files.
let listCmd = &"{getTarExePath()} -ztvf {filePath} --force-local"
let (cmdOutput, cmdExitCode) = doCmdEx(listCmd)
if cmdExitCode != QuitSuccess:
raise nimbleError(tryDoCmdExErrorMessage(listCmd, cmdOutput, cmdExitCode))
for line in cmdOutput.splitLines():
if line.contains(" -> "):
let parts = line.split
let linkPath = parts[^1]
let linkNameParts = parts[^3].split('/')
let linkName = linkNameParts[1 .. ^1].foldl(a / b)
writeFile(downloadDir / linkName, linkPath)

filePath.removeFile
return if queryRevision: getRevision(url, version) else: notSetSha1Hash

Expand Down
10 changes: 7 additions & 3 deletions src/nimblepkg/vcstools.nim
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,12 @@ proc getVcsRevision*(dir: Path): Sha1Hash =
proc getPackageFileListWithoutVcs(dir: Path): seq[string] =
## Recursively walks the directory `dir` and returns a list of files in it and
## its subdirectories.
for file in walkDirRec($dir, relative = true):
for file in walkDirRec($dir, yieldFilter = {pcFile, pcLinkToFile},
relative = true):
when defined(windows):
# On windows relative paths to files which are included in the calculation
# of the package checksum must be the same as on POSIX systems.
let file = file.replace('\\', '/')
result.add file

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

test "getPackageFileList":
check getPackageFileList(testNoVcsDir) ==
@[testFile, testSubDirFile.normalizedPath]
check getPackageFileList(testNoVcsDir) == @[testFile, testSubDirFile]

tearDownSuite(testNoVcsDir)

0 comments on commit 820e609

Please sign in to comment.