mirror of
https://github.com/anchore/syft
synced 2024-11-13 23:57:07 +00:00
create single dpkg bufio reader
This commit is contained in:
parent
09cf5b9862
commit
d56d157e90
2 changed files with 61 additions and 48 deletions
|
@ -10,7 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: consider keeping the remaining values as an embedded map
|
// TODO: consider keeping the remaining values as an embedded map
|
||||||
type DpkgEntry struct {
|
type Entry struct {
|
||||||
Package string `mapstructure:"Package"`
|
Package string `mapstructure:"Package"`
|
||||||
Architecture string `mapstructure:"Architecture"`
|
Architecture string `mapstructure:"Architecture"`
|
||||||
DependsPkgs string `mapstructure:"Depends"`
|
DependsPkgs string `mapstructure:"Depends"`
|
||||||
|
@ -60,29 +60,49 @@ type DpkgEntry struct {
|
||||||
// Triggers-Awaited (internal)
|
// Triggers-Awaited (internal)
|
||||||
// Triggers-Pending (internal)
|
// Triggers-Pending (internal)
|
||||||
// Version
|
// Version
|
||||||
//
|
|
||||||
|
|
||||||
var EndOfPackages = fmt.Errorf("no more packages to read")
|
var endOfPackages = fmt.Errorf("no more packages to read")
|
||||||
|
|
||||||
func Read(reader io.Reader) (entry DpkgEntry, err error) {
|
func ParseEntries(reader io.Reader) ([]Entry, error) {
|
||||||
buff := bufio.NewReader(reader)
|
buffedReader := bufio.NewReader(reader)
|
||||||
|
var entries = make([]Entry, 0)
|
||||||
|
|
||||||
|
for {
|
||||||
|
entry, err := parseEntry(buffedReader)
|
||||||
|
if err != nil {
|
||||||
|
if err == endOfPackages {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
entries = append(entries, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func parseEntry(reader *bufio.Reader) (entry Entry, err error) {
|
||||||
dpkgFields := make(map[string]string)
|
dpkgFields := make(map[string]string)
|
||||||
var key string
|
var key string
|
||||||
|
|
||||||
for {
|
for {
|
||||||
line, ioerr := buff.ReadString('\n')
|
line, err := reader.ReadString('\n')
|
||||||
fmt.Printf("line:'%+v' err:'%+v'\n", line, ioerr)
|
if err != nil {
|
||||||
if ioerr != nil {
|
if err == io.EOF {
|
||||||
if ioerr == io.EOF {
|
return Entry{}, endOfPackages
|
||||||
return DpkgEntry{}, EndOfPackages
|
|
||||||
}
|
}
|
||||||
return DpkgEntry{}, ioerr
|
return Entry{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
line = strings.TrimRight(line, "\n")
|
line = strings.TrimRight(line, "\n")
|
||||||
|
|
||||||
// stop if there is no contents in line
|
// empty line indicates end of entry
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
|
// if the entry has not started, keep parsing lines
|
||||||
|
if len(dpkgFields) == 0{
|
||||||
|
continue
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,12 +110,12 @@ func Read(reader io.Reader) (entry DpkgEntry, err error) {
|
||||||
case strings.HasPrefix(line, " "):
|
case strings.HasPrefix(line, " "):
|
||||||
// a field-body continuation
|
// a field-body continuation
|
||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
return DpkgEntry{}, fmt.Errorf("no match for continuation: line: '%s'", line)
|
return Entry{}, fmt.Errorf("no match for continuation: line: '%s'", line)
|
||||||
}
|
}
|
||||||
|
|
||||||
val, ok := dpkgFields[key]
|
val, ok := dpkgFields[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
return DpkgEntry{}, fmt.Errorf("no previous key exists, expecting: %s", key)
|
return Entry{}, fmt.Errorf("no previous key exists, expecting: %s", key)
|
||||||
}
|
}
|
||||||
// concatenate onto previous value
|
// concatenate onto previous value
|
||||||
val = fmt.Sprintf("%s\n %s", val, strings.TrimSpace(line))
|
val = fmt.Sprintf("%s\n %s", val, strings.TrimSpace(line))
|
||||||
|
@ -107,42 +127,21 @@ func Read(reader io.Reader) (entry DpkgEntry, err error) {
|
||||||
val := strings.TrimSpace(line[i+1:])
|
val := strings.TrimSpace(line[i+1:])
|
||||||
|
|
||||||
if _, ok := dpkgFields[key]; ok {
|
if _, ok := dpkgFields[key]; ok {
|
||||||
return DpkgEntry{}, fmt.Errorf("duplicate key discovered: %s", key)
|
return Entry{}, fmt.Errorf("duplicate key discovered: %s", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
dpkgFields[key] = val
|
dpkgFields[key] = val
|
||||||
} else {
|
} else {
|
||||||
return DpkgEntry{}, fmt.Errorf("cannot parse field from line: '%s'", line)
|
return Entry{}, fmt.Errorf("cannot parse field from line: '%s'", line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("OUTOFLOOP")
|
|
||||||
|
|
||||||
// map -> struct
|
|
||||||
err = mapstructure.Decode(dpkgFields, &entry)
|
err = mapstructure.Decode(dpkgFields, &entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DpkgEntry{}, err
|
return Entry{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry, nil
|
return entry, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadAllDpkgEntries(reader io.Reader) ([]DpkgEntry, error) {
|
|
||||||
var entries = make([]DpkgEntry, 0)
|
|
||||||
|
|
||||||
for {
|
|
||||||
// Read() until error
|
|
||||||
entry, err := Read(reader)
|
|
||||||
fmt.Printf("entry:'%+v'\n\terr:%+v\n", entry, err)
|
|
||||||
if err != nil {
|
|
||||||
if err == EndOfPackages {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
entries = append(entries, entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries, nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
package dpkg
|
package dpkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-test/deep"
|
"github.com/go-test/deep"
|
||||||
)
|
)
|
||||||
|
|
||||||
func compareEntries(t *testing.T, left, right DpkgEntry) {
|
func compareEntries(t *testing.T, left, right Entry) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if diff := deep.Equal(left, right); diff != nil {
|
if diff := deep.Equal(left, right); diff != nil {
|
||||||
t.Error(diff)
|
t.Error(diff)
|
||||||
|
@ -17,11 +18,11 @@ func compareEntries(t *testing.T, left, right DpkgEntry) {
|
||||||
func TestSinglePackage(t *testing.T) {
|
func TestSinglePackage(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
expected DpkgEntry
|
expected Entry
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Test Single Package",
|
name: "Test Single Package",
|
||||||
expected: DpkgEntry{
|
expected: Entry{
|
||||||
Package: "apt",
|
Package: "apt",
|
||||||
Status: "install ok installed",
|
Status: "install ok installed",
|
||||||
Priority: "required",
|
Priority: "required",
|
||||||
|
@ -49,8 +50,16 @@ func TestSinglePackage(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Unable to read test_fixtures/single: ", err)
|
t.Fatal("Unable to read test_fixtures/single: ", err)
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
entry, err := Read(file)
|
reader := bufio.NewReader(file)
|
||||||
|
|
||||||
|
entry, err := parseEntry(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Unable to read file contents: ", err)
|
t.Fatal("Unable to read file contents: ", err)
|
||||||
}
|
}
|
||||||
|
@ -61,14 +70,14 @@ func TestSinglePackage(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMultiplePackage(t *testing.T) {
|
func TestMultiplePackages(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
expected []DpkgEntry
|
expected []Entry
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Test Multiple Package",
|
name: "Test Multiple Package",
|
||||||
expected: []DpkgEntry{
|
expected: []Entry{
|
||||||
{
|
{
|
||||||
Package: "tzdata",
|
Package: "tzdata",
|
||||||
Status: "install ok installed",
|
Status: "install ok installed",
|
||||||
|
@ -110,9 +119,14 @@ func TestMultiplePackage(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Unable to read: ", err)
|
t.Fatal("Unable to read: ", err)
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer func() {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
entries, err := ReadAllDpkgEntries(file)
|
entries, err := ParseEntries(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Unable to read file contents: ", err)
|
t.Fatal("Unable to read file contents: ", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue