summaryrefslogtreecommitdiff
path: root/README.org
blob: 893befd2035978bb0025172dfb3276b2028fdde9 (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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
* My dotfiles
The config files are organized in [[https://www.gnu.org/software/emacs/][emacs]] [[https://orgmode.org/][org mode]] files. They are tangled
and symlinked to the appropriate directories.

[[file:emacs-init.org::tangle-hook][A hook]] tangles all files automatically on each save. In addition there
are shell scripts that tangle all =.org= files at once.

The symlinks can be created by manually running the appropriate [[https://orgmode.org/worg/org-contrib/babel/][babel]]
source block in each configuration file or by running the scripts
below.

** Git Setup
This repository somewhat abuses git branches. Every program's
configuration lives in its own separate branch. All branches are then
merged into =master= using an [[https://git-scm.com/docs/merge-strategies#Documentation/merge-strategies.txt-octopus][octopus merge]]. To keep the git history
clean I reset =master= for every merge. Here is a small script to do
that and push the changes. I mark branches, which I want to keep local
only, with a trailing =+= and then exclude them with the ~+$~ pattern
in grep.

#+begin_src shell :shebang "#!/bin/bash" :tangle tangle/merge.sh
git checkout master
git reset --hard init
git branch -a | grep -v -e +$ -e master | sed "s/[ *] //" | xargs git merge
git push --force origin master
#+end_src

To integrate changes from =origin= perform a rebase instead of merge
to loose the old merge commit but keep any local changes.

#+begin_src shell :shebang "#!/bin/bash" :tangle tangle/pull.sh
git fetch
git rebase origin/master master
#+end_src

** Updating all tangled files
This script (re-)tangles all =.org= and =.org.gpg= files in the
current directory. Run this in case the org files were updated outside
of your local emacs (e.g. after pulling from a remote). Make sure to
run it from the dotfiles directory.

#+begin_src shell :shebang "#!/bin/bash" :tangle no
emacs --batch --eval="\
  (progn (require 'org)
         (let ((org-confirm-babel-evaluate nil))
           (mapc 'org-babel-tangle-file (split-string \"$(ls *.org *.org.gpg)\"))))"
#+end_src

The above won't quite work for me as I use [[https://orgmode.org/worg/org-tutorials/encrypting-files.html#org697961a][org-crypt]] in some
configuration files and it also needs to be loaded & setup. For
details see [[file:emacs-init.org::org-crypt-tangle-setup][emacs-init.org]].

#+begin_src shell :shebang "#!/bin/bash" :tangle tangle/tangle.sh
emacs --batch --eval="\
  (progn (require 'org)
         (require 'org-crypt)
         (org-crypt-use-before-save-magic)
         (setq org-tags-exclude-from-inheritance '(\"crypt\"))
         (setq org-crypt-key \"F1EF502F9E81D81381B1679AF973BBEA6994521B\")
         (defun save-without-hook ()
           (let ((before-save-hook nil))
             (save-buffer)))
         (setq org-babel-pre-tangle-hook '(org-decrypt-entries save-without-hook))
         (advice-add 'org-babel-tangle :after '(lambda (&rest r)
                                                 (org-encrypt-entries)
                                                 (save-without-hook)))
         (let ((org-confirm-babel-evaluate nil))
           (mapc 'org-babel-tangle-file (split-string \"$(ls *.org *.org.gpg)\"))))"
#+end_src

** Creating symlinks
Each config files contains a source block which creates symlinks of
the tangled configurations to their respective target locations. These
blocks all have the ~:tangle tangle/symlink.sh~ and ~:shebang
#!/bin/bash~ header arguments. The symlinks are created with ~ln -siv~
to list created symlinks (~-v~) and to ask when overwriting existing
files (~-i~). To always replace all symlinks you can pipe ~yes~ into
the ~ln -siv~ calls: ~yes | tangle/link.sh~. Make sure to run it from
the dotfiles directory.

As the symlink shell source blocks are scattered in all configuration
files, all files are collected together using ~cat~ and then all blocks
with the correct ~:tangle~ target are tangled. Unfortunately there is
no function to directly only tangle blocks with a certain target, so
this is not straightforward.
#+begin_src shell :shebang "#!/bin/bash" :tangle tangle/link.sh
catFile="concat.org"
symlinkFile="tangle/symlink.sh"

cat <(cat *.org) <(ls *.org.gpg | xargs gpg --decrypt) > $catFile

emacs --batch --eval="\
  (progn (require 'org)
         (let ((org-confirm-babel-evaluate nil))
           (find-file \"$catFile\")
           (search-forward \":tangle $symlinkFile\")
           (org-babel-tangle '(16))))"

rm $catFile

$symlinkFile
#+end_src

** =dots= script
I place this script in my =PATH= to execute commands in the dotfiles
directory from anywhere.

#+begin_src shell :shebang "#!/bin/bash" :tangle tangle/dots.sh
cd ~/git/projects/dotfiles
$@
#+end_src

Create a symlink for this script.

#+BEGIN_SRC sh :tangle tangle/symlink.sh :results silent :shebang "#!/bin/bash"
ln -siv $(pwd)/tangle/dots.sh ~/.local/bin/dots
#+END_SRC