Skip to content

Commit

Permalink
Merge pull request #2 from cacoco/cacoco/UpateJSONScanning
Browse files Browse the repository at this point in the history
Major updates, fixes and more tests
  • Loading branch information
cacoco authored Feb 3, 2024
2 parents bbf1e4a + a68bf94 commit 48a1dd3
Show file tree
Hide file tree
Showing 53 changed files with 3,264 additions and 1,558 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*.so
*.dylib
bin/
dist/

# Test binary, built with `go test -c`
*.test
Expand Down
46 changes: 46 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com

# The lines below are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/need to use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj

version: 1

before:
hooks:
# You may remove this if you don't use go modules.
- go mod tidy
# you may remove this if you don't need go generate
- go generate ./...

builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin

archives:
- format: tar.gz
# this name template makes the OS and Arch compatible with the results of `uname`.
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end }}
# use zip for windows archives
format_overrides:
- goos: windows
format: zip

changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
29 changes: 16 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@ codemetagenerator --help
Available Commands:
add Adds resources [authors, contributors, keywords] to the in-progress codemeta.json file
clean Clean the $HOME/.codemetagenerator directory
edit Edit an existing property value by key, e.g., 'foo' or 'foo.bar' or 'foo[1]', or 'foo[1].bar' in the in-progress codemeta.json file
delete Delete an arbitrary key and its value in the in-progress codemeta.json file.
generate Generate the final codemeta.json file to the optional output file or to the console
help Help about any command
insert Insert a new property with the given value by key, e.g., 'foo' or 'foo.bar' or 'foo[1]', or 'foo[1].bar' into the in-progress codemeta.json file
licenses List (or refresh cached) SPDX license IDs
new Start a new codemeta.json file. When complete, run "codemetagenerator generate" to generate the final codemeta.json file
remove Remove a property by key, e.g., 'foo' or 'foo.bar' or 'foo[1]', or 'foo[1].bar' from the in-progress codemeta.json file
set Set the value of an arbitrary key in the in-progress codemeta.json file.
```

#### New
Expand All @@ -44,13 +43,15 @@ This will walk you through an interactive session and will store an "in-progress
you will continue to add more metadata, e.g., `author`, `contributor`, or `keyword`.

#### Add
Add helps with the addition of 3 specific fields: `author`, `contributor`, or `keyword`. The command provides a wizard for adding these values.

For example to add an `author`:

```bash
codemetagenerator add author
```

This will walk you through an interactive session to create a [`Person`](https://schema.org/Person) or [`Organization`](https://schema.org/Organization) author. This command can be run multiple times to add more authors. Similarly, this can also be done for adding one or more contributors:
will walk you through an interactive session to create a [`Person`](https://schema.org/Person) or [`Organization`](https://schema.org/Organization) author. This command can be run multiple times to add more authors. Similarly, this can also be done for adding one or more contributors:

```bash
codemetagenerator add contributor
Expand All @@ -64,31 +65,33 @@ To add one or more keywords:
codemetagenerator add keyword "Java" "JVM" "etc"
```

The `keyword` command accepts multiple terms but the command can also be run multiple times to add more keywords.
The `keyword` command accepts multiple terms but can also be run multiple times to add more keywords.

#### Remove
Properties can be removed by running the `remove` command. This allows for removing *any property* in the `codemeta.json` file including an author, contributor, or keyword.
#### Delete
Properties can be removed by running the `delete` command. This allows for removing *any value* in the `codemeta.json` file for a given key specified via the [Path Syntax](#path-syntax).

```bash
codemetagenerator remove "version"
codemetagenerator delete "version"
```

#### Insert
New properties can be inserted into object values in the `codemeta.json` file (arrays cannot be added to via insert). This allows for adding any other `Codemeta` key and value not covered in the generator.
#### Set
New properties can be inserted or exisiting properties can be updated in the `codemeta.json` file with the `set` command. Keys must be specified via the [Path Syntax](#path-syntax).

```bash
codemetagenerator insert "relatedLink" "https://thisisrelated.org"
codemetagenerator set "relatedLink" "https://thisisrelated.org"
```

Note: only a single JSON value can be inserted (e.g. no objects or arrays) for a given property key.

#### Generate
Once creating and editing are done, you can run `generate` to produce a final `codemeta.json`. Generation accepts an optional `-o | --output` flag that allows for specifying an output file. If this flag is not provided, the output is sent to the console.

```bash
codemetagenerator generate
```

### Path Syntax
The syntax follows the `sjson` ([https://github.com/tidwall/sjson](https://github.com/tidwall/sjson)) [Path Syntax](https://github.com/tidwall/sjson?tab=readme-ov-file#path-syntax).


## CodeMeta
[CodeMeta](https://codemeta.github.io) is a [JSON-LD](https://json-ld.org/) file format used to describe software projects. See a [full example](https://github.com/ropensci/codemetar/blob/main/codemeta.json).

Expand Down
6 changes: 3 additions & 3 deletions cmd/codemetagenerator/add.go → cmd/add.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package codemetagenerator
package cmd

import (
"fmt"
Expand Down Expand Up @@ -35,7 +35,7 @@ func checkArgs(cmd *cobra.Command, args []string) error {
return nil
}

func AddCmdRunE(cmd *cobra.Command, args []string) error {
func addCmdRunE(cmd *cobra.Command, args []string) error {
return fmt.Errorf("this command must be run with a resource sub-command like author, contributor or keyword")
}

Expand All @@ -51,7 +51,7 @@ running the "remove" command. When you are done adding resources, run
"generate" to generate the final codemeta.json file.
Note that this command must be run with a resource sub-command like author, contributor or keyword.`,
RunE: AddCmdRunE,
RunE: addCmdRunE,
}

