Skip to content

Commit 5f1bb14

Browse files
authored
Refactor packages and add docs (#15)
This is a large refactor of the library. Packages have been organized based on dependencies. A Streamer interface has been added as an abstraction for converting urls to streams. Some interfaces have been removed since they were not being used. All packages now have descriptions and relevant usage documentation.
1 parent eb3afd5 commit 5f1bb14

39 files changed

+1105
-1078
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
[![Build Status](https://travis-ci.org/aws-robotics/aws-robomaker-bundle-support-library.svg?branch=development)](https://travis-ci.org/aws-robotics/aws-robomaker-bundle-support-library) [![Go Report Card](https://goreportcard.com/badge/github.com/aws-robotics/aws-robomaker-bundle-support-library)](https://goreportcard.com/report/github.com/aws-robotics/aws-robomaker-bundle-support-library)
12
## AWS Robomaker Bundle Support Library
23

34
**This API is currently under active development and should not be considered stable.**

cmd/cli/main.go

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,56 @@
1+
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
/*
5+
Package cli provides a basic command line application to interact with bundles.
6+
7+
It will extract the bundle to the cache directory and then print the
8+
command that can be used to source the bundle into the environment.
9+
10+
Usage:
11+
go run github.com/aws-robotics/aws-robomaker-bundle-support-library \
12+
--bundle <path to bundle> \
13+
--cache (optional) <path to cache directory (default: cache)> \
14+
--prefix (optional) <prefix for source command paths (must include cache directory)>
15+
*/
116
package main
217

318
import (
419
"fmt"
20+
"github.com/aws-robotics/aws-robomaker-bundle-support-library/pkg/stream/local"
521
"io/ioutil"
622
"log"
723
"os"
824

925
"github.com/aws-robotics/aws-robomaker-bundle-support-library/pkg/bundle"
10-
"github.com/aws-robotics/aws-robomaker-bundle-support-library/pkg/file_system"
1126
"github.com/aws-robotics/aws-robomaker-bundle-support-library/pkg/store"
27+
"github.com/aws-robotics/aws-robomaker-bundle-support-library/pkg/stream"
1228
"github.com/urfave/cli"
1329
)
1430

1531
func main() {
1632
app := cli.NewApp()
17-
app.Name = "Bundle Info"
18-
app.Usage = "Get source command for bundle"
33+
app.Name = "Bundle Helper"
34+
app.Usage = "Extracts a bundle and prints the command to source the bundle into a shell environment. " +
35+
"Will intelligently cache in the cache directory."
1936
app.Flags = []cli.Flag{
2037
cli.StringFlag{Name: "bundle", Value: "", Usage: "Path to bundle file"},
2138
cli.StringFlag{Name: "prefix", Value: "", Usage: "Prefix to put onto the source command"},
39+
cli.StringFlag{Name: "cache", Value: "cache", Usage: "Folder to be used as the cache " +
40+
"directory for extracted bundles."},
2241
}
42+
43+
local := local.NewStreamer()
44+
stream.RegisterStreamer(local)
45+
2346
app.Action = func(c *cli.Context) error {
24-
fmt.Println("Opening ", c.String("bundle"))
25-
cache_path := "./cache"
26-
bundle_store := store.NewSimpleStore(cache_path, file_system.NewLocalFS())
47+
cachePath := c.String("cache")
48+
bundleStore := store.NewSimpleStore(cachePath)
2749

28-
bundle_path := c.String("bundle")
29-
prefix_path := c.String("prefix")
50+
bundlePath := c.String("bundle")
51+
prefixPath := c.String("prefix")
3052

31-
files, err := ioutil.ReadDir(cache_path)
53+
files, err := ioutil.ReadDir(cachePath)
3254
if err != nil {
3355
log.Fatal(err)
3456
}
@@ -40,20 +62,20 @@ func main() {
4062
}
4163
}
4264

43-
err = bundle_store.Load(keys)
65+
err = bundleStore.Load(keys)
4466
if err != nil {
4567
log.Fatal(err)
4668
return err
4769
}
4870

49-
bundle_provider := bundle.NewBundleProvider(bundle_store)
50-
b, err := bundle_provider.GetBundle(bundle_path)
71+
bundleProvider := bundle.NewProvider(bundleStore)
72+
b, err := bundleProvider.GetBundle(bundlePath)
5173
if err != nil {
5274
log.Fatal(err)
5375
return err
5476
}
5577
for i := 0; i < len(b.PosixSourceCommands()); i++ {
56-
fmt.Print(b.PosixSourceCommandsUsingLocation(prefix_path)[i])
78+
fmt.Print(b.PosixSourceCommandsUsingLocation(prefixPath)[i])
5779
}
5880

5981
return nil

example/s3_download/main.go

Lines changed: 0 additions & 67 deletions
This file was deleted.

example/test_app/main.go

Lines changed: 0 additions & 85 deletions
This file was deleted.

pkg/bundle/archive.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package bundle
5+
6+
//go:generate mockgen -destination=mock_archiver.go -package=bundle github.com/aws-robotics/aws-robomaker-bundle-support-library/pkg/3p/archiver Archiver
7+
8+
import (
9+
"archive/tar"
10+
"compress/gzip"
11+
"errors"
12+
"fmt"
13+
"github.com/aws-robotics/aws-robomaker-bundle-support-library/pkg/fs"
14+
"io"
15+
)
16+
17+
const (
18+
versionFileName = "version"
19+
defaultFileMode fs.FileMode = 0755
20+
)
21+
22+
// archive's responsibility is to be able to Extract bundles of all versions, v1, v2, etc.
23+
type archive struct {
24+
version string
25+
inputStream io.ReadSeeker
26+
bundleProcessor bundleProcessor
27+
}
28+
29+
func newBundleArchive(inputStream io.ReadSeeker) (*archive, error) {
30+
// read version to determine bundle version
31+
tarReader := tarReaderFromStream(inputStream)
32+
version, versionErr := readVersionFromBundle(tarReader)
33+
34+
if versionErr != nil {
35+
return nil, fmt.Errorf("unable to read version from bundle: %v", versionErr)
36+
}
37+
38+
// get the appropriate bundle processor for the version
39+
bundleProcessor := processorForVersion(version)
40+
if bundleProcessor == nil {
41+
return nil, fmt.Errorf("unsuppported bundle processor version: %s", version)
42+
}
43+
44+
// reset seek position to start of the stream and init with the stream
45+
inputStream.Seek(0, io.SeekStart)
46+
return &archive{
47+
version: version,
48+
inputStream: inputStream,
49+
bundleProcessor: bundleProcessor,
50+
}, nil
51+
}
52+
53+
// What version is this bundle?
54+
func (b *archive) Version() string {
55+
return b.version
56+
}
57+
58+
// Extract everything into the cache
59+
func (b *archive) Extract(bundleStore Cache) (Bundle, error) {
60+
return b.bundleProcessor.extract(b.inputStream, bundleStore)
61+
}
62+
63+
func readVersionFromBundle(tarReader *tar.Reader) (string, error) {
64+
header, headerErr := tarReader.Next()
65+
if headerErr != nil {
66+
fmt.Printf("bundleError parsing tar: %v", headerErr)
67+
return "", headerErr
68+
}
69+
70+
if header.Name != versionFileName {
71+
err := errors.New("invalid bundle format, first file should be a version file")
72+
return "", err
73+
}
74+
75+
versionData := make([]byte, header.Size)
76+
_, readVersionErr := tarReader.Read(versionData)
77+
// We need to read a second time to get the io.EOF message
78+
_, readVersionErr = tarReader.Read(nil)
79+
if readVersionErr != io.EOF {
80+
return "", fmt.Errorf("unable to read version: %v", readVersionErr)
81+
}
82+
83+
return string(versionData), nil
84+
}
85+
86+
func tarReaderFromStream(inputStream io.ReadSeeker) *tar.Reader {
87+
var tarReader *tar.Reader
88+
89+
// try as a gzReader
90+
gzReader, gzErr := gzip.NewReader(inputStream)
91+
if gzErr == nil {
92+
// this is a valid gz file
93+
// create the tar reader from the gzReader
94+
tarReader = tar.NewReader(gzReader)
95+
} else {
96+
// it wasn't a gz file, let's try to create the tar reader from the input stream
97+
inputStream.Seek(0, io.SeekStart)
98+
tarReader = tar.NewReader(inputStream)
99+
}
100+
return tarReader
101+
}

0 commit comments

Comments
 (0)