package configui import ( "archive/tar" "compress/gzip" "io" "os" "path/filepath" "reflect" "strings" "sync" ) func bundle(buf io.Writer, paths []string, rootDir string, flat bool) error { gw := gzip.NewWriter(buf) defer gw.Close() tw := tar.NewWriter(gw) defer tw.Close() for _, file := range paths { if err := func(file string) error { f, err := os.Open(file) if err != nil { return err } defer f.Close() info, err := f.Stat() if err != nil { return err } header, err := tar.FileInfoHeader(info, info.Name()) if err != nil { return err } // Use full path as name (FileInfoHeader only takes the basename) // If we don't do this the directory strucuture would // not be preserved // https://golang.org/src/archive/tar/common.go?#L626 if !flat { if !strings.HasPrefix(file, "/") { file = rootDir + "/" + file } else { file = rootDir + file } header.Name = file } // Write file header to the tar archive err = tw.WriteHeader(header) if err != nil { return err } // Copy file content to tar archive _, err = io.Copy(tw, f) if err != nil { return err } return nil }(file); err != nil { return err } } return nil } func mkdir(args ...interface{}) error { var path string var mode os.FileMode mode = 0755 for _, arg := range args { switch arg := arg.(type) { case string: path = filepath.Join(path, arg) case os.FileMode: mode = arg } } return os.MkdirAll(path, mode) } const mutexLocked = 1 func MutexLocked(m *sync.Mutex) bool { state := reflect.ValueOf(m).Elem().FieldByName("state") return state.Int()&mutexLocked == mutexLocked }