dslop 1.0.7 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +14 -11
- package/dist/index.js +53 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.2.0
|
|
4
|
+
|
|
5
|
+
[compare changes](https://github.com/turf-sports/dslop/compare/v1.1.0...v1.2.0)
|
|
6
|
+
|
|
7
|
+
### 🚀 Enhancements
|
|
8
|
+
|
|
9
|
+
- Default to checking uncommitted changes, add --all flag ([0492bba](https://github.com/turf-sports/dslop/commit/0492bba))
|
|
10
|
+
|
|
11
|
+
### ❤️ Contributors
|
|
12
|
+
|
|
13
|
+
- Siddharth Sharma <sharmasiddharthcs@gmail.com>
|
|
14
|
+
|
|
15
|
+
## v1.1.0
|
|
16
|
+
|
|
17
|
+
[compare changes](https://github.com/turf-sports/dslop/compare/v1.0.7...v1.1.0)
|
|
18
|
+
|
|
19
|
+
### 🚀 Enhancements
|
|
20
|
+
|
|
21
|
+
- Add --staged flag to check uncommitted changes ([48d66b1](https://github.com/turf-sports/dslop/commit/48d66b1))
|
|
22
|
+
|
|
23
|
+
### ❤️ Contributors
|
|
24
|
+
|
|
25
|
+
- Siddharth Sharma <sharmasiddharthcs@gmail.com>
|
|
26
|
+
|
|
3
27
|
## v1.0.7
|
|
4
28
|
|
|
5
29
|
## v1.0.6
|
package/README.md
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
Find duplicate code in your codebase.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npx dslop
|
|
6
|
+
npx dslop
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
+
By default, checks your uncommitted changes against the codebase.
|
|
10
|
+
|
|
9
11
|
## Install
|
|
10
12
|
|
|
11
13
|
```bash
|
|
@@ -15,21 +17,22 @@ npm i -g dslop
|
|
|
15
17
|
## Usage
|
|
16
18
|
|
|
17
19
|
```bash
|
|
18
|
-
dslop
|
|
20
|
+
dslop # check uncommitted changes for dupes
|
|
21
|
+
dslop --all # scan entire codebase
|
|
19
22
|
dslop ./src -m 6 -s 80 # 6 line min, 80% similarity
|
|
20
|
-
dslop
|
|
21
|
-
dslop . --json # json output
|
|
23
|
+
dslop --all --cross-package # cross-package dupes (monorepos)
|
|
22
24
|
```
|
|
23
25
|
|
|
24
26
|
## Options
|
|
25
27
|
|
|
26
|
-
| Flag |
|
|
27
|
-
|
|
28
|
-
| `-
|
|
29
|
-
| `-
|
|
30
|
-
| `-
|
|
31
|
-
|
|
|
32
|
-
| `--
|
|
28
|
+
| Flag | Description |
|
|
29
|
+
|------|-------------|
|
|
30
|
+
| `-a, --all` | scan entire codebase (default: uncommitted only) |
|
|
31
|
+
| `-m, --min-lines` | min lines per block (default: 4) |
|
|
32
|
+
| `-s, --similarity` | similarity threshold 0-100 (default: 70) |
|
|
33
|
+
| `-e, --extensions` | file extensions (default: ts,tsx,js,jsx) |
|
|
34
|
+
| `--cross-package` | only show dupes across packages |
|
|
35
|
+
| `--json` | json output |
|
|
33
36
|
|
|
34
37
|
## License
|
|
35
38
|
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// index.ts
|
|
4
4
|
import { parseArgs } from "util";
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
import path4 from "path";
|
|
5
7
|
|
|
6
8
|
// src/constants.ts
|
|
7
9
|
var DEFAULT_MIN_LINES = 4;
|
|
@@ -6559,7 +6561,27 @@ async function scanDirectory(targetPath, options) {
|
|
|
6559
6561
|
}
|
|
6560
6562
|
|
|
6561
6563
|
// index.ts
|
|
6562
|
-
var VERSION = process.env.npm_package_version || "1.0
|
|
6564
|
+
var VERSION = process.env.npm_package_version || "1.2.0";
|
|
6565
|
+
function getChangedFiles(targetPath) {
|
|
6566
|
+
const absolutePath = path4.resolve(targetPath);
|
|
6567
|
+
try {
|
|
6568
|
+
const staged = execSync("git diff --cached --name-only", { cwd: absolutePath, encoding: "utf-8" });
|
|
6569
|
+
const unstaged = execSync("git diff --name-only", { cwd: absolutePath, encoding: "utf-8" });
|
|
6570
|
+
const untracked = execSync("git ls-files --others --exclude-standard", { cwd: absolutePath, encoding: "utf-8" });
|
|
6571
|
+
const files = new Set;
|
|
6572
|
+
for (const file of [...staged.split(`
|
|
6573
|
+
`), ...unstaged.split(`
|
|
6574
|
+
`), ...untracked.split(`
|
|
6575
|
+
`)]) {
|
|
6576
|
+
if (file.trim()) {
|
|
6577
|
+
files.add(path4.resolve(absolutePath, file.trim()));
|
|
6578
|
+
}
|
|
6579
|
+
}
|
|
6580
|
+
return files;
|
|
6581
|
+
} catch {
|
|
6582
|
+
return new Set;
|
|
6583
|
+
}
|
|
6584
|
+
}
|
|
6563
6585
|
function showHelp() {
|
|
6564
6586
|
console.log(`
|
|
6565
6587
|
dslop - Detect Similar/Duplicate Lines Of Programming
|
|
@@ -6567,10 +6589,13 @@ dslop - Detect Similar/Duplicate Lines Of Programming
|
|
|
6567
6589
|
Usage:
|
|
6568
6590
|
dslop [path] [options]
|
|
6569
6591
|
|
|
6592
|
+
By default, checks uncommitted changes against the codebase.
|
|
6593
|
+
|
|
6570
6594
|
Arguments:
|
|
6571
6595
|
path Directory to scan (default: current directory)
|
|
6572
6596
|
|
|
6573
6597
|
Options:
|
|
6598
|
+
-a, --all Scan entire codebase (not just uncommitted changes)
|
|
6574
6599
|
-m, --min-lines <n> Minimum block size in lines (default: ${DEFAULT_MIN_LINES})
|
|
6575
6600
|
-s, --similarity <n> Minimum similarity threshold 0-100 (default: ${Math.round(DEFAULT_SIMILARITY * 100)})
|
|
6576
6601
|
-e, --extensions <s> File extensions to scan (default: ${DEFAULT_EXTENSIONS.join(",")})
|
|
@@ -6582,10 +6607,10 @@ Options:
|
|
|
6582
6607
|
-v, --version Show version
|
|
6583
6608
|
|
|
6584
6609
|
Examples:
|
|
6585
|
-
dslop
|
|
6610
|
+
dslop Check uncommitted changes for duplicates
|
|
6611
|
+
dslop --all Scan entire codebase
|
|
6586
6612
|
dslop ./src -m 6 -s 80 Scan src with 6 line min, 80% similarity
|
|
6587
|
-
dslop
|
|
6588
|
-
dslop . --cross-package Only duplicates across packages (great for monorepos)
|
|
6613
|
+
dslop --all --cross-package Cross-package duplicates in entire codebase
|
|
6589
6614
|
`);
|
|
6590
6615
|
}
|
|
6591
6616
|
function showVersion() {
|
|
@@ -6601,6 +6626,7 @@ async function main() {
|
|
|
6601
6626
|
ignore: { type: "string", short: "i", default: DEFAULT_IGNORE_PATTERNS.join(",") },
|
|
6602
6627
|
normalize: { type: "boolean", default: true },
|
|
6603
6628
|
"no-normalize": { type: "boolean", default: false },
|
|
6629
|
+
all: { type: "boolean", short: "a", default: false },
|
|
6604
6630
|
"cross-package": { type: "boolean", default: false },
|
|
6605
6631
|
json: { type: "boolean", default: false },
|
|
6606
6632
|
help: { type: "boolean", short: "h", default: false },
|
|
@@ -6622,6 +6648,7 @@ async function main() {
|
|
|
6622
6648
|
const extensions = values.extensions.split(",").map((e) => e.trim());
|
|
6623
6649
|
const ignorePatterns = values.ignore.split(",").map((p) => p.trim());
|
|
6624
6650
|
const normalize2 = !values["no-normalize"];
|
|
6651
|
+
const scanAll = values.all;
|
|
6625
6652
|
const crossPackage = values["cross-package"];
|
|
6626
6653
|
const jsonOutput = values.json;
|
|
6627
6654
|
if (minLines < 2) {
|
|
@@ -6638,14 +6665,24 @@ async function main() {
|
|
|
6638
6665
|
minLines,
|
|
6639
6666
|
normalize: normalize2
|
|
6640
6667
|
};
|
|
6668
|
+
const changedFiles = !scanAll ? getChangedFiles(targetPath) : null;
|
|
6669
|
+
if (!scanAll && changedFiles?.size === 0) {
|
|
6670
|
+
console.log(`
|
|
6671
|
+
No uncommitted changes found. Use --all to scan entire codebase.`);
|
|
6672
|
+
process.exit(0);
|
|
6673
|
+
}
|
|
6641
6674
|
console.log(`
|
|
6642
6675
|
Scanning ${targetPath}...`);
|
|
6676
|
+
if (!scanAll) {
|
|
6677
|
+
console.log(` Mode: checking ${changedFiles.size} uncommitted files`);
|
|
6678
|
+
} else {
|
|
6679
|
+
console.log(` Mode: full codebase scan`);
|
|
6680
|
+
}
|
|
6643
6681
|
console.log(` Extensions: ${extensions.join(", ")}`);
|
|
6644
6682
|
console.log(` Min block size: ${minLines} lines`);
|
|
6645
6683
|
console.log(` Similarity threshold: ${Math.round(similarity * 100)}%`);
|
|
6646
|
-
console.log(` Normalization: ${normalize2 ? "enabled" : "disabled"}`);
|
|
6647
6684
|
if (crossPackage) {
|
|
6648
|
-
console.log(` Cross-package
|
|
6685
|
+
console.log(` Cross-package: enabled`);
|
|
6649
6686
|
}
|
|
6650
6687
|
console.log();
|
|
6651
6688
|
try {
|
|
@@ -6662,6 +6699,9 @@ Scanning ${targetPath}...`);
|
|
|
6662
6699
|
const detectStart = performance.now();
|
|
6663
6700
|
let duplicates = findDuplicates(blocks, similarity, targetPath);
|
|
6664
6701
|
const detectTime = performance.now() - detectStart;
|
|
6702
|
+
if (!scanAll && changedFiles) {
|
|
6703
|
+
duplicates = duplicates.filter((group) => group.matches.some((m) => changedFiles.has(m.filePath)));
|
|
6704
|
+
}
|
|
6665
6705
|
if (crossPackage) {
|
|
6666
6706
|
duplicates = duplicates.filter((group) => {
|
|
6667
6707
|
const packages = new Set(group.matches.map((m) => {
|
|
@@ -6674,7 +6714,13 @@ Scanning ${targetPath}...`);
|
|
|
6674
6714
|
console.log(`Found ${duplicates.length} duplicate groups in ${Math.round(detectTime)}ms
|
|
6675
6715
|
`);
|
|
6676
6716
|
if (duplicates.length === 0) {
|
|
6677
|
-
|
|
6717
|
+
if (!scanAll) {
|
|
6718
|
+
console.log("No duplicates in your changes. You're good!");
|
|
6719
|
+
} else if (crossPackage) {
|
|
6720
|
+
console.log("No cross-package duplicates found!");
|
|
6721
|
+
} else {
|
|
6722
|
+
console.log("No duplicates found!");
|
|
6723
|
+
}
|
|
6678
6724
|
process.exit(0);
|
|
6679
6725
|
}
|
|
6680
6726
|
if (jsonOutput) {
|