Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/go-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: golangci-lint
on:
pull_request:
workflow_dispatch:

permissions:
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
pull-requests: read

jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.20'
cache: true
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: latest
31 changes: 31 additions & 0 deletions cmd/notation/internal/cmdutil/confirmation.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,34 @@ func AskForConfirmation(r io.Reader, prompt string, confirmed bool) (bool, error
return false, nil
}
}

import (
"bufio"
"fmt"
"io"
"strings"
)

// AskForConfirmation prints a propmt to ask for confirmation before doing an
// action and takes user input as response.
func AskForConfirmation(r io.Reader, prompt string, confirmed bool) (bool, error) {
if confirmed {
return true, nil
}

fmt.Print(prompt, " [y/N] ")

scanner := bufio.NewScanner(r)
if ok := scanner.Scan(); !ok {
return false, scanner.Err()
}
response := scanner.Text()

switch strings.ToLower(response) {
case "y", "yes":
return true, nil
default:
fmt.Println("Operation cancelled.")
return false, nil
}
}
38 changes: 38 additions & 0 deletions cmd/notation/internal/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,41 @@ type ErrorExceedMaxSignatures struct {
func (e ErrorExceedMaxSignatures) Error() string {
return fmt.Sprintf("exceeded configured limit of max signatures %d to examine", e.MaxSignatures)
}

import "fmt"

// ErrorReferrersAPINotSupported is used when the target registry does not
// support the Referrers API
type ErrorReferrersAPINotSupported struct {
Msg string
}

func (e ErrorReferrersAPINotSupported) Error() string {
if e.Msg != "" {
return e.Msg
}
return "referrers API not supported"
}

// ErrorOCILayoutMissingReference is used when signing local content in oci
// layout folder but missing input tag or digest.
type ErrorOCILayoutMissingReference struct {
Msg string
}

func (e ErrorOCILayoutMissingReference) Error() string {
if e.Msg != "" {
return e.Msg
}
return "reference is missing either digest or tag"
}

// ErrorExceedMaxSignatures is used when the number of signatures has surpassed
// the maximum limit that can be evaluated.
type ErrorExceedMaxSignatures struct {
MaxSignatures int
}

func (e ErrorExceedMaxSignatures) Error() string {
return fmt.Sprintf("exceeded configured limit of max signatures %d to examine", e.MaxSignatures)
}
82 changes: 82 additions & 0 deletions internal/osutil/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,85 @@ func IsRegularFile(path string) (bool, error) {

return fileStat.Mode().IsRegular(), nil
}

import (
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
)

// WriteFile writes to a path with all parent directories created.
func WriteFile(path string, data []byte) error {
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
return err
}
return os.WriteFile(path, data, 0o600)
}

// WriteFileWithPermission writes to a path with all parent directories created.
func WriteFileWithPermission(path string, data []byte, perm fs.FileMode, overwrite bool) error {
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
return err
}
flag := os.O_WRONLY | os.O_CREATE
if overwrite {
flag |= os.O_TRUNC
} else {
flag |= os.O_EXCL
}
file, err := os.OpenFile(path, flag, perm)
if err != nil {
return err
}
_, err = file.Write(data)
if err != nil {
file.Close()
return err
}
return file.Close()
}

// CopyToDir copies the src file to dst. Existing file will be overwritten.
func CopyToDir(src, dst string) (int64, error) {
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
}

if !sourceFileStat.Mode().IsRegular() {
return 0, fmt.Errorf("%s is not a regular file", src)
}

source, err := os.Open(src)
if err != nil {
return 0, err
}
defer source.Close()

if err := os.MkdirAll(dst, 0o700); err != nil {
return 0, err
}
certFile := filepath.Join(dst, filepath.Base(src))
destination, err := os.Create(certFile)
if err != nil {
return 0, err
}
defer destination.Close()
err = destination.Chmod(0o600)
if err != nil {
return 0, err
}
return io.Copy(destination, source)
}

// IsRegularFile checks if path is a regular file
func IsRegularFile(path string) (bool, error) {
fileStat, err := os.Stat(path)
if err != nil {
return false, err
}

return fileStat.Mode().IsRegular(), nil
}
10 changes: 10 additions & 0 deletions internal/slices/slices.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@ func Contains[E comparable](s []E, v E) bool {
}
return false
}

