mirror of
https://github.com/zrepl/zrepl.git
synced 2025-01-05 13:59:06 +01:00
parent
6f7467e8d8
commit
7d9a1b7eae
31
zfs/zfs.go
31
zfs/zfs.go
@ -577,10 +577,17 @@ type DrySendInfo struct {
|
||||
SizeEstimate int64 // -1 if size estimate is not possible
|
||||
}
|
||||
|
||||
var sendDryRunInfoLineRegex = regexp.MustCompile(`^(full|incremental)(\t(\S+))?\t(\S+)\t([0-9]+)$`)
|
||||
var (
|
||||
// keep same number of capture groups for unmarshalInfoLine homogenity
|
||||
|
||||
sendDryRunInfoLineRegexFull = regexp.MustCompile(`^(full)\t()([^\t]+@[^\t]+)\t([0-9]+)$`)
|
||||
// cannot enforce '[#@]' in incremental source, see test cases
|
||||
sendDryRunInfoLineRegexIncremental = regexp.MustCompile(`^(incremental)\t([^\t]+)\t([^\t]+@[^\t]+)\t([0-9]+)$`)
|
||||
)
|
||||
|
||||
// see test cases for example output
|
||||
func (s *DrySendInfo) unmarshalZFSOutput(output []byte) (err error) {
|
||||
debug("DrySendInfo.unmarshalZFSOutput: output=%q", output)
|
||||
lines := strings.Split(string(output), "\n")
|
||||
for _, l := range lines {
|
||||
regexMatched, err := s.unmarshalInfoLine(l)
|
||||
@ -592,7 +599,7 @@ func (s *DrySendInfo) unmarshalZFSOutput(output []byte) (err error) {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("no match for info line (regex %s)", sendDryRunInfoLineRegex)
|
||||
return fmt.Errorf("no match for info line (regex1 %s) (regex2 %s)", sendDryRunInfoLineRegexFull, sendDryRunInfoLineRegexIncremental)
|
||||
}
|
||||
|
||||
|
||||
@ -602,24 +609,32 @@ func (s *DrySendInfo) unmarshalZFSOutput(output []byte) (err error) {
|
||||
// => see test cases
|
||||
func (s *DrySendInfo) unmarshalInfoLine(l string) (regexMatched bool, err error) {
|
||||
|
||||
m := sendDryRunInfoLineRegex.FindStringSubmatch(l)
|
||||
if m == nil {
|
||||
mFull := sendDryRunInfoLineRegexFull.FindStringSubmatch(l)
|
||||
mInc := sendDryRunInfoLineRegexIncremental.FindStringSubmatch(l)
|
||||
var m []string
|
||||
if mFull == nil && mInc == nil {
|
||||
return false, nil
|
||||
} else if mFull != nil && mInc != nil {
|
||||
panic(fmt.Sprintf("ambiguous ZFS dry send output: %q", l))
|
||||
} else if mFull != nil {
|
||||
m = mFull
|
||||
} else if mInc != nil {
|
||||
m = mInc
|
||||
}
|
||||
s.Type, err = DrySendTypeFromString(m[1])
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
s.From = m[3]
|
||||
s.To = m[4]
|
||||
toFS, _, _ , err := DecomposeVersionString(s.To)
|
||||
s.From = m[2]
|
||||
s.To = m[3]
|
||||
toFS, _, _, err := DecomposeVersionString(s.To)
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("'to' is not a valid filesystem version: %s", err)
|
||||
}
|
||||
s.Filesystem = toFS
|
||||
|
||||
s.SizeEstimate, err = strconv.ParseInt(m[5], 10, 64)
|
||||
s.SizeEstimate, err = strconv.ParseInt(m[4], 10, 64)
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("cannot not parse size: %s", err)
|
||||
}
|
||||
|
@ -70,6 +70,10 @@ func TestZFSPropertySource(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestDrySendRegexesHaveSameCaptureGroupCount(t *testing.T) {
|
||||
assert.Equal(t, sendDryRunInfoLineRegexFull.NumSubexp(), sendDryRunInfoLineRegexIncremental.NumSubexp())
|
||||
}
|
||||
|
||||
func TestDrySendInfo(t *testing.T) {
|
||||
|
||||
// # full send
|
||||
@ -127,6 +131,11 @@ full zroot/test/a@3 10518512
|
||||
size 10518512
|
||||
`
|
||||
|
||||
fullWithSpaces := "\nfull\tpool1/otherjob/ds with spaces@blaffoo\t12912\nsize\t12912\n"
|
||||
fullWithSpacesInIntermediateComponent := "\nfull\tpool1/otherjob/another ds with spaces/childfs@blaffoo\t12912\nsize\t12912\n"
|
||||
incrementalWithSpaces := "\nincremental\tblaffoo\tpool1/otherjob/another ds with spaces@blaffoo2\t624\nsize\t624\n"
|
||||
incrementalWithSpacesInIntermediateComponent := "\nincremental\tblaffoo\tpool1/otherjob/another ds with spaces/childfs@blaffoo2\t624\nsize\t624\n"
|
||||
|
||||
type tc struct {
|
||||
name string
|
||||
in string
|
||||
@ -165,7 +174,7 @@ size 10518512
|
||||
SizeEstimate: 5383312,
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
name: "incNoToken", in: incNoToken,
|
||||
exp: &DrySendInfo{
|
||||
Type: DrySendTypeIncremental,
|
||||
@ -187,6 +196,46 @@ size 10518512
|
||||
SizeEstimate: 10518512,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "fullWithSpaces", in: fullWithSpaces,
|
||||
exp: &DrySendInfo{
|
||||
Type: DrySendTypeFull,
|
||||
Filesystem: "pool1/otherjob/ds with spaces",
|
||||
From: "",
|
||||
To: "pool1/otherjob/ds with spaces@blaffoo",
|
||||
SizeEstimate: 12912,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "fullWithSpacesInIntermediateComponent", in: fullWithSpacesInIntermediateComponent,
|
||||
exp: &DrySendInfo{
|
||||
Type: DrySendTypeFull,
|
||||
Filesystem: "pool1/otherjob/another ds with spaces/childfs",
|
||||
From: "",
|
||||
To: "pool1/otherjob/another ds with spaces/childfs@blaffoo",
|
||||
SizeEstimate: 12912,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "incrementalWithSpaces", in: incrementalWithSpaces,
|
||||
exp: &DrySendInfo{
|
||||
Type: DrySendTypeIncremental,
|
||||
Filesystem: "pool1/otherjob/another ds with spaces",
|
||||
From: "blaffoo",
|
||||
To: "pool1/otherjob/another ds with spaces@blaffoo2",
|
||||
SizeEstimate: 624,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "incrementalWithSpacesInIntermediateComponent", in: incrementalWithSpacesInIntermediateComponent,
|
||||
exp: &DrySendInfo{
|
||||
Type: DrySendTypeIncremental,
|
||||
Filesystem: "pool1/otherjob/another ds with spaces/childfs",
|
||||
From: "blaffoo",
|
||||
To: "pool1/otherjob/another ds with spaces/childfs@blaffoo2",
|
||||
SizeEstimate: 624,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
|
Loading…
Reference in New Issue
Block a user