forked from gnolang/gno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add the stdlib_diff tool to compare gno and go standard librari…
…es (gnolang#2869) continuing the work started on gnolang#1425 thanks FloRichardAloeCorp for the great job on this issue 👍 closes gnolang#1310 <!-- please provide a detailed description of the changes made in this pull request. --> <details><summary>Contributors' checklist...</summary> - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md). </details> --------- Co-authored-by: hthieu1110 <[email protected]> Co-authored-by: Florian Richard <[email protected]> Co-authored-by: Morgan Bazalgette <[email protected]>
- Loading branch information
Showing
15 changed files
with
1,061 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package main | ||
|
||
// SEND: 200000000ugnot | ||
|
||
import ( | ||
"strconv" | ||
|
||
"gno.land/r/demo/users" | ||
) | ||
|
||
func main() { | ||
{ | ||
// Verify pre-registered test1 user | ||
names := users.ListUsersByPrefix("test1", 1) | ||
println("# names: " + strconv.Itoa(len(names))) | ||
println("name: " + names[0]) | ||
} | ||
} | ||
|
||
// Output: | ||
// # names: 1 | ||
// name: test1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
stdlib_diff/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
all: clean gen | ||
|
||
gen: | ||
go run . -src $(GOROOT)/src -dst ../../gnovm/stdlibs -out ./stdlib_diff | ||
|
||
clean: | ||
rm -rf stdlib_diff |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# stdlibs_diff | ||
|
||
stdlibs_diff is a tool that generates an html report indicating differences between gno standard libraries and go standrad libraries | ||
|
||
## Usage | ||
|
||
Compare the `go` standard libraries the `gno` standard libraries | ||
|
||
```shell | ||
./stdlibs_diff -src <path to go standard libraries> -dst <path to gno standard libraries> -out <output directory> | ||
``` | ||
|
||
Compare the `gno` standard libraries the `go` standard libraries | ||
|
||
```shell | ||
./stdlibs_diff -src <path to gno standard libraries> -dst <path to go standard libraries> -out <output directory> | ||
``` | ||
|
||
|
||
## Parameters | ||
|
||
| Flag | Description | Default value | | ||
| ---------- | ------------------------------------------------------------------ | ------------- | | ||
| src | Directory containing packages that will be compared to destination | None | | ||
| dst | Directory containing packages; used to compare src packages | None | | ||
| out | Directory where the report will be created | None | | ||
|
||
## Tips | ||
|
||
An index.html is generated at the root of the report location. Utilize it to navigate easily through the report. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package main | ||
|
||
type diffStatus uint | ||
|
||
const ( | ||
missingInSrc diffStatus = iota | ||
missingInDst | ||
hasDiff | ||
noDiff | ||
) | ||
|
||
func (status diffStatus) String() string { | ||
switch status { | ||
case missingInSrc: | ||
return "missing in src" | ||
case missingInDst: | ||
return "missing in dst" | ||
case hasDiff: | ||
return "files differ" | ||
case noDiff: | ||
return "files are equal" | ||
default: | ||
return "Unknown" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/hexops/gotextdiff" | ||
"github.com/hexops/gotextdiff/myers" | ||
"github.com/hexops/gotextdiff/span" | ||
) | ||
|
||
// DiffChecker is a struct for comparing differences between two files. | ||
type DiffChecker struct { | ||
Src string // Name of the source file. | ||
Dst string // Name of the destination file. | ||
srcContent string // Content of the source file. | ||
dstContent string // Content of the destination file. | ||
srcLines []string // Lines of the source file. | ||
dstLines []string // Lines of the destination file. | ||
} | ||
|
||
// LineDifferrence represents a difference in a line during file comparison. | ||
type LineDifferrence struct { | ||
SrcLine string // The line on Src. | ||
DestLine string // The line on Src. | ||
SrcOperation operation // The operation performed on the line (e.g., "add", "delete", "equal"). | ||
DestOperation operation | ||
SrcNumber int | ||
DestNumber int | ||
} | ||
type Diff struct { | ||
Diffs []LineDifferrence | ||
MissingSrc bool | ||
MissingDst bool | ||
} | ||
|
||
// NewDiffChecker creates a new DiffChecker instance for comparing differences between | ||
// the specified source and destination files. It initializes the source and | ||
// destination file lines . | ||
func NewDiffChecker(srcPath, dstPath string) (*DiffChecker, error) { | ||
src, err := getFileContent(srcPath) | ||
if err != nil { | ||
return nil, fmt.Errorf("can't read src file: %w", err) | ||
} | ||
|
||
dst, err := getFileContent(dstPath) | ||
if err != nil { | ||
return nil, fmt.Errorf("can't read dst file: %w", err) | ||
} | ||
|
||
return &DiffChecker{ | ||
srcContent: src, | ||
dstContent: dst, | ||
srcLines: strings.Split(src, "\n"), | ||
dstLines: strings.Split(dst, "\n"), | ||
Src: srcPath, | ||
Dst: dstPath, | ||
}, nil | ||
} | ||
|
||
// Differences returns the differences in lines between the source and | ||
// destination files using the configured diff algorithm. | ||
func (f *DiffChecker) Differences() *Diff { | ||
var ( | ||
srcIndex, dstIndex int | ||
insertCount, deleteCount int | ||
diff []LineDifferrence | ||
) | ||
|
||
if len(f.dstContent) == 0 { | ||
return f.destEmpty() | ||
} | ||
|
||
if len(f.srcContent) == 0 { | ||
return f.srcEmpty() | ||
} | ||
|
||
/* printUntil prints all the lines than do not appear on the computed edits from gotextdiff | ||
so we need to add them manually looping always from the current value of | ||
srcIndex until the line before the start of the hunk computed diff, hunk.FromLine-1 | ||
We need to print all the lines before each hunk and then ensure the end of the file is printed too | ||
*/ | ||
printUntil := func(until int) { | ||
for i := srcIndex; i < until; i++ { | ||
diff = append(diff, LineDifferrence{ | ||
SrcLine: f.srcLines[srcIndex], | ||
DestLine: f.srcLines[srcIndex], | ||
DestOperation: equal, | ||
SrcOperation: equal, | ||
SrcNumber: srcIndex + 1, | ||
DestNumber: dstIndex + 1, | ||
}) | ||
|
||
srcIndex++ | ||
dstIndex++ | ||
} | ||
} | ||
|
||
edits := myers.ComputeEdits(span.URIFromPath(f.Src), f.srcContent, f.dstContent) | ||
unified := gotextdiff.ToUnified(f.Src, f.Dst, f.srcContent, edits) | ||
for _, hunk := range unified.Hunks { | ||
printUntil(hunk.FromLine - 1) | ||
|
||
currentLine := LineDifferrence{} | ||
for _, line := range hunk.Lines { | ||
switch line.Kind { | ||
case gotextdiff.Insert: | ||
if currentLine.DestLine != "" { | ||
diff = append(diff, currentLine) | ||
currentLine = LineDifferrence{} | ||
} | ||
|
||
insertCount++ | ||
dstIndex++ | ||
|
||
currentLine.DestLine = line.Content | ||
currentLine.DestOperation = insert | ||
currentLine.DestNumber = dstIndex | ||
|
||
case gotextdiff.Equal: | ||
if currentLine.DestLine != "" || currentLine.SrcLine != "" { | ||
diff = append(diff, currentLine) | ||
currentLine = LineDifferrence{} | ||
} | ||
|
||
srcIndex++ | ||
dstIndex++ | ||
|
||
currentLine = LineDifferrence{ | ||
SrcLine: line.Content, | ||
DestLine: line.Content, | ||
DestOperation: equal, | ||
SrcOperation: equal, | ||
SrcNumber: srcIndex, | ||
DestNumber: dstIndex, | ||
} | ||
|
||
case gotextdiff.Delete: | ||
if currentLine.SrcLine != "" { | ||
diff = append(diff, currentLine) | ||
currentLine = LineDifferrence{} | ||
} | ||
srcIndex++ | ||
deleteCount++ | ||
currentLine.SrcLine = line.Content | ||
currentLine.SrcOperation = delete | ||
currentLine.SrcNumber = srcIndex | ||
} | ||
} | ||
diff = append(diff, currentLine) | ||
} | ||
|
||
printUntil(len(f.srcLines)) | ||
|
||
return &Diff{ | ||
Diffs: diff, | ||
} | ||
} | ||
|
||
func (f *DiffChecker) destEmpty() *Diff { | ||
diffs := []LineDifferrence{} | ||
for index, line := range f.srcLines { | ||
diffs = append(diffs, LineDifferrence{SrcLine: line, SrcOperation: delete, SrcNumber: index + 1}) | ||
} | ||
|
||
return &Diff{ | ||
Diffs: diffs, | ||
MissingDst: true, | ||
} | ||
} | ||
|
||
func (f *DiffChecker) srcEmpty() *Diff { | ||
diffs := []LineDifferrence{} | ||
for index, line := range f.dstLines { | ||
diffs = append(diffs, LineDifferrence{DestLine: line, DestOperation: insert, DestNumber: index + 1}) | ||
} | ||
|
||
return &Diff{ | ||
Diffs: diffs, | ||
MissingSrc: true, | ||
} | ||
} | ||
|
||
// getFileContent reads and returns the lines of a file given its path. | ||
func getFileContent(p string) (string, error) { | ||
data, err := os.ReadFile(p) | ||
if err != nil { | ||
if os.IsNotExist(err) { | ||
return "", nil | ||
} | ||
return "", err | ||
} | ||
return strings.ReplaceAll(string(data), "\t", " "), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module github.com/gnolang/gno/misc/stdlib_diff | ||
|
||
go 1.21.0 | ||
|
||
require github.com/hexops/gotextdiff v1.0.3 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"log" | ||
) | ||
|
||
func main() { | ||
var srcPath string | ||
var dstPath string | ||
var outDirectory string | ||
|
||
flag.StringVar(&srcPath, "src", "", "Directory containing packages that will be compared to destination") | ||
flag.StringVar(&dstPath, "dst", "", "Directory containing packages; used to compare src packages") | ||
flag.StringVar(&outDirectory, "out", "", "Directory where the report will be created") | ||
flag.Parse() | ||
|
||
reportBuilder, err := NewReportBuilder(srcPath, dstPath, outDirectory) | ||
if err != nil { | ||
log.Fatal("can't build report builder: ", err.Error()) | ||
} | ||
|
||
log.Println("Building report...") | ||
if err := reportBuilder.Build(); err != nil { | ||
log.Fatalln("can't build report: ", err.Error()) | ||
} | ||
log.Println("Report generation done!") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package main | ||
|
||
// operation is an enumeration type representing different types of operations. Used in diff algorithm | ||
// to indicates differences between files. | ||
type operation uint | ||
|
||
const ( | ||
// insert represents an insertion operation. | ||
insert operation = iota + 1 | ||
// delete represents a deletion operation. | ||
delete | ||
// equal represents an equal operation. | ||
equal | ||
) | ||
|
||
// String returns a string representation of the operation. | ||
func (op operation) String() string { | ||
switch op { | ||
case insert: | ||
return "INS" | ||
case delete: | ||
return "DEL" | ||
case equal: | ||
return "EQ" | ||
default: | ||
return "UNKNOWN" | ||
} | ||
} |
Oops, something went wrong.