commit f3ff3937700b314f56c7810d5e0b1e8592b35dce Author: Yann Esposito (Yogsototh) Date: Mon Aug 19 23:59:22 2019 +0200 Initial commit diff --git a/README.org b/README.org new file mode 100644 index 0000000..d4aaaba --- /dev/null +++ b/README.org @@ -0,0 +1,17 @@ +#+Title: Autoload project.el +#+Author: Yann Esposito +#+Date: [2019-08-19 Mon] + +Autoload securely a =project.el= file when entering a project directory. + +It uses =projectile= package. +When entering a new project, load the =project.el= file at the root of the +project. +To make things safes, it check a =project.el.sig= GPG signature file and +verify the file was signed by one of the +=auto-load-project-trusted-gpg-key-fingerprint=. + +#+begin_src elisp +(setq auto-load-project-trusted-gpg-key-fingerprints + '("000011112222333344445555666677778888")) +#+end_src diff --git a/auto-load-project.el b/auto-load-project.el new file mode 100644 index 0000000..53bb0e3 --- /dev/null +++ b/auto-load-project.el @@ -0,0 +1,73 @@ +;;; auto-load-project.el --- Auto load elisp file on project open + +;; Copyright © 2019 Yann Esposito + +;;; Commentary: +;; + +;;; Code: + +(require 'projectile) + +(defvar auto-load-project-trusted-gpg-key-fingerprints + '() + "The list of GPG fingerprint you trust when decrypting a gpg file. +You can retrieve the fingerprints of your own private keys +with: `gpg --list-secret-keys' (take care of removing the +spaces when copauto-load-project-pasting here)") + +(defun auto-load-project-get-sign-key (file) + "Return the fingerprint of they key that signed FILE. + +To sign a file you should used + +`gpg --local-user my@email --output project.el.sig --detach-sign project.el`" + (string-trim-right + (shell-command-to-string + (concat + "gpg --status-fd 1 --verify" file ".sig " file "2>/dev/null" + "|grep VALIDSIG" + "|awk '{print $3}'")))) + +(defun auto-load-project-trusted-gpg-origin-p (file) + "Return non-nil if the FILE is encrypted with a trusted key." + (member (auto-load-project-get-sign-key file) auto-load-project-trusted-gpg-key-fingerprints)) + + +(defconst auto-load-project-project-file "project.el" + "Project configuration file name.") + +(defun auto-load-project-init-project-el-auto-load () + "Initialize the autoload of project.el for projects." + + (with-eval-after-load 'projectile + + (defvar auto-load-project-loaded-projects (list) + "Projects that have been loaded by `auto-load-project-load-project-file'.") + + (defun auto-load-project-load-project-file () + "Loads the `auto-load-project-project-file' for a project. This is run once + after the project is loaded signifying project setup." + (interactive) + (when (projectile-project-p) + (lexical-let* ((current-project-root (projectile-project-root)) + (project-init-file (expand-file-name auto-load-project-project-file current-project-root))) + (when (and (not (member current-project-root auto-load-project-loaded-projects)) + (file-exists-p project-init-file) + (auto-load-project-trusted-gpg-origin-p project-init-file)) + (message "Loading project init file for %s" (projectile-project-name)) + (condition-case ex + (progn (load project-init-file) + (add-to-list 'auto-load-project-loaded-projects current-project-root) + (message "%s loaded successfully" project-init-file)) + ('error + (message + "There was an error loading %s: %s" + project-init-file + (error-message-string ex)))))))) + (add-hook 'find-file-hook #'auto-load-project-load-project-file t) + (add-hook 'dired-mode-hook #'auto-load-project-load-project-file t))) + +(provide 'auto-load-project) + +;;; auto-load-project.el ends here