a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
84 lines
3.0 KiB
Go
84 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// clonesDaemonTool is the daemon-tool relay seam. It is indirected through a
|
|
// package var so tests can stub the daemon call (asserting the lowered
|
|
// tool + args) without a running daemon.
|
|
var clonesDaemonTool = requireDaemonTool
|
|
|
|
var (
|
|
clonesIndex string
|
|
clonesMinSimilarity float64
|
|
clonesDeadOnly bool
|
|
clonesPathPrefix string
|
|
clonesRepo string
|
|
clonesLimit int
|
|
clonesFormat string
|
|
)
|
|
|
|
var clonesCmd = &cobra.Command{
|
|
Use: "clones",
|
|
Short: "Surface near-duplicate (clone) function clusters (find_clones)",
|
|
Long: `Queries the EdgeSimilarTo graph layer for near-duplicate function/method
|
|
clusters found by the MinHash + LSH clone-detection pass — copy-paste and
|
|
renamed-variable (Type-1/Type-2) clones. Every member is flagged dead (zero
|
|
incoming calls/refs), so --dead-only yields the "dead duplicates of live code"
|
|
diagnostic.
|
|
|
|
gortex clones --dead-only --path-prefix internal/
|
|
gortex clones --min-similarity 0.85 --limit 20
|
|
|
|
Requires a running daemon that tracks the repo.`,
|
|
SilenceUsage: true,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
toolArgs := map[string]any{}
|
|
if cmd.Flags().Changed("min-similarity") {
|
|
toolArgs["min_similarity"] = clonesMinSimilarity
|
|
}
|
|
if cmd.Flags().Changed("dead-only") {
|
|
toolArgs["dead_only"] = clonesDeadOnly
|
|
}
|
|
if cmd.Flags().Changed("path-prefix") {
|
|
toolArgs["path_prefix"] = clonesPathPrefix
|
|
}
|
|
if cmd.Flags().Changed("repo-filter") {
|
|
toolArgs["repo"] = clonesRepo
|
|
}
|
|
if cmd.Flags().Changed("limit") {
|
|
toolArgs["limit"] = clonesLimit
|
|
}
|
|
if clonesFormat != "" {
|
|
toolArgs["format"] = clonesFormat
|
|
}
|
|
raw, err := clonesDaemonTool(clonesIndex, "find_clones", toolArgs)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
switch clonesFormat {
|
|
case "gcx", "toon":
|
|
fmt.Fprintln(cmd.OutOrStdout(), strings.TrimRight(string(raw), "\n"))
|
|
return nil
|
|
default:
|
|
return emitDaemonJSON(cmd, raw)
|
|
}
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
clonesCmd.Flags().StringVar(&clonesIndex, "index", ".", "repository path the daemon must track")
|
|
clonesCmd.Flags().StringVar(&clonesIndex, "repo", ".", "alias for --index")
|
|
clonesCmd.Flags().Float64Var(&clonesMinSimilarity, "min-similarity", 0, "report clone pairs at or above this estimated Jaccard similarity (0..1) (min_similarity)")
|
|
clonesCmd.Flags().BoolVar(&clonesDeadOnly, "dead-only", false, "only clusters containing a dead-code symbol — the dead-duplicates view (dead_only)")
|
|
clonesCmd.Flags().StringVar(&clonesPathPrefix, "path-prefix", "", "restrict to symbols whose file path starts with this prefix (path_prefix)")
|
|
clonesCmd.Flags().StringVar(&clonesRepo, "repo-filter", "", "restrict to symbols in a specific repository (RepoPrefix exact match) (repo)")
|
|
clonesCmd.Flags().IntVar(&clonesLimit, "limit", 0, "maximum clusters to return (default 50, largest-first)")
|
|
clonesCmd.Flags().StringVar(&clonesFormat, "format", "json", "output / wire format: json|gcx|toon|text")
|
|
rootCmd.AddCommand(clonesCmd)
|
|
}
|