Skip to content

Commit

Permalink
feat: Introduce .kraftignore
Browse files Browse the repository at this point in the history
Signed-off-by: Md Sahil <[email protected]>
  • Loading branch information
MdSahil-oss committed Jan 12, 2024
1 parent f641dcb commit 791a7ad
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 4 deletions.
28 changes: 27 additions & 1 deletion initrd/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ func (initrd *directory) Build(ctx context.Context) (string, error) {
}
}

if _, err := os.Stat(initrd.opts.output); err == nil {
if err = os.Remove(initrd.opts.output); err != nil {
return "", err
}
}

f, err := os.OpenFile(initrd.opts.output, os.O_RDWR|os.O_CREATE, 0o644)
if err != nil {
return "", fmt.Errorf("could not open initramfs file: %w", err)
Expand All @@ -75,6 +81,11 @@ func (initrd *directory) Build(ctx context.Context) (string, error) {
writer := cpio.NewWriter(f)
defer writer.Close()

ignoringItems, err := getKraftignoreItems(ctx, initrd)
if err != nil {
return "", err
}

if err := filepath.WalkDir(initrd.path, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return fmt.Errorf("received error before parsing path: %w", err)
Expand All @@ -84,7 +95,22 @@ func (initrd *directory) Build(ctx context.Context) (string, error) {
if internal == "" {
return nil // Do not archive empty paths
}
internal = "." + filepath.ToSlash(internal)
internal = filepath.ToSlash(internal)

if len(ignoringItems) > 0 && path != initrd.path {
switch isExistInKraftignoreFile(internal, d, ignoringItems) {
case SkipDir:
log.G(ctx).
WithField("directory", internal).
Trace("ignoring from archiving")
return filepath.SkipDir
case Exist:
log.G(ctx).
WithField("file", internal).
Trace("ignoring from archiving")
return nil
}
}

info, err := d.Info()
if err != nil {
Expand Down
121 changes: 121 additions & 0 deletions initrd/kraftignore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package initrd

import (
"bufio"
"context"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"

"kraftkit.sh/log"
)

// kraftignore filename
const KraftignoreFileName = ".kraftignore"

type IgnoringFileType string

const (
Exist = IgnoringFileType("Exist")
NotExist = IgnoringFileType("NotExist")
SkipDir = IgnoringFileType("SkipDir")
)

func getKraftignoreItems(ctx context.Context, initrd *directory) ([]string, error) {
if initrd.opts.kraftignorePath == "" {
cwd, err := os.Getwd()
if err != nil {
return []string{}, err
}
initrd.opts.kraftignorePath = filepath.Join(cwd, KraftignoreFileName)
}

if _, err := os.Stat(initrd.opts.kraftignorePath); errors.Is(err, os.ErrNotExist) {
return []string{}, nil
} else if err != nil {
return []string{}, err
}

kraftignoreFile, err := os.Open(initrd.opts.kraftignorePath)
if err != nil {
return []string{}, err
}

defer func() {
kraftIgnoreErr := kraftignoreFile.Close()
if kraftIgnoreErr != nil {
if err != nil {
err = fmt.Errorf("%s\n%s", err, kraftIgnoreErr)
} else {
err = kraftIgnoreErr
}
}
}()

kraftignoreScanner := bufio.NewScanner(kraftignoreFile)
kraftignoreScanner.Split(bufio.ScanLines)
var kraftignoreFileLines, ignoringItems []string

for kraftignoreScanner.Scan() {
kraftignoreFileLines = append(kraftignoreFileLines, kraftignoreScanner.Text())
}

for lineNum, line := range kraftignoreFileLines {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
items := strings.Split(line, " ")
for _, item := range items {
item = strings.TrimSpace(item)
if item == "" {
continue
}

if hasGlobPatterns(item) {
log.G(ctx).
WithField("file", initrd.opts.kraftignorePath).
Warn("contains a glob pattern ", item,
" at line ", lineNum,
" which is not supported by Kraftkit")
continue
}

if strings.HasPrefix(item, "./") {
item = strings.TrimPrefix(item, ".")
} else if !strings.HasPrefix(item, "/") {
item = "/" + item
}

item = strings.TrimSuffix(item, string(filepath.Separator))

ignoringItems = append(ignoringItems, item)
}
}

return ignoringItems, err
}

func isExistInKraftignoreFile(internal string, pathInfo fs.DirEntry, kraftignoreItems []string) IgnoringFileType {
for _, ignoringItem := range kraftignoreItems {
if internal == ignoringItem {
if pathInfo.IsDir() {
return SkipDir
}
return Exist
}
}
return NotExist
}

func hasGlobPatterns(item string) bool {
if strings.Contains(item, "*") || strings.Contains(item, "?") ||
strings.Contains(item, "!") || strings.Contains(item, "[") ||
strings.Contains(item, "{") {
return true
}
return false
}
19 changes: 16 additions & 3 deletions initrd/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@
// You may not use this file except in compliance with the License.
package initrd

import (
"path/filepath"
)

type InitrdOptions struct {
output string
cacheDir string
arch string
output string
cacheDir string
arch string
kraftignorePath string
}

type InitrdOption func(*InitrdOptions) error
Expand Down Expand Up @@ -41,3 +46,11 @@ func WithArchitecture(arch string) InitrdOption {
return nil
}
}

// WithKraftignorePath sets the path for .kraftignore.
func WithKraftignorePath(dir string) InitrdOption {
return func(opts *InitrdOptions) error {
opts.kraftignorePath = filepath.Join(dir, KraftignoreFileName)
return nil
}
}

0 comments on commit 791a7ad

Please sign in to comment.