Repository: getsops/sops (language: python)

Issue:
Cannot output empty yaml file since sops-v3.7.0
* sops-3.6.1

    ```
    $ curl -Lso sops-v3.6.1 https://github.com/mozilla/sops/releases/download/v3.6.1/sops-v3.6.1.linux
    $ chmod 755 sops-v3.6.1
    $ echo '{}' | ./sops-v3.6.1 --pgp FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4 --input-type yaml --output-type yaml -e /dev/stdin 2>/dev/null | ./sops-v3.6.1 --input-type yaml --output-type yaml -d /dev/stdin
    {}
    $
    ```

* sops-3.7.1 (same to sops-3.7.0)

    ```
    $ curl -Lso sops-v3.7.1 https://github.com/mozilla/sops/releases/download/v3.7.1/sops-v3.7.1.linux
    $ chmod 755 sops-v3.7.1
    $ echo '{}' | ./sops-v3.7.1 --pgp FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4 --input-type yaml --output-type yaml -e /dev/stdin 2>/dev/null | ./sops-v3.7.1 --input-type yaml --output-type yaml -d /dev/stdin
    Error dumping file: Error marshaling to yaml: yaml: expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got document end
    $
    ```


Encoded outputs are same for both versions:
* sops-v3.6.1

    ```
    $ echo '{}' | ./sops-v3.6.1 --pgp FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4 --input-type yaml --output-type yaml -e /dev/stdin 2>/dev/null
    sops:
        kms: []
        gcp_kms: []
        azure_kv: []
        hc_vault: []
        lastmodified: '2021-07-23T04:29:26Z'
        mac: ENC[AES256_GCM,data:UH3M6XfWD7emEY7SS7ZS3ix0ZJJaFbbyJBaJNQD4CuTsaCvNcoXtwfAPf/52/SjhEPVi+LwH6lNwexNUILT1pJqR9HA6SaTcVekXmZrsfM1KI8qn8Tg8ZYl5d51LcouwqO5CChFyvK7aWiTy9d0MPJsN/nZ5YABI7gSGuiTxwFU=,iv:zWvwY1E0kcHmlY3DhM00l1DMKq5WsoboO/FvS7eeFgY=,tag:lP6T17vSSf3FPD6JPCVb/g==,type:str]
        pgp:
        -   created_at: '2021-07-23T04:29:25Z'
            enc: |
                -----BEGIN PGP MESSAGE-----

                hQEMAyUpShfNkFB/AQf+IQre0LGWgNaNEXdJjcsDB54KLsvR5YV44Zf0eXnQBvvf
                TpBdeMvRYxfsh+rxxZBb6NT8Fhp+rNRgglUBv4MwL8c3qimskjqBcofQuwdU5RUB
                EC2jxQpenhEEup5BWF/IhkcygaWVdDYYDYeVqARmteZcw4w/FIic5P0Rm0AGcrp3
                FvjxqgxJIlYncx//1XjFeqmZvpeLuFNWh+z4K1Ycy2t0ArF1wrKOYseJ4hLTmE0A
                n2e3jVJA0x9UXWkqmMsk0olcbWrZBlHuojMqv+oLZxtHN64tcScB0FL7LmBSoOL+
                eBmYZtOCu9SuSx/r4zl7HxMrvWeTm9ArkCVtsVUF0dJeAQbR6v9OfJvZipuiWAqN
                6sJIpGIBVFZXx90ZQ0f2f29RhPmwA2eng0W/GyNUeBqa6M0NiI54CzgCgSyqCvQF
                oc2pt992TbBbR4ZMUrFGo/celqQOvCygonUgQ8jkrw==
                =Pu21
                -----END PGP MESSAGE-----
            fp: FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4
        unencrypted_suffix: _unencrypted
        version: 3.6.1
    $
    ```

