in utils/file.go [61:112]
func copyFile(src, dst string) error {
var err error
var sourceFD *os.File
var destFD *os.File
var srcInfo os.FileInfo
var srcDirInfo os.FileInfo
wskprint.PrintlnOpenWhiskVerbose(Flags.Verbose, "Source File ["+src+"] is being copied to ["+dst+"]")
// open source file to read it from disk and defer to close the file
// once this function is done executing
if sourceFD, err = os.Open(src); err != nil {
return err
}
defer sourceFD.Close()
// running stat on Dir(src), Dir returns all but the last element of the src
// this info is needed in case when a destination path has a directory structure which does not exist
if srcDirInfo, err = os.Stat(filepath.Dir(src)); err != nil {
return err
}
// check if the parent directory exist before creating a destination file
// create specified path along with creating any parent directory
// e.g. when destination is greeting/common/utils.js and parent dir common
// doesn't exist, its getting created here at greeting/common
if _, err = os.Stat(filepath.Dir(dst)); os.IsNotExist(err) {
wskprint.PrintlnOpenWhiskVerbose(Flags.Verbose, "Creating directory pattern ["+filepath.Dir(dst)+"] before creating destination file")
if err = os.MkdirAll(filepath.Dir(dst), srcDirInfo.Mode()); err != nil {
return err
}
}
// create destination file before copying source content
// defer closing the destination file until the function is done executing
if destFD, err = os.Create(dst); err != nil {
return err
}
defer destFD.Close()
// now, actually copy the source file content into destination file
if _, err = io.Copy(destFD, sourceFD); err != nil {
return err
}
// retrieve the file mode bits of the source file
// so that the bits can be set to the destination file
if srcInfo, err = os.Stat(src); err != nil {
return err
}
return os.Chmod(dst, srcInfo.Mode())
}