Skip to content

Commit

Permalink
Update README and add trackable git hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
hhefesto committed Aug 27, 2024
1 parent c924b43 commit bfe1baa
Show file tree
Hide file tree
Showing 14 changed files with 788 additions and 20 deletions.
40 changes: 20 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,50 +18,50 @@ This project is in active development. Do expect bugs and general trouble, and p
## Quick Start

1. Clone this repository and change directory to it:
```
```sh
$ git clone https://github.com/Stand-In-Language/stand-in-language.git
$ cd stand-in-language
```
2. [Install Nix](https://nixos.org/nix/download.html):
```
```sh
$ curl https://nixos.org/nix/install | sh
```
3. Optional (reduces build time by using telomare's cache):
```
```sh
# Install cachix with nix-env or adding `cachix` to your `/etc/nixos/configuration.nix`'s' `environment.systemPackages` if in NixOS.
$ nix-env -iA cachix -f https://cachix.org/api/v1/install
$ cachix use telomare
```
4. Enter a Nix shell. This will setup an environment where all external dependencies will be available (such as `cabal` for building):
```
$ nix-shell shell.nix
```sh
$ nix develop # or nix develop -c zsh
```
5. Build the project:
```
$ cabal new-build
```sh
$ cabal build # or nix build
```
6. Run the tictactoe example and start playing with a friend (or run your own telomare file):
```
$ cabal new-run telomare -- tictactoe.tel
```sh
$ cabal run telomare -- tictactoe.tel # or nix run . -- tictactoe.tel
```
7. Profit!

## Running `cabal new-repl`

There is a known issue (#7) for getting a repl.

To get around it, you should copy `libgc.so.1` (provided by the `bohem` garbage collector) into your repository (telomare/lib is a good choice) and rename it to `libgc.so`. You will also need to reference it on `telomare.cabal` under the `library` stanza. Be sure to use the complete path for `libgc.so` on `telomare.cabal` (a commented version on `telomare.cabal` is provided as an example).

## Telomare REPL
1. Run:
```
```sh
$ cd <your/local/proyect/location>/telomare
$ nix-shell shell.nix
$ cabal new-build
$ cabal new-run telomare-repl -- --haskell
$ nix develop -c zsh
$ cabal run telomare-repl -- --haskell # or nix run .#repl
```
2. Profit!

## Git Hooks

You can setup your git configuration to automatically format and look for lint suggestions. Just run:

``` sh
$ git config core.hooksPath hooks
```

## Contributing
If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome.

Expand Down
15 changes: 15 additions & 0 deletions hooks/applypatch-msg.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/nix/store/a4yw1svqqk4d8lhwinn9xp847zz9gfma-bash-4.4-p23/bin/bash
#
# An example hook script to check the commit log message taken by
# applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit. The hook is
# allowed to edit the commit message file.
#
# To enable this hook, rename this file to "applypatch-msg".

. git-sh-setup
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
:
24 changes: 24 additions & 0 deletions hooks/commit-msg.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/nix/store/a4yw1svqqk4d8lhwinn9xp847zz9gfma-bash-4.4-p23/bin/bash
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".

# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"

# This example catches duplicate Signed-off-by lines.

test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}
173 changes: 173 additions & 0 deletions hooks/fsmonitor-watchman.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#!/nix/store/20qcfkjgmjb84ldsq4in1ayygqjasqji-perl-5.32.1/bin/perl

use strict;
use warnings;
use IPC::Open2;

# An example hook script to integrate Watchman
# (https://facebook.github.io/watchman/) with git to speed up detecting
# new and modified files.
#
# The hook is passed a version (currently 2) and last update token
# formatted as a string and outputs to stdout a new update token and
# all files that have been modified since the update token. Paths must
# be relative to the root of the working tree and separated by a single NUL.
#
# To enable this hook, rename this file to "query-watchman" and set
# 'git config core.fsmonitor .git/hooks/query-watchman'
#
my ($version, $last_update_token) = @ARGV;

# Uncomment for debugging
# print STDERR "$0 $version $last_update_token\n";

# Check the hook interface version
if ($version ne 2) {
die "Unsupported query-fsmonitor hook version '$version'.\n" .
"Falling back to scanning...\n";
}

my $git_work_tree = get_working_dir();

my $retry = 1;

my $json_pkg;
eval {
require JSON::XS;
$json_pkg = "JSON::XS";
1;
} or do {
require JSON::PP;
$json_pkg = "JSON::PP";
};

launch_watchman();

sub launch_watchman {
my $o = watchman_query();
if (is_work_tree_watched($o)) {
output_result($o->{clock}, @{$o->{files}});
}
}

sub output_result {
my ($clockid, @files) = @_;

# Uncomment for debugging watchman output
# open (my $fh, ">", ".git/watchman-output.out");
# binmode $fh, ":utf8";
# print $fh "$clockid\n@files\n";
# close $fh;

binmode STDOUT, ":utf8";
print $clockid;
print "\0";
local $, = "\0";
print @files;
}

sub watchman_clock {
my $response = qx/watchman clock "$git_work_tree"/;
die "Failed to get clock id on '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;

return $json_pkg->new->utf8->decode($response);
}

sub watchman_query {
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
or die "open2() failed: $!\n" .
"Falling back to scanning...\n";

# In the query expression below we're asking for names of files that
# changed since $last_update_token but not from the .git folder.
#
# To accomplish this, we're using the "since" generator to use the
# recency index to select candidate nodes and "fields" to limit the
# output to file names only. Then we're using the "expression" term to
# further constrain the results.
if (substr($last_update_token, 0, 1) eq "c") {
$last_update_token = "\"$last_update_token\"";
}
my $query = <<" END";
["query", "$git_work_tree", {
"since": $last_update_token,
"fields": ["name"],
"expression": ["not", ["dirname", ".git"]]
}]
END

# Uncomment for debugging the watchman query
# open (my $fh, ">", ".git/watchman-query.json");
# print $fh $query;
# close $fh;

print CHLD_IN $query;
close CHLD_IN;
my $response = do {local $/; <CHLD_OUT>};

# Uncomment for debugging the watch response
# open ($fh, ">", ".git/watchman-response.json");
# print $fh $response;
# close $fh;

die "Watchman: command returned no output.\n" .
"Falling back to scanning...\n" if $response eq "";
die "Watchman: command returned invalid output: $response\n" .
"Falling back to scanning...\n" unless $response =~ /^\{/;

return $json_pkg->new->utf8->decode($response);
}

sub is_work_tree_watched {
my ($output) = @_;
my $error = $output->{error};
if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
$retry--;
my $response = qx/watchman watch "$git_work_tree"/;
die "Failed to make watchman watch '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
$output = $json_pkg->new->utf8->decode($response);
$error = $output->{error};
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;

# Uncomment for debugging watchman output
# open (my $fh, ">", ".git/watchman-output.out");
# close $fh;

# Watchman will always return all files on the first query so
# return the fast "everything is dirty" flag to git and do the
# Watchman query just to get it over with now so we won't pay
# the cost in git to look up each individual file.
my $o = watchman_clock();
$error = $output->{error};

die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;

output_result($o->{clock}, ("/"));
$last_update_token = $o->{clock};

eval { launch_watchman() };
return 0;
}

die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;

return 1;
}

sub get_working_dir {
my $working_dir;
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
$working_dir = Win32::GetCwd();
$working_dir =~ tr/\\/\//;
} else {
require Cwd;
$working_dir = Cwd::cwd();
}

return $working_dir;
}
8 changes: 8 additions & 0 deletions hooks/post-update.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/nix/store/a4yw1svqqk4d8lhwinn9xp847zz9gfma-bash-4.4-p23/bin/bash
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".

exec git update-server-info
14 changes: 14 additions & 0 deletions hooks/pre-applypatch.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/nix/store/a4yw1svqqk4d8lhwinn9xp847zz9gfma-bash-4.4-p23/bin/bash
#
# An example hook script to verify what is about to be committed
# by applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-applypatch".

. git-sh-setup
precommit="$(git rev-parse --git-path hooks/pre-commit)"
test -x "$precommit" && exec "$precommit" ${1+"$@"}
:
27 changes: 27 additions & 0 deletions hooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash

echo "Formatting:"
# Formatting
nix develop -c stylish-haskell -irv .
output=$(git diff)
if [ "$output" = "" ]; then
echo "Success! No formatting suggestions applied."
else
echo "These stylish-haskell formatting changes will be made for your commit:"
echo "$output"
fi
echo "Finished formatting"

# Linting
# TODO: The --refactor flag does not work even after adding `apply-refactor` to the devShell
echo "Linting:"
output=$(nix develop -c hlint . --no-exit-code)
if [ "$output" = "No hints" ]; then
echo "Success! No Hlint suggestions."
else
echo "Failure: Hlint has some suggestions for your commit"
echo "$output"
echo "Please fix or add an exception to the .hlint.yaml file"
exit 1
fi
echo "Finished linting"
13 changes: 13 additions & 0 deletions hooks/pre-merge-commit.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/nix/store/a4yw1svqqk4d8lhwinn9xp847zz9gfma-bash-4.4-p23/bin/bash
#
# An example hook script to verify what is about to be committed.
# Called by "git merge" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message to
# stderr if it wants to stop the merge commit.
#
# To enable this hook, rename this file to "pre-merge-commit".

. git-sh-setup
test -x "$GIT_DIR/hooks/pre-commit" &&
exec "$GIT_DIR/hooks/pre-commit"
:
Loading

0 comments on commit bfe1baa

Please sign in to comment.