diff --git a/pkg/partition_info/partition_info.go b/pkg/partition_info/partition_info.go index 304f4c1..fc157f5 100644 --- a/pkg/partition_info/partition_info.go +++ b/pkg/partition_info/partition_info.go @@ -3,6 +3,7 @@ package partition_info import ( "fmt" "io/ioutil" + "os" "strings" "github.com/jaypipes/ghw/pkg/block" @@ -22,16 +23,27 @@ type PartitionInfo struct { mapping map[string]string } -func NewPartitionInfoFromFile(file string) (*PartitionInfo, error) { +// NewPartitionInfoFromFile reads the given partition info file (if one exists) +// and returns a pointer to a PartitionInfo object. +// If a file doesn't exist, the function will create one and return an "empty" +// PartitionInfo object. +// The boolean return value indicates whether a file existed or not (true means, +// a file existed already). +func NewPartitionInfoFromFile(file string) (*PartitionInfo, bool, error) { + existed, err := createInfoFileIfNotExists(file) + if err != nil { + return nil, existed, err + } + mapping, err := ParsePartitionInfoFile(file) if err != nil { - return nil, err + return nil, existed, err } return &PartitionInfo{ file: file, mapping: mapping, - }, nil + }, existed, nil } func (pi PartitionInfo) LookupUUIDForLabel(l string) string { @@ -98,3 +110,16 @@ func ParsePartitionInfoFile(file string) (map[string]string, error) { return result, nil } + +// createInfoFileIfNotExists returns true if file already exists or creates the +// the file if it doesn't exist and returns false. +func createInfoFileIfNotExists(fileName string) (bool, error) { + _, err := os.Stat(fileName) + if errors.Is(err, os.ErrNotExist) { + if _, err := os.Create(fileName); err != nil { + return false, err + } + return false, nil + } + return true, nil +} diff --git a/pkg/partition_info/partition_info_test.go b/pkg/partition_info/partition_info_test.go index b77483b..49949a6 100644 --- a/pkg/partition_info/partition_info_test.go +++ b/pkg/partition_info/partition_info_test.go @@ -1,8 +1,11 @@ package partition_info_test import ( + "fmt" "io/ioutil" "os" + "path" + "time" "github.com/jaypipes/ghw/pkg/block" . "github.com/onsi/ginkgo/v2" @@ -18,11 +21,31 @@ var _ = Describe("Partition Info file parsing", func() { BeforeEach(func() { file = "../../tests/assets/partition_info.yaml" }) + When("the files exists already", func() { + It("returns 'true' and a PartitionInfo object", func() { + result, existed, err := pi.NewPartitionInfoFromFile(file) + Expect(err).ToNot(HaveOccurred()) + Expect(result).ToNot(BeNil()) + Expect(existed).To(BeTrue()) + }) + }) - It("returns a PartitionInfo", func() { - result, err := pi.NewPartitionInfoFromFile(file) - Expect(err).ToNot(HaveOccurred()) - Expect(result).ToNot(BeNil()) + When("a file doesn't exist", func() { + var fileName string + BeforeEach(func() { + fileName = path.Join( + os.TempDir(), + fmt.Sprintf("partition-info-%d.yaml", time.Now().UnixNano())) + }) + + It("creates the file and returns 'false' and an (empty) mapping", func() { + result, existed, err := pi.NewPartitionInfoFromFile(fileName) + Expect(err).ToNot(HaveOccurred()) + Expect(result).ToNot(BeNil()) + Expect(existed).To(BeFalse()) + _, err = os.Stat(fileName) + Expect(err).ToNot(HaveOccurred()) + }) }) }) @@ -86,7 +109,7 @@ var _ = Describe("Partition Info file parsing", func() { _, err = file.Write([]byte("TO_KEEP: old_uuid_1")) Expect(err).ToNot(HaveOccurred()) - partitionInfo, err = pi.NewPartitionInfoFromFile(file.Name()) + partitionInfo, _, err = pi.NewPartitionInfoFromFile(file.Name()) Expect(err).ToNot(HaveOccurred()) }) @@ -117,7 +140,7 @@ TO_KEEP: old_uuid_1 BeforeEach(func() { file = "../../tests/assets/partition_info.yaml" - partitionInfo, err = pi.NewPartitionInfoFromFile(file) + partitionInfo, _, err = pi.NewPartitionInfoFromFile(file) Expect(err).ToNot(HaveOccurred()) }) @@ -139,7 +162,7 @@ TO_KEEP: old_uuid_1 BeforeEach(func() { file = "../../tests/assets/partition_info.yaml" - partitionInfo, err = pi.NewPartitionInfoFromFile(file) + partitionInfo, _, err = pi.NewPartitionInfoFromFile(file) Expect(err).ToNot(HaveOccurred()) })