Skip to content

Commit

Permalink
Use pointers internally for frontmatter (#556)
Browse files Browse the repository at this point in the history
Changes to further relax the requirement that Session Outputs always
require document-level lifecycle identity.
  • Loading branch information
sourishkrout authored Apr 16, 2024
1 parent 856b9ef commit cf7fe77
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 39 deletions.
38 changes: 24 additions & 14 deletions internal/document/editor/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,35 @@ func Deserialize(data []byte, identityResolver *identity.IdentityResolver) (*Not

func Serialize(notebook *Notebook, outputMetadata *document.RunmeMetadata) ([]byte, error) {
var result []byte
var err error
var frontmatter *document.Frontmatter

// Serialize frontmatter.
if intro, ok := notebook.Metadata[PrefixAttributeName(InternalAttributePrefix, FrontmatterKey)]; ok {
raw := []byte(intro)

if outputMetadata != nil {
frontmatter, err := document.ParseFrontmatter(raw)
if err != nil {
return nil, err
}
frontmatter.Runme.Session = outputMetadata.Session
frontmatter.Runme.Session.Updated = prettyTime(time.Now())
frontmatter.Runme.Document = outputMetadata.Document

// true because no outputs serialization without lifecycle identity
raw, err = frontmatter.Marshal(true)
if err != nil {
return nil, err
}
frontmatter, err = document.ParseFrontmatter(raw)
if err != nil {
return nil, err
}
}

var raw []byte
if outputMetadata != nil {
if frontmatter == nil {
frontmatter = document.NewYAMLFrontmatter()
}
frontmatter.Runme.Session = outputMetadata.Session
frontmatter.Runme.Session.Updated = prettyTime(time.Now())
frontmatter.Runme.Document = outputMetadata.Document
}

if frontmatter != nil {
// if the deserializer didn't add the ID first, it means it's not required
requireIdentity := !frontmatter.Runme.IsEmpty() && frontmatter.Runme.ID != ""
raw, err = frontmatter.Marshal(requireIdentity)
if err != nil {
return nil, err
}

lb := document.DetectLineBreak(raw)
Expand Down
4 changes: 2 additions & 2 deletions internal/document/editor/editor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,11 @@ A paragraph
rpath := "README.md"
invalidTs := "invalid-timestamp-should-be-overwritten"
outputMetadata := &document.RunmeMetadata{
Session: document.RunmeMetadataSession{
Session: &document.RunmeMetadataSession{
ID: sid,
Updated: invalidTs,
},
Document: document.RunmeMetadataDocument{RelativePath: rpath},
Document: &document.RunmeMetadataDocument{RelativePath: rpath},
}
result, err := Serialize(notebook, outputMetadata)
require.NoError(t, err)
Expand Down
6 changes: 3 additions & 3 deletions internal/document/editor/editorservice/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (s *parserServiceServer) Deserialize(_ context.Context, req *parserv1.Deser
runme.Version = notebook.Frontmatter.Runme.Version
}

if notebook.Frontmatter.Runme.Session.ID != "" {
if notebook.Frontmatter.Runme.Session != nil && notebook.Frontmatter.Runme.Session.ID != "" {
runme.Session = &parserv1.RunmeSession{
Id: notebook.Frontmatter.Runme.Session.ID,
Document: &parserv1.RunmeSessionDocument{
Expand Down Expand Up @@ -123,10 +123,10 @@ func (s *parserServiceServer) Serialize(_ context.Context, req *parserv1.Seriali
}

outputMetadata = &document.RunmeMetadata{
Session: document.RunmeMetadataSession{
Session: &document.RunmeMetadataSession{
ID: req.Options.Session.GetId(),
},
Document: document.RunmeMetadataDocument{
Document: &document.RunmeMetadataDocument{
RelativePath: relativePath,
},
}
Expand Down
10 changes: 5 additions & 5 deletions internal/document/editor/editorservice/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ func Test_IdentityUnspecified(t *testing.T) {
assert.True(t, ok)
assert.Len(t, dResp.Notebook.Metadata, 3)
assert.Contains(t, rawFrontmatter, "prop: value\n")
assert.Contains(t, rawFrontmatter, "id: 123\n")
assert.Contains(t, rawFrontmatter, "version: v99\n")
assert.Contains(t, rawFrontmatter, "id: \"123\"\n")
assert.Contains(t, rawFrontmatter, "version: v")
} else {
assert.False(t, ok)
assert.Len(t, dResp.Notebook.Metadata, 2)
Expand Down Expand Up @@ -224,7 +224,7 @@ func Test_IdentityCell(t *testing.T) {
assert.True(t, ok)
assert.Len(t, dResp.Notebook.Metadata, 3)
assert.Contains(t, rawFrontmatter, "prop: value\n")
assert.Contains(t, rawFrontmatter, "id: 123\n")
assert.Contains(t, rawFrontmatter, "id: \"123\"\n")
assert.Regexp(t, versionRegex, rawFrontmatter, "Wrong version")
} else {
assert.False(t, ok)
Expand All @@ -238,8 +238,8 @@ func Test_IdentityCell(t *testing.T) {

if tt.hasExtraFrontmatter {
assert.Contains(t, content, "runme:\n")
assert.Contains(t, content, "id: 123\n")
assert.Contains(t, content, "version: v99\n")
assert.NotContains(t, content, "id: \"123\"\n")
assert.Contains(t, content, "version: v")
} else {
assert.NotRegexp(t, "^---\n", content)
assert.NotRegexp(t, "^\n\n", content)
Expand Down
60 changes: 46 additions & 14 deletions internal/document/frontmatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,55 @@ type RunmeMetadataSession struct {
Updated string `yaml:"updated,omitempty" json:"updated,omitempty" toml:"updated,omitempty"`
}

func (s *RunmeMetadataSession) GetID() string {
if s == nil {
return ""
}

return s.ID
}

type RunmeMetadata struct {
ID string `yaml:"id,omitempty" json:"id,omitempty" toml:"id,omitempty"`
Version string `yaml:"version,omitempty" json:"version,omitempty" toml:"version,omitempty"`
Document RunmeMetadataDocument `yaml:"document,omitempty" json:"document,omitempty" toml:"document,omitempty"`
Session RunmeMetadataSession `yaml:"session,omitempty" json:"session,omitempty" toml:"session,omitempty"`
ID string `yaml:"id,omitempty" json:"id,omitempty" toml:"id,omitempty"`
Version string `yaml:"version,omitempty" json:"version,omitempty" toml:"version,omitempty"`
Document *RunmeMetadataDocument `yaml:"document,omitempty" json:"document,omitempty" toml:"document,omitempty"`
Session *RunmeMetadataSession `yaml:"session,omitempty" json:"session,omitempty" toml:"session,omitempty"`
}

func (m *RunmeMetadata) IsEmpty() bool {
if m == nil {
return true
}

return m.ID == "" && m.Version == "" && m.Document == nil && m.Session == nil
}

type Frontmatter struct {
Runme RunmeMetadata `yaml:"runme,omitempty"`
Shell string `yaml:"shell"`
Cwd string `yaml:"cwd"`
Category string `yaml:"category"`
SkipPrompts bool `yaml:"skipPrompts,omitempty"`
Runme *RunmeMetadata `yaml:"runme,omitempty"`
Shell string `yaml:"shell"`
Cwd string `yaml:"cwd"`
Category string `yaml:"category"`
SkipPrompts bool `yaml:"skipPrompts,omitempty"`

format string
raw string // using string to be able to compare using ==
}

func newBlankFrontmatter(format string) *Frontmatter {
return &Frontmatter{
format: format,
}
}

func NewYAMLFrontmatter() *Frontmatter {
f := newBlankFrontmatter(frontmatterFormatYAML)
f.raw = ""
return f
}

func newFrontmatter() *Frontmatter {
return &Frontmatter{
Runme: RunmeMetadata{
Runme: &RunmeMetadata{
ID: ulid.GenerateID(),
Version: version.BaseVersion(),
},
Expand Down Expand Up @@ -84,7 +112,7 @@ func (f *Frontmatter) marshal(requireIdentity bool) ([]byte, error) {
return nil, errors.WithStack(err)
}

if requireIdentity {
if !f.Runme.IsEmpty() {
m["runme"] = f.Runme
}

Expand All @@ -107,15 +135,15 @@ func (f *Frontmatter) marshal(requireIdentity bool) ([]byte, error) {
return nil, errors.WithStack(err)
}

if requireIdentity {
if !f.Runme.IsEmpty() {
m["runme"] = f.Runme
}

data, err := json.Marshal(m)
if err != nil {
return nil, errors.WithStack(err)
}
return append(append([]byte("---\n"), data...), []byte("---")...), nil
return append(append([]byte("---\n"), data...), []byte("\n---")...), nil

case frontmatterFormatTOML:
m := make(map[string]interface{})
Expand All @@ -124,7 +152,7 @@ func (f *Frontmatter) marshal(requireIdentity bool) ([]byte, error) {
return nil, errors.WithStack(err)
}

if requireIdentity {
if !f.Runme.IsEmpty() {
m["runme"] = f.Runme
}

Expand All @@ -140,6 +168,10 @@ func (f *Frontmatter) marshal(requireIdentity bool) ([]byte, error) {
}

func (f *Frontmatter) ensureID() {
if f.Runme.IsEmpty() {
f.Runme = &RunmeMetadata{}
}

if !ulid.ValidID(f.Runme.ID) {
f.Runme.ID = ulid.GenerateID()
}
Expand Down
2 changes: 1 addition & 1 deletion internal/project/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ func getCodeBlocks(data []byte) (document.CodeBlocks, error) {
identityResolver := identity.NewResolver(identity.DefaultLifecycleIdentity)
d := document.New(data, identityResolver)

if f, err := d.Frontmatter(); err == nil && f != nil && f.Runme.Session.ID != "" {
if f, err := d.Frontmatter(); err == nil && f != nil && !f.Runme.IsEmpty() && f.Runme.Session.GetID() != "" {
return nil, nil
}

Expand Down

0 comments on commit cf7fe77

Please sign in to comment.