* sops-v3.7.1

    ```
    $ echo '{}' | ./sops-v3.7.1 --pgp FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4 --input-type yaml --output-type yaml -e /dev/stdin 2>/dev/null
    sops:
        kms: []
        gcp_kms: []
        azure_kv: []
        hc_vault: []
        age: []
        lastmodified: "2021-07-23T04:29:07Z"
        mac: ENC[AES256_GCM,data:xSr4qYnQFnrbtqBQertx8eW5uE7E2sT00Sv4VegoHptfYPyzh/h4DzgTgN7/1dcAAeEl9UaoEUXc047RFzffuDNg9jLXYgqLtYQ3EKMmve6oMqGaWrmEyRoDLfi7fxwcFclr50YfVav6cc1a3UEwQQfXV/zx0aSQqVgKHXcCVdo=,iv:wJzZ6tFjM/5yKoPPL7GdJFaLVxeJDxpKjZmNqGKix04=,tag:j6LDnnOXFqW1SdAVhV2SEA==,type:str]
        pgp:
            - created_at: "2021-07-23T04:29:05Z"
              enc: |
                -----BEGIN PGP MESSAGE-----

                hQEMAyUpShfNkFB/AQgAr7skCg1FfuugFib5AI8vBVagI3rtpBQNslvZoCn8qZ28
                WWJBq9ym9pcJQDO70ja9Y4/mfnfEkD4B0zjpXcth6B2myBST2FlITT97wbiClWjY
                8o2Bzdq5CDFvDgoKNXZM6fEf2kYgSIzTTBw3J1I5R7o0bmYuPEuFVunfgo3Wsk3u
                Qp6DyKtXhgWZs6tNkP06zml6OhGwcrIPejWciZZDhXi0gL/eGGsOOmzkfokDHkwV
                Zzj59JVmQDGmNRLJnPabHqy38UtyA4+CN4A7jYxG+0YPaqkDIU8XIMsaGjC9sokI
                3ryZTha5CBg0HVvkE+iewGMxgpBw2umKCCozIvhrltJeAesExKXBNFpUellDdRqj
                CCFx9j7mE7ixRaJdw+LuaOh+Mzv6bt+YVuQ0tUEapephHafrZ0oxBs7emySBeFVY
                S00SnOAkvmk1IzBR1aUzym88thTzUBCHKXE6TPG9xw==
                =xcLN
                -----END PGP MESSAGE-----
              fp: FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4
        unencrypted_suffix: _unencrypted
        version: 3.7.1
    $
    ```

Cannot output empty yaml file since sops-v3.7.0
* sops-3.6.1

    ```
    $ curl -Lso sops-v3.6.1 https://github.com/mozilla/sops/releases/download/v3.6.1/sops-v3.6.1.linux
    $ chmod 755 sops-v3.6.1
    $ echo '{}' | ./sops-v3.6.1 --pgp FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4 --input-type yaml --output-type yaml -e /dev/stdin 2>/dev/null | ./sops-v3.6.1 --input-type yaml --output-type yaml -d /dev/stdin
    {}
    $
    ```

* sops-3.7.1 (same to sops-3.7.0)

    ```
    $ curl -Lso sops-v3.7.1 https://github.com/mozilla/sops/releases/download/v3.7.1/sops-v3.7.1.linux
    $ chmod 755 sops-v3.7.1
    $ echo '{}' | ./sops-v3.7.1 --pgp FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4 --input-type yaml --output-type yaml -e /dev/stdin 2>/dev/null | ./sops-v3.7.1 --input-type yaml --output-type yaml -d /dev/stdin
    Error dumping file: Error marshaling to yaml: yaml: expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got document end
    $
    ```


Encoded outputs are same for both versions:
* sops-v3.6.1

    ```
    $ echo '{}' | ./sops-v3.6.1 --pgp FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4 --input-type yaml --output-type yaml -e /dev/stdin 2>/dev/null
    sops:
        kms: []
        gcp_kms: []
        azure_kv: []
        hc_vault: []
        lastmodified: '2021-07-23T04:29:26Z'
        mac: ENC[AES256_GCM,data:UH3M6XfWD7emEY7SS7ZS3ix0ZJJaFbbyJBaJNQD4CuTsaCvNcoXtwfAPf/52/SjhEPVi+LwH6lNwexNUILT1pJqR9HA6SaTcVekXmZrsfM1KI8qn8Tg8ZYl5d51LcouwqO5CChFyvK7aWiTy9d0MPJsN/nZ5YABI7gSGuiTxwFU=,iv:zWvwY1E0kcHmlY3DhM00l1DMKq5WsoboO/FvS7eeFgY=,tag:lP6T17vSSf3FPD6JPCVb/g==,type:str]
        pgp:
        -   created_at: '2021-07-23T04:29:25Z'
            enc: |
                -----BEGIN PGP MESSAGE-----

                hQEMAyUpShfNkFB/AQf+IQre0LGWgNaNEXdJjcsDB54KLsvR5YV44Zf0eXnQBvvf
                TpBdeMvRYxfsh+rxxZBb6NT8Fhp+rNRgglUBv4MwL8c3qimskjqBcofQuwdU5RUB
                EC2jxQpenhEEup5BWF/IhkcygaWVdDYYDYeVqARmteZcw4w/FIic5P0Rm0AGcrp3
                FvjxqgxJIlYncx//1XjFeqmZvpeLuFNWh+z4K1Ycy2t0ArF1wrKOYseJ4hLTmE0A
                n2e3jVJA0x9UXWkqmMsk0olcbWrZBlHuojMqv+oLZxtHN64tcScB0FL7LmBSoOL+
                eBmYZtOCu9SuSx/r4zl7HxMrvWeTm9ArkCVtsVUF0dJeAQbR6v9OfJvZipuiWAqN
                6sJIpGIBVFZXx90ZQ0f2f29RhPmwA2eng0W/GyNUeBqa6M0NiI54CzgCgSyqCvQF
                oc2pt992TbBbR4ZMUrFGo/celqQOvCygonUgQ8jkrw==
                =Pu21
                -----END PGP MESSAGE-----
            fp: FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4
        unencrypted_suffix: _unencrypted
        version: 3.6.1
    $
    ```