// Contains reports whether v is present in s.
func Contains[E comparable](s []E, v E) bool {
for _, vs := range s {
if v == vs {
return true
}
}
return false
}
24 changes: 24 additions & 0 deletions internal/slices/slices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,27 @@ func TestContainerElement(t *testing.T) {
}
}
}

import (
"testing"
)

func TestContainerElement(t *testing.T) {
tests := []struct {
c []string
v string
want bool
}{
{nil, "", false},
{[]string{}, "", false},
{[]string{"1", "2", "3"}, "4", false},
{[]string{"1", "2", "3"}, "2", true},
{[]string{"1", "2", "2", "3"}, "2", true},
{[]string{"1", "2", "3", "2"}, "2", true},
}
for _, tt := range tests {
if got := Contains(tt.c, tt.v); got != tt.want {
t.Errorf("ContainerElement() = %v, want %v", got, tt.want)
}
}
}
56 changes: 56 additions & 0 deletions internal/tree/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,59 @@ func print(prefix string, itemMarker string, nextPrefix string, n *Node) {
}
}
}

import (
"fmt"
)

const (
treeItemPrefix = "├── "
treeItemPrefixLast = "└── "
subTreePrefix = "│ "
subTreePrefixLast = " "
)

// represents a Node in a tree
type Node struct {
Value string
Children []*Node
}

// creates a new Node with the given value
func New(value string) *Node {
return &Node{Value: value}
}

// adds a new child node with the given value
func (parent *Node) Add(value string) *Node {
node := New(value)
parent.Children = append(parent.Children, node)
return node
}

// adds a new child node with the formatted pair as the value
func (parent *Node) AddPair(key string, value string) *Node {
return parent.Add(key + ": " + value)
}

// prints the tree represented by the root node
func (root *Node) Print() {
print("", "", "", root)
}

func print(prefix string, itemMarker string, nextPrefix string, n *Node) {
fmt.Println(prefix + itemMarker + n.Value)

nextItemPrefix := treeItemPrefix
nextSubTreePrefix := subTreePrefix

if len(n.Children) > 0 {
for i, child := range n.Children {
if i == len(n.Children)-1 {
nextItemPrefix = treeItemPrefixLast
nextSubTreePrefix = subTreePrefixLast
}
print(nextPrefix, nextItemPrefix, nextPrefix+nextSubTreePrefix, child)
}
}
}
82 changes: 82 additions & 0 deletions internal/tree/tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,85 @@ func (n *Node) ContainsChild(value string) bool {

return false
}

import (
"reflect"
"testing"
)

func TestNodeCreation(t *testing.T) {
node := New("root")
expected := Node{Value: "root"}

if !reflect.DeepEqual(*node, expected) {
t.Fatalf("expected %+v, got %+v", expected, *node)
}
}

func TestNodeAdd(t *testing.T) {
root := New("root")
root.Add("child")

if !root.ContainsChild("child") {
t.Error("expected root to have child node with value 'child'")
t.Fatalf("actual root: %+v", root)
}
}

func TestNodeAddPair(t *testing.T) {
root := New("root")
root.AddPair("key", "value")

if !root.ContainsChild("key: value") {
t.Error("expected root to have child node with value 'key: value'")
t.Fatalf("actual root: %+v", root)
}
}

func ExampleRootPrint() {
root := New("root")
root.Print()

// Output:
// root
}

func ExampleSingleLayerPrint() {
root := New("root")
root.Add("child1")
root.Add("child2")
root.Print()

// Output:
// root
// ├── child1
// └── child2
}

func ExampleMultiLayerPrint() {
root := New("root")
child1 := root.Add("child1")
child1.AddPair("key", "value")
child2 := root.Add("child2")
child2.Add("child2.1")
child2.Add("child2.2")
root.Print()

// Output:
// root
// ├── child1
// │ └── key: value
// └── child2
// ├── child2.1
// └── child2.2
}

func (n *Node) ContainsChild(value string) bool {
for _, child := range n.Children {
if child.Value == value {
return true
}
}

return false
}
Loading