Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 37 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,17 @@ deno task install
semver <command>

Commands:
semver get Get the version
semver set <value> Set the version
semver inc Increment the version
semver parse [value] Parse the version and print
semver cmp <v1> <v2> Compare v1 to v2 and return -1/0/1
semver gt <v1> <v2> Return 0 if v1 is greater than v2, else 1
semver gte <v1> <v2> Return 0 if v1 is greater than or equal to v2, else 1
semver lt <v1> <v2> Return 0 if v1 is less than v2, else 1
semver lte <v1> <v2> Return 0 if v1 is less than or equal to v2, else 1
semver eq <v1> <v2> Return 0 if v1 is equal to v2, else 1
semver get Get the version
semver set <value> Set the version
semver inc Increment the version
semver parse [value] Parse the version and print
semver cmp <v1> <v2> Compare v1 to v2 and return -1/0/1
semver gt <v1> <v2> Return 0 if v1 is greater than v2, else 1
semver gte <v1> <v2> Return 0 if v1 is greater than or equal to v2, else 1
semver lt <v1> <v2> Return 0 if v1 is less than v2, else 1
semver lte <v1> <v2> Return 0 if v1 is less than or equal to v2, else 1
semver eq <v1> <v2> Return 0 if v1 is equal to v2, else 1
semver sort [versions..] Sort semantic versions

Options:
--help Show help [boolean]
Expand All @@ -74,6 +75,10 @@ command will create the `VERSION` file if it doesn't already exist.
The `parse` command accepts a version string as input and parses and prints that
version as output if it is valid.

The `sort` command accepts one or more version strings and outputs them in
sorted order (descending by default, one version per line). Use the `-a` flag
for ascending order, or read versions from stdin using `--`.

#### examples

```sh
Expand All @@ -97,6 +102,28 @@ semver get # 1.2.3
semver parse 1.0.0 # {"major":1,"minor":1,"patch":0,"prerelease":[],"build":[]}
```

```sh
# sort versions in descending order (default)
semver sort 2.0.0 1.0.0 3.0.0
# 3.0.0
# 2.0.0
# 1.0.0
```

```sh
# sort versions in ascending order
semver sort -a 2.0.0 1.0.0 3.0.0
# 1.0.0
# 2.0.0
# 3.0.0
```

```sh
# sort versions from stdin
cat versions.txt | semver sort --
# (sorted output)
```

### Incrementing

