Skip to content

Commit

Permalink
Merge branch 'multiple-archive-support' into feat/pro-archives
Browse files Browse the repository at this point in the history
  • Loading branch information
rebornplusplus committed Oct 8, 2024
2 parents f84e257 + 82587f6 commit 74c5851
Show file tree
Hide file tree
Showing 28 changed files with 3,290 additions and 879 deletions.
17 changes: 12 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,27 +89,34 @@ jobs:
CHISEL_VERSION: ${{ steps.build.outputs.CHISEL_VERSION }}
run: |
ARCHIVE_FILE=chisel_${CHISEL_VERSION}_${GOOS}_${GOARCH}.tar.gz
ARCHIVE_FILE_SHA384="${ARCHIVE_FILE}.sha384"
echo "Creating archive $ARCHIVE_FILE"
mkdir -p dist/build
cp chisel LICENSE README.md dist/build
find dist/build -printf "%P\n" | tar -czf dist/$ARCHIVE_FILE --no-recursion -C dist/build -T -
mkdir -p dist/
cp chisel LICENSE README.md dist/
find dist -printf "%P\n" | tar -czf $ARCHIVE_FILE --no-recursion -C dist -T -
sha384sum "${ARCHIVE_FILE}" > "${ARCHIVE_FILE_SHA384}"
# Share variables with subsequent steps
echo "ARCHIVE_FILE=${ARCHIVE_FILE}" >>$GITHUB_OUTPUT
echo "ARCHIVE_FILE_SHA384=${ARCHIVE_FILE_SHA384}" >>$GITHUB_OUTPUT
- name: Upload archive as Actions artifact
uses: actions/upload-artifact@v3
with:
name: ${{ steps.archive.outputs.ARCHIVE_FILE }}
path: dist/${{ steps.archive.outputs.ARCHIVE_FILE }}
path: |
${{ steps.archive.outputs.ARCHIVE_FILE }}
${{ steps.archive.outputs.ARCHIVE_FILE_SHA384 }}
- name: Upload archive to release
env:
CHISEL_VERSION: ${{ steps.build.outputs.CHISEL_VERSION }}
ARCHIVE_FILE: ${{ steps.archive.outputs.ARCHIVE_FILE }}
ARCHIVE_FILE_SHA384: ${{ steps.archive.outputs.ARCHIVE_FILE_SHA384 }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: ${{ github.event_name == 'release' }}
run: |
echo "Uploading $ARCHIVE_FILE to release $CHISEL_VERSION"
gh release upload $CHISEL_VERSION dist/$ARCHIVE_FILE
gh release upload $CHISEL_VERSION $ARCHIVE_FILE
gh release upload $CHISEL_VERSION $ARCHIVE_FILE_SHA384
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,11 +269,16 @@ have additional information for identifying the kind of content to expect:
which are only available for certain architectures. Example:
`/usr/bin/hello: {arch: amd64}` will instruct Chisel to extract and install
the "/usr/bin/hello" file only when chiselling an amd64 filesystem.
- **generate**: accepts a `manifest` value to instruct Chisel to generate the
manifest files in the directory. Example: `/var/lib/chisel/**:{generate:
manifest}`. NOTE: the provided path has to be of the form
`/slashed/path/to/dir/**` and no wildcards can appear apart from the trailing
`**`.

## TODO

- [ ] Preserve ownerships when possible
- [ ] GPG signature checking for archives
- [x] GPG signature checking for archives
- [ ] Use a fake server for the archive tests
- [ ] Functional tests

Expand Down
2 changes: 1 addition & 1 deletion cmd/chisel/cmd_cut.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (cmd *cmdCut) Execute(args []string) error {
archives[archiveName] = openArchive
}

_, err = slicer.Run(&slicer.RunOptions{
err = slicer.Run(&slicer.RunOptions{
Selection: selection,
Archives: archives,
TargetDir: cmd.RootDir,
Expand Down
2 changes: 0 additions & 2 deletions cmd/chisel/cmd_find_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ func makeSamplePackage(pkg string, slices []string) *setup.Package {
}

var sampleRelease = &setup.Release{
DefaultArchive: "ubuntu",

Archives: map[string]*setup.Archive{
"ubuntu": {
Name: "ubuntu",
Expand Down
2 changes: 1 addition & 1 deletion cmd/chisel/cmd_help.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ type helpCategory struct {
var helpCategories = []helpCategory{{
Label: "Basic",
Description: "general operations",
Commands: []string{"find", "help", "version"},
Commands: []string{"find", "info", "help", "version"},
}, {
Label: "Action",
Description: "make things happen",
Expand Down
137 changes: 137 additions & 0 deletions cmd/chisel/cmd_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package main

import (
"fmt"
"strconv"
"strings"

"github.com/jessevdk/go-flags"
"gopkg.in/yaml.v3"

"github.com/canonical/chisel/internal/setup"
)

var shortInfoHelp = "Show information about package slices"
var longInfoHelp = `
The info command shows detailed information about package slices.
It accepts a whitespace-separated list of strings. The list can be
composed of package names, slice names, or a combination of both. The
default output format is YAML. When multiple arguments are provided,
the output is a list of YAML documents separated by a "---" line.
Slice definitions are shown verbatim according to their definition in
the selected release. For example, globs are not expanded.
`

var infoDescs = map[string]string{
"release": "Chisel release name or directory (e.g. ubuntu-22.04)",
}

type infoCmd struct {
Release string `long:"release" value-name:"<branch|dir>"`

Positional struct {
Queries []string `positional-arg-name:"<pkg|slice>" required:"yes"`
} `positional-args:"yes"`
}

func init() {
addCommand("info", shortInfoHelp, longInfoHelp, func() flags.Commander { return &infoCmd{} }, infoDescs, nil)
}

func (cmd *infoCmd) Execute(args []string) error {
if len(args) > 0 {
return ErrExtraArgs
}

release, err := obtainRelease(cmd.Release)
if err != nil {
return err
}

packages, notFound := selectPackageSlices(release, cmd.Positional.Queries)

for i, pkg := range packages {
data, err := yaml.Marshal(pkg)
if err != nil {
return err
}
if i > 0 {
fmt.Fprintln(Stdout, "---")
}
fmt.Fprint(Stdout, string(data))
}

if len(notFound) > 0 {
for i := range notFound {
notFound[i] = strconv.Quote(notFound[i])
}
return fmt.Errorf("no slice definitions found for: " + strings.Join(notFound, ", "))
}

return nil
}

// selectPackageSlices takes in a release and a list of query strings
// of package names and/or slice names, and returns a list of packages
// containing the found slices. It also returns a list of query
// strings that were not found.
func selectPackageSlices(release *setup.Release, queries []string) (packages []*setup.Package, notFound []string) {
var pkgOrder []string
pkgSlices := make(map[string][]string)
allPkgSlices := make(map[string]bool)

sliceExists := func(key setup.SliceKey) bool {
pkg, ok := release.Packages[key.Package]
if !ok {
return false
}
_, ok = pkg.Slices[key.Slice]
return ok
}
for _, query := range queries {
var pkg, slice string
if strings.Contains(query, "_") {
key, err := setup.ParseSliceKey(query)
if err != nil || !sliceExists(key) {
notFound = append(notFound, query)
continue
}
pkg, slice = key.Package, key.Slice
} else {
if _, ok := release.Packages[query]; !ok {
notFound = append(notFound, query)
continue
}
pkg = query
}
if len(pkgSlices[pkg]) == 0 && !allPkgSlices[pkg] {
pkgOrder = append(pkgOrder, pkg)
}
if slice == "" {
allPkgSlices[pkg] = true
} else {
pkgSlices[pkg] = append(pkgSlices[pkg], slice)
}
}

for _, pkgName := range pkgOrder {
var pkg *setup.Package
if allPkgSlices[pkgName] {
pkg = release.Packages[pkgName]
} else {
releasePkg := release.Packages[pkgName]
pkg = &setup.Package{
Name: releasePkg.Name,
Archive: releasePkg.Archive,
Slices: make(map[string]*setup.Slice),
}
for _, sliceName := range pkgSlices[pkgName] {
pkg.Slices[sliceName] = releasePkg.Slices[sliceName]
}
}
packages = append(packages, pkg)
}
return packages, notFound
}
Loading

0 comments on commit 74c5851

Please sign in to comment.