mirror of
https://github.com/taigrr/yq
synced 2025-01-18 04:53:17 -08:00
Compare commits
25 Commits
3.1.1
...
array-leng
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2937645fcd | ||
|
|
1a97b27041 | ||
|
|
da398765b8 | ||
|
|
d356fa0d0b | ||
|
|
d22bfc241b | ||
|
|
954affea23 | ||
|
|
b0d1afb601 | ||
|
|
b286636909 | ||
|
|
bdf47c9797 | ||
|
|
1cc20d52bb | ||
|
|
651d9edf88 | ||
|
|
903605df39 | ||
|
|
0f9facc84b | ||
|
|
5af86b1333 | ||
|
|
2bd2a85a4c | ||
|
|
ceb76e5c17 | ||
|
|
44322f0248 | ||
|
|
0347516d82 | ||
|
|
a46386e093 | ||
|
|
f5c3beb159 | ||
|
|
9864afc4e7 | ||
|
|
69fae2d9cb | ||
|
|
83c13ce392 | ||
|
|
d83c46eec2 | ||
|
|
65802f9e0e |
45
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
45
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Input Yaml**
|
||||
Concise yaml document(s) (as simple as possible to show the bug)
|
||||
data1.yml:
|
||||
```yaml
|
||||
this: should really work
|
||||
```
|
||||
|
||||
data2.yml:
|
||||
```yaml
|
||||
but: it strangely didn't
|
||||
```
|
||||
|
||||
**Command**
|
||||
The command you ran:
|
||||
```
|
||||
yq merge data1.yml data2.yml
|
||||
```
|
||||
|
||||
**Actual behavior**
|
||||
|
||||
```yaml
|
||||
cat: meow
|
||||
```
|
||||
|
||||
**Expected behavior**
|
||||
|
||||
```yaml
|
||||
this: should really work
|
||||
but: it strangely didn't
|
||||
```
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
36
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
If we have data1.yml like:
|
||||
|
||||
```yaml
|
||||
country: Australia
|
||||
```
|
||||
|
||||
And we run a command:
|
||||
|
||||
```bash
|
||||
yq predictWeather data1.yml
|
||||
```
|
||||
|
||||
it could output
|
||||
|
||||
```yaml
|
||||
temp: 32
|
||||
```
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
28
.github/workflows/go.yml
vendored
Normal file
28
.github/workflows/go.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Go
|
||||
on: [push]
|
||||
jobs:
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.13
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
if [ -f Gopkg.toml ]; then
|
||||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
dep ensure
|
||||
fi
|
||||
|
||||
- name: Build
|
||||
run: make local test
|
||||
76
CODE_OF_CONDUCT.md
Normal file
76
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at mikefarah@gmail.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
||||
8
CONTRIBUTING.md
Normal file
8
CONTRIBUTING.md
Normal file
@@ -0,0 +1,8 @@
|
||||
1. Install (golang)[https://golang.org/]
|
||||
1. Run `scripts/devtools.sh` to install the required devtools
|
||||
2. Run `make [local] vendor` to install the vendor dependencies
|
||||
2. Run `make [local] test` to ensure you can run the existing tests
|
||||
3. Write unit tests - (see existing examples). Changes will not be accepted without corresponding unit tests.
|
||||
4. Make the code changes.
|
||||
5. `make [local] test` to lint code and run tests
|
||||
6. Profit! ok no profit, but raise a PR and get kudos :)
|
||||
24
README.md
24
README.md
@@ -12,15 +12,13 @@ V3 is officially out - if you've been using v2 and want/need to upgrade, checkou
|
||||
|
||||
## Install
|
||||
|
||||
### Download the latest binary
|
||||
### [Download the latest binary](https://github.com/mikefarah/yq/releases/latest)
|
||||
|
||||
[Here](https://github.com/mikefarah/yq/releases/latest)
|
||||
|
||||
### On MacOS:
|
||||
### MacOS:
|
||||
```
|
||||
brew install yq
|
||||
```
|
||||
### On Ubuntu and other Linux distros supporting `snap` packages:
|
||||
### Ubuntu and other Linux distros supporting `snap` packages:
|
||||
```
|
||||
snap install yq
|
||||
```
|
||||
@@ -44,11 +42,14 @@ rm /etc/myfile.tmp
|
||||
```
|
||||
|
||||
### On Ubuntu 16.04 or higher from Debian package:
|
||||
```
|
||||
```sh
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CC86BB64
|
||||
sudo add-apt-repository ppa:rmescandon/yq
|
||||
sudo apt update
|
||||
sudo apt install yq -y
|
||||
```
|
||||
Supported by @rmescandon
|
||||
|
||||
### Go Get:
|
||||
```
|
||||
GO111MODULE=on go get github.com/mikefarah/yq/v3
|
||||
@@ -122,14 +123,3 @@ Flags:
|
||||
|
||||
Use "yq [command] --help" for more information about a command.
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
**Note: v3 is currently in progress - for the moment I won't be accepting new feature PRs until v3 is ready :)**
|
||||
|
||||
1. `scripts/devtools.sh`
|
||||
2. `make [local] vendor`
|
||||
3. add unit tests
|
||||
4. apply changes to go.mod
|
||||
5. `make [local] build`
|
||||
7. profit
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
|
||||
Major release! Upgraded underlying yaml parser, re-written majority of yq. This has brought on a number of features that have been in demand for a while (see below).
|
||||
|
||||
This is in beta and needs some community feedback and testing :)
|
||||
|
||||
# New Features
|
||||
- Keeps yaml comments and formatting, can specify yaml tags when updating. https://github.com/mikefarah/yq/issues/19, https://github.com/mikefarah/yq/issues/169, https://github.com/mikefarah/yq/issues/107, https://github.com/mikefarah/yq/issues/171, https://github.com/mikefarah/yq/issues/245, https://github.com/mikefarah/yq/issues/303,https://github.com/mikefarah/yq/issues/308,https://github.com/mikefarah/yq/issues/314
|
||||
- Handles anchors! https://github.com/mikefarah/yq/issues/310, https://github.com/mikefarah/yq/issues/178
|
||||
- Can print out matching paths and values when splatting https://github.com/mikefarah/yq/issues/20
|
||||
- JSON output works for all commands! Yaml files with multiple documents are printed out as one JSON document per line.
|
||||
- Deep splat (**) to match arbitrary paths
|
||||
|
||||
|
||||
# Breaking changes
|
||||
|
||||
## Update scripts file format has changed to be more powerful.
|
||||
Comments can be added, and delete commands have been introduced.
|
||||
|
||||
Before:
|
||||
```yaml
|
||||
b.e[+].name: Mike Farah
|
||||
```
|
||||
|
||||
After:
|
||||
```yaml
|
||||
- command: update
|
||||
path: b.e[+].thing
|
||||
value:
|
||||
#great
|
||||
things: frog # wow!
|
||||
- command: delete
|
||||
path: b.d
|
||||
```
|
||||
|
||||
https://github.com/mikefarah/yq/issues/305
|
||||
|
||||
## Reading and splatting, matching results are printed once per line.
|
||||
e.g:
|
||||
|
||||
```json
|
||||
parent:
|
||||
childA:
|
||||
no: matches here
|
||||
childB:
|
||||
there: matches
|
||||
hi: no match
|
||||
there2: also matches
|
||||
```
|
||||
|
||||
```bash
|
||||
yq r sample.yaml 'parent.*.there*'
|
||||
```
|
||||
|
||||
old
|
||||
```yaml
|
||||
- null
|
||||
- - matches
|
||||
- also matches
|
||||
```
|
||||
|
||||
new
|
||||
```yaml
|
||||
matches
|
||||
also matches
|
||||
```
|
||||
|
||||
and you can print the matching paths:
|
||||
|
||||
yq r --printMode pv sample.yaml 'parent.*.there*'
|
||||
|
||||
```yaml
|
||||
parent.childB.there: matches
|
||||
parent.childB.there2: also matches
|
||||
```
|
||||
11
action.yml
Normal file
11
action.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
name: 'YAML processor'
|
||||
description: 'YAML processor for running in Github action'
|
||||
inputs:
|
||||
cmd:
|
||||
description: 'The Command which should be run'
|
||||
required: true
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'github-action/Dockerfile'
|
||||
args:
|
||||
- ${{ inputs.cmd }}
|
||||
@@ -91,7 +91,7 @@ func TestReadCmd(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "2", result.Output)
|
||||
test.AssertResult(t, "2\n", result.Output)
|
||||
}
|
||||
|
||||
func TestCompareCmd(t *testing.T) {
|
||||
@@ -157,7 +157,7 @@ func TestReadWithAdvancedFilterCmd(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "4", result.Output)
|
||||
test.AssertResult(t, "4\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadWithAdvancedFilterMapCmd(t *testing.T) {
|
||||
@@ -190,6 +190,157 @@ func TestReadArrayCmd(t *testing.T) {
|
||||
test.AssertResult(t, "b.e.[1].name: sam\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadArrayLengthCmd(t *testing.T) {
|
||||
content := `- things
|
||||
- whatever
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -l %s", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "2\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadArrayLengthDeepCmd(t *testing.T) {
|
||||
content := `holder:
|
||||
- things
|
||||
- whatever
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -l %s holder", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "2\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadArrayLengthDeepMultipleCmd(t *testing.T) {
|
||||
content := `holderA:
|
||||
- things
|
||||
- whatever
|
||||
holderB:
|
||||
- other things
|
||||
- cool
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -l %s holder*", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "4\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadArrayLengthDeepMultipleWithPathCmd(t *testing.T) {
|
||||
content := `holderA:
|
||||
- things
|
||||
- whatever
|
||||
holderB:
|
||||
- other things
|
||||
- cool
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -l %s -ppv holder*", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "holderA: 2\nholderB: 2", result.Output)
|
||||
}
|
||||
|
||||
func TestReadObjectLengthCmd(t *testing.T) {
|
||||
content := `cat: meow
|
||||
dog: bark
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -l %s", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "2\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadObjectLengthDeepCmd(t *testing.T) {
|
||||
content := `holder:
|
||||
cat: meow
|
||||
dog: bark
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -l %s holder", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "2\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadObjectLengthDeepMultipleCmd(t *testing.T) {
|
||||
content := `holderA:
|
||||
cat: meow
|
||||
dog: bark
|
||||
holderB:
|
||||
elephant: meow
|
||||
zebra: bark
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -l %s holder*", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "4\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadObjectLengthDeepMultipleWithPathsCmd(t *testing.T) {
|
||||
content := `holderA:
|
||||
cat: meow
|
||||
dog: bark
|
||||
holderB:
|
||||
elephant: meow
|
||||
zebra: bark
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -l -ppv %s holder*", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "holderA: 2\nholderB: 2\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadScalarLengthCmd(t *testing.T) {
|
||||
content := `meow`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -l %s", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "2\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadDeepSplatCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p pv ../examples/sample.yaml b.**")
|
||||
@@ -226,7 +377,7 @@ func TestReadWithKeyCmd(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "b.c", result.Output)
|
||||
test.AssertResult(t, "b.c\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadAnchorsCmd(t *testing.T) {
|
||||
@@ -235,7 +386,7 @@ func TestReadAnchorsCmd(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "1", result.Output)
|
||||
test.AssertResult(t, "1\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadAnchorsWithKeyAndValueCmd(t *testing.T) {
|
||||
@@ -279,7 +430,7 @@ func TestReadMergeAnchorsOriginalCmd(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "original", result.Output)
|
||||
test.AssertResult(t, "original\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadMergeAnchorsExplodeJsonCmd(t *testing.T) {
|
||||
@@ -318,7 +469,7 @@ pointer: *value-pointer`
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
expectedOutput := `the value`
|
||||
expectedOutput := "the value\n"
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
@@ -378,7 +529,7 @@ pointer: *value-pointer`
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
expectedOutput := `the value`
|
||||
expectedOutput := "the value\n"
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
@@ -433,7 +584,7 @@ func TestReadMergeAnchorsOverrideCmd(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "ice", result.Output)
|
||||
test.AssertResult(t, "ice\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadMergeAnchorsPrefixMatchCmd(t *testing.T) {
|
||||
@@ -455,7 +606,7 @@ func TestReadMergeAnchorsListOriginalCmd(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "original", result.Output)
|
||||
test.AssertResult(t, "original\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadMergeAnchorsListOverrideInListCmd(t *testing.T) {
|
||||
@@ -464,7 +615,7 @@ func TestReadMergeAnchorsListOverrideInListCmd(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "coconut", result.Output)
|
||||
test.AssertResult(t, "coconut\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadMergeAnchorsListOverrideCmd(t *testing.T) {
|
||||
@@ -473,7 +624,7 @@ func TestReadMergeAnchorsListOverrideCmd(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "newbar", result.Output)
|
||||
test.AssertResult(t, "newbar\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadInvalidDocumentIndexCmd(t *testing.T) {
|
||||
@@ -515,7 +666,7 @@ func TestReadMultiCmd(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "here", result.Output)
|
||||
test.AssertResult(t, "here\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadMultiWithKeyAndValueCmd(t *testing.T) {
|
||||
@@ -536,7 +687,8 @@ func TestReadMultiAllCmd(t *testing.T) {
|
||||
test.AssertResult(t,
|
||||
`first document
|
||||
second document
|
||||
third document`, result.Output)
|
||||
third document
|
||||
`, result.Output)
|
||||
}
|
||||
|
||||
func TestReadMultiAllWithKeyAndValueCmd(t *testing.T) {
|
||||
@@ -558,7 +710,7 @@ func TestReadCmd_ArrayYaml(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "false", result.Output)
|
||||
test.AssertResult(t, "false\n", result.Output)
|
||||
}
|
||||
|
||||
func TestReadEmptyContentCmd(t *testing.T) {
|
||||
@@ -575,6 +727,28 @@ func TestReadEmptyContentCmd(t *testing.T) {
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestReadEmptyNodesPrintPathCmd(t *testing.T) {
|
||||
content := `map:
|
||||
that: {}
|
||||
array:
|
||||
great: []
|
||||
null:
|
||||
indeed: ~`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read %s -ppv **", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
expectedOutput := `map.that: {}
|
||||
array.great: []
|
||||
null.indeed: ~
|
||||
`
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestReadEmptyContentWithDefaultValueCmd(t *testing.T) {
|
||||
content := ``
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
@@ -718,7 +892,8 @@ func TestReadCmd_ArrayYaml_SplatWithKeyCmd(t *testing.T) {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
expectedOutput := `[0]
|
||||
[1]`
|
||||
[1]
|
||||
`
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
@@ -729,7 +904,8 @@ func TestReadCmd_ArrayYaml_SplatKey(t *testing.T) {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
expectedOutput := `false
|
||||
true`
|
||||
true
|
||||
`
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
@@ -928,7 +1104,8 @@ b:
|
||||
}
|
||||
|
||||
expectedOutput := `more things
|
||||
more things also`
|
||||
more things also
|
||||
`
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
@@ -983,7 +1160,8 @@ b:
|
||||
}
|
||||
|
||||
expectedOutput := `b.there.c
|
||||
b.there2.c`
|
||||
b.there2.c
|
||||
`
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
@@ -1218,6 +1396,56 @@ func TestWriteCmd(t *testing.T) {
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestWriteEmptyMultiDocCmd(t *testing.T) {
|
||||
content := `# this is empty
|
||||
---
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("write %s c 7", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
expectedOutput := `c: 7
|
||||
|
||||
# this is empty
|
||||
`
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestWriteSurroundingEmptyMultiDocCmd(t *testing.T) {
|
||||
content := `---
|
||||
# empty
|
||||
---
|
||||
cat: frog
|
||||
---
|
||||
|
||||
# empty
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("write %s -d1 c 7", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
expectedOutput := `
|
||||
|
||||
# empty
|
||||
---
|
||||
cat: frog
|
||||
c: 7
|
||||
---
|
||||
|
||||
|
||||
# empty
|
||||
`
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestWriteFromFileCmd(t *testing.T) {
|
||||
content := `b:
|
||||
c: 3
|
||||
@@ -1257,6 +1485,26 @@ func TestWriteEmptyCmd(t *testing.T) {
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestWriteAutoCreateCmd(t *testing.T) {
|
||||
content := `applications:
|
||||
- name: app
|
||||
env:`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("write %s applications[0].env.hello world", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
expectedOutput := `applications:
|
||||
- name: app
|
||||
env:
|
||||
hello: world
|
||||
`
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestWriteCmdScript(t *testing.T) {
|
||||
content := `b:
|
||||
c: 3
|
||||
@@ -1559,7 +1807,7 @@ func TestWriteCmd_SplatMapEmpty(t *testing.T) {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
expectedOutput := `b:
|
||||
c: thing
|
||||
c: {}
|
||||
d: another thing
|
||||
`
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
@@ -1957,6 +2205,27 @@ apples: red
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestMergeSpecialCharacterKeysCmd(t *testing.T) {
|
||||
content := ``
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
mergeContent := `key[bracket]: value
|
||||
key.bracket: value
|
||||
key"value": value
|
||||
key'value': value
|
||||
`
|
||||
mergeFilename := test.WriteTempYamlFile(mergeContent)
|
||||
defer test.RemoveTempYamlFile(mergeFilename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("merge %s %s", filename, mergeFilename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, mergeContent, result.Output)
|
||||
}
|
||||
|
||||
func TestMergeYamlMultiAllOverwriteCmd(t *testing.T) {
|
||||
content := `b:
|
||||
c: 3
|
||||
@@ -1987,6 +2256,25 @@ apples: red
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestMergeYamlNullMapCmd(t *testing.T) {
|
||||
content := `b:`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
mergeContent := `b:
|
||||
thing: a frog
|
||||
`
|
||||
mergeFilename := test.WriteTempYamlFile(mergeContent)
|
||||
defer test.RemoveTempYamlFile(mergeFilename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("merge %s %s", filename, mergeFilename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, mergeContent, result.Output)
|
||||
}
|
||||
|
||||
func TestMergeCmd_Error(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "merge")
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
|
||||
var customTag = ""
|
||||
var printMode = "v"
|
||||
var resultsAsArray = false
|
||||
var printLength = false
|
||||
var writeInplace = false
|
||||
var writeScript = ""
|
||||
var sourceYamlFile = ""
|
||||
|
||||
@@ -26,6 +26,8 @@ yq r -- things.yaml '--key-starting-with-dashes.blah'
|
||||
cmdRead.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
|
||||
cmdRead.PersistentFlags().StringVarP(&printMode, "printMode", "p", "v", "print mode (v (values, default), p (paths), pv (path and value pairs)")
|
||||
cmdRead.PersistentFlags().StringVarP(&defaultValue, "defaultValue", "D", "", "default value printed when there are no results")
|
||||
cmdRead.PersistentFlags().BoolVarP(&resultsAsArray, "asArray", "a", false, "print results as array")
|
||||
cmdRead.PersistentFlags().BoolVarP(&printLength, "length", "l", false, "print length of results")
|
||||
cmdRead.PersistentFlags().BoolVarP(&explodeAnchors, "explodeAnchors", "X", false, "explode anchors")
|
||||
return cmdRead
|
||||
}
|
||||
|
||||
73
cmd/utils.go
73
cmd/utils.go
@@ -77,9 +77,29 @@ func appendDocument(originalMatchingNodes []*yqlib.NodeContext, dataBucket yaml.
|
||||
return append(originalMatchingNodes, matchingNodes...), nil
|
||||
}
|
||||
|
||||
func printValue(node *yaml.Node, writer io.Writer) error {
|
||||
func lengthOf(node *yaml.Node) int {
|
||||
kindToCheck := node.Kind
|
||||
if node.Kind == yaml.DocumentNode && len(node.Content) == 1 {
|
||||
log.Debugf("length of document node, calculating length of child")
|
||||
kindToCheck = node.Content[0].Kind
|
||||
}
|
||||
switch kindToCheck {
|
||||
case yaml.ScalarNode:
|
||||
return len(node.Value)
|
||||
case yaml.MappingNode:
|
||||
return len(node.Content) / 2
|
||||
default:
|
||||
return len(node.Content)
|
||||
}
|
||||
}
|
||||
|
||||
func printValue(node *yaml.Node, writer io.Writer, shouldPrintLength bool) error {
|
||||
if shouldPrintLength {
|
||||
return writeString(writer, fmt.Sprintf("%v\n", lengthOf(node)))
|
||||
}
|
||||
|
||||
if node.Kind == yaml.ScalarNode {
|
||||
_, errorWriting := writer.Write([]byte(node.Value))
|
||||
_, errorWriting := writer.Write([]byte(node.Value + "\n"))
|
||||
return errorWriting
|
||||
}
|
||||
return printNode(node, writer)
|
||||
@@ -159,41 +179,42 @@ func printResults(matchingNodes []*yqlib.NodeContext, writer io.Writer) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var counter = 0
|
||||
|
||||
var errorWriting error
|
||||
for index, mappedDoc := range matchingNodes {
|
||||
for _, mappedDoc := range matchingNodes {
|
||||
switch printMode {
|
||||
case "p":
|
||||
errorWriting = writeString(bufferedWriter, lib.PathStackToString(mappedDoc.PathStack))
|
||||
errorWriting = writeString(bufferedWriter, lib.PathStackToString(mappedDoc.PathStack)+"\n")
|
||||
if errorWriting != nil {
|
||||
return errorWriting
|
||||
}
|
||||
if index < len(matchingNodes)-1 {
|
||||
errorWriting = writeString(bufferedWriter, "\n")
|
||||
if errorWriting != nil {
|
||||
return errorWriting
|
||||
}
|
||||
}
|
||||
case "pv", "vp":
|
||||
// put it into a node and print that.
|
||||
var parentNode = yaml.Node{Kind: yaml.MappingNode}
|
||||
parentNode.Content = make([]*yaml.Node, 2)
|
||||
parentNode.Content[0] = &yaml.Node{Kind: yaml.ScalarNode, Value: lib.PathStackToString(mappedDoc.PathStack)}
|
||||
parentNode.Content[1] = mappedDoc.Node
|
||||
if err := printValue(&parentNode, bufferedWriter); err != nil {
|
||||
if printLength {
|
||||
parentNode.Content[1] = &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", lengthOf(mappedDoc.Node))}
|
||||
} else {
|
||||
parentNode.Content[1] = mappedDoc.Node
|
||||
}
|
||||
if err := printValue(&parentNode, bufferedWriter, false); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
if err := printValue(mappedDoc.Node, bufferedWriter); err != nil {
|
||||
if printLength {
|
||||
counter = counter + lengthOf(mappedDoc.Node)
|
||||
} else if err := printValue(mappedDoc.Node, bufferedWriter, false); err != nil {
|
||||
return err
|
||||
}
|
||||
// Printing our Scalars does not print a new line at the end
|
||||
// we only want to do that if there are more values (so users can easily script extraction of values in the yaml)
|
||||
if index < len(matchingNodes)-1 && mappedDoc.Node.Kind == yaml.ScalarNode {
|
||||
errorWriting = writeString(bufferedWriter, "\n")
|
||||
if errorWriting != nil {
|
||||
return errorWriting
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if printLength {
|
||||
if err := writeString(bufferedWriter, fmt.Sprintf("%v\n", counter)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +234,11 @@ func parseDocumentIndex() (bool, int, error) {
|
||||
|
||||
type updateDataFn func(dataBucket *yaml.Node, currentIndex int) error
|
||||
|
||||
func isNullDocument(dataBucket *yaml.Node) bool {
|
||||
return dataBucket.Kind == yaml.DocumentNode && (len(dataBucket.Content) == 0 ||
|
||||
dataBucket.Content[0].Kind == yaml.ScalarNode && dataBucket.Content[0].Tag == "!!null")
|
||||
}
|
||||
|
||||
func mapYamlDecoder(updateData updateDataFn, encoder yqlib.Encoder) yamlDecoderFn {
|
||||
return func(decoder *yaml.Decoder) error {
|
||||
var dataBucket yaml.Node
|
||||
@@ -232,8 +258,11 @@ func mapYamlDecoder(updateData updateDataFn, encoder yqlib.Encoder) yamlDecoderF
|
||||
|
||||
if errorReading == io.EOF && docIndexInt == 0 && currentIndex == 0 {
|
||||
//empty document, lets just make one
|
||||
child := yaml.Node{Kind: yaml.MappingNode}
|
||||
dataBucket = yaml.Node{Kind: yaml.DocumentNode, Content: make([]*yaml.Node, 1)}
|
||||
child := yaml.Node{Kind: yaml.MappingNode}
|
||||
dataBucket.Content[0] = &child
|
||||
} else if isNullDocument(&dataBucket) && (updateAll || docIndexInt == currentIndex) {
|
||||
child := yaml.Node{Kind: yaml.MappingNode}
|
||||
dataBucket.Content[0] = &child
|
||||
} else if errorReading == io.EOF {
|
||||
if !updateAll && currentIndex <= docIndexInt {
|
||||
|
||||
@@ -11,7 +11,7 @@ var (
|
||||
GitDescribe string
|
||||
|
||||
// Version is main version number that is being run at the moment.
|
||||
Version = "3.1.1"
|
||||
Version = "3.1.2"
|
||||
|
||||
// VersionPrerelease is a pre-release marker for the version. If this is "" (empty string)
|
||||
// then it means that it is a final release. Otherwise, this is a pre-release
|
||||
|
||||
28
debian/changelog
vendored
28
debian/changelog
vendored
@@ -1,3 +1,31 @@
|
||||
yq (3.1-2) eoan; urgency=medium
|
||||
|
||||
* Bug fix: yq 3 was removing empty inline-style objects and arrays (#355)
|
||||
* Bug fix: Merge option returned different output when switching order of
|
||||
merging files(#347)
|
||||
* Bug fix: Add new object to existing array object was failing in 3.1.1 (#361)
|
||||
* Bug fix: yq 3 empty keys did not allow merging of values (#356)
|
||||
* Bug fix: keys quoted during merge (#363)
|
||||
* Bug fix: Correct length with wc -l (#362)
|
||||
* Bug fix: Write to empty document removed path (#359)
|
||||
|
||||
-- Roberto Mier Escandon <rmescandon@gmail.com> Mon, 24 Feb 2020 20:31:58 +0100
|
||||
|
||||
yq (3.1-1) eoan; urgency=medium
|
||||
|
||||
* Keeps yaml comments and formatting, can specify yaml tags when updating.
|
||||
* Handles anchors
|
||||
* Can print out matching paths and values when splatting
|
||||
* JSON output works for all commands
|
||||
* Yaml files with multiple documents are printed out as one JSON
|
||||
document per line.
|
||||
* Deep splat (**) to match arbitrary paths
|
||||
* Update scripts file format has changed to be more powerful
|
||||
* Reading and splatting, matching results are printed once per line
|
||||
* Bugfixing
|
||||
|
||||
-- Roberto Mier Escandon <rmescandon@gmail.com> Tue, 11 Feb 2020 22:18:24 +0100
|
||||
|
||||
yq (2.2-1) bionic; urgency=medium
|
||||
|
||||
* Added Windows support for the "--inplace" command flag
|
||||
|
||||
2
debian/compat
vendored
2
debian/compat
vendored
@@ -1 +1 @@
|
||||
9
|
||||
10
|
||||
|
||||
22
debian/control
vendored
22
debian/control
vendored
@@ -1,22 +1,22 @@
|
||||
Source: yq
|
||||
Section: devel
|
||||
Priority: extra
|
||||
Priority: optional
|
||||
Maintainer: Roberto Mier EscandĂłn <rmescandon@gmail.com>
|
||||
Build-Depends: debhelper (>= 9),
|
||||
dh-golang,
|
||||
golang-1.10-go,
|
||||
Build-Depends: debhelper (>=10),
|
||||
dh-golang (>=1.34),
|
||||
golang-1.13,
|
||||
rsync
|
||||
Standards-Version: 3.9.6
|
||||
Standards-Version: 4.1.4
|
||||
Homepage: https://github.com/mikefarah/yq.git
|
||||
Vcs-Browser: https://github.com/mikefarah/yq.git
|
||||
Vcs-Git: https://github.com/mikefarah/yq.git
|
||||
XS-Go-Import-Path: github.com/mikefarah/yq
|
||||
XSBC-Original-Maintainer: Roberto Mier EscandĂłn <rmescandon@gmail.com>
|
||||
|
||||
Package: yq
|
||||
Architecture: any
|
||||
Built-Using: ${misc:Built-Using}
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends}
|
||||
Description:
|
||||
a lightweight and portable command-line YAML processor
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: lightweight and portable command-line YAML processor
|
||||
.
|
||||
The aim of the project is to be the [jq](https://github.com/stedolan/jq) or sed of yaml files.
|
||||
The aim of the project is to be the
|
||||
[jq](https://github.com/stedolan/jq) or sed of yaml files.
|
||||
|
||||
21
debian/copyright
vendored
21
debian/copyright
vendored
@@ -3,5 +3,22 @@ Upstream-Name: yq
|
||||
Source: https://github.com/mikefarah/yq.git
|
||||
|
||||
Files: *
|
||||
Copyright: 2017 Mike Farah Ltd. All rights reserved
|
||||
License: Proprietary
|
||||
Copyright: 2017 Mike Farah
|
||||
License: Expat
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1
debian/files
vendored
Normal file
1
debian/files
vendored
Normal file
@@ -0,0 +1 @@
|
||||
yq_3.1-2_source.buildinfo devel optional
|
||||
26
debian/rules
vendored
26
debian/rules
vendored
@@ -14,46 +14,44 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
PROJECT := yq
|
||||
OWNER := mikefarah
|
||||
REPO := github.com
|
||||
GOVERSION := 1.10
|
||||
GOVERSION := 1.13
|
||||
|
||||
export DH_OPTIONS
|
||||
export DH_GOPKG := ${REPO}/${OWNER}/${PROJECT}
|
||||
export GOROOT := /usr/lib/go-${GOVERSION}
|
||||
export GOPATH := ${CURDIR}/_build
|
||||
export GOBIN := ${GOPATH}/bin
|
||||
export PATH := ${GOROOT}/bin:${GOBIN}:${PATH}
|
||||
BLDPATH := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
||||
SRCDIR := ${CURDIR}/_build/src/${DH_GOPKG}
|
||||
export GOCACHE := /tmp/gocache
|
||||
export GOFLAGS := -mod=vendor
|
||||
|
||||
SRCDIR := ${GOPATH}/src/${DH_GOPKG}
|
||||
DESTDIR := ${CURDIR}/debian/${PROJECT}
|
||||
BINDIR := /usr/bin
|
||||
ASSETSDIR := /usr/share/${PROJECT}
|
||||
|
||||
%:
|
||||
dh $@ --buildsystem=golang --with=golang
|
||||
dh $@ --builddirectory=${GOPATH} --buildsystem=golang
|
||||
|
||||
override_dh_auto_build:
|
||||
mkdir -p ${SRCDIR}
|
||||
mkdir -p ${GOBIN}
|
||||
# copy project to local srcdir to build from there
|
||||
rsync -avz --progress --exclude=obj-${BLDPATH} --exclude=debian . $(SRCDIR)
|
||||
rsync -avz --progress --exclude=_build --exclude=debian --exclude=tmp. --exclude=go.mod --exclude=docs . $(SRCDIR)
|
||||
# build go code
|
||||
(cd ${SRCDIR} && go install ./...)
|
||||
|
||||
(cd ${SRCDIR} && go install -buildmode=pie ./...)
|
||||
|
||||
override_dh_auto_test:
|
||||
(cd ${SRCDIR} && go test -v ./...)
|
||||
|
||||
override_dh_auto_install:
|
||||
mkdir -p ${DESTDIR}/${BINDIR}
|
||||
mkdir -p ${DESTDIR}/${ASSETSDIR}
|
||||
cp ${CURDIR}/_build/bin/yq ${DESTDIR}/${BINDIR}
|
||||
cp -rf ${SRCDIR}/LICENSE ${DESTDIR}/${ASSETSDIR}
|
||||
cp -rf ${SRCDIR}/README.md ${DESTDIR}/${PLUGINSDIR}
|
||||
cp ${GOBIN}/yq ${DESTDIR}/${BINDIR}
|
||||
cp -f ${SRCDIR}/LICENSE ${DESTDIR}/${ASSETSDIR}
|
||||
chmod a+x ${DESTDIR}/${BINDIR}/yq
|
||||
|
||||
override_dh_auto_clean:
|
||||
dh_clean
|
||||
rm -rf ${CURDIR}/obj-${BLDPATH}
|
||||
rm -rf ${CURDIR}/_build
|
||||
|
||||
3
debian/yq.dirs
vendored
Normal file
3
debian/yq.dirs
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
usr/bin
|
||||
usr/share/yq
|
||||
usr/share/man/man1
|
||||
5
github-action/Dockerfile
Normal file
5
github-action/Dockerfile
Normal file
@@ -0,0 +1,5 @@
|
||||
FROM mikefarah/yq:3
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
4
github-action/entrypoint.sh
Executable file
4
github-action/entrypoint.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh -l
|
||||
|
||||
echo "$1"
|
||||
eval $1
|
||||
3
go.mod
3
go.mod
@@ -20,8 +20,7 @@ require (
|
||||
golang.org/x/tools v0.0.0-20191213221258-04c2e8eff935 // indirect
|
||||
gopkg.in/imdario/mergo.v0 v0.3.7 // indirect
|
||||
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2
|
||||
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71
|
||||
)
|
||||
|
||||
go 1.13
|
||||
|
||||
2
go.sum
2
go.sum
@@ -145,4 +145,6 @@ gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
||||
@@ -60,7 +60,7 @@ func (n *navigator) doTraverse(value *yaml.Node, head interface{}, tail []interf
|
||||
|
||||
func (n *navigator) getOrReplace(original *yaml.Node, expectedKind yaml.Kind) *yaml.Node {
|
||||
if original.Kind != expectedKind {
|
||||
log.Debug("wanted %v but it was %v, overriding", expectedKind, original.Kind)
|
||||
log.Debug("wanted %v but it was %v, overriding", KindString(expectedKind), KindString(original.Kind))
|
||||
return &yaml.Node{Kind: expectedKind}
|
||||
}
|
||||
return original
|
||||
@@ -84,6 +84,8 @@ func (n *navigator) recurse(value *yaml.Node, head interface{}, tail []interface
|
||||
|
||||
if head == "+" {
|
||||
return n.appendArray(value, head, tail, pathStack)
|
||||
} else if len(value.Content) == 0 && head == "**" {
|
||||
return n.navigationStrategy.Visit(NewNodeContext(value, head, tail, pathStack))
|
||||
}
|
||||
return n.splatArray(value, head, tail, pathStack)
|
||||
}
|
||||
@@ -111,7 +113,7 @@ func (n *navigator) recurseMap(value *yaml.Node, head string, tail []interface{}
|
||||
if n.navigationStrategy.ShouldTraverse(NewNodeContext(contents[indexInMap+1], head, tail, newPathStack), contents[indexInMap].Value) {
|
||||
log.Debug("recurseMap: Going to traverse")
|
||||
traversedEntry = true
|
||||
// contents[indexInMap+1] = n.getOrReplace(contents[indexInMap+1], guessKind(head, tail, contents[indexInMap+1].Kind))
|
||||
contents[indexInMap+1] = n.getOrReplace(contents[indexInMap+1], guessKind(head, tail, contents[indexInMap+1].Kind))
|
||||
errorTraversing := n.doTraverse(contents[indexInMap+1], head, tail, newPathStack)
|
||||
log.Debug("recurseMap: Finished traversing")
|
||||
n.navigationStrategy.DebugVisitedNodes()
|
||||
@@ -126,7 +128,9 @@ func (n *navigator) recurseMap(value *yaml.Node, head string, tail []interface{}
|
||||
return errorVisiting
|
||||
}
|
||||
|
||||
if traversedEntry || n.navigationStrategy.GetPathParser().IsPathExpression(head) || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) {
|
||||
if len(value.Content) == 0 && head == "**" {
|
||||
return n.navigationStrategy.Visit(NewNodeContext(value, head, tail, pathStack))
|
||||
} else if traversedEntry || n.navigationStrategy.GetPathParser().IsPathExpression(head) || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,23 @@ type UpdateCommand struct {
|
||||
Overwrite bool
|
||||
}
|
||||
|
||||
func KindString(kind yaml.Kind) string {
|
||||
switch kind {
|
||||
case yaml.ScalarNode:
|
||||
return "ScalarNode"
|
||||
case yaml.SequenceNode:
|
||||
return "SequenceNode"
|
||||
case yaml.MappingNode:
|
||||
return "MappingNode"
|
||||
case yaml.DocumentNode:
|
||||
return "DocumentNode"
|
||||
case yaml.AliasNode:
|
||||
return "AliasNode"
|
||||
default:
|
||||
return "unknown!"
|
||||
}
|
||||
}
|
||||
|
||||
func DebugNode(value *yaml.Node) {
|
||||
if value == nil {
|
||||
log.Debug("-- node is nil --")
|
||||
@@ -30,7 +47,7 @@ func DebugNode(value *yaml.Node) {
|
||||
log.Error("Error debugging node, %v", errorEncoding.Error())
|
||||
}
|
||||
encoder.Close()
|
||||
log.Debug("Tag: %v", value.Tag)
|
||||
log.Debug("Tag: %v, Kind: %v", value.Tag, KindString(value.Kind))
|
||||
log.Debug("%v", buf.String())
|
||||
}
|
||||
}
|
||||
@@ -54,13 +71,20 @@ func mergePathStackToString(pathStack []interface{}, appendArrays bool) string {
|
||||
s := fmt.Sprintf("%v", path)
|
||||
var _, errParsingInt = strconv.ParseInt(s, 10, 64) // nolint
|
||||
|
||||
hasDot := strings.Contains(s, ".")
|
||||
if hasDot || errParsingInt == nil {
|
||||
sb.WriteString("\"")
|
||||
hasSpecial := strings.Contains(s, ".") || strings.Contains(s, "[") || strings.Contains(s, "]") || strings.Contains(s, "\"")
|
||||
hasDoubleQuotes := strings.Contains(s, "\"")
|
||||
wrappingCharacterStart := "\""
|
||||
wrappingCharacterEnd := "\""
|
||||
if hasDoubleQuotes {
|
||||
wrappingCharacterStart = "("
|
||||
wrappingCharacterEnd = ")"
|
||||
}
|
||||
if hasSpecial || errParsingInt == nil {
|
||||
sb.WriteString(wrappingCharacterStart)
|
||||
}
|
||||
sb.WriteString(s)
|
||||
if hasDot || errParsingInt == nil {
|
||||
sb.WriteString("\"")
|
||||
if hasSpecial || errParsingInt == nil {
|
||||
sb.WriteString(wrappingCharacterEnd)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,12 +115,14 @@ func guessKind(head interface{}, tail []interface{}, guess yaml.Kind) yaml.Kind
|
||||
return yaml.SequenceNode
|
||||
}
|
||||
pathParser := NewPathParser()
|
||||
if (pathParser.IsPathExpression(nextString) || head == "**") && (guess == yaml.SequenceNode || guess == yaml.MappingNode) {
|
||||
if pathParser.IsPathExpression(nextString) && (guess == yaml.SequenceNode || guess == yaml.MappingNode) {
|
||||
return guess
|
||||
}
|
||||
if guess == yaml.AliasNode {
|
||||
} else if guess == yaml.AliasNode {
|
||||
log.Debug("guess was an alias, okey doke.")
|
||||
return guess
|
||||
} else if head == "**" {
|
||||
log.Debug("deep wildcard, go with the guess")
|
||||
return guess
|
||||
}
|
||||
log.Debug("forcing a mapping node")
|
||||
log.Debug("yaml.SequenceNode %v", guess == yaml.SequenceNode)
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
- docker build . -t mikefarah/yq:latest -t mikefarah/yq:VERSION
|
||||
|
||||
- debian package
|
||||
- ensure you get all vendor dependencies before packaging
|
||||
```go mod vendor```
|
||||
- execute
|
||||
```dch -i```
|
||||
- fill debian/changelog with changes from last version
|
||||
@@ -42,4 +44,4 @@
|
||||
- put to PPA
|
||||
```dput ppa:<REPOSITORY> ../yq_<VERSION>_source.changes```
|
||||
(current distro repository is ppa:rmescandon/yq. In case that a new version
|
||||
is released, please contact rmescandon@gmail.com to bump debian package)
|
||||
is released, please contact rmescandon@gmail.com to bump debian package)
|
||||
|
||||
@@ -32,5 +32,5 @@ upload() {
|
||||
done < <(find ./build -mindepth 1 -maxdepth 1 -print0)
|
||||
}
|
||||
|
||||
# release
|
||||
release
|
||||
upload
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: yq
|
||||
version: '3.1.1'
|
||||
version: '3.1.2'
|
||||
summary: A lightweight and portable command-line YAML processor
|
||||
description: |
|
||||
The aim of the project is to be the jq or sed of yaml files.
|
||||
|
||||
Reference in New Issue
Block a user