aboutsummaryrefslogtreecommitdiff
path: root/hooked/src/main.rs
blob: d4124692d2b7825972e40e09f819700a02e1e784 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#[cfg(windows)]
use anyhow::bail;
use anyhow::Result;
use shared::find_root;
#[cfg(not(windows))]
use std::os::unix::fs::{
  symlink,
  PermissionsExt,
};
#[cfg(windows)]
use std::os::windows::fs::symlink_file;
use std::{
  fs,
  io::Write,
};

const HOOKS: [&str; 18] = [
  "applypatch-msg",
  "post-applypatch",
  "pre-commit",
  "prepare-commit-msg",
  "commit-msg",
  "post-commit",
  "pre-rebase",
  "post-checkout",
  "post-merge",
  "pre-push",
  "pre-receive",
  "update",
  "post-receive",
  "post-update",
  "push-to-checkout",
  "pre-auto-gc",
  "post-rewrite",
  "sendemail-validate",
];

#[derive(structopt::StructOpt)]
enum Args {
  /// Initialize the repo to use ticket
  Init,
}

#[paw::main]
fn main(args: Args) {
  if let Err(e) = match args {
    Args::Init => init(),
  } {
    eprintln!("{}", e);
    std::process::exit(1);
  }
}

fn init() -> Result<()> {
  #[cfg(windows)]
  bail!("Windows is currently unsupported!");

  let root = find_root()?;
  let git_hooks = &root.join(".git").join("hooks");
  let root = root.join(".dev-suite").join("hooked");
  fs::create_dir_all(&root)?;

  for hook in &HOOKS {
    let path = &root.join(hook);
    let git_hook = &git_hooks.join(hook);

    if !path.exists() {
      let mut file = fs::File::create(&path)?;
      let mut perms = file.metadata()?.permissions();
      perms.set_mode(0o755);
      file.set_permissions(perms)?;
      file.write_all(b"#! /bin/bash")?;
    }
    let path = path.canonicalize()?;

    if !git_hook.exists() {
      #[cfg(not(windows))]
      symlink(&path, &git_hook)?;
      #[cfg(windows)]
      symlink_file(&path, &git_hook)?;
    }
  }

  Ok(())
}