-
Notifications
You must be signed in to change notification settings - Fork 181
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(oci-layout): use Parser to process option input (#736)
This PR adds a new option parser which can be used to process input before cmd execution. This change will be used in OCI layout support. Signed-off-by: Billy Zha <jinzha1@microsoft.com>
- Loading branch information
Showing
23 changed files
with
257 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
Copyright The ORAS Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package option_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/spf13/pflag" | ||
"oras.land/oras/cmd/oras/internal/option" | ||
) | ||
|
||
func (t *Test) ApplyFlags(fs *pflag.FlagSet) { | ||
*t.CntPtr += 1 | ||
} | ||
|
||
func TestApplyFlags(t *testing.T) { | ||
cnt := 0 | ||
type args struct { | ||
Test | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
wantErr bool | ||
}{ | ||
{"flags should be applied once", args{Test{CntPtr: &cnt}}, false}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
option.ApplyFlags(&tt.args, nil) | ||
if cnt != 1 { | ||
t.Errorf("Expect ApplyFlags() to be called once but got %v", cnt) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
Copyright The ORAS Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package option | ||
|
||
import ( | ||
"reflect" | ||
) | ||
|
||
// FlagParser parses flags in an option. | ||
type FlagParser interface { | ||
Parse() error | ||
} | ||
|
||
// Parse parses applicable fields of the passed-in option pointer and returns | ||
// error during parsing. | ||
func Parse(optsPtr interface{}) error { | ||
return rangeFields(optsPtr, func(fp FlagParser) error { | ||
return fp.Parse() | ||
}) | ||
} | ||
|
||
// rangeFields goes through all fields of ptr, optionally run fn if a field is | ||
// public AND typed T. | ||
func rangeFields[T any](ptr any, fn func(T) error) error { | ||
v := reflect.ValueOf(ptr).Elem() | ||
for i := 0; i < v.NumField(); i++ { | ||
f := v.Field(i) | ||
if f.CanSet() { | ||
iface := f.Addr().Interface() | ||
if opts, ok := iface.(T); ok { | ||
if err := fn(opts); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
Copyright The ORAS Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package option_test | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
|
||
"oras.land/oras/cmd/oras/internal/option" | ||
) | ||
|
||
type Test struct { | ||
CntPtr *int | ||
} | ||
|
||
func (t *Test) Parse() error { | ||
*t.CntPtr += 1 | ||
if *t.CntPtr == 2 { | ||
return errors.New("should not be tried twice") | ||
} | ||
return nil | ||
} | ||
|
||
func TestParse_once(t *testing.T) { | ||
cnt := 0 | ||
type args struct { | ||
Test | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
wantErr bool | ||
}{ | ||
{"parse should be called once", args{Test{CntPtr: &cnt}}, false}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if err := option.Parse(&tt.args); (err != nil) != tt.wantErr { | ||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr) | ||
} | ||
|
||
if cnt != 1 { | ||
t.Errorf("Expect Parse() to be called once but got %v", cnt) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestParse_err(t *testing.T) { | ||
cnt := 0 | ||
type args struct { | ||
Test1 Test | ||
Test2 Test | ||
Test3 Test | ||
Test4 Test | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
wantErr bool | ||
}{ | ||
{"parse should be called twice and aborted with error", args{Test{CntPtr: &cnt}, Test{CntPtr: &cnt}, Test{CntPtr: &cnt}, Test{CntPtr: &cnt}}, true}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if err := option.Parse(&tt.args); (err != nil) != tt.wantErr { | ||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr) | ||
} | ||
|
||
if cnt != 2 { | ||
t.Errorf("Expect Parse() to be called twice but got %v", cnt) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.