<commit_before>// Package fileutils wraps or implements common file operations with familiar function names.
package fileutils

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
)

// ChmodR is like `chmod -R`
func ChmodR(name string, mode os.FileMode) error {
	return filepath.Walk(name, func(path string, info os.FileInfo, err error) error {
		if err == nil {
			err = os.Chmod(path, mode)
		}
		return err
	})
}

// ChownR is like `chown -R`
func ChownR(path string, uid, gid int) error {
	return filepath.Walk(path, func(name string, info os.FileInfo, err error) error {
		if err == nil {
			err = os.Chown(name, uid, gid)
		}
		return err
	})
}

// Cp is like `cp`
func Cp(src, dest string) (err error) {
	return cpFollowLinks(src, dest)
}

func cpSymlink(src, dest string) (err error) {
	var linkTarget string
	linkTarget, err = os.Readlink(src)
	if err != nil {
		return
	}

	if err = os.Symlink(linkTarget, dest); err != nil {
		return
	}

	//preserve file permissions on copying
	return cpSymlinkPermissions(linkTarget, dest)

}

func cpSymlinkPermissions(linkTarget, dest string) (err error) {
	linkTargetInfo, err := os.Stat(linkTarget)
	if err != nil {
		return err
	}

	destMode := linkTargetInfo.Mode()

	if err = os.Chmod(dest, destMode); err != nil {
		return
	}
	return nil
}

func cpFollowLinks(src, dest string) (err error) {

	// get info on src
	si, err := os.Lstat(src)
	if err != nil {
		return
	}

	destMode := si.Mode()

	var linkTarget string

	if !si.Mode().IsRegular() {
		linkTarget, err = os.Readlink(src)
		if err != nil {
			return err
		}
	}

	//open source
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

	//create dest
	out, err := os.Create(dest)
	if err != nil {
		return
	}
	defer func() {
		cerr := out.Close()
		if err == nil {
			err = cerr
		}
	}()

	//copy to dest from source
	if _, err = io.Copy(out, in); err != nil {
		return
	}

	if linkTarget == "" {
		if err = out.Chmod(destMode); err != nil {
			return
		}

	} else {
		if err = cpSymlinkPermissions(linkTarget, dest); err != nil {
			return
		}

	}

	//sync dest to disk
	err = out.Sync()

	return
}

func cpPreserveLinks(src, dest string) (err error) {
	// get info on src
	si, err := os.Lstat(src)
	if err != nil {
		return
	}

	// handle symlinks
	if !si.Mode().IsRegular() {
		return cpSymlink(src, dest)
	}

	//open source
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()<commit_msg>[OOPS] not trying ot be as clever with symlink permissions<commit_after>// Package fileutils wraps or implements common file operations with familiar function names.
package fileutils

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
)

// ChmodR is like `chmod -R`
func ChmodR(name string, mode os.FileMode) error {
	return filepath.Walk(name, func(path string, info os.FileInfo, err error) error {
		if err == nil {
			err = os.Chmod(path, mode)
		}
		return err
	})
}

// ChownR is like `chown -R`
func ChownR(path string, uid, gid int) error {
	return filepath.Walk(path, func(name string, info os.FileInfo, err error) error {
		if err == nil {
			err = os.Chown(name, uid, gid)
		}
		return err
	})
}

// Cp is like `cp`
func Cp(src, dest string) (err error) {
	return cpFollowLinks(src, dest)
}

func cpSymlink(src, dest string) (err error) {
	var linkTarget string
	linkTarget, err = os.Readlink(src)
	if err != nil {
		return
	}

	return os.Symlink(linkTarget, dest)
}

func cpFollowLinks(src, dest string) (err error) {
	// get info on src
	si, err := os.Lstat(src)
	if err != nil {
		return
	}

	//open src
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

	//create dest
	out, err := os.Create(dest)
	if err != nil {
		return
	}
	defer func() {
		cerr := out.Close()
		if err == nil {
			err = cerr
		}
	}()

	//copy to dest from source
	if _, err = io.Copy(out, in); err != nil {
		return
	}

	if err = out.Chmod(si.Mode()); err != nil {
		return
	}

	//sync dest to disk
	err = out.Sync()

	return
}

func cpPreserveLinks(src, dest string) (err error) {
	// get info on src
	si, err := os.Lstat(src)
	if err != nil {
		return
	}

	// handle symlinks
	if !si.Mode().IsRegular() {
		return cpSymlink(src, dest)
	}

	//open source
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()
{'fraction_non_alphanumeric': 0.13985691207015924, 'fraction_numerical': 0.0, 'mean_word_length': 3.009250693802035, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2519078', 'n_tokens_mistral': 1752, 'n_tokens_neox': 1654, 'n_words': 508}