Skip to content
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

feat: add file and directory report skeleton #116

Merged
merged 70 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
a09f06f
Add fileCreator proxy for use in chisel.db
letFunny Dec 1, 2023
ec3690f
Tests
letFunny Dec 1, 2023
a171780
Fix tests when running whole suite
letFunny Dec 1, 2023
2a1731b
Link
letFunny Dec 1, 2023
f6346be
Tests for report
letFunny Dec 4, 2023
0295aed
Final touches
letFunny Dec 4, 2023
c371d1a
Better test coverage
letFunny Dec 7, 2023
dfc7647
Address review comments
letFunny Dec 12, 2023
d39f337
sort imports
letFunny Jan 11, 2024
dc19319
remove proxy
letFunny Jan 15, 2024
bdf1f70
Merge branch 'main' into chisel-db-proxy
letFunny Jan 15, 2024
1fdad8a
fix tests
letFunny Jan 15, 2024
5a06152
increase test coverage
letFunny Jan 15, 2024
b0e0712
remove unnecessary tests
letFunny Jan 16, 2024
d47ec8d
sort imports
letFunny Jan 16, 2024
c1eb773
remove report to split PRs
letFunny Jan 16, 2024
1441994
simplify naming terminology
letFunny Jan 16, 2024
c8c2ba7
more naming simplification
letFunny Jan 16, 2024
3b5bb4a
more naming simplification
letFunny Jan 16, 2024
13d4b06
more naming simplification
letFunny Jan 16, 2024
631b2b5
Merge branch 'chisel-db-proxy' into chisel-db-report
letFunny Jan 16, 2024
3dd73c3
feat: add file and directory report skeleton
letFunny Jan 16, 2024
0449354
remove unnecessary mutex
letFunny Jan 17, 2024
0fccd1f
address review comments
letFunny Jan 29, 2024
6e62d64
rename fsCreator
letFunny Jan 29, 2024
0737e43
default for missing Creator in options
letFunny Jan 29, 2024
2aa844d
comments
letFunny Jan 29, 2024
5eb8f7e
conform to godoc format
letFunny Jan 29, 2024
fad7257
Merge branch 'chisel-db-proxy' into chisel-db-report
letFunny Jan 29, 2024
325531b
remove unused attribute for now
letFunny Jan 29, 2024
aa09fd0
simplify redundant checks
letFunny Jan 30, 2024
fd87b6d
change comment
letFunny Jan 30, 2024
8d53d66
typo
letFunny Jan 30, 2024
a21f777
clarified tests with comment
letFunny Feb 2, 2024
07091ac
remove stateful tests
letFunny Feb 2, 2024
c06869c
nitpick naming
letFunny Feb 2, 2024
ac5decc
remove redundant check
letFunny Feb 2, 2024
1314466
typo
letFunny Feb 2, 2024
ae7dac3
typo in comment
letFunny Feb 2, 2024
abdc587
typo in comment
letFunny Feb 2, 2024
9897388
sort slice for stable tests
letFunny Feb 2, 2024
803e9c5
naming and nitpicks
letFunny Feb 5, 2024
6d111ac
change test expected from slice to map
letFunny Feb 5, 2024
7660433
reword comment
letFunny Feb 5, 2024
9ee449f
remove shallow copy of Options
letFunny Feb 5, 2024
d2227b0
Merge branch 'chisel-db-proxy' into chisel-db-report
letFunny Feb 5, 2024
8fdbcd9
comments and naming changes
letFunny Feb 5, 2024
42d6c6e
move fsutil.Creator creation to the outer scope
letFunny Feb 5, 2024
38b899a
Merge branch 'main' into chisel-db-report
letFunny Feb 5, 2024
41c1c89
improve performance
letFunny Feb 5, 2024
30bb29e
remove Creator and use a closure
letFunny Feb 6, 2024
7d8fa69
add error check to report.Add
letFunny Feb 6, 2024
04c7117
final touches
letFunny Feb 7, 2024
22933d4
slicer returns Report to allow future testing
letFunny Feb 7, 2024
74feda8
remove experimental slices package
letFunny Feb 7, 2024
3aa311c
fix tests
letFunny Feb 7, 2024
55dd7c4
move comment
letFunny Feb 7, 2024
9f51f80
return ptr instead of value
letFunny Feb 8, 2024
002204c
add slicer tests and make path in report relative
letFunny Feb 9, 2024
1745ba9
renaming
letFunny Feb 12, 2024
1554233
better relative path management
letFunny Feb 19, 2024
b5bf664
better error reporting for report
letFunny Feb 26, 2024
a6179ee
naming and comments
letFunny Feb 26, 2024
7c013a3
fsutil.Info -> fsutil.Entry
letFunny Feb 27, 2024
cdb50f0
remove internal error prefix
letFunny Feb 27, 2024
4c2d67f
/root/ -> /base/
letFunny Feb 27, 2024
b2b7231
tests for Options.Create
letFunny Feb 27, 2024
dbe9e2e
info -> entry, variables and comments
letFunny Feb 27, 2024
f4557ec
explicit test for nil Create closure
letFunny Feb 28, 2024
5f16450
change created to notCreated for better test clarity
letFunny Mar 1, 2024
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
3 changes: 2 additions & 1 deletion cmd/chisel/cmd_cut.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,12 @@ func (cmd *cmdCut) Execute(args []string) error {
archives[archiveName] = openArchive
}

