Skip to content
1 change: 0 additions & 1 deletion x/gov/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ func GetQueryCmd() *cobra.Command {
GetCmdQueryDeposits(),
GetCmdQueryTally(),
GetCmdConstitution(),
GetCmdGenerateConstitutionAmendment(),
)

return govQueryCmd
Expand Down
19 changes: 15 additions & 4 deletions x/gov/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/cosmos/cosmos-sdk/version"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"

"github.com/atomone-hub/atomone/x/gov/client/utils"
govutils "github.com/atomone-hub/atomone/x/gov/client/utils"
"github.com/atomone-hub/atomone/x/gov/types"
v1 "github.com/atomone-hub/atomone/x/gov/types/v1"
Expand Down Expand Up @@ -73,6 +74,7 @@ func NewTxCmd(legacyPropCmds []*cobra.Command) *cobra.Command {
NewCmdWeightedVote(),
NewCmdSubmitProposal(),
NewCmdDraftProposal(),
NewCmdGenerateConstitutionAmendment(),

// Deprecated
cmdSubmitLegacyProp,
Expand Down Expand Up @@ -377,11 +379,11 @@ $ %s tx gov weighted-vote 1 yes=0.6,no=0.3,abstain=0.1 --from mykey
return cmd
}

// GetCmdConstitutionAmendmentMsg returns the command to generate the sdk.Msg
// NewCmdConstitutionAmendmentMsg returns the command to generate the sdk.Msg
// required for a constitution amendment proposal generating the unified diff
// between the current constitution (queried) and the updated constitution
// from the provided markdown file.
func GetCmdGenerateConstitutionAmendment() *cobra.Command {
func NewCmdGenerateConstitutionAmendment() *cobra.Command {
cmd := &cobra.Command{
Use: "generate-constitution-amendment [path/to/updated/constitution.md]",
Args: cobra.ExactArgs(1),
Expand All @@ -394,6 +396,10 @@ valid constitution amendment proposal message containing the unified diff
between the current constitution and the updated constitution provided
in a markdown file.

NOTE: this is just a utility command, it is not able to generate or submit a valid Tx
to submit on-chain. Use the 'tx gov submit-proposal' command in conjunction with the
result of this one to submit the proposal.

Example:
$ %s tx gov generate-constitution-amendment path/to/updated/constitution.md
`,
Expand All @@ -419,7 +425,7 @@ $ %s tx gov generate-constitution-amendment path/to/updated/constitution.md
}

// Generate the unified diff between the current and updated constitutions
diff, err := types.GenerateUnifiedDiff(resp.Constitution, updatedConstitution)
diff, err := utils.GenerateUnifiedDiff(resp.Constitution, updatedConstitution)
if err != nil {
return err
}
Expand All @@ -430,7 +436,12 @@ $ %s tx gov generate-constitution-amendment path/to/updated/constitution.md
},
}

flags.AddTxFlagsToCmd(cmd)
// This is not a tx command (but a utility for the proposal tx), so we don't need to add tx flags.
// It might actually be confusing, so we just add the query flags.
flags.AddQueryFlagsToCmd(cmd)
// query commands have the FlagOutput default to "text", but we want to override it to "json"
// in this case.
cmd.Flags().Set(flags.FlagOutput, "json")

return cmd
}
2 changes: 1 addition & 1 deletion x/gov/client/cli/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ func (s *CLITestSuite) TestCmdGenerateConstitutionAmendment() {
tc := tc

s.Run(tc.name, func() {
cmd := cli.GetCmdGenerateConstitutionAmendment()
cmd := cli.NewCmdGenerateConstitutionAmendment()
out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
s.Require().NoError(err)
s.Require().Contains(out.String(), tc.expCmdOutput)
Expand Down
35 changes: 35 additions & 0 deletions x/gov/client/utils/unified_diff.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package utils

import (
"fmt"

"github.com/hexops/gotextdiff"
"github.com/hexops/gotextdiff/myers"
"github.com/hexops/gotextdiff/span"
)

// GenerateUnifiedDiff generates a unified diff from src and dst strings using gotextdiff.
// This is the only function that uses the gotextdiff library as its primary use is for
// clients.
func GenerateUnifiedDiff(src, dst string) (string, error) {
// Create spans for the source and destination texts
srcURI := span.URIFromPath("src")

if src == "" || src[len(src)-1] != '\n' {
src += "\n" // Add an EOL to src if it's empty or newline is missing
}
if dst == "" || dst[len(dst)-1] != '\n' {
dst += "\n" // Add an EOL to dst if it's empty or newline is missing
}

// Compute the edits using the Myers diff algorithm
eds := myers.ComputeEdits(srcURI, src, dst)

// Generate the unified diff string
diff := gotextdiff.ToUnified("src", "dst", src, eds)

// Convert the diff to a string
diffStr := fmt.Sprintf("%v", diff)

return diffStr, nil
}
93 changes: 93 additions & 0 deletions x/gov/client/utils/unified_diff_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package utils_test

import (
"strings"
"testing"

"github.com/atomone-hub/atomone/x/gov/client/utils"
"github.com/atomone-hub/atomone/x/gov/types"
"github.com/stretchr/testify/require"
)

func TestGenerateUnifiedDiff(t *testing.T) {
tests := []struct {
name string
src string
dst string
expected string
}{
{
name: "No changes",
src: "Line one\nLine two\nLine three",
dst: "Line one\nLine two\nLine three",
expected: ``,
},
{
name: "Line added",
src: "Line one\nLine two",
dst: "Line one\nLine two\nLine three",
expected: `@@ -1,2 +1,3 @@
Line one
Line two
+Line three
`,
},
{
name: "Line deleted",
src: "Line one\nLine two\nLine three",
dst: "Line one\nLine three",
expected: `@@ -1,3 +1,2 @@
Line one
-Line two
Line three
`,
},
{
name: "Line modified",
src: "Line one\nLine two\nLine three",
dst: "Line one\nLine two modified\nLine three",
expected: `@@ -1,3 +1,3 @@
Line one
-Line two
+Line two modified
Line three
`,
},
{
name: "Multiple changes",
src: "Line one\nLine two\nLine three",
dst: "Line zero\nLine one\nLine three\nLine four",
expected: `@@ -1,3 +1,4 @@
+Line zero
Line one
-Line two
Line three
+Line four
`,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff, err := utils.GenerateUnifiedDiff(tt.src, tt.dst)
require.NoError(t, err)

diffContent := strings.TrimPrefix(diff, "--- src\n+++ dst\n")
expectedContent := strings.TrimPrefix(tt.expected, "--- src\n+++ dst\n")

require.Equal(t, expectedContent, diffContent)
})
}
}

func TestUnifiedDiffIntegration(t *testing.T) {
src := "Line one\nLine two\nLine three"
dst := "Line zero\nLine one\nLine three\nLine four"

diffStr, err := utils.GenerateUnifiedDiff(src, dst)
require.NoError(t, err)

result, err := types.ApplyUnifiedDiff(src, diffStr)
require.NoError(t, err)
require.Equal(t, dst, result)
}
30 changes: 0 additions & 30 deletions x/gov/types/unified_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ import (
"fmt"
"strconv"
"strings"

"github.com/hexops/gotextdiff"
"github.com/hexops/gotextdiff/myers"
"github.com/hexops/gotextdiff/span"
)

// Hunk represents a single change hunk in a unified diff.
Expand Down Expand Up @@ -271,29 +267,3 @@ func ApplyUnifiedDiff(src, diffStr string) (string, error) {

return strings.Join(resultLines, "\n"), nil
}

// GenerateUnifiedDiff generates a unified diff from src and dst strings using gotextdiff.
// This is the only function that uses the gotextdiff library as its primary use is for
// clients.
func GenerateUnifiedDiff(src, dst string) (string, error) {
// Create spans for the source and destination texts
srcURI := span.URIFromPath("src")

if src == "" || src[len(src)-1] != '\n' {
src += "\n" // Add an EOL to src if it's empty or newline is missing
}
if dst == "" || dst[len(dst)-1] != '\n' {
dst += "\n" // Add an EOL to dst if it's empty or newline is missing
}

// Compute the edits using the Myers diff algorithm
eds := myers.ComputeEdits(srcURI, src, dst)

// Generate the unified diff string
diff := gotextdiff.ToUnified("src", "dst", src, eds)

// Convert the diff to a string
diffStr := fmt.Sprintf("%v", diff)

return diffStr, nil
}
84 changes: 0 additions & 84 deletions x/gov/types/unified_diff_test.go
Original file line number Diff line number Diff line change
@@ -1,83 +1,11 @@
package types

import (
"strings"
"testing"

"github.com/stretchr/testify/require"
)

func TestGenerateUnifiedDiff(t *testing.T) {
tests := []struct {
name string
src string
dst string
expected string
}{
{
name: "No changes",
src: "Line one\nLine two\nLine three",
dst: "Line one\nLine two\nLine three",
expected: ``,
},
{
name: "Line added",
src: "Line one\nLine two",
dst: "Line one\nLine two\nLine three",
expected: `@@ -1,2 +1,3 @@
Line one
Line two
+Line three
`,
},
{
name: "Line deleted",
src: "Line one\nLine two\nLine three",
dst: "Line one\nLine three",
expected: `@@ -1,3 +1,2 @@
Line one
-Line two
Line three
`,
},
{
name: "Line modified",
src: "Line one\nLine two\nLine three",
dst: "Line one\nLine two modified\nLine three",
expected: `@@ -1,3 +1,3 @@
Line one
-Line two
+Line two modified
Line three
`,
},
{
name: "Multiple changes",
src: "Line one\nLine two\nLine three",
dst: "Line zero\nLine one\nLine three\nLine four",
expected: `@@ -1,3 +1,4 @@
+Line zero
Line one
-Line two
Line three
+Line four
`,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff, err := GenerateUnifiedDiff(tt.src, tt.dst)
require.NoError(t, err)

diffContent := strings.TrimPrefix(diff, "--- src\n+++ dst\n")
expectedContent := strings.TrimPrefix(tt.expected, "--- src\n+++ dst\n")

require.Equal(t, expectedContent, diffContent)
})
}
}

func TestApplyUnifiedDiff(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -221,18 +149,6 @@ func TestApplyUnifiedDiff(t *testing.T) {
}
}

func TestUnifiedDiffIntegration(t *testing.T) {
src := "Line one\nLine two\nLine three"
dst := "Line zero\nLine one\nLine three\nLine four"

diffStr, err := GenerateUnifiedDiff(src, dst)
require.NoError(t, err)

result, err := ApplyUnifiedDiff(src, diffStr)
require.NoError(t, err)
require.Equal(t, dst, result)
}

func TestParseUnifiedDiff(t *testing.T) {
diffStr := `@@ -1,3 +1,4 @@
+Line zero
Expand Down