Skip to content

Feature/validate commit order #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 4, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
validate commit order
Signed-off-by: shmck <[email protected]>
  • Loading branch information
ShMcK committed Jun 4, 2020
commit 907d2837df72569b207abb7bec2e7d886bad3175
1 change: 0 additions & 1 deletion src/build.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as yamlParser from "js-yaml";
import * as path from "path";
import * as _ from "lodash";
import * as fs from "fs";
import * as util from "util";
import { parse } from "./utils/parse";
Expand Down
51 changes: 51 additions & 0 deletions src/utils/commitOrder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// should flag commits that are out of order based on the previous commit
// position is a string like 'INIT', 'L1', 'L1S1'
export function addToCommitOrder(position: string) {
// add position to list
}

export function validateCommitOrder(positions: string[]): boolean {
// loop over positions
const errors: number[] = [];
let previous = { level: 0, step: 0 };
let current = { level: 0, step: 0 };
positions.forEach((position: string, index: number) => {
if (position === "INIT") {
if (previous.level !== 0 && previous.step !== 0) {
console.log("ERROR HERE");
errors.push(index);
}
current = { level: 0, step: 0 };
return;
} else {
const levelMatch = position.match(/^L([0-9])+$/);
const stepMatch = position.match(/^L([0-9])+S([0-9])+$/);
if (levelMatch) {
// allows next level or step
const [_, levelString] = levelMatch;
const level = Number(levelString);
current = { level, step: 0 };
} else if (stepMatch) {
// allows next level or step
const [_, levelString, stepString] = stepMatch;
const level = Number(levelString);
const step = Number(stepString);
current = { level, step };
} else {
// error
console.error(`Invalid commit position: ${position}`);
return;
}
if (
current.level < previous.level ||
(current.level === previous.level && current.step < previous.step)
) {
errors.push(index);
}
}
previous = current;
});

// TODO: log errors based on index
return !errors.length;
}
11 changes: 8 additions & 3 deletions src/utils/commits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as fs from "fs";
import util from "util";
import * as path from "path";
import gitP, { SimpleGit } from "simple-git/promise";
import * as T from "../../typings/tutorial";
import { addToCommitOrder, validateCommitOrder } from "./commitOrder";

const mkdir = util.promisify(fs.mkdir);
const exists = util.promisify(fs.exists);
Expand All @@ -21,19 +21,20 @@ export async function getCommits({
}: GetCommitOptions): Promise<CommitLogObject> {
const git: SimpleGit = gitP(localDir);

// check that a repo is created
const isRepo = await git.checkIsRepo();

if (!isRepo) {
throw new Error("No git repo provided");
}

// setup .tmp directory
const tmpDir = path.join(localDir, ".tmp");

const tmpDirExists = await exists(tmpDir);
if (tmpDirExists) {
await rmdir(tmpDir, { recursive: true });
}
await mkdir(tmpDir);

const tempGit = gitP(tmpDir);
await tempGit.clone(localDir, tmpDir);

Expand All @@ -57,6 +58,7 @@ export async function getCommits({

// Load all logs
const logs = await git.log();
const positions: string[] = [];

for (const commit of logs.all) {
const matches = commit.message.match(
Expand All @@ -73,6 +75,7 @@ export async function getCommits({
// add to the list
commits[position].push(commit.hash);
}
positions.push(position);
} else {
const initMatches = commit.message.match(/^INIT/);
if (initMatches && initMatches.length) {
Expand All @@ -83,9 +86,11 @@ export async function getCommits({
// add to the list
commits.INIT.push(commit.hash);
}
positions.push("INIT");
}
}
}
validateCommitOrder(positions);
} catch (e) {
console.error("Error with checkout or commit matching");
throw new Error(e.message);
Expand Down
4 changes: 2 additions & 2 deletions src/utils/parse.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as _ from "lodash";
import { truncate } from "lodash";
import { CommitLogObject } from "./commits";
import * as T from "../../typings/tutorial";

Expand Down Expand Up @@ -68,7 +68,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
title: levelTitle.trim(),
summary: levelSummary
? levelSummary.trim()
: _.truncate(levelContent.trim(), { length: 80, omission: "..." }),
: truncate(levelContent.trim(), { length: 80, omission: "..." }),
content: levelContent.trim(),
};
} else {
Expand Down
17 changes: 13 additions & 4 deletions src/validate.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import * as path from "path";
import * as fs from "fs";
import util from "util";
import gitP, { SimpleGit } from "simple-git/promise";
import { getCommits, CommitLogObject } from "./utils/commits";

const mkdir = util.promisify(fs.mkdir);
const exists = util.promisify(fs.exists);
const rmdir = util.promisify(fs.rmdir);

async function validate(args: string[]) {
// dir - default .
const dir = !args.length || args[0].match(/^-/) ? "." : args[0];
console.warn("Not yet implemented. Coming soon");
return;

// setup .tmp directory
// git clone branch
const localDir = path.join(process.cwd(), dir);
const codeBranch = "";

const commits = getCommits({ localDir, codeBranch });
// VALIDATE SKELETON WITH COMMITS
// parse tutorial skeleton for order and commands

Expand Down Expand Up @@ -37,7 +47,6 @@ async function validate(args: string[]) {
// on error, show level/step & error message

// CLEANUP
// finally: remove .tmp directory
}

export default validate;
47 changes: 47 additions & 0 deletions tests/commitOrder.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { validateCommitOrder } from "../src/utils/commitOrder";

describe("commitOrder", () => {
it("should return true if order is valid", () => {
const positions = ["INIT", "L1", "L1S1", "L1S2", "L2", "L2S1"];
const result = validateCommitOrder(positions);
expect(result).toBe(true);
});
it("should return true if valid with duplicates", () => {
const positions = [
"INIT",
"INIT",
"L1",
"L1",
"L1S1",
"L1S1",
"L1S2",
"L1S2",
"L2",
"L2",
"L2S1",
"L2S1",
];
const result = validateCommitOrder(positions);
expect(result).toBe(true);
});
it("should return false if INIT is out of order", () => {
const positions = ["INIT", "L1", "L1S1", "L1S2", "INIT", "L2", "L2S1"];
const result = validateCommitOrder(positions);
expect(result).toBe(false);
});
it("should return false if level after step is out of order", () => {
const positions = ["INIT", "L1", "L1S1", "L1S2", "L2S1", "L2"];
const result = validateCommitOrder(positions);
expect(result).toBe(false);
});
it("should return false if level is out of order", () => {
const positions = ["INIT", "L1", "L3", "L2"];
const result = validateCommitOrder(positions);
expect(result).toBe(false);
});
it("should return false if step is out of order", () => {
const positions = ["INIT", "L1", "L1S1", "L1S3", "L1S2"];
const result = validateCommitOrder(positions);
expect(result).toBe(false);
});
});
2 changes: 1 addition & 1 deletion tests/validate.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as T from "../typings/tutorial";
import { validateSchema } from "../src/utils/validate";
import { validateSchema } from "../src/utils/validateSchema";

describe("validate", () => {
it("should reject an empty tutorial", () => {
Expand Down