return slicer.Run(&slicer.RunOptions{
_, err = slicer.Run(&slicer.RunOptions{
Selection: selection,
Archives: archives,
TargetDir: cmd.RootDir,
})
return err
}

// TODO These need testing, and maybe moving into a common file.
Expand Down
2 changes: 0 additions & 2 deletions internal/archive/archive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"github.com/canonical/chisel/internal/archive"
"github.com/canonical/chisel/internal/archive/testarchive"
"github.com/canonical/chisel/internal/deb"
"github.com/canonical/chisel/internal/fsutil"
"github.com/canonical/chisel/internal/testutil"
)

Expand Down Expand Up @@ -501,7 +500,6 @@ func (s *S) testOpenArchiveArch(c *C, release ubuntuRelease, arch string) {
{Path: "/hostname"},
},
},
Creator: fsutil.NewCreator(),
})
c.Assert(err, IsNil)

Expand Down
28 changes: 19 additions & 9 deletions internal/deb/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type ExtractOptions struct {
TargetDir string
Extract map[string][]ExtractInfo
Globbed map[string][]string
Creator *fsutil.Creator
Create func(options *fsutil.CreateOptions) error
}

type ExtractInfo struct {
Expand All @@ -34,16 +34,26 @@ type ExtractInfo struct {
Optional bool
}

func checkExtractOptions(options *ExtractOptions) error {
func getValidOptions(options *ExtractOptions) (*ExtractOptions, error) {
for extractPath, extractInfos := range options.Extract {
isGlob := strings.ContainsAny(extractPath, "*?")
if isGlob {
if len(extractInfos) != 1 || extractInfos[0].Path != extractPath || extractInfos[0].Mode != 0 {
return fmt.Errorf("when using wildcards source and target paths must match: %s", extractPath)
return nil, fmt.Errorf("when using wildcards source and target paths must match: %s", extractPath)
}
}
}
return nil

if options.Create == nil {
validOpts := *options
validOpts.Create = func(o *fsutil.CreateOptions) error {
_, err := fsutil.Create(o)
return err
}
return &validOpts, nil
}

return options, nil
}

func Extract(pkgReader io.Reader, options *ExtractOptions) (err error) {
Expand All @@ -55,12 +65,12 @@ func Extract(pkgReader io.Reader, options *ExtractOptions) (err error) {

logf("Extracting files from package %q...", options.Package)

err = checkExtractOptions(options)
validOpts, err := getValidOptions(options)
if err != nil {
return err
}

_, err = os.Stat(options.TargetDir)
_, err = os.Stat(validOpts.TargetDir)
if os.IsNotExist(err) {
return fmt.Errorf("target directory does not exist")
} else if err != nil {
Expand Down Expand Up @@ -100,7 +110,7 @@ func Extract(pkgReader io.Reader, options *ExtractOptions) (err error) {
dataReader = zstdReader
}
}
return extractData(dataReader, options)
return extractData(dataReader, validOpts)
}

func extractData(dataReader io.Reader, options *ExtractOptions) error {
Expand Down Expand Up @@ -186,7 +196,7 @@ func extractData(dataReader io.Reader, options *ExtractOptions) error {
// Base directory for extracted content. Relevant mainly to preserve
// the metadata, since the extracted content itself will also create
// any missing directories unaccounted for in the options.
err := options.Creator.Create(&fsutil.CreateOptions{
err := options.Create(&fsutil.CreateOptions{
Path: filepath.Join(options.TargetDir, sourcePath),
Mode: tarHeader.FileInfo().Mode(),
MakeParents: true,
Expand Down Expand Up @@ -227,7 +237,7 @@ func extractData(dataReader io.Reader, options *ExtractOptions) error {
if extractInfo.Mode != 0 {
tarHeader.Mode = int64(extractInfo.Mode)
}
err := options.Creator.Create(&fsutil.CreateOptions{
err := options.Create(&fsutil.CreateOptions{
Path: targetPath,
Mode: tarHeader.FileInfo().Mode(),
Data: pathReader,
Expand Down
82 changes: 78 additions & 4 deletions internal/deb/extract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package deb_test

import (
"bytes"
"io/fs"
"path/filepath"
"sort"
"strings"

. "gopkg.in/check.v1"

Expand All @@ -14,9 +18,12 @@ type extractTest struct {
summary string
pkgdata []byte
options deb.ExtractOptions
hackopt func(o *deb.ExtractOptions)
globbed map[string][]string
result map[string]string
error string
// paths which the extractor did not create explicitly.
notCreated []string
error string
}

var extractTests = []extractTest{{
Expand Down Expand Up @@ -60,8 +67,45 @@ var extractTests = []extractTest{{
"/etc/": "dir 0755",
"/etc/os-release": "symlink ../usr/lib/os-release",
},
notCreated: []string{},
}, {
summary: "Extract a few entries, nil Create closure",
pkgdata: testutil.PackageData["base-files"],
options: deb.ExtractOptions{
Extract: map[string][]deb.ExtractInfo{
"/usr/bin/hello": []deb.ExtractInfo{{
Path: "/usr/bin/hello",
}},
"/etc/os-release": []deb.ExtractInfo{{
Path: "/etc/os-release",
}},
"/usr/lib/os-release": []deb.ExtractInfo{{
Path: "/usr/lib/os-release",
}},
"/usr/share/doc/": []deb.ExtractInfo{{
Path: "/usr/share/doc/",
}},
"/tmp/": []deb.ExtractInfo{{
Path: "/tmp/",
}},
},
},
result: map[string]string{
"/tmp/": "dir 01777",
"/usr/": "dir 0755",
"/usr/bin/": "dir 0755",
"/usr/bin/hello": "file 0775 eaf29575",
"/usr/share/": "dir 0755",
"/usr/share/doc/": "dir 0755",
"/usr/lib/": "dir 0755",
"/usr/lib/os-release": "file 0644 ec6fae43",
"/etc/": "dir 0755",
"/etc/os-release": "symlink ../usr/lib/os-release",
},
hackopt: func(o *deb.ExtractOptions) {
o.Create = nil
},
}, {

summary: "Copy a couple of entries elsewhere",
pkgdata: testutil.PackageData["base-files"],
options: deb.ExtractOptions{
Expand All @@ -83,8 +127,8 @@ var extractTests = []extractTest{{
"/usr/foo/bin/hello-2": "file 0600 eaf29575",
"/usr/other/": "dir 0700",
},
notCreated: []string{"/usr/foo/", "/usr/foo/bin/"},
}, {

summary: "Copy same file twice",
pkgdata: testutil.PackageData["base-files"],
options: deb.ExtractOptions{
Expand All @@ -102,6 +146,7 @@ var extractTests = []extractTest{{
"/usr/bin/hello": "file 0775 eaf29575",
"/usr/bin/hallo": "file 0775 eaf29575",
},
notCreated: []string{},
}, {
summary: "Globbing a single dir level",
pkgdata: testutil.PackageData["base-files"],
Expand All @@ -117,6 +162,7 @@ var extractTests = []extractTest{{
"/etc/dpkg/": "dir 0755",
"/etc/default/": "dir 0755",
},
notCreated: []string{"/etc/"},
}, {
summary: "Globbing for files with multiple levels at once",
pkgdata: testutil.PackageData["base-files"],
Expand All @@ -136,6 +182,7 @@ var extractTests = []extractTest{{
"/etc/default/": "dir 0755",
"/etc/debian_version": "file 0644 cce26cfe",
},
notCreated: []string{"/etc/"},
}, {
summary: "Globbing with reporting of globbed paths",
pkgdata: testutil.PackageData["base-files"],
Expand All @@ -159,6 +206,7 @@ var extractTests = []extractTest{{
"/etc/dp*/": []string{"/etc/dpkg/"},
"/etc/de**": []string{"/etc/debian_version", "/etc/default/"},
},
notCreated: []string{"/etc/"},
}, {
summary: "Globbing must have matching source and target",
pkgdata: testutil.PackageData["base-files"],
Expand Down Expand Up @@ -266,6 +314,7 @@ var extractTests = []extractTest{{
"/usr/bin/": "dir 0755",
"/tmp/": "dir 01777",
},
notCreated: []string{},
}, {
summary: "Optional entries mixed in cannot be missing",
pkgdata: testutil.PackageData["base-files"],
Expand All @@ -291,7 +340,20 @@ func (s *S) TestExtract(c *C) {
options := test.options
options.Package = "base-files"
options.TargetDir = dir
options.Creator = fsutil.NewCreator()
letFunny marked this conversation as resolved.
Show resolved Hide resolved
createdPaths := make(map[string]bool)
options.Create = func(o *fsutil.CreateOptions) error {
relPath := filepath.Clean("/" + strings.TrimPrefix(o.Path, dir))
if o.Mode&fs.ModeDir != 0 {
relPath = relPath + "/"
}
createdPaths[relPath] = true
_, err := fsutil.Create(o)
return err
}

if test.hackopt != nil {
test.hackopt(&options)
}

if test.globbed != nil {
options.Globbed = make(map[string][]string)
Expand All @@ -309,6 +371,18 @@ func (s *S) TestExtract(c *C) {
c.Assert(options.Globbed, DeepEquals, test.globbed)
}

if test.notCreated != nil {
notCreated := []string{}
for path := range test.result {
if !createdPaths[path] {
notCreated = append(notCreated, path)
}
}
sort.Strings(notCreated)
sort.Strings(test.notCreated)
c.Assert(notCreated, DeepEquals, test.notCreated)
}

result := testutil.TreeDump(dir)
c.Assert(result, DeepEquals, test.result)
}
Expand Down
26 changes: 8 additions & 18 deletions internal/fsutil/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,17 @@ type CreateOptions struct {
MakeParents bool
}

type Info struct {
type Entry struct {
Path string
Mode fs.FileMode
Hash string
Size int
Link string
}

type Creator struct {
// Created keeps track of information about the filesystem entries created.
// If an entry is created several times it only tracks the latest one.
Created map[string]Info
}

func NewCreator() *Creator {
return &Creator{Created: make(map[string]Info)}
}

// Create creates a filesystem entry according to the provided options.
func (c *Creator) Create(options *CreateOptions) error {
// Create creates a filesystem entry according to the provided options and returns
// the information about the created entry.
func Create(options *CreateOptions) (*Entry, error) {
rp := &readerProxy{inner: options.Data, h: sha256.New()}
// Use the proxy instead of the raw Reader.
optsCopy := *options
Expand All @@ -50,7 +41,7 @@ func (c *Creator) Create(options *CreateOptions) error {
var err error
if o.MakeParents {
if err := os.MkdirAll(filepath.Dir(o.Path), 0755); err != nil {
return err
return nil, err
}
}
switch o.Mode & fs.ModeType {
Expand All @@ -64,18 +55,17 @@ func (c *Creator) Create(options *CreateOptions) error {
err = fmt.Errorf("unsupported file type: %s", o.Path)
}
if err != nil {
return err
return nil, err
}

info := Info{
entry := &Entry{
Path: o.Path,
Mode: o.Mode,
Hash: hex.EncodeToString(rp.h.Sum(nil)),
Size: rp.size,
Link: o.Link,
}
c.Created[o.Path] = info
return nil
return entry, nil
}

func createDir(o *CreateOptions) error {
Expand Down
Loading
Loading