Skip to content

Commit

Permalink
feat(git-hooks): draft git hooks integration
Browse files Browse the repository at this point in the history
  • Loading branch information
umbopepato committed May 13, 2020
1 parent 7244a71 commit 210f0b7
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 13 deletions.
27 changes: 17 additions & 10 deletions cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,43 @@ import { printScriptsInfo } from "./src/scripts_info.ts";
import { log } from "./src/logger.ts";
import { didYouMean } from "./src/did_you_mean.ts";
import { handleOption } from "./src/options.ts";
import { checkGitHooks } from "./src/git_hooks.ts";

if (import.meta.main) {
let isOption = false, configData;
const args = Deno.args;
try {
configData = loadConfig();
} catch (e) {
log.error(e.message);
Deno.exit(2);
}
if (args.length > 0 && args[0].startsWith("-")) {
isOption = true;
try {
await handleOption(args[0]);
await handleOption(args, configData);
} catch (e) {
log.error(e.message);
Deno.exit(1);
}
Deno.exit();
}
let configData;
try {
configData = loadConfig();
} catch (e) {
log.error(e.message);
Deno.exit(2);
}
const { config, cwd } = configData;
if (!config.scripts || Object.entries(config.scripts).length < 1) {
log.warning(
"No scripts available.\nSee https://github.com/umbopepato/velociraptor for guidance on how to create scripts.",
"No scripts available.\nSee https://deno.land/x/velociraptor for guidance on how to create scripts.",
);
Deno.exit();
}
try {
checkGitHooks(config, cwd);
} catch (e) {
log.error(e);
}
if (args.length < 1) {
printScriptsInfo(config);
Deno.exit();
}
if (isOption) Deno.exit();
const scriptName = args[0];
if (!(scriptName in config.scripts)) {
log.error(`Script ${bold(scriptName)} not found`);
Expand Down
1 change: 1 addition & 0 deletions deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { stringSimilarity } from "https://unpkg.com/string-similarity-js@2.1.2/s
export { parse as parseYaml } from "https://deno.land/std@v0.42.0/encoding/yaml.ts";
export { readJsonSync } from "https://deno.land/std@v0.42.0/fs/read_json.ts";
export { readFileStrSync } from "https://deno.land/std@v0.42.0/fs/read_file_str.ts";
export { writeFileStrSync } from "https://deno.land/std@0.42.0/fs/write_file_str.ts";
export { existsSync } from "https://deno.land/std@v0.42.0/fs/exists.ts";
export * as path from "https://deno.land/std@v0.42.0/path/mod.ts";
export * as logger from "https://deno.land/std@v0.42.0/log/mod.ts";
Expand Down
66 changes: 66 additions & 0 deletions src/git_hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {
writeFileStrSync,
existsSync,
path,
} from "../deps.ts";
import {
ScriptsConfiguration,
isScriptObject,
} from "./scripts_config.ts";

const hooks = [
"applypatch-msg",
"pre-applypatch",
"post-applypatch",
"pre-commit",
"pre-merge-commit",
"prepare-commit-msg",
"commit-msg",
"post-commit",
"pre-rebase",
"post-checkout",
"post-merge",
"pre-push",
"post-update",
"push-to-checkout",
"pre-auto-gc",
"post-rewrite",
"sendemail-validate",
];

function hookScript(hook: string): string {
return `!/bin/sh
vr --git-hook=${hook} "$@"
`;
}

function areGitHooksInstalled(cwd: string): boolean {
return existsSync(path.join(cwd, ".git", "hooks", ".velociraptor"));
}

function installGitHooks(cwd: string) {
const hooksFolder = path.join(cwd, ".git", "hooks");
hooks.forEach((hook) => {
const hookFile = path.join(hooksFolder, hook);
writeFileStrSync(hookFile, hookScript(hook));
try {
Deno.chmodSync(hookFile, 0o0755);
} catch (e) {
// silently fail
}
});
writeFileStrSync(path.join(hooksFolder, ".velociraptor"), "");
}

export function checkGitHooks(config: ScriptsConfiguration, cwd: string) {
if (
!areGitHooksInstalled(cwd) &&
Object.values(config.scripts)
.filter((s) => s instanceof Object && isScriptObject(s)) // TODO move instanceof in isScriptObject
.some((s: any) => {
return "githook" in s && hooks.includes(s.githook);
})
) {
installGitHooks(cwd);
}
}
17 changes: 14 additions & 3 deletions src/options.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { bold } from "../deps.ts";
import { version } from "./version.ts";
import { ScriptsConfiguration } from "./scripts_config.ts";

type Action = () => void | Promise<void>;
type ConfigData = { config: ScriptsConfiguration; cwd: string };

type Action = (configData?: ConfigData) => void | Promise<void>;

const options = new Map<string, Action>();

Expand Down Expand Up @@ -41,11 +44,19 @@ registerOption({
},
});

export async function handleOption(option: string) {
registerOption({
name: "--git-hook",
action: (configData) => {
console.log(version);
},
});

export async function handleOption(args: string[], configData: ConfigData) {
const option = args[0];
if (options.has(option)) {
const action = options.get(option);
if (action && action.call) {
const ret = action();
const ret = action(configData);
if (ret instanceof Promise) await ret;
}
} else {
Expand Down
4 changes: 4 additions & 0 deletions src/scripts_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ export interface ScriptObject extends ScriptOptions {
* **Note** nested `ScriptObject`'s `desc` are ignored
*/
desc?: string;
/**
* A git hook where to execute this command
*/
githook?: string;
}

/**
Expand Down

0 comments on commit 210f0b7

Please sign in to comment.