Skip to content

Commit 4ab0059

Browse files
author
Simon Renoult
committed
feat(#7): support URL in addition to local directory
1 parent 3abecbd commit 4ab0059

File tree

5 files changed

+61
-25
lines changed

5 files changed

+61
-25
lines changed

README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ view, using information from our version control systems, we can get a better
1515
sense of the effects of our refactoring efforts.*
1616

1717

18-
Note: the current complexity implementation is based on source lines of code (using the `node-sloc` package). Better means are open to discussion in
19-
the repo Issues.
18+
Note: `code-complexity` currently measures complexity using lines of code count.
19+
While imperfect, this measure gives a good enough idea of what's going on.
2020

2121
## Usage
2222

2323
```sh
24-
$ npx code-complexity <path-to-git-directory>
24+
$ npx code-complexity <path-to-git-directory or URL>
2525
```
2626

2727
## Help
@@ -43,17 +43,18 @@ $ npx code-complexity <path-to-git-directory>
4343
4444
Examples:
4545
46-
$ code-complexity <dir>
47-
$ code-complexity <dir> --limit 3
48-
$ code-complexity <dir> --sort score
49-
$ code-complexity <dir> --filter 'src/**,!src/front/**'
50-
$ code-complexity <dir> --limit 10 --sort score
46+
$ code-complexity .
47+
$ code-complexity https://github.com/simonrenoult/code-complexity
48+
$ code-complexity foo --limit 3
49+
$ code-complexity ../foo --sort score
50+
$ code-complexity /foo/bar --filter 'src/**,!src/front/**'
51+
$ code-complexity . --limit 10 --sort score
5152
```
5253

5354
## Output
5455

5556
```sh
56-
$ npx code-complexity . --sort=score --limit=3
57+
$ npx code-complexity https://github.com/simonrenoult/code-complexity --sort=score --limit=3
5758

5859
┌──────────────────────────────┬────────────┬───────┬───────┐
5960
│ file │ complexity │ churn │ score │

src/io/cli.ts

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import * as commander from "commander";
22
import { CommanderStatic } from "commander";
3-
import { lstatSync } from "fs";
3+
import { URL } from "url";
44

55
import { buildDebugger, getPackageJson } from "../utils";
66
import { Format, Options, Sort } from "../lib/types";
7+
import { lstatSync } from "fs";
8+
import { execSync } from "child_process";
79

810
const internal = { debug: buildDebugger("cli") };
911

10-
export default { parse };
12+
export default { parse, cleanup };
1113

1214
async function parse(): Promise<Options> {
1315
const { description, version } = await getPackageJson();
1416
const cli = getRawCli(description, version).parse(process.argv);
1517

1618
assertArgsAreProvided(cli);
17-
assertIsDirectory(cli.args[0]);
1819

1920
const options = buildOptions(cli);
2021

@@ -23,12 +24,18 @@ async function parse(): Promise<Options> {
2324
return options;
2425
}
2526

27+
function cleanup(options: Options): void {
28+
if (options.target instanceof URL) {
29+
execSync(`rm -rf ${options.directory}`, { stdio: "ignore" });
30+
}
31+
}
32+
2633
function getRawCli(
2734
description: string | undefined,
2835
version: string | undefined
2936
): CommanderStatic {
3037
return commander
31-
.usage("<dir> [options]")
38+
.usage("<target> [options]")
3239
.version(version || "")
3340
.description(description || "")
3441
.option(
@@ -57,36 +64,59 @@ function getRawCli(
5764
console.log("Examples:");
5865
console.log();
5966
[
60-
"$ code-complexity <dir>",
61-
"$ code-complexity <dir> --limit 3",
62-
"$ code-complexity <dir> --sort score",
63-
"$ code-complexity <dir> --filter 'src/**,!src/front/**'",
64-
"$ code-complexity <dir> --limit 10 --sort score",
67+
"$ code-complexity .",
68+
"$ code-complexity https://github.com/simonrenoult/code-complexity",
69+
"$ code-complexity foo --limit 3",
70+
"$ code-complexity ../foo --sort score",
71+
"$ code-complexity /foo/bar --filter 'src/**,!src/front/**'",
72+
"$ code-complexity . --limit 10 --sort score",
6573
].forEach((example) => console.log(example.padStart(2)));
6674
});
6775
}
6876

6977
function buildOptions(cli: CommanderStatic): Options {
78+
const target = parseTarget(cli.args[0]);
7079
return {
71-
directory: cli.args[0],
80+
target,
81+
directory: parseDirectory(target),
7282
format: cli.format ? (String(cli.format) as Format) : "table",
7383
filter: cli.filter || [],
7484
limit: cli.limit ? Number(cli.limit) : undefined,
7585
since: cli.since ? String(cli.since) : undefined,
7686
sort: cli.sort ? (String(cli.sort) as Sort) : undefined,
7787
};
88+
89+
// FIXME: I'm not a fan of pulling the code here but it's good enough.
90+
function parseDirectory(target: string | URL): string {
91+
if (target instanceof URL) {
92+
const tmp = `code-complexity-${new Date().getTime()}`;
93+
execSync(`git clone ${target} ${tmp}`, { stdio: "ignore" });
94+
return tmp;
95+
} else {
96+
return target;
97+
}
98+
}
99+
100+
function parseTarget(target: string): string | URL {
101+
try {
102+
return new URL(target);
103+
} catch (e) {
104+
try {
105+
lstatSync(target);
106+
return target;
107+
} catch (e) {
108+
throw new Error(
109+
"Argument 'target' is neither a directory nor a valid URL."
110+
);
111+
}
112+
}
113+
}
78114
}
79115

80116
function commaSeparatedList(value: string): string[] {
81117
return value.split(",");
82118
}
83119

84-
function assertIsDirectory(directory: string): void {
85-
if (!lstatSync(directory).isDirectory()) {
86-
throw new Error(`Argument 'dir' must be a directory.`);
87-
}
88-
}
89-
90120
function assertArgsAreProvided(internalCli: CommanderStatic): void {
91121
if (!internalCli.args || !internalCli.args.length) {
92122
internalCli.help();

src/io/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ import Statistics from "../lib";
66
export default async function main(): Promise<void> {
77
const options = await Cli.parse();
88
const statistics: Map<Path, Statistics> = await Statistics.compute(options);
9+
Cli.cleanup(options);
910
Output.render(statistics, options);
1011
}

src/lib/types.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import { URL } from "url";
2+
13
export type Path = string;
24
export type Sort = "score" | "churn" | "complexity" | "file" | "ratio";
35
export type Format = "table" | "json";
46
export type Options = {
7+
target: string | URL;
58
directory: string;
69
limit?: number;
710
since?: string;

test/lib/statistics.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Options } from "../../src/lib/types";
77
describe("Statistics", () => {
88
const defaultOptions: Options = {
99
directory: join(__dirname, "..", "code-complexity-fixture"),
10+
target: join(__dirname, "..", "code-complexity-fixture"),
1011
format: "table",
1112
filter: [],
1213
limit: 3,

0 commit comments

Comments
 (0)