-
Notifications
You must be signed in to change notification settings - Fork 573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
asserts: introduce SequenceMemberAfter in the asserts backstores #8906
Changes from all commits
4422c93
137f32a
e70ab5b
1119b42
439333e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,8 +21,11 @@ package asserts | |
|
||
import ( | ||
"fmt" | ||
"io" | ||
"os" | ||
"path/filepath" | ||
"sort" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
|
@@ -31,14 +34,21 @@ findWildcard invokes foundCb once for each parent directory of regular files mat | |
|
||
<top>/<descendantWithWildcard[0]>/<descendantWithWildcard[1]>... | ||
|
||
where each descendantWithWildcard component can contain the * wildcard; | ||
where each descendantWithWildcard component can contain the * wildcard. | ||
|
||
One of the descendantWithWildcard components except the last | ||
can be "#>" or "#<", in which case that level is assumed to have names | ||
that can be parsed as positive integers, which will be enumerated in | ||
ascending (#>) or descending order respectively (#<); if seqnum != -1 | ||
then only the values >seqnum or respectively <seqnum will be | ||
considered. | ||
|
||
foundCb is invoked with the paths of the found regular files relative to top (that means top/ is excluded). | ||
|
||
Unlike filepath.Glob any I/O operation error stops the walking and bottoms out, so does a foundCb invocation that returns an error. | ||
*/ | ||
func findWildcard(top string, descendantWithWildcard []string, foundCb func(relpath []string) error) error { | ||
return findWildcardDescend(top, top, descendantWithWildcard, foundCb) | ||
func findWildcard(top string, descendantWithWildcard []string, seqnum int, foundCb func(relpath []string) error) error { | ||
return findWildcardDescend(top, top, descendantWithWildcard, seqnum, foundCb) | ||
} | ||
|
||
func findWildcardBottom(top, current string, pat string, names []string, foundCb func(relpath []string) error) error { | ||
|
@@ -74,13 +84,21 @@ func findWildcardBottom(top, current string, pat string, names []string, foundCb | |
return foundCb(hits) | ||
} | ||
|
||
func findWildcardDescend(top, current string, descendantWithWildcard []string, foundCb func(relpath []string) error) error { | ||
func findWildcardDescend(top, current string, descendantWithWildcard []string, seqnum int, foundCb func(relpath []string) error) error { | ||
k := descendantWithWildcard[0] | ||
if k == "#>" || k == "#<" { | ||
if len(descendantWithWildcard) == 1 { | ||
return fmt.Errorf("findWildcard: sequence wildcard (#>|<#) cannot be the last component") | ||
} | ||
return findWildcardSequence(top, current, k, descendantWithWildcard[1:], seqnum, foundCb) | ||
} | ||
if len(descendantWithWildcard) > 1 && strings.IndexByte(k, '*') == -1 { | ||
return findWildcardDescend(top, filepath.Join(current, k), descendantWithWildcard[1:], foundCb) | ||
return findWildcardDescend(top, filepath.Join(current, k), descendantWithWildcard[1:], seqnum, foundCb) | ||
} | ||
|
||
d, err := os.Open(current) | ||
// ignore missing directory, higher level will produce | ||
// NotFoundError as needed | ||
if os.IsNotExist(err) { | ||
return nil | ||
} | ||
|
@@ -101,11 +119,69 @@ func findWildcardDescend(top, current string, descendantWithWildcard []string, f | |
return fmt.Errorf("findWildcard: invoked with malformed wildcard: %v", err) | ||
} | ||
if ok { | ||
err = findWildcardDescend(top, filepath.Join(current, name), descendantWithWildcard[1:], foundCb) | ||
err = findWildcardDescend(top, filepath.Join(current, name), descendantWithWildcard[1:], seqnum, foundCb) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func findWildcardSequence(top, current, seqWildcard string, descendantWithWildcard []string, seqnum int, foundCb func(relpath []string) error) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function looks good. |
||
filter := func(i int) bool { return true } | ||
if seqnum != -1 { | ||
if seqWildcard == "#>" { | ||
filter = func(i int) bool { return i > seqnum } | ||
} else { // "#<", guaranteed by the caller | ||
filter = func(i int) bool { return i < seqnum } | ||
} | ||
} | ||
|
||
d, err := os.Open(current) | ||
// ignore missing directory, higher level will produce | ||
// NotFoundError as needed | ||
if os.IsNotExist(err) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a comment explaining what is the meaning of not-exists here and why it is not propagated? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the comment |
||
return nil | ||
} | ||
if err != nil { | ||
return err | ||
} | ||
defer d.Close() | ||
var seq []int | ||
for { | ||
names, err := d.Readdirnames(100) | ||
zyga marked this conversation as resolved.
Show resolved
Hide resolved
stolowski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err == io.EOF { | ||
break | ||
} | ||
if err != nil { | ||
return err | ||
} | ||
for _, n := range names { | ||
sqn, err := strconv.Atoi(n) | ||
if err != nil || sqn < 0 { | ||
return fmt.Errorf("cannot parse %q name as a sequence number", filepath.Join(current, n)) | ||
} | ||
if filter(sqn) { | ||
seq = append(seq, sqn) | ||
} | ||
} | ||
} | ||
sort.Ints(seq) | ||
|
||
var start, direction int | ||
if seqWildcard == "#>" { | ||
start = 0 | ||
direction = 1 | ||
} else { | ||
start = len(seq) - 1 | ||
direction = -1 | ||
} | ||
for i := start; i >= 0 && i < len(seq); i += direction { | ||
err = findWildcardDescend(top, filepath.Join(current, strconv.Itoa(seq[i])), descendantWithWildcard, -1, foundCb) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although the tree structure is controller, this will trigger interesting behavior if sequence directory name is eg. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we'll just miss things that arre not well-formed but you are right that I should probably review the uses of Atoi in the package (it's an orthogonal problem) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it sounds like a follow up topic if anything. |
||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the part about omitted headers from this description alone. Does it mean that it can return both an error and a
SequenceMember
that are together non-nil?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, Headers here refer to the Headers field of NotFoundError itself, the with can refer only to that in the previous part of the sentence, so I'm not entirely sure how to make it clearer. We have that exact sentence in the docs of preexisting methods already.