fix: trust .dump extension when file doesn't exist in DetectArchiveFormat
The format detection now returns PostgreSQL Dump format for .dump files when the file cannot be opened (e.g., when just checking filename pattern), instead of falling back to SQL format. This fixes the test that passes just a filename string without an actual file.
This commit is contained in:
@@ -1,24 +1,24 @@
|
|||||||
package restore
|
package restore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ArchiveFormat represents the type of backup archive
|
// ArchiveFormat represents the type of backup archive
|
||||||
type ArchiveFormat string
|
type ArchiveFormat string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FormatPostgreSQLDump ArchiveFormat = "PostgreSQL Dump (.dump)"
|
FormatPostgreSQLDump ArchiveFormat = "PostgreSQL Dump (.dump)"
|
||||||
FormatPostgreSQLDumpGz ArchiveFormat = "PostgreSQL Dump Compressed (.dump.gz)"
|
FormatPostgreSQLDumpGz ArchiveFormat = "PostgreSQL Dump Compressed (.dump.gz)"
|
||||||
FormatPostgreSQLSQL ArchiveFormat = "PostgreSQL SQL (.sql)"
|
FormatPostgreSQLSQL ArchiveFormat = "PostgreSQL SQL (.sql)"
|
||||||
FormatPostgreSQLSQLGz ArchiveFormat = "PostgreSQL SQL Compressed (.sql.gz)"
|
FormatPostgreSQLSQLGz ArchiveFormat = "PostgreSQL SQL Compressed (.sql.gz)"
|
||||||
FormatMySQLSQL ArchiveFormat = "MySQL SQL (.sql)"
|
FormatMySQLSQL ArchiveFormat = "MySQL SQL (.sql)"
|
||||||
FormatMySQLSQLGz ArchiveFormat = "MySQL SQL Compressed (.sql.gz)"
|
FormatMySQLSQLGz ArchiveFormat = "MySQL SQL Compressed (.sql.gz)"
|
||||||
FormatClusterTarGz ArchiveFormat = "Cluster Archive (.tar.gz)"
|
FormatClusterTarGz ArchiveFormat = "Cluster Archive (.tar.gz)"
|
||||||
FormatUnknown ArchiveFormat = "Unknown"
|
FormatUnknown ArchiveFormat = "Unknown"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DetectArchiveFormat detects the format of a backup archive from its filename and content
|
// DetectArchiveFormat detects the format of a backup archive from its filename and content
|
||||||
@@ -30,20 +30,25 @@ func DetectArchiveFormat(filename string) ArchiveFormat {
|
|||||||
return FormatClusterTarGz
|
return FormatClusterTarGz
|
||||||
}
|
}
|
||||||
|
|
||||||
// For .dump files, check if they're actually custom format or SQL text
|
// For .dump files, assume PostgreSQL custom format based on extension
|
||||||
|
// If the file exists and can be read, verify with magic bytes
|
||||||
if strings.HasSuffix(lower, ".dump.gz") {
|
if strings.HasSuffix(lower, ".dump.gz") {
|
||||||
if isCustomFormat(filename, true) {
|
// Check if file exists and has content signature
|
||||||
|
result := isCustomFormat(filename, true)
|
||||||
|
// If file doesn't exist or we can't read it, trust the extension
|
||||||
|
// If file exists and has PGDMP signature, it's custom format
|
||||||
|
// If file exists but doesn't have signature, it might be SQL named as .dump
|
||||||
|
if result == formatCheckCustom || result == formatCheckFileNotFound {
|
||||||
return FormatPostgreSQLDumpGz
|
return FormatPostgreSQLDumpGz
|
||||||
}
|
}
|
||||||
// If not custom format, treat as SQL
|
|
||||||
return FormatPostgreSQLSQLGz
|
return FormatPostgreSQLSQLGz
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasSuffix(lower, ".dump") {
|
if strings.HasSuffix(lower, ".dump") {
|
||||||
if isCustomFormat(filename, false) {
|
result := isCustomFormat(filename, false)
|
||||||
|
if result == formatCheckCustom || result == formatCheckFileNotFound {
|
||||||
return FormatPostgreSQLDump
|
return FormatPostgreSQLDump
|
||||||
}
|
}
|
||||||
// If not custom format, treat as SQL
|
|
||||||
return FormatPostgreSQLSQL
|
return FormatPostgreSQLSQL
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,11 +77,21 @@ func DetectArchiveFormat(filename string) ArchiveFormat {
|
|||||||
return FormatUnknown
|
return FormatUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// formatCheckResult represents the result of checking file format
|
||||||
|
type formatCheckResult int
|
||||||
|
|
||||||
|
const (
|
||||||
|
formatCheckFileNotFound formatCheckResult = iota
|
||||||
|
formatCheckCustom
|
||||||
|
formatCheckNotCustom
|
||||||
|
)
|
||||||
|
|
||||||
// isCustomFormat checks if a file is PostgreSQL custom format (has PGDMP signature)
|
// isCustomFormat checks if a file is PostgreSQL custom format (has PGDMP signature)
|
||||||
func isCustomFormat(filename string, compressed bool) bool {
|
func isCustomFormat(filename string, compressed bool) formatCheckResult {
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
// File doesn't exist or can't be opened - return file not found
|
||||||
|
return formatCheckFileNotFound
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
@@ -86,7 +101,7 @@ func isCustomFormat(filename string, compressed bool) bool {
|
|||||||
if compressed {
|
if compressed {
|
||||||
gz, err := gzip.NewReader(file)
|
gz, err := gzip.NewReader(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return formatCheckFileNotFound
|
||||||
}
|
}
|
||||||
defer gz.Close()
|
defer gz.Close()
|
||||||
reader = gz
|
reader = gz
|
||||||
@@ -96,10 +111,13 @@ func isCustomFormat(filename string, compressed bool) bool {
|
|||||||
buffer := make([]byte, 5)
|
buffer := make([]byte, 5)
|
||||||
n, err := reader.Read(buffer)
|
n, err := reader.Read(buffer)
|
||||||
if err != nil || n < 5 {
|
if err != nil || n < 5 {
|
||||||
return false
|
return formatCheckNotCustom
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(buffer) == "PGDMP"
|
if string(buffer) == "PGDMP" {
|
||||||
|
return formatCheckCustom
|
||||||
|
}
|
||||||
|
return formatCheckNotCustom
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsCompressed returns true if the archive format is compressed
|
// IsCompressed returns true if the archive format is compressed
|
||||||
|
|||||||
Reference in New Issue
Block a user