* sops-v3.7.1

    ```
    $ echo '{}' | ./sops-v3.7.1 --pgp FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4 --input-type yaml --output-type yaml -e /dev/stdin 2>/dev/null
    sops:
        kms: []
        gcp_kms: []
        azure_kv: []
        hc_vault: []
        age: []
        lastmodified: "2021-07-23T04:29:07Z"
        mac: ENC[AES256_GCM,data:xSr4qYnQFnrbtqBQertx8eW5uE7E2sT00Sv4VegoHptfYPyzh/h4DzgTgN7/1dcAAeEl9UaoEUXc047RFzffuDNg9jLXYgqLtYQ3EKMmve6oMqGaWrmEyRoDLfi7fxwcFclr50YfVav6cc1a3UEwQQfXV/zx0aSQqVgKHXcCVdo=,iv:wJzZ6tFjM/5yKoPPL7GdJFaLVxeJDxpKjZmNqGKix04=,tag:j6LDnnOXFqW1SdAVhV2SEA==,type:str]
        pgp:
            - created_at: "2021-07-23T04:29:05Z"
              enc: |
                -----BEGIN PGP MESSAGE-----

                hQEMAyUpShfNkFB/AQgAr7skCg1FfuugFib5AI8vBVagI3rtpBQNslvZoCn8qZ28
                WWJBq9ym9pcJQDO70ja9Y4/mfnfEkD4B0zjpXcth6B2myBST2FlITT97wbiClWjY
                8o2Bzdq5CDFvDgoKNXZM6fEf2kYgSIzTTBw3J1I5R7o0bmYuPEuFVunfgo3Wsk3u
                Qp6DyKtXhgWZs6tNkP06zml6OhGwcrIPejWciZZDhXi0gL/eGGsOOmzkfokDHkwV
                Zzj59JVmQDGmNRLJnPabHqy38UtyA4+CN4A7jYxG+0YPaqkDIU8XIMsaGjC9sokI
                3ryZTha5CBg0HVvkE+iewGMxgpBw2umKCCozIvhrltJeAesExKXBNFpUellDdRqj
                CCFx9j7mE7ixRaJdw+LuaOh+Mzv6bt+YVuQ0tUEapephHafrZ0oxBs7emySBeFVY
                S00SnOAkvmk1IzBR1aUzym88thTzUBCHKXE6TPG9xw==
                =xcLN
                -----END PGP MESSAGE-----
              fp: FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4
        unencrypted_suffix: _unencrypted
        version: 3.7.1
    $
    ```



Discussion / hints:
This looks caused for here: https://github.com/mozilla/sops/blob/v3.7.1/stores/yaml/store.go#L364
No `Content` is set and cause the error.
I can't get why this code exists.

https://github.com/mozilla/sops/blob/v3.7.1/stores/yaml/store_test.go#L168
might be related?

This looks caused for here: https://github.com/mozilla/sops/blob/v3.7.1/stores/yaml/store.go#L364
No `Content` is set and cause the error.
I can't get why this code exists.

https://github.com/mozilla/sops/blob/v3.7.1/stores/yaml/store_test.go#L168
might be related?


Fix patch:
diff --git a/stores/yaml/store.go b/stores/yaml/store.go
index d9e78b528..da9b946b2 100644
--- a/stores/yaml/store.go
+++ b/stores/yaml/store.go
@@ -361,11 +361,7 @@ func (store *Store) EmitPlainFile(branches sops.TreeBranches) ([]byte, error) {
 		mapping.Kind = yaml.MappingNode
 		// Marshal branch to global mapping node
 		store.appendTreeBranch(branch, &mapping)
-		if len(mapping.Content) == 0 {
-			doc.HeadComment = mapping.HeadComment
-		} else {
-			doc.Content = append(doc.Content, &mapping)
-		}
+		doc.Content = append(doc.Content, &mapping)
 		// Encode YAML
 		err := e.Encode(&doc)
 		if err != nil {


Test patch:
diff --git a/stores/yaml/store_test.go b/stores/yaml/store_test.go
index 05249f4a5..bf7c972f5 100644
--- a/stores/yaml/store_test.go
+++ b/stores/yaml/store_test.go
@@ -198,6 +198,15 @@ func TestEmpty2(t *testing.T) {
 }
 */
 
+func TestEmpty3(t *testing.T) {
+	branches, err := (&Store{}).LoadPlainFile([]byte("{}\n"))
+	assert.Nil(t, err)
+	assert.Equal(t, len(branches), 1)
+	bytes, err := (&Store{}).EmitPlainFile(branches)
+	assert.Nil(t, err)
+	assert.Equal(t, "{}\n", string(bytes))
+}
+
 func TestComment6(t *testing.T) {
 	branches, err := (&Store{}).LoadPlainFile(COMMENT_6)
 	assert.Nil(t, err)