diff --git a/archive.go b/archive.go index a18d799..953527e 100644 --- a/archive.go +++ b/archive.go @@ -141,6 +141,17 @@ func (a *Archive) Extract(opts ExtractOptions) error { return extract(Filesystem{file: true}, opts, a) } +// ExtractFile extracts a specified file from an archive to a specified directory. +// It takes a file path, and ExtractFileOptions as its parameters. +// The function returns an error, if any. +func (a *Archive) ExtractFile(path string, opts ExtractFileOptions) error { + file, err := a.GetFile(path) + if err != nil { + return err + } + return file.Extract(opts) +} + // Close closes the Archive. // The function returns an error, if any. func (a *Archive) Close() error { diff --git a/archive_test.go b/archive_test.go index 293f311..3ba3a7a 100644 --- a/archive_test.go +++ b/archive_test.go @@ -92,30 +92,80 @@ func TestArchiveExtract(t *testing.T) { }) assert.NoError(t, err) + err = os.RemoveAll(testArchiveBaseDir + "/extracted/zip") + assert.NoError(t, err) + + t.Log("== ExtractFileZip ==") + err = ExtractFile(testArchiveBaseDir+"/test.zip", "test1.txt", ExtractFileOptions{ + Folder: testArchiveBaseDir + "/extracted/zip", + }) + assert.NoError(t, err) + assert.FileExists(t, testArchiveBaseDir+"/extracted/zip/test1.txt") + t.Log("== ExtractTar ==") err = Extract(testArchiveBaseDir+"/test.tar", ExtractOptions{ Folder: testArchiveBaseDir + "/extracted/tar", }) assert.NoError(t, err) + err = os.RemoveAll(testArchiveBaseDir + "/extracted/tar") + assert.NoError(t, err) + + t.Log("== ExtractFileTar ==") + err = ExtractFile(testArchiveBaseDir+"/test.tar", "test1.txt", ExtractFileOptions{ + Folder: testArchiveBaseDir + "/extracted/tar", + }) + assert.NoError(t, err) + assert.FileExists(t, testArchiveBaseDir+"/extracted/tar/test1.txt") + t.Log("== ExtractTarXz ==") err = Extract(testArchiveBaseDir+"/test.tar.xz", ExtractOptions{ Folder: testArchiveBaseDir + "/extracted/xz", }) assert.NoError(t, err) + err = os.RemoveAll(testArchiveBaseDir + "/extracted/xz") + assert.NoError(t, err) + + t.Log("== ExtractFileTarXz ==") + err = ExtractFile(testArchiveBaseDir+"/test.tar.xz", "test1.txt", ExtractFileOptions{ + Folder: testArchiveBaseDir + "/extracted/xz", + }) + assert.NoError(t, err) + assert.FileExists(t, testArchiveBaseDir+"/extracted/xz/test1.txt") + t.Log("== ExtractTarBz ==") err = Extract(testArchiveBaseDir+"/test.tar.bz2", ExtractOptions{ Folder: testArchiveBaseDir + "/extracted/bzip", }) assert.NoError(t, err) + err = os.RemoveAll(testArchiveBaseDir + "/extracted/bzip") + assert.NoError(t, err) + + t.Log("== ExtractFileTarBz ==") + err = ExtractFile(testArchiveBaseDir+"/test.tar.bz2", "test1.txt", ExtractFileOptions{ + Folder: testArchiveBaseDir + "/extracted/bzip", + }) + assert.NoError(t, err) + assert.FileExists(t, testArchiveBaseDir+"/extracted/bzip/test1.txt") + t.Log("== ExtractTarGz ==") err = Extract(testArchiveBaseDir+"/test.tar.gz", ExtractOptions{ Folder: testArchiveBaseDir + "/extracted/gz", }) assert.NoError(t, err) + err = os.RemoveAll(testArchiveBaseDir + "/extracted/gz") + assert.NoError(t, err) + + t.Log("== ExtractFileTarGz ==") + err = ExtractFile(testArchiveBaseDir+"/test.tar.gz", "test1.txt", ExtractFileOptions{ + Folder: testArchiveBaseDir + "/extracted/gz", + }) + assert.NoError(t, err) + assert.FileExists(t, testArchiveBaseDir+"/extracted/gz/test1.txt") + err = os.RemoveAll(testArchiveBaseDir + "/extracted") assert.NoError(t, err) diff --git a/open.go b/open.go index 4953d73..3e6b699 100644 --- a/open.go +++ b/open.go @@ -69,6 +69,30 @@ func Extract(path string, options ExtractOptions) error { return nil } +// ExtractFile opens an archive file and extracts a specific file within the archive. +// It takes a path, a file path, and ExtractFileOptions for its parameters. +// The function returns an error, if any. +func ExtractFile(path string, file string, options ExtractFileOptions) error { + archive, err := Open(path) + if err != nil { + return err + } + defer archive.Close() + + archiveFile, err := archive.GetFile(file) + if err != nil { + return err + } + + if err := archiveFile.Extract(options); err != nil { + return err + } + if err := archive.Close(); err != nil { + return err + } + return nil +} + func openArchive(filesystem Filesystem, path string) (*Archive, error) { archive := new(Archive) archive.files = make(map[string]*File)