func copyFile()

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())
}