mikefarah / yq

yq is a portable command-line YAML, JSON, XML, CSV, TOML and properties processor
https://mikefarah.gitbook.io/yq/
MIT License
11.65k stars 579 forks source link

sortKeys() needs to consider yaml anchor #943

Open williamjoy opened 2 years ago

williamjoy commented 2 years ago

Describe the bug yq sortKeys() may output yaml with unknown anchor 'c' referenced

Note that any how to questions should be posted in the discussion board and not raised as an issue.

Version of yq: 4.13.2 Operating system: mac Installed via: homebrew

Input Yaml Concise yaml document(s) (as simple as possible to show the bug, please keep it to 10 lines or less) test.yaml:

c: &c 0
a: *c
b: 2

Command The command you ran:

yq eval 'sortKeys(.)' test.yaml

Actual behavior

a: *c
b: 2
c: &c 0

Expected behavior

It should output valid yaml anchor order

➜  ~ yq eval 'sortKeys(.)' test.yaml | yq eval
Error: yaml: unknown anchor 'c' referenced

Additional context Debug

yq eval 'sortKeys(.)' test.yaml -v       
16:05:58 func1 [DEBU] opTokenWithPrefs sortKeys
16:05:58 Tokenise [DEBU] Tokenising SORT_KEYS (50)
16:05:58 Tokenise [DEBU] Tokenising (
16:05:58 Tokenise [DEBU] Tokenising SELF (55)
16:05:58 Tokenise [DEBU] Tokenising )
16:05:58 handleToken [DEBU] processing SORT_KEYS (50)
16:05:58 handleToken [DEBU]   adding token to the fixed list
16:05:58 handleToken [DEBU] processing (
16:05:58 handleToken [DEBU]   adding token to the fixed list
16:05:58 handleToken [DEBU] processing SELF (55)
16:05:58 handleToken [DEBU]   adding token to the fixed list
16:05:58 handleToken [DEBU] processing )
16:05:58 handleToken [DEBU]   adding token to the fixed list
16:05:58 ConvertToPostfix [DEBU] postfix processing currentToken SORT_KEYS (50)
16:05:58 ConvertToPostfix [DEBU] put SORT_KEYS (50) onto the opstack
16:05:58 ConvertToPostfix [DEBU] postfix processing currentToken (
16:05:58 ConvertToPostfix [DEBU] put ( onto the opstack
16:05:58 ConvertToPostfix [DEBU] postfix processing currentToken SELF (55)
16:05:58 ConvertToPostfix [DEBU] put SELF (55) onto the opstack
16:05:58 ConvertToPostfix [DEBU] postfix processing currentToken )
16:05:58 popOpToResult [DEBU] popped SELF (55) from opstack to results
16:05:58 ConvertToPostfix [DEBU] postfix processing currentToken )
16:05:58 popOpToResult [DEBU] popped SORT_KEYS (50) from opstack to results
16:05:58 ConvertToPostfix [DEBU] opstackLen: 0
16:05:58 ConvertToPostfix [DEBU] PostFix Result:
16:05:58 ConvertToPostfix [DEBU] > SELF
16:05:58 ConvertToPostfix [DEBU] > SORT_KEYS
16:05:58 createExpressionTree [DEBU] pathTree SELF 
16:05:58 createExpressionTree [DEBU] pathTree SORT_KEYS 
16:05:58 GetMatchingNodes [DEBU] Processing Op: SORT_KEYS
16:05:58 GetMatchingNodes [DEBU] D0, P[], (doc)::# $yqLeadingContent$

c: &c 0
a: *c
b: 2
16:05:58 GetMatchingNodes [DEBU] >>
16:05:58 GetMatchingNodes [DEBU] Processing Op: SELF
16:05:58 GetMatchingNodes [DEBU] D0, P[], (doc)::# $yqLeadingContent$

c: &c 0
a: *c
b: 2
16:05:58 GetMatchingNodes [DEBU] >>
16:05:58 PrintResults [DEBU] PrintResults for 1 matches
16:05:58 PrintResults [DEBU] -- print sep logic: p.firstTimePrinting: false, previousDocIndex: 0, mappedDoc.Document: 0, printDocSeparators: true
16:05:58 PrintResults [DEBU] headcommentwas $yqLeadingContent$
16:05:58 PrintResults [DEBU] finished headcomment
a: *c
b: 2
c: &c 0
mikefarah commented 2 years ago

Oh I see - the anchors need to go on the top. I guess it could order keys that are anchors first, then regular keys.

miqm commented 2 months ago

this same problem is when you merge multiple files - anchors are kept and when everything sorted - reading the output yaml in a different parser throws exceptions on missing anchors. In other words - the output yaml is invalid.

@mikefarah - Can this be prioritized? I think when you do eval, you should be removing anchors as they are local to each file.