Skip to content

Commit b151522

Browse files
cobyfrombrooklyn-botcobyfrombrooklyn-bot
andauthored
fix: preserve original filename when using --front-matter (#2613)
When using --front-matter, yq creates a temporary file for the extracted YAML content but replaces the original filename in args with the temp file path. This caused the 'filename' operator to return the temp file path instead of the original filename. Added a filename alias mechanism: when front matter processing replaces the file path, it registers the original filename as an alias. The readDocuments and stream evaluator functions resolve aliases before setting candidateNode.filename. Fixes #2538 Co-authored-by: cobyfrombrooklyn-bot <[email protected]>
1 parent c5cbf97 commit b151522

5 files changed

Lines changed: 80 additions & 0 deletions

File tree

cmd/evaluate_all_command.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,15 @@ func evaluateAll(cmd *cobra.Command, args []string) (cmdError error) {
101101
}
102102

103103
if frontMatter != "" {
104+
originalFilename := args[0]
104105
frontMatterHandler := yqlib.NewFrontMatterHandler(args[0])
105106
err = frontMatterHandler.Split()
106107
if err != nil {
107108
return err
108109
}
109110
args[0] = frontMatterHandler.GetYamlFrontMatterFilename()
111+
yqlib.SetFilenameAlias(args[0], originalFilename)
112+
defer yqlib.ClearFilenameAliases()
110113

111114
if frontMatter == "process" {
112115
reader := frontMatterHandler.GetContentReader()

cmd/evaluate_sequence_command.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,15 @@ func evaluateSequence(cmd *cobra.Command, args []string) (cmdError error) {
122122

123123
if frontMatter != "" {
124124
yqlib.GetLogger().Debug("using front matter handler")
125+
originalFilename := args[0]
125126
frontMatterHandler := yqlib.NewFrontMatterHandler(args[0])
126127
err = frontMatterHandler.Split()
127128
if err != nil {
128129
return err
129130
}
130131
args[0] = frontMatterHandler.GetYamlFrontMatterFilename()
132+
yqlib.SetFilenameAlias(args[0], originalFilename)
133+
defer yqlib.ClearFilenameAliases()
131134

132135
if frontMatter == "process" {
133136
reader := frontMatterHandler.GetContentReader()

pkg/yqlib/front_matter_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,55 @@ yaml: doc
108108
fmHandler.CleanUp()
109109
}
110110

111+
func TestFrontMatterFilenamePreserved(t *testing.T) {
112+
// Regression test for https://github.com/mikefarah/yq/issues/2538
113+
// When using --front-matter, the filename operator should return
114+
// the original filename, not the path to the temporary file.
115+
file := createTestFile(`---
116+
name: john
117+
---
118+
Some content
119+
`)
120+
originalFilename := "/path/to/original/file.md"
121+
122+
fmHandler := NewFrontMatterHandler(file)
123+
err := fmHandler.Split()
124+
if err != nil {
125+
panic(err)
126+
}
127+
128+
tempFilename := fmHandler.GetYamlFrontMatterFilename()
129+
130+
// Register the alias (as the command code does)
131+
SetFilenameAlias(tempFilename, originalFilename)
132+
defer ClearFilenameAliases()
133+
134+
// Verify resolveFilename returns the original name
135+
resolved := resolveFilename(tempFilename)
136+
test.AssertResult(t, originalFilename, resolved)
137+
138+
// Read documents using the temp file, verify they get the original filename
139+
reader, err := readStream(tempFilename)
140+
if err != nil {
141+
panic(err)
142+
}
143+
decoder := NewYamlDecoder(ConfiguredYamlPreferences)
144+
docs, err := readDocuments(reader, tempFilename, 0, decoder)
145+
if err != nil {
146+
panic(err)
147+
}
148+
149+
if docs.Len() == 0 {
150+
t.Fatal("expected at least one document")
151+
}
152+
153+
firstDoc := docs.Front().Value.(*CandidateNode)
154+
test.AssertResult(t, originalFilename, firstDoc.filename)
155+
156+
tryRemoveTempFile(file)
157+
fmHandler.CleanUp()
158+
}
159+
111160
func TestFrontMatterSplitWithArray(t *testing.T) {
112161
file := createTestFile(`[1,2,3]
113162
---

pkg/yqlib/stream_evaluator.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func (s *streamEvaluator) EvaluateFiles(expression string, filenames []string, p
7676
}
7777

7878
func (s *streamEvaluator) Evaluate(filename string, reader io.Reader, node *ExpressionNode, printer Printer, decoder Decoder) (uint, error) {
79+
filename = resolveFilename(filename)
7980

8081
var currentIndex uint
8182
err := decoder.Init(reader)

pkg/yqlib/utils.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,29 @@ import (
99
"os"
1010
)
1111

12+
// filenameAliases maps real file paths to display names.
13+
// Used by front matter handling to preserve original filenames
14+
// when the actual content is read from temporary files.
15+
var filenameAliases = map[string]string{}
16+
17+
// SetFilenameAlias registers a display name for a file path so that
18+
// the filename operator returns the original name instead of a temp path.
19+
func SetFilenameAlias(realPath string, displayName string) {
20+
filenameAliases[realPath] = displayName
21+
}
22+
23+
// ClearFilenameAliases removes all filename aliases.
24+
func ClearFilenameAliases() {
25+
filenameAliases = map[string]string{}
26+
}
27+
28+
func resolveFilename(filename string) string {
29+
if alias, ok := filenameAliases[filename]; ok {
30+
return alias
31+
}
32+
return filename
33+
}
34+
1235
func readStream(filename string) (io.Reader, error) {
1336
var reader *bufio.Reader
1437
if filename == "-" {
@@ -36,6 +59,7 @@ func ReadDocuments(reader io.Reader, decoder Decoder) (*list.List, error) {
3659
}
3760

3861
func readDocuments(reader io.Reader, filename string, fileIndex int, decoder Decoder) (*list.List, error) {
62+
filename = resolveFilename(filename)
3963
err := decoder.Init(reader)
4064
if err != nil {
4165
return nil, err

0 commit comments

Comments
 (0)