Для тестирования:
Вы можете передать смоделированную переменную zipFile
, которая влияет на интерфейс io.Writer
, в качестве аргумента для функции zipit
и сравнить ее с ожидаемыми данными втест.
Также вам понадобится известный набор файлов в месте назначения, чтобы вы сравнили его со значением в макете.
См. Это для тестирования io.Writer
Код тестирования:
Строковое значение сжатого файла, созданного с конкретными значениями source
& newBaseDir
, должно быть заранее известно и сохранено в want
.
func TestZipIt(t *testing.T) {
source := ""
newBaseDir := ""
var zipFileMock bytes.Buffer
if err := zipit(zipFileMock, source, newBaseDir); err != nil {
t.Fatalf("zipit() returned an error: %s", err)
}
got := b.String()
// want is the value of the zipped file as a string
want := ...
if got != want {
t.Errorf("zipit() test failed")
// t.Errorf("zipit() = %q, want %q", got, want)
}
}
Программный код:
func main() {
...
// params[0] is source
// params[1] is destination
// params[2] is newBaseDirectory
zipfile, err := os.Create(destination)
if err != nil {
// handle error
}
defer zipfile.Close()
if err = zipit(zipfile, source, newBaseDir); err != nil {
// handle error
}
...
}
func zipit(zipFile io.Writer, source, newBaseDir string) error {
archive := zip.NewWriter(zipfile)
defer archive.Close()
info, err := os.Stat(source)
if err != nil {
return err
}
var baseDir string
if info.IsDir() {
baseDir = filepath.Dir(source)
}
if baseDir != "" {
baseDir += "/"
}
filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
if baseDir != "" {
header.Name = filepath.Join(newBaseDir, strings.TrimPrefix(path, baseDir))
}
header.Method = zip.Deflate
writer, err := archive.CreateHeader(header)
if err != nil {
return err
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
return err
})
return err
}
Оригинальный ответ:
Есть несколько вещей, которые следует учитывать.
Вам нужно использовать filepath.Dir
вместо filepath.Base
.Base дает последний элемент пути, а не базовый каталог.
if info.IsDir(); len(params) > 2 {
только проверяет условие len(params) > 2
, info.IsDir()
вычисляется, но нигде не используется.
См .: Если с кратким форматом выписки в Go [1] [2]
Должно быть
if info.IsDir() {
if len(params) > 2 {
...
} else {
...
}
}
- Если мое понимание вашего требования верно.Старый базовый путь должен быть удален из заголовков файла и заменен значением param [2], если оно доступно, или предполагается, что мы сохраняем относительную файловую структуру, если она пуста.
Изменения:
var baseDir string
if info.IsDir(); len(params) > 2 {
baseDir = params[2]
} else {
baseDir = filepath.Base(params[0])
}
должно быть
var baseDir, newBaseDir string
if info.IsDir() {
baseDir = filepath.Dir(params[0])
if len(params) > 2 {
newBaseDir = params[2]
}
}
И
header.Name = filepath.Join(strings.TrimPrefix(path, baseDir))
становится
header.Name = filepath.Join(newBaseDir, strings.TrimPrefix(path, baseDir))