utils/file.go (89 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package utils import ( "io" "io/ioutil" "os" "path" "path/filepath" "github.com/apache/openwhisk-wskdeploy/wskprint" ) // check if the path represents file path or dir path func isFilePath(path string) bool { // when split returns dir and file, splitting path on the final "/" // check if file is not empty to classify that path as a file path _, file := filepath.Split(path) if len(file) == 0 { return false } return true } // check if the given path exists as a file func isFile(path string) (bool, error) { var err error var info os.FileInfo // run stat on the file and if the it returns no error, // read the fileInfo to check if its a file or not if info, err = os.Stat(path); err == nil { if info.Mode().IsRegular() { return true, nil } } // stat returned an error and here we are checking if it was os.PathError if !os.IsNotExist(err) { return false, nil } // after running through all the possible checks, return false and an err return false, err } // copy one single source file to the destination path 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()) } // recursively copy the entire source directory to destination path func copyDir(src, dst string) error { var err error var fileDescriptors []os.FileInfo var srcInfo os.FileInfo // retrieve os.fileInfo of the source directory if srcInfo, err = os.Stat(src); err != nil { return err } // create destination directory with parent directories if err = os.MkdirAll(dst, srcInfo.Mode()); err != nil { return err } // now, retrieve all the directory/file entries under the source directory if fileDescriptors, err = ioutil.ReadDir(src); err != nil { return err } // iterating over the entire list of files/directories under the destination path // run copyFile or recursive copyDir based on if its file or dir for _, fd := range fileDescriptors { srcFilePath := path.Join(src, fd.Name()) dstFilePath := path.Join(dst, fd.Name()) if fd.IsDir() { if err = copyDir(srcFilePath, dstFilePath); err != nil { return err } } else { if err = copyFile(srcFilePath, dstFilePath); err != nil { return err } } } return nil }