func init() {
Expand Down
12 changes: 6 additions & 6 deletions cmd/codemetagenerator/add_test.go → cmd/add_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package codemetagenerator
package cmd

import (
"bytes"
Expand All @@ -8,7 +8,7 @@ import (
)

func Test_ExecuteAddCmd(t *testing.T) {
add := &cobra.Command{Use: "add", RunE: AddCmdRunE}
add := &cobra.Command{Use: "add", RunE: addCmdRunE}
b := bytes.NewBufferString("")
add.SetOut(b)
add.SetErr(b)
Expand All @@ -20,7 +20,7 @@ func Test_ExecuteAddCmd(t *testing.T) {
}

func Test_ExecuteAddCmd1(t *testing.T) {
add := &cobra.Command{Use: "add", Args: checkArgs, RunE: AddCmdRunE}
add := &cobra.Command{Use: "add", Args: checkArgs, RunE: addCmdRunE}
b := bytes.NewBufferString("")
add.SetOut(b)
add.SetErr(b)
Expand All @@ -34,7 +34,7 @@ func Test_ExecuteAddCmd1(t *testing.T) {
}

func Test_ExecuteAddCmd2(t *testing.T) {
add := &cobra.Command{Use: "add", Args: checkArgs, RunE: AddCmdRunE}
add := &cobra.Command{Use: "add", Args: checkArgs, RunE: addCmdRunE}
b := bytes.NewBufferString("")
add.SetOut(b)
add.SetErr(b)
Expand All @@ -48,7 +48,7 @@ func Test_ExecuteAddCmd2(t *testing.T) {
}

func Test_ExecuteAddCmd3(t *testing.T) {
add := &cobra.Command{Use: "add", Args: checkArgs, RunE: AddCmdRunE}
add := &cobra.Command{Use: "add", Args: checkArgs, RunE: addCmdRunE}
b := bytes.NewBufferString("")
add.SetOut(b)
add.SetErr(b)
Expand All @@ -62,7 +62,7 @@ func Test_ExecuteAddCmd3(t *testing.T) {
}

func Test_ExecuteAddCmd4(t *testing.T) {
add := &cobra.Command{Use: "add", Args: checkArgs, RunE: AddCmdRunE}
add := &cobra.Command{Use: "add", Args: checkArgs, RunE: addCmdRunE}
b := bytes.NewBufferString("")
add.SetOut(b)
add.SetErr(b)
Expand Down
44 changes: 28 additions & 16 deletions cmd/codemetagenerator/author.go → cmd/author.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
package codemetagenerator
package cmd

import (
"errors"
"fmt"

"github.com/cacoco/codemetagenerator/internal"
"github.com/cacoco/codemetagenerator/internal/model"
"github.com/cacoco/codemetagenerator/internal/utils"
"github.com/spf13/cobra"
)

func newAuthor(reader utils.Reader, writer utils.Writer) (*map[string]any, error) {
author, err := utils.NewPersonOrOrganizationPrompt(&reader, &writer, "Author")
if err != nil {
return nil, err
}
return author, nil
}

// authorCmd represents the author command
var authorCmd = &cobra.Command{
Use: "author",
Expand All @@ -22,26 +30,30 @@ to edit properties of an author.
When complete, run "generate" to generate the final codemeta.json file.`,
RunE: func(cmd *cobra.Command, args []string) error {
codemeta, err := internal.LoadInProgressCodeMetaFile()
stdin := &utils.StdinReader{}
stdout := &utils.StdoutWriter{}

inProgressFilePath := utils.GetInProgressFilePath(utils.UserHomeDir)

codemeta, err := utils.Unmarshal(inProgressFilePath)
if err != nil {
msg := "unable to load the in-progress codemeta.json file for editing. Have you run \"codemetagenerator new\" yet?"
return errors.New(msg)
}
author, newAuthorErr := internal.NewPersonOrOrganizationPrompt("Author")
if newAuthorErr != nil {
return fmt.Errorf("unable to create new author: %s", newAuthorErr.Error())
return fmt.Errorf("unable to load the in-progress codemeta.json file for editing. Have you run \"codemetagenerator new\" yet?")
}
mutateMap := *codemeta
currentValue := mutateMap[internal.Author]
currentValue := mutateMap[model.Author]
author, err := newAuthor(stdin, stdout)
if err != nil {
return fmt.Errorf("unable to create new author: %s", err.Error())
}
if currentValue == nil {
mutateMap[internal.Author] = []any{author}
mutateMap[model.Author] = []any{author}
} else {
mutateMap[internal.Author] = append(currentValue.([]any), author)
mutateMap[model.Author] = append(currentValue.([]any), author)
}

saveErr := internal.SaveInProgressCodeMetaFile(&mutateMap)
if saveErr != nil {
return fmt.Errorf("unable to save in-progress codemeta.json file after editing: %s", saveErr.Error())
err = utils.Marshal(inProgressFilePath, &mutateMap)
if err != nil {
return fmt.Errorf("unable to save in-progress codemeta.json file after editing: %s", err.Error())
} else {
fmt.Println("⭐ Successfully updated in-progress codemeta.json file.")
}
Expand Down
38 changes: 38 additions & 0 deletions cmd/author_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cmd

import (
"testing"

"github.com/cacoco/codemetagenerator/internal/model"
"github.com/cacoco/codemetagenerator/internal/utils"
"github.com/onsi/gomega"
)

func TestNewAuthor(t *testing.T) {
g := gomega.NewWithT(t)

var stack utils.Stack[string]
stack.Push("id\n")
stack.Push("person@email.org\n")
stack.Push("familyName\n")
stack.Push("givenName\n")
stack.Push("\n") // enter to select the first option
reader := utils.TestReader{In: utils.TestStdin{Data: stack}}
writer := utils.TestWriter{}

author, err := newAuthor(&reader, &writer)
if author == nil {
t.Errorf("Expected author to not be nil")
}
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected := map[string]any{
model.Type: model.PersonType,
model.FamilyName: "familyName",
model.GivenName: "givenName",
model.Email: "person@email.org",
model.Id: "id",
}
g.Ω(*author).Should(gomega.Equal(expected))
}
37 changes: 37 additions & 0 deletions cmd/clean.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package cmd

import (
"fmt"
"os"

"github.com/cacoco/codemetagenerator/internal/utils"
"github.com/spf13/cobra"
)

func clean(basedir string, writer utils.Writer) error {
codemetageneratorHomeDir := utils.GetHomeDir(basedir)
if _, err := os.Stat(codemetageneratorHomeDir); err == nil {
err := os.RemoveAll(codemetageneratorHomeDir)
if err != nil {
return fmt.Errorf("unable to remove codemetagenerator home directory: %s", err.Error())
}
writer.Println("✅ Successfully cleaned the $HOME/.codemetagenerator directory.")
}
return nil
}

// cleanCmd represents the clean command
var cleanCmd = &cobra.Command{
Use: "clean",
Args: cobra.NoArgs,
Short: "Clean the $HOME/.codemetagenerator directory",
Long: `Removes the $HOME/.codemetagenerator directory used to store the in-progress
codemeta.json file.`,
RunE: func(cmd *cobra.Command, args []string) error {
return clean(utils.UserHomeDir, &utils.StdoutWriter{})
},
}

func init() {
rootCmd.AddCommand(cleanCmd)
}
Loading

0 comments on commit 48a1dd3

Please sign in to comment.