pkg/epoch: extract parsing SOURCE_DATE_EPOCH to a function

This introduces a ParseSourceDateEpoch function, which can be used
to parse "SOURCE_DATE_EPOCH" values for situations where those
values are not passed through an env-var (or the env-var has been
read through other means).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2023-06-23 14:38:36 +02:00
parent 9924e56f42
commit 8760b87174
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
2 changed files with 36 additions and 7 deletions

View File

@ -37,12 +37,11 @@ func SourceDateEpoch() (*time.Time, error) {
if !ok || v == "" { if !ok || v == "" {
return nil, nil // not an error return nil, nil // not an error
} }
i64, err := strconv.ParseInt(v, 10, 64) t, err := ParseSourceDateEpoch(v)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid %s value %q: %w", SourceDateEpochEnv, v, err) return nil, fmt.Errorf("invalid %s value: %w", SourceDateEpochEnv, err)
} }
unix := time.Unix(i64, 0).UTC() return t, nil
return &unix, nil
} }
// SourceDateEpochOrNow returns the SOURCE_DATE_EPOCH time if available, // SourceDateEpochOrNow returns the SOURCE_DATE_EPOCH time if available,
@ -58,6 +57,20 @@ func SourceDateEpochOrNow() time.Time {
return time.Now().UTC() return time.Now().UTC()
} }
// ParseSourceDateEpoch parses the given source date epoch, as *time.Time.
// It returns an error if sourceDateEpoch is empty or not well-formatted.
func ParseSourceDateEpoch(sourceDateEpoch string) (*time.Time, error) {
if sourceDateEpoch == "" {
return nil, fmt.Errorf("value is empty")
}
i64, err := strconv.ParseInt(sourceDateEpoch, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid value: %w", err)
}
unix := time.Unix(i64, 0).UTC()
return &unix, nil
}
// SetSourceDateEpoch sets the SOURCE_DATE_EPOCH env var. // SetSourceDateEpoch sets the SOURCE_DATE_EPOCH env var.
func SetSourceDateEpoch(tm time.Time) { func SetSourceDateEpoch(tm time.Time) {
_ = os.Setenv(SourceDateEpochEnv, strconv.Itoa(int(tm.Unix()))) _ = os.Setenv(SourceDateEpochEnv, strconv.Itoa(int(tm.Unix())))

View File

@ -19,6 +19,7 @@ package epoch
import ( import (
"os" "os"
"runtime" "runtime"
"strconv"
"testing" "testing"
"time" "time"
@ -56,19 +57,25 @@ func TestSourceDateEpoch(t *testing.T) {
}) })
t.Run("WithEmptySourceDateEpoch", func(t *testing.T) { t.Run("WithEmptySourceDateEpoch", func(t *testing.T) {
t.Setenv(SourceDateEpochEnv, "") const emptyValue = ""
t.Setenv(SourceDateEpochEnv, emptyValue)
vp, err := SourceDateEpoch() vp, err := SourceDateEpoch()
require.NoError(t, err) require.NoError(t, err)
require.Nil(t, vp) require.Nil(t, vp)
vp, err = ParseSourceDateEpoch(emptyValue)
require.Error(t, err, "value is empty")
require.Nil(t, vp)
now := time.Now().UTC() now := time.Now().UTC()
v := SourceDateEpochOrNow() v := SourceDateEpochOrNow()
require.True(t, rightAfter(now, v), "now: %s, v: %s", now, v) require.True(t, rightAfter(now, v), "now: %s, v: %s", now, v)
}) })
t.Run("WithSourceDateEpoch", func(t *testing.T) { t.Run("WithSourceDateEpoch", func(t *testing.T) {
sourceDateEpoch, err := time.Parse(time.RFC3339, "2022-01-23T12:34:56Z") const rfc3339Str = "2022-01-23T12:34:56Z"
sourceDateEpoch, err := time.Parse(time.RFC3339, rfc3339Str)
require.NoError(t, err) require.NoError(t, err)
SetSourceDateEpoch(sourceDateEpoch) SetSourceDateEpoch(sourceDateEpoch)
@ -76,6 +83,10 @@ func TestSourceDateEpoch(t *testing.T) {
vp, err := SourceDateEpoch() vp, err := SourceDateEpoch()
require.NoError(t, err) require.NoError(t, err)
require.True(t, vp.Equal(sourceDateEpoch.UTC()))
vp, err = ParseSourceDateEpoch(strconv.Itoa(int(sourceDateEpoch.Unix())))
require.NoError(t, err)
require.True(t, vp.Equal(sourceDateEpoch)) require.True(t, vp.Equal(sourceDateEpoch))
v := SourceDateEpochOrNow() v := SourceDateEpochOrNow()
@ -83,12 +94,17 @@ func TestSourceDateEpoch(t *testing.T) {
}) })
t.Run("WithInvalidSourceDateEpoch", func(t *testing.T) { t.Run("WithInvalidSourceDateEpoch", func(t *testing.T) {
t.Setenv(SourceDateEpochEnv, "foo") const invalidValue = "foo"
t.Setenv(SourceDateEpochEnv, invalidValue)
vp, err := SourceDateEpoch() vp, err := SourceDateEpoch()
require.ErrorContains(t, err, "invalid SOURCE_DATE_EPOCH value") require.ErrorContains(t, err, "invalid SOURCE_DATE_EPOCH value")
require.Nil(t, vp) require.Nil(t, vp)
vp, err = ParseSourceDateEpoch(invalidValue)
require.ErrorContains(t, err, "invalid value:")
require.Nil(t, vp)
now := time.Now().UTC() now := time.Now().UTC()
v := SourceDateEpochOrNow() v := SourceDateEpochOrNow()
require.True(t, rightAfter(now, v), "now: %s, v: %s", now, v) require.True(t, rightAfter(now, v), "now: %s, v: %s", now, v)