diff --git a/README.md b/README.md index b7487346..fafb0f6b 100644 --- a/README.md +++ b/README.md @@ -63,16 +63,18 @@ $ go get github.com/mholt/archiver/v4 Creating archives can be done entirely without needing a real disk or storage device since all you need is a list of [`File` structs](https://pkg.go.dev/github.com/mholt/archiver/v4#File) to pass in. -However, creating archives from files on disk is very common, so you can use the `FilesFromDisk()` function to help you map filenames on disk to their paths in the archive. Then create and customize the format type. +However, creating archives from files on disk is very common, so you can use the [`FilesFromDisk()` function](https://pkg.go.dev/github.com/mholt/archiver/v4#FilesFromDisk) to help you map filenames on disk to their paths in the archive. Then create and customize the format type. -In this example, we add 2 files and a directory (which includes its contents recursively) to a .tar.gz file: +In this example, we add 4 files and a directory (which includes its contents recursively) to a .tar.gz file: ```go // map files on disk to their paths in the archive -files, err := archiver.FilesFromDisk(map[string]string{ +files, err := archiver.FilesFromDisk(nil, map[string]string{ "/path/on/disk/file1.txt": "file1.txt", "/path/on/disk/file2.txt": "subfolder/file2.txt", - "/path/on/disk/folder": "", + "/path/on/disk/file3.txt": "", // put in root of archive as file3.txt + "/path/on/disk/file4.txt": "subfolder/", // put in subfolder as file4.txt + "/path/on/disk/folder": "Custom Folder", // contents added recursively }) if err != nil { return err @@ -99,6 +101,8 @@ if err != nil { } ``` +The first parameter to `FilesFromDisk()` is an optional options struct, allowing you to customize how files are added. + ### Extract archive Extracting an archive, extracting _from_ an archive, and walking an archive are all the same function. diff --git a/archiver.go b/archiver.go index a763a4fe..da7176e5 100644 --- a/archiver.go +++ b/archiver.go @@ -45,18 +45,23 @@ func (f File) Stat() (fs.FileInfo, error) { return f.FileInfo, nil } // given filenames map. The keys are the names on disk, and the values are // their associated names in the archive. For convenience, empty values are // interpreted as the base name of the file (sans path) in the root of the -// archive. Keys that specify directories on disk will be walked and added -// to the archive recursively, rooted at the named directory. +// archive; and values that end in a slash will use the bae name of the file +// in that folder of the archive. Keys that specify directories on disk will +// be walked and added to the archive recursively, rooted at the named +// directory. // // File gathering will adhere to the settings specified in options. // // This function is primarily used when preparing a list of files to add to // an archive. -func FilesFromDisk(options FromDiskOptions, filenames map[string]string) ([]File, error) { +func FilesFromDisk(options *FromDiskOptions, filenames map[string]string) ([]File, error) { var files []File for rootOnDisk, rootInArchive := range filenames { if rootInArchive == "" { - rootInArchive = filepath.Base(rootInArchive) + rootInArchive = filepath.Base(rootOnDisk) + } + if strings.HasSuffix(rootInArchive, "/") { + rootInArchive += filepath.Base(rootOnDisk) } filepath.WalkDir(rootOnDisk, func(filename string, d fs.DirEntry, err error) error { @@ -73,7 +78,7 @@ func FilesFromDisk(options FromDiskOptions, filenames map[string]string) ([]File var linkTarget string if isSymlink(info) { - if options.FollowSymlinks { + if options != nil && options.FollowSymlinks { // dereference symlinks filename, err = os.Readlink(filename) if err != nil {