cmd/aebundler/aebundler.go
func copyTree(tw *tar.Writer, dstDir, srcDir string) error {
	entries, err := ioutil.ReadDir(srcDir)
	if err != nil {
		return fmt.Errorf("unable to read dir %v: %v", srcDir, err)
	}
	for _, entry := range entries {
		n := entry.Name()
		if skipFiles[n] {
			continue
		}
		s := filepath.Join(srcDir, n)
		d := filepath.Join(dstDir, n)
		if entry.IsDir() {
			if err := copyTree(tw, d, s); err != nil {
				return fmt.Errorf("unable to copy dir %v to %v: %v", s, d, err)
			}
			continue
		}
		if err := copyFile(tw, d, s); err != nil {
			return fmt.Errorf("unable to copy dir %v to %v: %v", s, d, err)
		}
	}
	return nil
}
func copyTree(tw *tar.Writer, dstDir, srcDir string) error {
	entries, err := ioutil.ReadDir(srcDir)
	if err != nil {
		return fmt.Errorf("unable to read dir %v: %v", srcDir, err)
	}
	for _, entry := range entries {
		n := entry.Name()
		if skipFiles[n] {
			continue
		}
		s := filepath.Join(srcDir, n)
		d := filepath.Join(dstDir, n)
		if entry.IsDir() {
			if err := copyTree(tw, d, s); err != nil {
				return fmt.Errorf("unable to copy dir %v to %v: %v", s, d, err)
			}
			continue
		}
		if err := copyFile(tw, d, s); err != nil {
			return fmt.Errorf("unable to copy dir %v to %v: %v", s, d, err)
		}
	}
	return nil
}
// copyTree copies srcDir to tar file dstDir, ignoring skipFiles.