aboutsummaryrefslogtreecommitdiff
path: root/dev/tools
diff options
context:
space:
mode:
Diffstat (limited to 'dev/tools')
-rw-r--r--dev/tools/anomaly-traces-parser.el28
-rwxr-xr-xdev/tools/backport-pr.sh16
-rwxr-xr-xdev/tools/check-eof-newline.sh42
-rw-r--r--dev/tools/coqdev.el107
-rwxr-xr-xdev/tools/github-check-prs.py47
-rwxr-xr-xdev/tools/merge-pr.sh20
-rwxr-xr-xdev/tools/pre-commit73
-rwxr-xr-xdev/tools/should-check-whitespace.sh6
-rwxr-xr-xdev/tools/sudo-apt-get-update.sh4
9 files changed, 293 insertions, 50 deletions
diff --git a/dev/tools/anomaly-traces-parser.el b/dev/tools/anomaly-traces-parser.el
deleted file mode 100644
index 68f54266f9..0000000000
--- a/dev/tools/anomaly-traces-parser.el
+++ /dev/null
@@ -1,28 +0,0 @@
-;; This Elisp snippet adds a regexp parser for the format of Anomaly
-;; backtraces (coqc -bt ...), to the error parser of the Compilation
-;; mode (C-c C-c: "Compile command: ..."). Once the
-;; coq-change-error-alist-for-backtraces function has run, file
-;; locations in traces are recognized and can be jumped from easily
-;; from the *compilation* buffer.
-
-;; You can just copy everything below to your .emacs and this will be
-;; enabled from any compilation command launched from an OCaml file.
-
-(defun coq-change-error-alist-for-backtraces ()
- "Hook to change the compilation-error-regexp-alist variable, to
- search the coq backtraces for error locations"
- (interactive)
- (add-to-list
- 'compilation-error-regexp-alist-alist
- '(coq-backtrace
- "^ *\\(?:raise\\|frame\\) @ file \\(\"?\\)\\([^,\" \n\t<>]+\\)\\1,\
- lines? \\([0-9]+\\)-?\\([0-9]+\\)?\\(?:$\\|,\
- \\(?: characters? \\([0-9]+\\)-?\\([0-9]+\\)?:?\\)?\\)"
- 2 (3 . 4) (5 . 6)))
- (add-to-list 'compilation-error-regexp-alist 'coq-backtrace))
-
-;; this Anomaly parser should be available when one is hacking
-;; on the *OCaml* code of Coq (adding bugs), so we enable it
-;; through the OCaml mode hooks.
-(add-hook 'caml-mode-hook 'coq-change-error-alist-for-backtraces)
-(add-hook 'tuareg-mode-hook 'coq-change-error-alist-for-backtraces)
diff --git a/dev/tools/backport-pr.sh b/dev/tools/backport-pr.sh
index 4c4dbe1e97..e4359f7038 100755
--- a/dev/tools/backport-pr.sh
+++ b/dev/tools/backport-pr.sh
@@ -1,10 +1,11 @@
#!/usr/bin/env bash
-# Usage: dev/tools/backport-pr.sh <PR number>
+# Usage: dev/tools/backport-pr.sh <PR number> [--stop-before-merging]
set -e
PRNUM=$1
+OPTION=$2
if ! git log master --grep "Merge PR #${PRNUM}" | grep "." > /dev/null; then
echo "PR #${PRNUM} does not exist."
@@ -49,6 +50,19 @@ else
fi
+if ! git diff --exit-code HEAD ${BRANCH} -- "*.mli"; then
+ echo
+ read -p "Some mli files are modified. Bypass? [y/N] " -n 1 -r
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ exit 1
+ fi
+fi
+
+if [[ "${OPTION}" == "--stop-before-merging" ]]; then
+ exit 0
+fi
+
git merge -S --no-ff ${BRANCH} -m "${MESSAGE}"
git branch -d ${BRANCH}
diff --git a/dev/tools/check-eof-newline.sh b/dev/tools/check-eof-newline.sh
index 1c578c05ce..e244d9ab80 100755
--- a/dev/tools/check-eof-newline.sh
+++ b/dev/tools/check-eof-newline.sh
@@ -1,9 +1,41 @@
#!/usr/bin/env bash
-if [ -z "$(tail -c 1 "$1")" ]
+# Usage: check-eof-newline.sh [--fix] FILES...
+# Detect missing end of file newlines for FILES.
+# Files are skipped if untracked by git and depending on gitattributes.
+# With --fix, automatically append a newline.
+# Exit status:
+# Without --fix: 1 if any file had a missing newline, 0 otherwise.
+# With --fix: 1 if any non writable file had a missing newline, 0 otherwise.
+
+FIX=
+if [ "$1" = --fix ];
then
- exit 0
-else
- echo "No newline at end of file $1!"
- exit 1
+ FIX=1
+ shift
fi
+
+CODE=0
+for f in "$@"; do
+ if git ls-files --error-unmatch "$f" >/dev/null 2>&1 && \
+ git check-attr whitespace -- "$f" | grep -q -v -e 'unset$' -e 'unspecified$' && \
+ [ -n "$(tail -c 1 "$f")" ]
+ then
+ if [ -n "$FIX" ];
+ then
+ if [ -w "$f" ];
+ then
+ echo >> "$f"
+ echo "Newline appended to file $f!"
+ else
+ echo "File $f is missing a newline and not writable!"
+ CODE=1
+ fi
+ else
+ echo "No newline at end of file $f!"
+ CODE=1
+ fi
+ fi
+done
+
+exit "$CODE"
diff --git a/dev/tools/coqdev.el b/dev/tools/coqdev.el
new file mode 100644
index 0000000000..62fdaec802
--- /dev/null
+++ b/dev/tools/coqdev.el
@@ -0,0 +1,107 @@
+;;; coqdev.el --- Emacs helpers for Coq development -*- lexical-binding:t -*-
+
+;; Copyright (C) 2018 The Coq Development Team
+
+;; Maintainer: coqdev@inria.fr
+
+;;; Commentary:
+
+;; Helpers to set compilation commands, proof general variables, etc
+;; for Coq development
+
+;; You can disable individual features without editing this file by
+;; using `remove-hook', for instance
+;; (remove-hook 'hack-local-variables-hook #'coqdev-setup-compile-command)
+
+;;; Installation:
+
+;; To use this, with coqdev.el located at /path/to/coqdev.el, add the
+;; following to your init:
+
+;; (add-to-list 'load-path "/path/to/coqdev/")
+;; (require 'coqdev)
+
+;; If you load this file from a git repository, checking out an old
+;; commit will make it disappear and cause errors for your Emacs
+;; startup. To ignore those errors use (require 'coqdev nil t). If you
+;; check out a malicious commit Emacs startup would allow it to run
+;; arbitrary code, to avoid this you can copy coqdev.el to any
+;; location and adjust the load path accordingly (of course if you run
+;; ./configure to compile Coq it is already too late).
+
+;;; Code:
+
+(defun coqdev-default-directory ()
+ "Return the Coq repository containing `default-directory'."
+ (let ((dir (locate-dominating-file default-directory "META.coq")))
+ (when dir (expand-file-name dir))))
+
+(defun coqdev-setup-compile-command ()
+ "Setup `compile-command' for Coq development."
+ (let ((dir (coqdev-default-directory)))
+ ;; we add a space at the end to make it easy to add arguments (eg -j or target)
+ (when dir (setq-local compile-command (concat "make -C " (shell-quote-argument dir) " ")))))
+(add-hook 'hack-local-variables-hook #'coqdev-setup-compile-command)
+
+(defvar camldebug-command-name) ; from camldebug.el (caml package)
+(defvar ocamldebug-command-name) ; from ocamldebug.el (tuareg package)
+(defun coqdev-setup-camldebug ()
+ "Setup ocamldebug for Coq development.
+
+Specifically `camldebug-command-name' and `ocamldebug-command-name'."
+ (let ((dir (coqdev-default-directory)))
+ (when dir
+ (setq-local camldebug-command-name
+ (concat dir "dev/ocamldebug-coq"))
+ (setq-local ocamldebug-command-name
+ (concat dir "dev/ocamldebug-coq")))))
+(add-hook 'hack-local-variables-hook #'coqdev-setup-camldebug)
+
+(defun coqdev-setup-tags ()
+ "Setup `tags-file-name' for Coq development."
+ (let ((dir (coqdev-default-directory)))
+ (when dir (setq-local tags-file-name (concat dir "TAGS")))))
+(add-hook 'hack-local-variables-hook #'coqdev-setup-tags)
+
+(defvar coq-prog-args)
+(defvar coq-prog-name)
+
+;; Lets us detect whether there are file local variables
+;; even though PG sets it with `setq' when there's a _Coqproject.
+;; Also makes sense generally, so might make it into PG someday.
+(make-variable-buffer-local 'coq-prog-args)
+(setq-default coq-prog-args nil)
+
+(defun coqdev-setup-proofgeneral ()
+ "Setup Proofgeneral variables for Coq development.
+
+Note that this function is executed before _Coqproject is read if it exists."
+ (let ((dir (coqdev-default-directory)))
+ (when dir
+ (unless coq-prog-args
+ (setq coq-prog-args
+ `("-coqlib" ,dir "-R" ,(concat dir "plugins")
+ "Coq" "-R" ,(concat dir "theories")
+ "Coq")))
+ (setq-local coq-prog-name (concat dir "bin/coqtop")))))
+(add-hook 'hack-local-variables-hook #'coqdev-setup-proofgeneral)
+
+;; This Elisp snippet adds a regexp parser for the format of Anomaly
+;; backtraces (coqc -bt ...), to the error parser of the Compilation
+;; mode (C-c C-c: "Compile command: ..."). File locations in traces
+;; are recognized and can be jumped from easily in the *compilation*
+;; buffer.
+(defvar compilation-error-regexp-alist-alist)
+(defvar compilation-error-regexp-alist)
+(with-eval-after-load 'compile
+ (add-to-list
+ 'compilation-error-regexp-alist-alist
+ '(coq-backtrace
+ "^ *\\(?:raise\\|frame\\) @ file \\(\"?\\)\\([^,\" \n\t<>]+\\)\\1,\
+ lines? \\([0-9]+\\)-?\\([0-9]+\\)?\\(?:$\\|,\
+ \\(?: characters? \\([0-9]+\\)-?\\([0-9]+\\)?:?\\)?\\)"
+ 2 (3 . 4) (5 . 6)))
+ (add-to-list 'compilation-error-regexp-alist 'coq-backtrace))
+
+(provide 'coqdev)
+;;; coqdev ends here
diff --git a/dev/tools/github-check-prs.py b/dev/tools/github-check-prs.py
new file mode 100755
index 0000000000..beb26d9104
--- /dev/null
+++ b/dev/tools/github-check-prs.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+
+# Requires PyGithub https://pypi.python.org/pypi/PyGithub, for instance
+# debian package: python3-github
+# nix: nix-shell -p python3 python3Packages.PyGithub --run ./github-check-rebase.py
+from github import Github
+import argparse
+
+REPO = "coq/coq"
+REBASE_LABEL="needs: rebase"
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--token-file", type=argparse.FileType('r'))
+args = parser.parse_args()
+
+if args.token_file is None:
+ token = input("Github access token: ").strip()
+else:
+ token = args.token_file.read().rstrip("\n")
+ args.token_file.close()
+
+if token == "":
+ print ("Warning: using the GitHub API without a token")
+ print ("We may run into rate limit issues")
+ g = Github()
+else:
+ g = Github(token)
+
+repo = g.get_repo(REPO)
+
+for pull in repo.get_pulls():
+ # if conflicts then dirty
+ # otherwise blocked (because I have no rights)
+ dirty = pull.mergeable_state == "dirty"
+ labelled = False
+ for label in repo.get_issue(pull.number).get_labels():
+ if label.name == REBASE_LABEL:
+ labelled = True
+ if labelled and not dirty:
+ print ("PR #" + str(pull.number) + " is not dirty but is labelled")
+ print ("("+ pull.html_url +")")
+ elif dirty and not labelled:
+ print ("PR #" + str(pull.number) + " is dirty and not labelled")
+ print ("("+ pull.html_url +")")
+ else:
+ # give some feedback so the user can see we didn't crash
+ print ("PR #" + str(pull.number) + " OK")
diff --git a/dev/tools/merge-pr.sh b/dev/tools/merge-pr.sh
index 0c4a79bfd3..9f24960fff 100755
--- a/dev/tools/merge-pr.sh
+++ b/dev/tools/merge-pr.sh
@@ -9,18 +9,18 @@ set -e
PR=$1
-CURRENT_LOCAL_BRANCH=`git rev-parse --abbrev-ref HEAD`
-REMOTE=`git config --get branch.$CURRENT_LOCAL_BRANCH.remote`
-git fetch $REMOTE refs/pull/$PR/head
+CURRENT_LOCAL_BRANCH=$(git rev-parse --abbrev-ref HEAD)
+REMOTE=$(git config --get "branch.$CURRENT_LOCAL_BRANCH.remote")
+git fetch "$REMOTE" "refs/pull/$PR/head"
API=https://api.github.com/repos/coq/coq
-BASE_BRANCH=`curl -s $API/pulls/$PR | jq -r '.base.label'`
+BASE_BRANCH=$(curl -s "$API/pulls/$PR" | jq -r '.base.label')
-COMMIT=`git rev-parse FETCH_HEAD`
-STATUS=`curl -s $API/commits/$COMMIT/status | jq -r '.state'`
+COMMIT=$(git rev-parse FETCH_HEAD)
+STATUS=$(curl -s "$API/commits/$COMMIT/status" | jq -r '.state')
-if [ $BASE_BRANCH != "coq:$CURRENT_LOCAL_BRANCH" ]; then
+if [ "$BASE_BRANCH" != "coq:$CURRENT_LOCAL_BRANCH" ]; then
echo "Wrong base branch"
read -p "Bypass? [y/N] " -n 1 -r
echo
@@ -30,7 +30,7 @@ if [ $BASE_BRANCH != "coq:$CURRENT_LOCAL_BRANCH" ]; then
fi
fi;
-if [ $STATUS != "success" ]; then
+if [ "$STATUS" != "success" ]; then
echo "CI status is \"$STATUS\""
read -p "Bypass? [y/N] " -n 1 -r
echo
@@ -40,10 +40,10 @@ if [ $STATUS != "success" ]; then
fi
fi;
-git merge -S --no-ff FETCH_HEAD -m "Merge PR #$PR: `curl -s $API/pulls/$PR | jq -r '.title'`" -e
+git merge -S --no-ff FETCH_HEAD -m "Merge PR #$PR: $(curl -s "$API/pulls/$PR" | jq -r '.title')" -e
# TODO: improve this check
-if [[ `git diff $REMOTE/$CURRENT_LOCAL_BRANCH dev/ci` ]]; then
+if ! git diff --quiet "$REMOTE/$CURRENT_LOCAL_BRANCH" -- dev/ci; then
echo "******************************************"
echo "** WARNING: does this PR have overlays? **"
echo "******************************************"
diff --git a/dev/tools/pre-commit b/dev/tools/pre-commit
new file mode 100755
index 0000000000..c9cdee84ab
--- /dev/null
+++ b/dev/tools/pre-commit
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+# configure automatically sets up a wrapper at .git/hooks/pre-commit
+# which calls this script (if it exists).
+
+set -e
+
+if ! git diff --cached --name-only -z | xargs -0 dev/tools/check-eof-newline.sh ||
+ ! git diff-index --check --cached HEAD >/dev/null 2>&1 ;
+then
+ 1>&2 echo "Auto fixing whitespace issues..."
+
+ # We fix whitespace in the index and in the working tree
+ # separately to preserve non-added changes.
+ index=$(mktemp "git-fix-ws-index.XXXXX")
+ fixed_index=$(mktemp "git-fix-ws-index-fixed.XXXXX")
+ tree=$(mktemp "git-fix-ws-tree.XXXXX")
+ 1>&2 echo "Patches are saved in '$index', '$fixed_index' and '$tree'."
+ 1>&2 echo "If an error destroys your changes you can recover using them."
+ 1>&2 echo "(The files are cleaned up on success.)"
+ 1>&2 echo #newline
+
+ git diff-index -p --cached HEAD > "$index"
+ git diff-index -p HEAD > "$tree"
+
+ # reset work tree and index
+ # NB: untracked files which were not added are untouched
+ git apply --cached -R "$index"
+ git apply -R "$tree"
+
+ # Fix index
+ # For end of file newlines we must go through the worktree
+ 1>&2 echo "Fixing staged changes..."
+ git apply --cached --whitespace=fix "$index"
+ git apply --whitespace=fix "$index" 2>/dev/null # no need to repeat yourself
+ git diff --cached --name-only -z | xargs -0 dev/tools/check-eof-newline.sh --fix
+ git add -u
+ 1>&2 echo #newline
+
+ # reset work tree
+ git diff-index -p --cached HEAD > "$fixed_index"
+ # If all changes were bad whitespace changes the patch is empty
+ # making git fail. Don't fail now: we fix the worktree first.
+ if [ -s "$fixed_index" ]
+ then
+ git apply -R "$fixed_index"
+ fi
+
+ # Fix worktree
+ 1>&2 echo "Fixing unstaged changes..."
+ git apply --whitespace=fix "$tree"
+ git diff --name-only -z | xargs -0 dev/tools/check-eof-newline.sh --fix
+ 1>&2 echo #newline
+
+ if ! [ -s "$fixed_index" ]
+ then
+ 1>&2 echo "No changes after fixing whitespace issues!"
+ exit 1
+ fi
+
+ # Check that we did fix whitespace
+ if ! git diff-index --check --cached HEAD;
+ then
+ 1>&2 echo "Auto-fixing whitespace failed: errors remain."
+ 1>&2 echo "This may fix itself if you try again."
+ 1>&2 echo "(Consider whether the number of errors decreases after each run.)"
+ exit 1
+ fi
+ 1>&2 echo "Whitespace issues fixed!"
+
+ # clean up temporary files
+ rm "$index" "$tree" "$fixed_index"
+fi
diff --git a/dev/tools/should-check-whitespace.sh b/dev/tools/should-check-whitespace.sh
deleted file mode 100755
index d85d651070..0000000000
--- a/dev/tools/should-check-whitespace.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env bash
-
-# determine if a file has whitespace checking enabled in .gitattributes
-
-git ls-files --error-unmatch "$1" >/dev/null 2>&1 &&
-git check-attr whitespace -- "$1" | grep -q -v -e 'unset$' -e 'unspecified$'
diff --git a/dev/tools/sudo-apt-get-update.sh b/dev/tools/sudo-apt-get-update.sh
new file mode 100755
index 0000000000..f8bf6bed41
--- /dev/null
+++ b/dev/tools/sudo-apt-get-update.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+(sudo apt-get update "$@" 2>&1 || echo 'E: update failed') | tee /tmp/apt.err
+! grep -q '^\(E:\|W: Failed to fetch\)' /tmp/apt.err || exit $?