-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
image/manifest: Recursively remove pre-existing entries when unpacking #42
image/manifest: Recursively remove pre-existing entries when unpacking #42
Conversation
Implementing the logic that is in-flight with [1], but using recursive removal [2]. GNU tar has a --recursive-unlink option that's not enabled by default, with the motivation being something like "folks would be mad if we blew away a full tree and replaced it with a broken symlink" [3]. That makes sense for working filesystems, but we're building the rootfs from scratch here so losing information is not a concern. This commit always uses recursive removal to get that old thing off the filesystem (whatever it takes ;). The exception to the removal is if both the tar entry and existing path occupant are directories. In this case we want to use GNU tar's default --overwrite-dir behavior, but unpackLayer's metadata handling is currently very weak so I've left it at "don't delete the old directory". The reworked directory case also fixes a minor bug from 44210d0 (cmd/oci-image-tool: fix unpacking..., 2016-07-22, opencontainers#177) where the: if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) { block would not error out if the Lstat failed for a reason besides the acceptable IsNotExist. Instead, it would attempt to call MkdirAll, which would probably fail for the same reason that Lstat failed (e.g. ENOTDIR). But it's better to handle the Lstat errors directly. [1]: opencontainers/image-spec#317 [2]: https://github.com/opencontainers/image-spec/pull/317/files#r79214718 [3]: https://www.gnu.org/software/tar/manual/html_node/Dealing-with-Old-Files.html Signed-off-by: W. Trevor King <wking@tremily.us>
81825a0
to
6055f4d
Compare
To help address: $ make lint checking lint image/manifest.go:140::warning: cyclomatic complexity 39 of function unpackLayer() is high (> 35) (gocyclo) ... Signed-off-by: W. Trevor King <wking@tremily.us>
4ddda11
to
bb40ed1
Compare
I've pushed an additional bb40ed1 to address the cyclomatic complexity warning, and Travis is happy now. |
} | ||
err = os.MkdirAll(path, info.Mode()) | ||
if err != nil { | ||
return err | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A debatable view: if it is easier to understand to use like below?
fi, err := os.Lstat(path)
if err==nil{
...
}else if os.IsNotExist(err){
...
}else if err!=nil
...
}
And, if fi, err := os.Lstat(path)
can be replaced to upper lines, like
fi, err := os.Lstat(path)
if err == nil && !fi.IsDir() {
remove path
}else if !os.IsNotExist(err){
return err
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both of your proposals will end up duplicating the MkdirAll
call. And idiomatic Go seems to be “check for and exit on unrecoverable errors as quickly as possible” (which is how I handle it now with the if err != nil && !os.IsNotExist(err)
). But I don't really care. If the maintainers feel that avoiding !
s in the conditionals is worth pushing the unrecoverable error to the end of the case
block, I can reroll to do so.
ping @coolljt0725 @xiekeyang |
Implementing the logic that is in-flight with opencontainers/image-spec#317, but using recursive removal. GNU tar has a
--recursive-unlink
option that's not enabled by default, with the motivation being something like “folks would be mad if we blew away a full tree and replaced it with a broken symlink”. That makes sense for working filesystems, but we're building the rootfs from scratch here so losing information is not a concern. This commit always uses recursive removal to get that old thing off the filesystem (whatever it takes ;).The exception to the removal is if both the tar entry and existing path occupant are directories. In this case we want to use GNU tar's default
--overwrite-dir
behavior, butunpackLayer
's metadata handling is currently very weak (the in-flight #3 strengthens it a bit) so I've left it at “don't delete the old directory”.The reworked directory case also fixes a minor bug from 44210d0 (opencontainers/image-spec#177) where the:
block would not error out if the
Lstat
failed for a reason besides the acceptableIsNotExist
. Instead, it would attempt to callMkdirAll
, which would probably fail for the same reason thatLstat
failed (ENOTDIR?). But it's better to handle theLstat
errors directly.Fixes #41.