When calling the command `inc` the `VERSION` file will be updated based on the
Expand Down
19 changes: 18 additions & 1 deletion deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
lte,
parse,
set,
sort,
} from "./src/commands/mod.ts";
import { getContext } from "./src/context.ts";
import { ApplicationError } from "./src/errors/application.error.ts";
Expand All @@ -34,6 +35,7 @@ try {
.command(lt)
.command(lte)
.command(eq)
.command(sort)
.strictOptions()
.strictCommands()
.demandCommand(1)
Expand Down
1 change: 1 addition & 0 deletions src/commands/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from "./gte.ts";
export * from "./lt.ts";
export * from "./lte.ts";
export * from "./eq.ts";
export * from "./sort.ts";
190 changes: 190 additions & 0 deletions src/commands/sort.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { describe, it } from "testing/bdd";
import { assertSpyCall, assertSpyCalls, stub } from "testing/mock";
import { Arguments } from "yargs";
import { sort } from "./sort.ts";
import { testContext } from "../util/testContext.ts";
import { IContext } from "../context.ts";

describe("sort", () => {
const ctx = testContext({
consoleLog: () => stub(console, "log"),
});

it("SORT00 - sorts versions in descending order by default", async () => {
await sort.handler(
{
_: [],
versions: ["2.0.0", "1.0.0", "3.0.0"],
asc: false,
desc: false,
} as unknown as Arguments & IContext,
);
assertSpyCall(ctx.consoleLog, 0, {
args: ["3.0.0"],
});
assertSpyCall(ctx.consoleLog, 1, {
args: ["2.0.0"],
});
assertSpyCall(ctx.consoleLog, 2, {
args: ["1.0.0"],
});
assertSpyCalls(ctx.consoleLog, 3);
});

it("SORT01 - sorts versions in ascending order with -a flag", async () => {
await sort.handler(
{
_: [],
versions: ["2.0.0", "1.0.0", "3.0.0"],
asc: true,
desc: false,
} as unknown as Arguments & IContext,
);
assertSpyCall(ctx.consoleLog, 0, {
args: ["1.0.0"],
});
assertSpyCall(ctx.consoleLog, 1, {
args: ["2.0.0"],
});
assertSpyCall(ctx.consoleLog, 2, {
args: ["3.0.0"],
});
assertSpyCalls(ctx.consoleLog, 3);
});

it("SORT02 - sorts versions in descending order with -d flag", async () => {
await sort.handler(
{
_: [],
versions: ["1.0.0", "3.0.0", "2.0.0"],
asc: false,
desc: true,
} as unknown as Arguments & IContext,
);
assertSpyCall(ctx.consoleLog, 0, {
args: ["3.0.0"],
});
assertSpyCall(ctx.consoleLog, 1, {
args: ["2.0.0"],
});
assertSpyCall(ctx.consoleLog, 2, {
args: ["1.0.0"],
});
assertSpyCalls(ctx.consoleLog, 3);
});

it("SORT03 - handles prerelease versions correctly", async () => {
await sort.handler(
{
_: [],
versions: ["1.0.0", "1.0.0-alpha", "1.0.0-beta"],
asc: true,
desc: false,
} as unknown as Arguments & IContext,
);
assertSpyCall(ctx.consoleLog, 0, {
args: ["1.0.0-alpha"],
});
assertSpyCall(ctx.consoleLog, 1, {
args: ["1.0.0-beta"],
});
assertSpyCall(ctx.consoleLog, 2, {
args: ["1.0.0"],
});
assertSpyCalls(ctx.consoleLog, 3);
});

it("SORT04 - handles build metadata correctly", async () => {
await sort.handler(
{
_: [],
versions: ["1.0.0+build1", "1.0.0+build2", "1.0.0"],
asc: true,
desc: false,
} as unknown as Arguments & IContext,
);
// Build metadata should not affect sort order
assertSpyCalls(ctx.consoleLog, 3);
Comment thread
justinmchase marked this conversation as resolved.
Outdated
});

it("SORT05 - sorts complex semver versions", async () => {
await sort.handler(
{
_: [],
versions: ["1.0.0", "2.1.0", "2.0.0", "1.1.0", "1.0.1"],
asc: true,
desc: false,
} as unknown as Arguments & IContext,
);
assertSpyCall(ctx.consoleLog, 0, {
args: ["1.0.0"],
});
assertSpyCall(ctx.consoleLog, 1, {
args: ["1.0.1"],
});
assertSpyCall(ctx.consoleLog, 2, {
args: ["1.1.0"],
});
assertSpyCall(ctx.consoleLog, 3, {
args: ["2.0.0"],
});
assertSpyCall(ctx.consoleLog, 4, {
args: ["2.1.0"],
});
assertSpyCalls(ctx.consoleLog, 5);
});

it("SORT06 - handles single version", async () => {
await sort.handler(
{
_: [],
versions: ["1.0.0"],
asc: false,
desc: false,
} as unknown as Arguments & IContext,
);
assertSpyCall(ctx.consoleLog, 0, {
args: ["1.0.0"],
});
assertSpyCalls(ctx.consoleLog, 1);
});

it("SORT07 - handles empty versions array gracefully", async () => {
await sort.handler(
{
_: [],
versions: [],
asc: false,
desc: false,
} as unknown as Arguments & IContext,
);
// Should not output anything and not throw
assertSpyCalls(ctx.consoleLog, 0);
});

it("SORT08 - handles null versions gracefully", async () => {
await sort.handler(
{
_: [],
versions: null,
asc: false,
desc: false,
} as unknown as Arguments & IContext,
);
// Should not output anything and not throw
assertSpyCalls(ctx.consoleLog, 0);
});

it("SORT09 - handles undefined versions gracefully", async () => {
await sort.handler(
{
_: [],
versions: undefined,
asc: false,
desc: false,
} as unknown as Arguments & IContext,
);
// Should not output anything and not throw
assertSpyCalls(ctx.consoleLog, 0);
});
});
Loading