code:
# -*- mode: sh -*-

################################################################
### Environment

MY_GUIX_PROFILE_NAMES="main build misc guile games fonts emacs"

export MY_CONFIG_DIR="$HOME/config"
export MY_GUILE_DIR="$MY_CONFIG_DIR/guile"
export MY_GUIX_DIR="$MY_CONFIG_DIR/guix"
export MY_SHELL_DIR="$MY_CONFIG_DIR/shell"
export MY_PATH="$HOME/bin:$MY_GUILE_DIR/scripts:$MY_SHELL_DIR/scripts:$MY_CONFIG_DIR/guile-daemon/scripts"

export MY_GUIX_PROFILES_DIR="$HOME/.guix-profiles"
export MY_GUIX_USER_PROFILE_DIR="$MY_GUIX_PROFILES_DIR/main/main"
export MY_GUIX_SYSTEM_PROFILE_DIR="/run/current-system/profile"

add_dir_to_var_if_exists () {
    # Add directory $1 (if it exists) to environment variable $2.
    [ -d "$1" ] && eval $(echo "$2=$1:\$$2")
}

display_file_if_exists () {
    [ -a "$1" ] && echo "$1"
}

display_guix_profiles_paths () {
    for name in $MY_GUIX_PROFILE_NAMES
    do
        display_file_if_exists "$MY_GUIX_PROFILES_DIR/$name/$name"
    done
    display_file_if_exists "$MY_GUIX_SYSTEM_PROFILE_DIR"
}

set_guix_env () {
    # Calculate environment for all Guix profiles and add it to the
    # current environment.
    guix=$(PATH="$MY_PATH:$PATH" which guix)
    if [ $? -eq 0 ]; then   # if 'guix' executable is found
        env_cmd="$guix package --search-paths=prefix"
        for path in $(display_guix_profiles_paths)
        do
            env_cmd="$env_cmd --profile=$path"
            # XXX Currently XDG_... variables are not set by 'guix
            # package --search-paths' command, so handle them manually.
            add_dir_to_var_if_exists "$path/share" xdg_data_dirs
            add_dir_to_var_if_exists "$path/etc/xdg" xdg_config_dirs
        done
        export XDG_DATA_DIRS="$xdg_data_dirs$XDG_DATA_DIRS"
        export XDG_CONFIG_DIRS="$xdg_config_dirs$XDG_CONFIG_DIRS"
        echo "Running: $env_cmd"
        eval $($env_cmd)
    fi
}

locale_dir="$MY_GUIX_PROFILES_DIR/locales/locales/lib/locale"
[ -d "$locale_dir" ] && export GUIX_LOCPATH="$locale_dir"
export LANG=en_US.UTF-8

# Set some variables to default values if needed.
[ ! -v MANPATH ] && [ -d /usr/share/man ] && export MANPATH=/usr/share/man
[ ! -v XDG_DATA_DIRS ] && [ -d /usr/share ] && export XDG_DATA_DIRS=/usr/share
[ ! -v XDG_CONFIG_DIRS ] && [ -d /etc/xdg ] && export XDG_CONFIG_DIRS=/etc/xdg

set_guix_env

if [ -d $MY_GUIX_SYSTEM_PROFILE_DIR ]; then   # if it is GuixSD
    export PATH="/run/setuid-programs:$PATH"
fi

if [ -d $MY_GUIX_USER_PROFILE_DIR ]; then
    # Find GTK themes.
    export GTK_DATA_PREFIX="$MY_GUIX_USER_PROFILE_DIR"

    # Without this, other git outputs (like 'send-email') wouldn't work.
    export GIT_EXEC_PATH="$MY_GUIX_USER_PROFILE_DIR/libexec/git-core"

    aspell_dir="$MY_GUIX_USER_PROFILE_DIR/lib/aspell"
    if [ -d $aspell_dir ]; then
        # export ASPELL_CONF="data-dir $aspell_dir; dict-dir $aspell_dir"
        export ASPELL_CONF="dict-dir $aspell_dir"
    fi
fi

certs_dir=/var/guix/profiles/system/profile/etc/ssl/certs
if [ -d "$certs_dir" ]; then
    export SSL_CERT_DIR="$certs_dir"
    export SSL_CERT_FILE="$certs_dir/ca-certificates.crt"
    export GIT_SSL_CAINFO="$SSL_CERT_FILE"
fi

export PATH="$MY_PATH:$PATH"
export SSH_AUTH_SOCK="$HOME/.gnupg/S.gpg-agent.ssh"
export GUIX_PACKAGE_PATH="$MY_GUIX_DIR/guix-package-path"

misc_guile_dirs="$MY_GUILE_DIR/modules:$MY_GUIX_DIR/modules:$HOME/devel/guix:$HOME/devel/shepherd/modules"
export GUILE_LOAD_PATH="$misc_guile_dirs${GUILE_LOAD_PATH:+:}$GUILE_LOAD_PATH"
export GUILE_LOAD_COMPILED_PATH="$misc_guile_dirs${GUILE_LOAD_COMPILED_PATH:+:}$GUILE_LOAD_COMPILED_PATH"

export EDITOR='emacsclient'
export VIEWER='emacsclient'

export XDG_CONFIG_HOME="$HOME/.config"
export XDG_CACHE_HOME="$HOME/.cache"
export XDG_DATA_HOME="$HOME/.local/share"

# Always show normal scrollbars.
export GTK_OVERLAY_SCROLLING=0

# Prevent sox from using pulseaudio.
export AUDIODRIVER=alsa
# Without this, there is no sound in programs (usually games) that use
# sdl-mixer (at least on GuixSD).
export SDL_AUDIODRIVER=alsa

################################################################

[[ -f ~/.bashrc ]] && . ~/.bashrc

# Start shepherd if it is not already running.
[[ -z $(pgrep -U $(id --user) "^shepherd$") ]] \
    && shepherd &>> $HOME/.config/shepherd/shepherd.log

path: bash/user-profile


code:
#!/bin/sh

# Original source: <https://gist.github.com/naelstrof/6530959>.

IMAGE_DIR="$HOME/tmp/screenshots/"
VIDEO_DIR="$HOME/tmp/screenshots/"
IMAGE_ENCODING=".png"
VIDEO_ENCODING=".webm"
IMAGE_SND="$HOME/docs/audio/small/screen-capture.oga"
VIDEO_SND="$HOME/docs/audio/small/complete.oga"
SLOP_IMAGE="slop --nodecorations --bordersize 3 --color 0,1,0"  # green
SLOP_VIDEO="slop --nodecorations --bordersize 5 --color 1,0,0"  # red
PID_FILE="/tmp/capture_record.pid"
PLAY="play --no-show-progress"

case "$1" in
    desktop)
        name="${IMAGE_DIR}$(date +%F_%T)${IMAGE_ENCODING}"
        maim "$name"
        $PLAY "$IMAGE_SND"
        ;;
    image)
        eval $($SLOP_IMAGE)
        [ "${Cancel}" = "true" ] && exit 0
        name="${IMAGE_DIR}$(date +%F_%T)${IMAGE_ENCODING}"
        maim --hidecursor --geometry $G "$name"
        $PLAY "$IMAGE_SND"
        ;;
    video)
        if [ -f "$PID_FILE" ]; then
            # Finish recording.
            pid=$(cat "$PID_FILE")
            kill ${pid}
            rm "$PID_FILE"
            $PLAY "$VIDEO_SND"
        else
            # Start recording.
            eval $($SLOP_VIDEO)
            [ "${Cancel}" = "true" ] && exit 0
            name="${VIDEO_DIR}$(date +%F_%T)${VIDEO_ENCODING}"
            # Populate PID_FILE when recording begins using "&" and "$!".
            ffmpeg -f x11grab \
                   -s "${W}x${H}" -i "+${X},${Y}" \
                   "$name" &
            pid=$!
            echo -n "$pid" > "$PID_FILE"
        fi
        ;;
    *)
        echo "Usage: $0 {desktop|image|video}"
        exit 1
        ;;
esac

repo_name: alezost/shell

path: scripts/capture

license: mit


code:
#!/bin/sh

# Original source:
# <http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html>.

# This file echoes a bunch of color codes to the terminal to demonstrate
# what's available.  Each line is the color code of one forground color,
# out of 17 (default + 16 escapes), followed by a test use of that color
# on all nine background colors (default + 8 escapes).

TEST_TEXT='gYw'

echo -e "\n                 40m     41m     42m     43m\
     44m     45m     46m     47m";

for FGs in '    m' '   1m' '  30m' '1;30m' '  31m' '1;31m' '  32m' \
           '1;32m' '  33m' '1;33m' '  34m' '1;34m' '  35m' '1;35m' \
           '  36m' '1;36m' '  37m' '1;37m';
do FG=${FGs// /}
  echo -en " $FGs \033[$FG  $TEST_TEXT  "
  for BG in 40m 41m 42m 43m 44m 45m 46m 47m;
  do echo -en "$EINS \033[$FG\033[$BG  $TEST_TEXT  \033[0m";
  done
  echo;
done
echo

path: scripts/colors


code:
#!/bin/sh

INI=$HOME/src/conkeror/application.ini

# Use icecat on GuixSD.
if [ -d "/run/current-system" ]; then
    PROG='icecat --app'
else
    # PROG='xulrunner'
    PROG='firefox --app'
fi

$PROG $INI "$@" &> /dev/null

path: scripts/conkeror


code:
#!/bin/sh

conkeror -no-remote -P tor "$@"

path: scripts/conkeror-tor


code:
#!/bin/sh

# Copyright © 2012 Alex Kost

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

DirCheck() {
    if [ ! -d "$1" ]; then
        echo "$1 - is not a directory"
        exit 1
    fi
}

DirCheck "$1"
DirCheck "$2"

# Getting destination variable and moving to the source directory.
pushd "$2" > /dev/null
dest=$(pwd)
popd > /dev/null
cd "$1"
source=$(pwd)

echo "COPYING \"$source\" INTO \"$dest\""
dest=$dest/$(basename "$source")

echo -e "\n---- Making directory structure"
mkdir -v "$dest"
find . -type d | sed 1d | sort | xargs -I === mkdir -v "$dest/==="

filesAmount=$(find . -type f | wc -l)
echo -e "\n---- Copying files (total $filesAmount):"
num=0

# TODO Do not hardcode "mp3"; make a script option to pass to "find".
find . -type f -name '*.mp3' | sort | while read fl
do
    let num+=1 #num=$(($num+1))
    echo "($num of $filesAmount):  $dest/$fl"
    cp "$fl" "$dest/$fl"
done

echo -e "\nThe job has been done."

path: scripts/copyinorder


code:
#!/bin/sh

#### HELP MESSAGE ##############################################
hlp='Usage: emacs-eval arg
Evaluate ARG as an Emacs Lisp expression (using "emacsclient --eval").
Activate Emacs if it is not activated.'

if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
    echo "$hlp"
    exit 0
fi
################################################################

emacsclient --eval "$1" &
wmctrl -ia $(emacsclient --eval "(string-to-number (frame-parameter nil 'outer-window-id))")

# # this variant shows the first emacs frame and it is very slow process -
# # it would be better to define the active window by a C prog (using Xlib)
# #if [ -z "$(xprop -id $(xprop -root | awk '/^_NET_ACTIVE_WINDOW/ { print $5; exit }') | grep 'WM_CLASS' | grep --only-matching 'emacs')" ]; then
# if [ -z $(xprop -id $(xdotool getactivewindow) | grep 'WM_CLASS' | grep --only-matching 'emacs') ]; then
#     wmctrl -xa emacs
# fi

path: scripts/emacs-eval


code:
#!/bin/sh

guild compile \
      -Wunbound-variable -Wunused-variable \
      -Wformat -Warity-mismatch "$@"

path: scripts/guile-compile


code:
#!/bin/sh

$HOME/devel/guix/pre-inst-env guix "$@"

path: scripts/guix


code:
#!/bin/sh

find /gnu/store -name "*$1*"

path: scripts/guix-find


code:
#!/bin/sh

find /gnu/store -maxdepth 1 -name "*$1*"

path: scripts/guix-find-simple


code:
#!/bin/sh

# Copyright © 2013 Alex Kost

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

#### HELP MESSAGE ##############################################
hlp='Usage: ln-dir SOURCE DESTINATION
Make "hard link to a directory", i.e. create a whole directory structure
for SOURCE dir in DESTINATION dir and make hard links for all files in
new directories.'

if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
    echo "$hlp"
    exit 0
fi
################################################################

Dir_Check()
{
    if [ ! -d "$1" ]; then
        echo "$1 - is not a directory"
        exit 1
    fi
}

Dir_Check "$1"
Dir_Check "$2"

# set source and destination vars and move to source dir
dest=$(cd "$2"; pwd)
cd "$1"
source=$(pwd)

echo "HARDLINKING \"$source\" INTO \"$dest\""
dest=$dest/$(basename "$source")

echo -e "\n---- Making directory structure"
mkdir -v "$dest"
find . -mindepth 1 -type d | xargs -I === mkdir -v "$dest/==="

echo -e "\n---- Making hard links"
find . -type d | \
while read dir; do
    ln -v "$dir"/* "$dest/$dir" 2> /dev/null
done

path: scripts/ln-dir


code:
#!/bin/sh

# Original source:
# <http://blog.gonzih.me/blog/2012/02/17/how-to-use-magnet-links-with-rtorrent/>.

DIR="${HOME}/downloads/_torrents/misc"

[[ -d "$DIR" ]] || mkdir --parents "$DIR"

[[ "$1" =~ xt=urn:btih:([^&/]+) ]] || exit;
FILE="${DIR}/meta-${BASH_REMATCH[1]}.torrent"
echo "d10:magnet-uri${#1}:${1}e" > "$FILE"
notify-send "Magnet link downloaded" "$FILE"


code:
#!/bin/sh

# Copyright © 2014 Alex Kost

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Idea is taken from <https://wiki.archlinux.org/index.php/DPMS>.

usage () {
    echo 'Usage: monitor blank|standby|suspend|off|on
"monitor blank" is the same as "xset s activate".
Other keys are equivalents of "xset dmps force …".'
}

case "$1" in
    blank)
        sleep 1
        xset s activate
        ;;
    standby | suspend | off | on)
        sleep 1
        xset dpms force $1
        ;;
    *)
        usage
        ;;
esac

path: scripts/monitor


code:
#!/bin/sh

# Copyright © 2013 Alex Kost

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

#### HELP MESSAGE ##############################################
hlp='Usage: mute
Toggle the sound on or off (mute/unmute).'

if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
    echo "$hlp"
    exit 0
fi
################################################################

## PulseAudio
# amixer get Master | grep -o '\[off\]' > /dev/null
# # if exit status after grep is 0/1 then the sound is off/on
# pactl set-sink-mute 0 $(echo $?)

## Alsa
STATE=$(amixer get Master | grep -o '\[o.*\]' | sed -n 1p)
if [ $STATE == '[on]' ]; then
    amixer -q set Master mute
else
    for ELEMENT in Master Headphone PCM
    do
	amixer -q set $ELEMENT unmute
    done &>/dev/null
fi

path: scripts/mute


code:
#!/bin/sh

# Copyright © 2012 Alex Kost

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

#### HELP MESSAGE ##############################################
hlp='Usage: run-or-focus APP_NAME [APP_CLASS]
Set focus on application APP_CLASS (recognized by wmctrl) or run
APP_NAME if it does not exist.
If APP_CLASS is not specified, use APP_NAME (case is ignored)'

if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
    echo "$hlp"
    exit 0
fi
################################################################

app_exec=$1
if [ -z "$2" ]; then
    app_wm_class=$app_exec
else
    app_wm_class=$2
fi

if [ -z "$(wmctrl -xl | grep -i $app_wm_class)" ]; then
    $app_exec &
else
    wmctrl -x -a $app_wm_class
fi

path: scripts/run-or-focus


code:
#!/bin/sh

herd stop root
sleep 2
# Use 'halt' on GuixSD.
if [ -d "/run/current-system" ]; then
    sudo /run/current-system/profile/sbin/halt
else
    systemctl poweroff
fi

path: scripts/shutdown


code:
#!/bin/sh

sleep 1 # to move the hands away from keyboard
if [ -d "/run/current-system" ]; then  # if GuixSD
    sudo /run/current-system/profile/bin/suspend
else
    systemctl suspend
fi

path: scripts/suspend


code:
#!/bin/sh

name=$(xinput list --name-only | grep Touchpad)

xinput set-prop "$name" "Device Enabled" \
       $(xinput --list-props "$name" | grep -c 'Device Enabled.*0')

path: scripts/toggle-touchpad


code:
#!/bin/sh

# Copyright © 2012-2016 Alex Kost

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

LOGPATH="$HOME/.turnoff_log"
SHUTDOWN=no
CONKEROR=no
TVTIME=no
EMACS=no
EMMS=no

usage () {
    echo 'Usage: turnoff [OPTION ...] [TIME]
Switch to VT11 or shut down the computer with some preparations.

Options:
  -h, --help                    display help and exit;
  -s, --shutdown [KEY]          shutdown (otherwise switch to VT11);
  -c, --conkeror [KEY]          close conkeror;
  -t, --tvtime [KEY]            close tvtime.
  -e, --emacs [KEY]             close emacs;
  -m, --emms [KEY]              stop EMMS;
  -a, --all                     enable all the above keys (close everything).

KEY is an optional argument: can be "yes" or "no" (default: "yes").

TIME can be in any format, supported by GNU "date" function.'
}

TEMP=`getopt -o has::c::t::e::m:: \
             -l help,all,shutdown::,conkeror::,tvtime::,emacs::,emms:: \
             -n turnoff -- "$@"`
eval set -- "$TEMP"

while true; do
    case "$1" in
	-h | --help)
            usage
            exit 0 ;;
        -a | --all)
            SHUTDOWN=yes
            CONKEROR=yes
            TVTIME=yes
            EMACS=yes
            EMMS=yes
            shift ;;
	-s | --shutdown)
            case "$2" in
		"") SHUTDOWN=yes ; shift 2 ;;
		*) SHUTDOWN="$2" ; shift 2 ;;
	    esac ;;
        -c | --conkeror)
            case "$2" in
		"") CONKEROR=yes ; shift 2 ;;
		*) CONKEROR="$2" ; shift 2 ;;
	    esac ;;
        -t | --tvtime)
            case "$2" in
		"") TVTIME=yes ; shift 2 ;;
		*) TVTIME="$2" ; shift 2 ;;
	    esac ;;
        -e | --emacs)
            case "$2" in
		"") EMACS=yes ; shift 2 ;;
		*) EMACS="$2" ; shift 2 ;;
	    esac ;;
        -m | --emms)
            case "$2" in
		"") EMMS=yes ; shift 2 ;;
		*) EMMS="$2" ; shift 2 ;;
	    esac ;;
	--)
            shift
            break ;;
	*)
            echo "Internal error!"
            exit 1 ;;
    esac
done

if [ -z "$1" ]; then
    DEADLINE=now
    SECONDS=0
else
    DEADLINE="$1"
    SECONDS=$(( $(date --date="$DEADLINE" +%s) - $(date +%s) ))
fi

echo "shutdown: $SHUTDOWN"
echo "conkeror: $CONKEROR"
echo "tvtime:   $TVTIME"
echo "emacs:    $EMACS"
echo "emms:     $EMMS"

echo "---------------- $(date) ----------------" | tee -a "$LOGPATH"
echo 'Computer will be turned off at "'$(date --date="$DEADLINE")\" | tee -a "$LOGPATH"
echo "Sleeping for $SECONDS seconds..." | tee -a "$LOGPATH"
sleep $SECONDS

if [ $EMMS == "yes" ]; then
    emacsclient --socket-name=server-emms --eval '(emms-stop)'
    echo 'EMMS has been stopped ('$(date)')' | tee -a "$LOGPATH"
    sleep 1
fi

if [ $EMACS == "yes" ]; then
    wmctrl -x -c emacs
    echo 'Closing emacs... ('$(date)')' | tee -a "$LOGPATH"
    sleep 1
fi

if [ $CONKEROR == "yes" ]; then
    wmctrl -x -c conkeror
    echo 'Closing conkeror... ('$(date)')' | tee -a "$LOGPATH"
    sleep 1
fi

if [ $TVTIME == "yes" ]; then
    tvtime-command quit
    echo 'Closing tvtime... ('$(date)')' | tee -a "$LOGPATH"
    sleep 1
fi

if [ $SHUTDOWN == "yes" ]; then
    echo -e 'Shutting down now... ('$(date)')'"\n" | tee -a "$LOGPATH"
    shutdown now
else
    echo -e 'Switching to VT11 ('$(date)')'"\n" | tee -a "$LOGPATH"
    sudo chvt 11
fi

path: scripts/turnoff


code:
#!/bin/sh

# Copyright © 2013 Alex Kost

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

#### HELP MESSAGE ##############################################
hlp='Usage: tvguide-refresh
Download TV guide and put it into a right place.'

if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
    echo "$hlp"
    exit 0
fi
################################################################

guide_url='http://www.teleguide.info/download/new3/xmltv.xml.gz'
backup_dir="$HOME/.tvtime/tvguide"
guide_full="${backup_dir}/current_full.xml"
guide_short="${backup_dir}/current_short.xml"

# Day of Monday of the current week.
date_part=$(date --date="$([ 1 -ne $(date +%u) ] && echo last) Monday" '+%Y-%m-%d')
guide_name="xmltv_${date_part}.xml.gz"
guide_path="${backup_dir}/${guide_name}"

if [ -f "$guide_path" ]; then
    echo "File '$guide_path' exists.  Update has not been made."
    exit 0
fi
wget -O "$guide_path" "$guide_url"
gunzip --stdout "$guide_path" > "$guide_full"
tvguide.py "$guide_full" "$guide_short"

path: scripts/tvguide-refresh


code:
#!/bin/sh

runbut tvtime-command "${BASH_SOURCE[0]}" -- "$@" &>> /dev/null

path: scripts/tvtime-command


code:
#!/bin/sh

readlink --canonicalize $(which "$1")

path: scripts/where


code:
#!/bin/sh

xsane mustek_usb:libusb

path: scripts/xsane-mustek


code:
VARIABLES

Global Constants

  - declared outside of any functions in the CONSTANTS section
  - CAPITALIZED so their nature is obvious

Global Variables

  -- declared inside love.load()
  -- usually have an _underscore in the name

Local Variables

  - should be declared within a function or function header
  - are always lowercase

repo_name: ericxdu/spykes


code:
* Spykes
Simple platform game. Touch screen left or right to jump to the next platform If you touch the spikes you die. Have fun!

* Running the game
This game requires [[https://www.lua.org][lua]]  and [[https://love2d.org][love2d]] (version 11+ required), in most GNU/Linux distributions you can just do:

#+BEGIN_SRC
$ sudo apt install love
#+END_SRC

#+BEGIN_SRC
$ sudo dnf install love
#+END_SRC

Once you have installed the dependencies just git clone and run the game:

#+BEGIN_SRC
$ git clone https://notabug.org/ericxdu/spykes.git
$ love spykes
#+END_SRC

If you want to be inside the =spykes= directory then run:

#+BEGIN_SRC
$ cd spykes
$ love .
#+END_SRC

* Licensing
Spykes is a [[https://www.gnu.org/philosophy/free-sw.en.html][Free Software]]  game. The source code is available under the GPL v3 license, and all the artwork is either public domain or released under a variety of Creative Commons licenses. (To determine the copyright status of any of the artwork, consult the copyright file.)


code:
Song: Jump and Run - Tropical Mix
Author: bart
License(s): GPLv2, GPLv3, CC-BY 3.0, CC-BY-SA 3.0
URL: https://opengameart.org/content/jump-and-run-tropical-mix
============================================================
Sound: Jump Landing
Author: Macro (Dan Knoflicek)
License: CC0
URL: https://opengameart.org/content/jump-landing
============================================================
Art: Jump Game
Author: JanaChumi
License(s): GPLv2, GPLv3, CC-BY 3.0, CC-BY-SA 3.0
URL: https://opengameart.org/content/jump-game-0
============================================================
Font: COMPUTER SPEAK
Designer: Mcguy215
License: CC-BY 3.0
URL: https://fontlibrary.org/en/font/computer-speak
============================================================


code:
--[[=======================
            LICENSE
    This file is GPLv3.
    Praise our lord and saviour RMS
========================= ]]
--[[=======================
            CONSTANS
   ========================= ]]
SONG_TYPE = "stream"
SONG_FILE = "art/jump_and_run_tropics.ogg"
SONG = love.audio.newSource(SONG_FILE, SONG_TYPE)
FONT_SIZE = 40
FONT_FILE = "art/computer_speak_v0.3.ttf"
FONT_COMPUTER = love.graphics.newFont(FONT_FILE, FONT_SIZE)
WINDOW_HEIGHT = 730
WINDOW_WIDTH  = 600
WINDOW_TITLE = "Spykes"

BACKGROUND_IMAGE = "art/jumpGame_ByJanaChumi/assets/bg3.png"
BACKGROUND_X = 0
BACKGROUND_Y = 0

PLATFORM_IMAGE = "art/jumpGame_ByJanaChumi/assets/plat1.png"
SPIKE_IMAGE   = "art/jumpGame_ByJanaChumi/assets/espinho.png"

SCORE_TEXT = "SCORE "
SCORE_COLOR = {0.8627450980392157, 0.6745098039215687, 0.39215686274509803}
SCORE_FONT_SIZE = "SCORE "
SCORE_X = 250
SCORE_Y = 50

LAND = "land"
AIR = "air"
GAMEOVER = "game-over"
BEGIN = "begin"

ESC_KEY = "escape"

function love.load()
    -- LOVE DEFAULTS
    love.audio.play(SONG)
    love.window.setMode(WINDOW_HEIGHT, WINDOW_WIDTH)
    love.window.setTitle(WINDOW_TITLE)
    -- LOVE CONSTANTS
    BACKGROUND_IMG = love.graphics.newImage(BACKGROUND_IMAGE)
    PLATFORM_IMG = love.graphics.newImage(PLATFORM_IMAGE)
    SPIKE_IMG = love.graphics.newImage(SPIKE_IMAGE)

    -- LOVE VARIABLES
    platform_num = 4
    gap = 160

    player_status = LAND
    player_position = LEFT
    player = {player_status, player_position}

    time = 0
    position = 0
    scroll = 0  -- pixel amount that the platforms are scrolled downward
    bscroll = 0  -- pixel amount background is scrolled downward
    scrolling = false  -- whether the screen is scrolling
    scrollspeed = 320
    spikes = {}
    createSpikes(spikes, platform_num)
    game = {time, position, spikes, player}  -- Deprecated: remove after game_state is implemented
    -- Global state variables
    -- TODO: a lot of the above variables are global and should be moved
    -- into the following
    finite_state = BEGIN
    score = 0
    world_state = {position}
    game_state = {finite_state, score, world_state}
end

--[[=======================
            LOGIC
========================= ]]
-- Produces a random position
-- -> LEFT or RIGHT
function randomPosition()
    local LEFT = 100  -->FIX THIS, should be global?
    local RIGHT = 500 -->FIX THIS, should be global?
    local n = math.random(0,1)
    if n == 0 then
        return LEFT
    else
        return RIGHT
    end
end

-- time deltaTime --> time
-- produces new time
function deltaTime(t, dt)
    local total = t + dt
    if total > 800 then  --> FIX THIS should be constant, what does 800 mean?
        return 0         --> FIX THIS should be constant, what does 0 mean?
    else
        return total
    end
end

-- spikes_table number -> spikes_table
-- outputs an spikes_table with spikes at random position
function createSpikes(spikes, platform_num)
    for i=0,platform_num do
        spikes[i] = randomPosition()
    end
    return spikes
end

-- table of spikes -> tablo of spikes
-- adds a new spike at the end
function newSpike(spikes, platform)
    local spike = randomPosition()
    spikes[platform] = spike
    return spikes
end

-- table of spikes -> table of spikes
-- removes first spike
function removeSpike(spikes, platform)
    spikes[platform] = nil
    return spikes
end

-- position delta_time -> position
-- outputs new position for platforms and background
function scrollGame(scroll, dt)
    local PLATHEIGHT = 20
    local scroll = scroll + (scrollspeed*dt)
    local bscroll = bscroll + (scrollspeed*dt)
    local width, height = love.graphics.getDimensions()  --> FIX THS, should this use the GLOBAL variables WIDTH and HEIGHT?
    --if scroll > height then
    --    scroll = -PLATHEIGHT
    --end
    if bscroll > height then
        bscroll = 0
    end
    return scroll, bscroll
end

-- position -> platforms ??
-- what does this function do?
function getPlatforms(scroll)
    local platforms = {}  -- FIX this should be local?? local platforms = {}
    for i=1,platform_num do
        local platformY = scroll+((i-1)*gap)
        table.insert(platforms, platformY)
    end
    return platforms
end

-- spikes index -> spikeX
-- what does this function do?
function getSpike(spikes, index)
    local spikeX = -1000       --> FIX THIS, should be constant? what does -1000 mean?
    local spikeX = spikes[index]
    return spikeX
end

-- delta time -> game
-- creates new game state
function love.update(dt)
    local width, height = love.graphics.getDimensions()
    t = deltaTime(game[1], dt)
    -- print(t)
    spikes = game[3]
    if scrolling then
        scroll, bscroll = scrollGame(scroll, dt)
        local p = getPlatforms(scroll)
        lastplat = p[#p]
        if lastplat > height then  -- TODO: this should be handled in scrollGame() probably
            scrolling = false
            scroll = scroll - gap
            --removeSpike(spikes, #p)
            --newSpike(spikes, 0)
        end
    end
end
--[[=======================
                MOVE PLAYER
========================= ]]

function movePlayer(player)
    if player[1] == LAND then
        getNextPosition(player)
    else
        return(player)
    end
end

--[[=======================
          EVENTS
   ========================= ]]
-- key -> event
-- handles key events
function love.keypressed(key)
    if key == ESC_KEY then
        love.event.quit()
    end
end

function love.mousepressed(x, y, button)
    --scroll = scroll + 1
    scrolling = true
end

--[[=======================
          DRAW
   ========================= ]]
-- spikes position --> image
-- outputs image of spikes
function drawSpikes(spikes, scroll)
    for i,platformY in ipairs(getPlatforms(scroll)) do
        local spikeX = getSpike(spikes, i)
        local spikeY = platformY - SPIKE_IMG:getHeight()
        love.graphics.draw(SPIKE_IMG, spikeX, spikeY)
    end
end

-- position --> image
-- outputs image of platforms
function drawPlatforms(scroll)
    local LINE = "line"
    local PLATWIDTH = 200
    local PLATHEIGHT = 20
    local PLATLEFT = 50
    local PLATRIGHT = 450
    for i,platformY in ipairs(getPlatforms(scroll)) do
        love.graphics.rectangle(LINE, PLATLEFT, platformY,
            PLATWIDTH, PLATHEIGHT)
        love.graphics.rectangle(LINE, PLATRIGHT, platformY,
            PLATWIDTH, PLATHEIGHT)
    end
end

function drawBackground(scroll)
    local width, height = love.graphics.getDimensions()
    local iwidth, iheight = love.graphics.getDimensions(BACKGROUND_IMG)
    local sx = width/iwidth
    local sy = height/iheight
    local r = 0  -- no rotation
    local scroll1 = scroll-iheight
    local scroll2 = scroll
    love.graphics.draw(BACKGROUND_IMG, BACKGROUND_X, scroll1, r, sx, sy)
    love.graphics.draw(BACKGROUND_IMG, BACKGROUND_X, scroll2, r, sx, sy)
end

function love.draw()
    -- draw game
    drawBackground(bscroll)
    drawPlatforms(scroll)
    drawSpikes(spikes, scroll)
    love.graphics.setFont(FONT_COMPUTER)
    love.graphics.print({SCORE_COLOR, SCORE_TEXT, score}, SCORE_X, SCORE_Y)
end


code:
;; Per-directory local variables for GNU Emacs 23 and later.

((nil
  . ((fill-column . 78)
     (tab-width   .  8)
     (sentence-end-double-space . t)

     ;; For use with 'bug-reference-prog-mode'.
     (bug-reference-url-format . "http://bugs.gnu.org/%s")
     (bug-reference-bug-regexp
      . "<https?://\\(debbugs\\|bugs\\)\\.gnu\\.org/\\([0-9]+\\)>")))
 (c-mode          . ((c-file-style . "gnu")))
 (scheme-mode
  .
  ((indent-tabs-mode . nil)
   (eval . (put 'eval-when 'scheme-indent-function 1))
   (eval . (put 'call-with-prompt 'scheme-indent-function 1))
   (eval . (put 'test-assert 'scheme-indent-function 1))
   (eval . (put 'test-assertm 'scheme-indent-function 1))
   (eval . (put 'test-equalm 'scheme-indent-function 1))
   (eval . (put 'test-equal 'scheme-indent-function 1))
   (eval . (put 'test-eq 'scheme-indent-function 1))
   (eval . (put 'call-with-input-string 'scheme-indent-function 1))
   (eval . (put 'guard 'scheme-indent-function 1))
   (eval . (put 'lambda* 'scheme-indent-function 1))
   (eval . (put 'substitute* 'scheme-indent-function 1))
   (eval . (put 'match-record 'scheme-indent-function 2))

   ;; 'modify-phases' and its keywords.
   (eval . (put 'modify-phases 'scheme-indent-function 1))
   (eval . (put 'replace 'scheme-indent-function 1))
   (eval . (put 'add-before 'scheme-indent-function 2))
   (eval . (put 'add-after 'scheme-indent-function 2))

   (eval . (put 'modify-services 'scheme-indent-function 1))
   (eval . (put 'with-directory-excursion 'scheme-indent-function 1))
   (eval . (put 'package 'scheme-indent-function 0))
   (eval . (put 'origin 'scheme-indent-function 0))
   (eval . (put 'build-system 'scheme-indent-function 0))
   (eval . (put 'bag 'scheme-indent-function 0))
   (eval . (put 'graft 'scheme-indent-function 0))
   (eval . (put 'operating-system 'scheme-indent-function 0))
   (eval . (put 'file-system 'scheme-indent-function 0))
   (eval . (put 'manifest-entry 'scheme-indent-function 0))
   (eval . (put 'manifest-pattern 'scheme-indent-function 0))
   (eval . (put 'substitute-keyword-arguments 'scheme-indent-function 1))
   (eval . (put 'with-store 'scheme-indent-function 1))
   (eval . (put 'with-error-handling 'scheme-indent-function 0))
   (eval . (put 'with-mutex 'scheme-indent-function 1))
   (eval . (put 'with-atomic-file-output 'scheme-indent-function 1))
   (eval . (put 'call-with-compressed-output-port 'scheme-indent-function 2))
   (eval . (put 'call-with-decompressed-port 'scheme-indent-function 2))
   (eval . (put 'call-with-gzip-input-port 'scheme-indent-function 1))
   (eval . (put 'call-with-gzip-output-port 'scheme-indent-function 1))
   (eval . (put 'signature-case 'scheme-indent-function 1))
   (eval . (put 'emacs-batch-eval 'scheme-indent-function 0))
   (eval . (put 'emacs-batch-edit-file 'scheme-indent-function 1))
   (eval . (put 'emacs-substitute-sexps 'scheme-indent-function 1))
   (eval . (put 'emacs-substitute-variables 'scheme-indent-function 1))
   (eval . (put 'with-derivation-narinfo 'scheme-indent-function 1))
   (eval . (put 'with-derivation-substitute 'scheme-indent-function 2))
   (eval . (put 'with-status-report 'scheme-indent-function 1))

   (eval . (put 'mlambda 'scheme-indent-function 1))
   (eval . (put 'mlambdaq 'scheme-indent-function 1))
   (eval . (put 'syntax-parameterize 'scheme-indent-function 1))
   (eval . (put 'with-monad 'scheme-indent-function 1))
   (eval . (put 'mbegin 'scheme-indent-function 1))
   (eval . (put 'mwhen 'scheme-indent-function 1))
   (eval . (put 'munless 'scheme-indent-function 1))
   (eval . (put 'mlet* 'scheme-indent-function 2))
   (eval . (put 'mlet 'scheme-indent-function 2))
   (eval . (put 'run-with-store 'scheme-indent-function 1))
   (eval . (put 'run-with-state 'scheme-indent-function 1))
   (eval . (put 'wrap-program 'scheme-indent-function 1))
   (eval . (put 'with-imported-modules 'scheme-indent-function 1))
   (eval . (put 'with-extensions 'scheme-indent-function 1))

   (eval . (put 'with-database 'scheme-indent-function 2))

   (eval . (put 'call-with-container 'scheme-indent-function 1))
   (eval . (put 'container-excursion 'scheme-indent-function 1))
   (eval . (put 'eventually 'scheme-indent-function 1))

   (eval . (put 'call-with-progress-reporter 'scheme-indent-function 1))

   ;; This notably allows '(' in Paredit to not insert a space when the
   ;; preceding symbol is one of these.
   (eval . (modify-syntax-entry ?~ "'"))
   (eval . (modify-syntax-entry ?$ "'"))
   (eval . (modify-syntax-entry ?+ "'"))))
 (emacs-lisp-mode . ((indent-tabs-mode . nil)))
 (texinfo-mode    . ((indent-tabs-mode . nil)
                     (fill-column . 72))))


code:
*.eps
*.go
*.log
*.pdf
*.png
*.tar.xz
*.tmp
*~
.#*
\#*\#
,*
/ABOUT-NLS
/INSTALL
/aclocal.m4
/autom4te.cache
/build-aux/ar-lib
/build-aux/compile
/build-aux/config.guess
/build-aux/config.rpath
/build-aux/config.sub
/build-aux/depcomp
/build-aux/install-sh
/build-aux/mdate-sh
/build-aux/missing
/build-aux/test-driver
/build-aux/texinfo.tex
/config.status
/configure
/doc/*.1
/doc/.dirstamp
/doc/guix.*.aux
/doc/guix.*.cp
/doc/guix.*.cps
/doc/guix.*.fn
/doc/guix.*.fns
/doc/guix.*.html
/doc/guix.*.info
/doc/guix.*.info-[0-9]
/doc/guix.*.ky
/doc/guix.*.pg
/doc/guix.*.toc
/doc/guix.*.t2p
/doc/guix.*.tp
/doc/guix.*.vr
/doc/guix.*.vrs
/doc/guix.aux
/doc/guix.cp
/doc/guix.cps
/doc/guix.fn
/doc/guix.fns
/doc/guix.html
/doc/guix.info
/doc/guix.info-[0-9]
/doc/guix.ky
/doc/guix.pg
/doc/guix.toc
/doc/guix.t2p
/doc/guix.tp
/doc/guix.vr
/doc/guix.vrs
/doc/os-config-bare-bones.texi
/doc/os-config-desktop.texi
/doc/stamp-vti
/doc/version.texi
/doc/version-*.texi
/etc/guix-daemon.cil
/etc/guix-daemon.conf
/etc/guix-daemon.service
/etc/guix-publish.conf
/etc/guix-publish.service
/guix-daemon
/guix/config.scm
/libformat.a
/libstore.a
/libutil.a
/m4/*
/m4/ChangeLog
/m4/gettext.m4
/m4/iconv.m4
/m4/lib-ld.m4
/m4/lib-link.m4
/m4/lib-prefix.m4
/m4/nls.m4
/m4/po.m4
/m4/progtest.m4
/nix-setuid-helper
/nix/AUTHORS
/nix/COPYING
/nix/config.h
/nix/config.h.in
/nix/nix-daemon/nix-daemon.cc
/nix/nix-setuid-helper/nix-setuid-helper.cc
/nix/scripts/guix-authenticate
/nix/scripts/list-runtime-roots
/nix/scripts/offload
/nix/scripts/substitute
/po/doc/*.mo
/po/guix/*.gmo
/po/guix/*.insert-header
/po/guix/*.mo
/po/guix/ChangeLog
/po/guix/Makefile.in.in
/po/guix/Makevars.template
/po/guix/POTFILES
/po/guix/Rules-quot
/po/guix/boldquot.sed
/po/guix/en@boldquot.*
/po/guix/en@quot.*
/po/guix/guix.pot
/po/guix/insert-header.sin
/po/guix/quot.sed
/po/guix/remove-potcdate.sed
/po/guix/remove-potcdate.sin
/po/guix/stamp-po
/po/packages/*.gmo
/po/packages/*.insert-header
/po/packages/*.mo
/po/packages/ChangeLog
/po/packages/Makefile.in.in
/po/packages/Makevars.template
/po/packages/POTFILES
/po/packages/Rules-quot
/po/packages/boldquot.sed
/po/packages/en@boldquot.*
/po/packages/en@quot.*
/po/packages/guix-packages.pot
/po/packages/insert-header.sin
/po/packages/quot.sed
/po/packages/remove-potcdate.sed
/po/packages/remove-potcdate.sin
/po/packages/stamp-po
/pre-inst-env
/scripts/guix
/test-env
/test-tmp
/tests/*.trs
GPATH
GRTAGS
GTAGS
Makefile
Makefile.in
config.cache
stamp-h[0-9]
tmp
/doc/os-config-lightweight-desktop.texi
/nix/scripts/download
/etc/indent-code.el
/.version
/doc/stamp-[0-9]

path: .gitignore


code:
# This list is used to avoid multiple name/email instances of the same
# contributors reported by "git log" and "git shortlog" commands.

Adriano Peluso <catonano@gmail.com>
Al McElrath <hello@yrns.org> <hello@atonesir.com>
Alex Sassmannshausen <alex@pompo.co> <alex.sassmannshausen@gmail.com>
Alexander I. Grafov <grafov@gmail.com>
Alírio Eyng <alirioeyng@gmail.com>
Amirouche Boubekki <amirouche@hypermove.net>
Andreas Enge <andreas@enge.fr> <andreas.enge@inria.fr>
Andreas Enge <andreas@enge.fr> <privat@xobs-novena>
Andy Wingo <wingo@igalia.com> <wingo@pobox.com>
Ben Woodcroft <donttrustben@gmail.com>
Ben Woodcroft <donttrustben@gmail.com> <b.woodcroft@uq.edu.au>
Ben Woodcroft <donttrustben@gmail.com> <donttrustben near gmail.com>
Claes Wallin (韋嘉誠) <claes.wallin@greatsinodevelopment.com>
Cyprien Nicolas <cyprien@nicolas.tf> <c.nicolas+gitorious@gmail.com>
Daniel Pimentel <d4n1@d4n1.org> <d4n1@member.fsf.org>
Danny Milosavljevic <dannym@scratchpost.org> <dannym+a@scratchpost.org>
David Hashe <david.hashe@dhashe.com> <address@hidden>
David Thompson <davet@gnu.org> <dthompson2@worcester.edu>
David Thompson <davet@gnu.org> <dthompson@member.fsf.org>
David Thompson <davet@gnu.org> <dthompson@vistahigherlearning.com>
Deck Pickard <deck.r.pickard@gmail.com> <nebu@kipple>
Eric Bavier <bavier@member.fsf.org> <ericbavier@gmail.com>
Eric Dvorsak <eric@dvorsak.fr> <yenda1@gmail.com>
George Clemmer <myglc2@gmail.com>
Ivan Vilata i Balaguer <ivan@selidor.net>
Jeff Mickey <j@codemac.net> <jm@igneous.io>
John Darrington <jmd@gnu.org> <john@darrington.wattle.id.au>
John J. Foerch <jjfoerch@earthlink.net>
Joshua Grant <tadni@riseup.net> <gzg@riseup.net>
Joshua Grant <tadni@riseup.net> <jgrant@parenthetical.io>
Joshua Grant <tadni@riseup.net> <tadnimi@gmail.com>
Joshua Grant <tadni@riseup.net> <youlysses@riseup.net>
Kei Kebreau <kei@openmailbox.org> <kkebreau@posteo.net>
Leo Famulari <leo@famulari.name> <lfamular@gmail.com>
Ludovic Courtès <ludo@gnu.org> <ludovic.courtes@inria.fr>
Marek Benc <dusxmt@gmx.com> <merkur32@gmail.com>
Marius Bakke <mbakke@fastmail.com> <m.bakke@warwick.ac.uk>
Mathieu Lirzin <mthl@gnu.org> <mthl@openmailbox.org>
Mathieu Lirzin <mthl@gnu.org> <mathieu.lirzin@openmailbox.org>
Mathieu Othacehe <m.othacehe@gmail.com>
Nikita Karetnikov <nikita@karetnikov.org> <nikita.karetnikov@gmail.com>
Nils Gillmann <ng0@n0.is> ng0 <ng0@n0.is>
Nils Gillmann <ng0@n0.is> Nils Gillmann <gillmann@infotropique.org>
Nils Gillmann <ng0@n0.is> ng0 <ng0@crash.cx>
Nils Gillmann <ng0@n0.is> ng0 <ng0@crash.cx>
Nils Gillmann <ng0@n0.is> <ng0@infotropique.org>
Nils Gillmann <ng0@n0.is> <ng0@no-reply.infotropique.org>
Nils Gillmann <ng0@n0.is> <ng0@no-reply.pragmatique.xyz>
Nils Gillmann <ng0@n0.is> <ng0@pragmatique.xyz>
Nils Gillmann <ng0@n0.is> <contact.ng0@cryptolab.net>
Nils Gillmann <ng0@n0.is> <ng0@we.make.ritual.n0.is>
Nils Gillmann <ng0@n0.is> <ngillmann@runbox.com>
Nils Gillmann <ng0@n0.is> <niasterisk@grrlz.net>
Nils Gillmann <ng0@n0.is> <ng@niasterisk.space>
Nils Gillmann <ng0@n0.is> <ng0@libertad.pw>
Pierre Neidhardt <mail@ambrevar.xyz>
Pierre-Antoine Rouby <pierre-antoine.rouby@inria.fr>
Pjotr Prins <pjotr.guix@thebird.nl> <pjotr.public01@thebird.nl>
Pjotr Prins <pjotr.guix@thebird.nl> <pjotr.public12@thebird.nl>
Pjotr Prins <pjotr.guix@thebird.nl> <pjotr.public12@email>
Raimon Grau <raimonster@gmail.com> <raimon@3scale.net>
Raoul Jean Pierre Bonnal <ilpuccio.febo@gmail.com>
Raymond Nicholson <rain1@openmailbox.org>
Rene Saavedra <rennes@openmailbox.org>
Ricardo Wurmus <rekado@elephly.net>
Ricardo Wurmus <rekado@elephly.net> <ricardo.wurmus@mdc-berlin.de>
Sou Bunnbu (宋文武) <iyzsong@gmail.com>
Sou Bunnbu (宋文武) <iyzsong@gmail.com> <iyzsong@member.fsf.org>
Stefan Reichör <stefan@xsteve.at>
Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
Theodoros Foradis <theodoros.for@openmailbox.org> <theodoros@foradis.org>
Thomas Danckaert <thomas.danckaert@gmail.com> <post@thomasdanckaert.be>
Tobias Geerinckx-Rice <me@tobias.gr> <tobias.geerinckx.rice@gmail.com>
Tomáš Čech <sleep_walker@gnu.org> <sleep_walker@suse.cz>
Vincent Legoll <vincent.legoll@gmail.com> <vincent.legoll@idgrilles.fr>

path: .mailmap


code:
GNU Guix consists of Scheme code that implements the deployment model
of the Nix package management tool.  In fact, it currently talks to a
build daemon whose code comes from Nix (see the manual for details.)

Nix was initially written by Eelco Dolstra; other people have been
contributing to it.  See `nix/AUTHORS' for details.

The list of GNU Guix contributors is now generated from the output of
'git log' and written to this file, as can be seen in release tarballs.

path: AUTHORS


code:
Contributor Covenant Code of Conduct

  Note: In the sequel, "project" refers to GNU Guix, and "project
  maintainer(s)" refers to maintainer(s) of GNU Guix.

Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance, race,
religion, or sexual identity and orientation.

Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others’ private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting

Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at guix-maintainers@gnu.org. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project’s leadership.

Attribution

This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

path: CODE-OF-CONDUCT


code:
Normally a ChangeLog is generated at "make dist" time and available in
source tarballs.

If not, see the Git commit log at <http://git.sv.gnu.org/cgit/guix.git/>.

path: ChangeLog


code:
-*- mode: org; coding: utf-8; -*-

#+TITLE: Hacking GNU Guix and Its Incredible Distro

Copyright © 2012, 2013, 2014, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
Copyright © 2015, 2017 Mathieu Lirzin <mthl@gnu.org>
Copyright © 2017 Leo Famulari <leo@famulari.name>
Copyright © 2017 Arun Isaac <arunisaac@systemreboot.net>

  Copying and distribution of this file, with or without modification,
  are permitted in any medium without royalty provided the copyright
  notice and this notice are preserved.

* Contributing

See the manual for useful hacking informations, either by running

  info -f doc/guix.info "Contributing"

or by checking the [[http://www.gnu.org/software/guix/manual/guix.html#Contributing][web copy of the manual]].

* Commit Access

For frequent contributors, having write access to the repository is
convenient.  When you deem it necessary, feel free to ask for it on the
mailing list.  When you get commit access, please make sure to follow the
policy below (discussions of the policy can take place on guix-devel@gnu.org.)

Non-trivial patches should always be posted to guix-patches@gnu.org (trivial
patches include fixing typos, etc.).  This mailing list fills the
patch-tracking database at [[https://bugs.gnu.org/guix-patches]]; see
"Contributing" in the manual for details.

For patches that just add a new package, and a simple one, it’s OK to commit,
if you’re confident (which means you successfully built it in a chroot setup,
and have done a reasonable copyright and license auditing.)  Likewise for
package upgrades, except upgrades that trigger a lot of rebuilds (for example,
upgrading GnuTLS or GLib.)  We have a mailing list for commit notifications
(guix-commits@gnu.org), so people can notice.  Before pushing your changes,
make sure to run ‘git pull --rebase’.

All commits that are pushed to the central repository on Savannah must be
signed with an OpenPGP key, and the public key should be uploaded to your user
account on Savannah and to public key servers, such as ‘pgp.mit.edu’.  To
configure Git to automatically sign commits, run:

  git config commit.gpgsign true
  git config user.signingkey CABBA6EA1DC0FF33

You can prevent yourself from accidentally pushing unsigned commits to
Savannah by using the pre-push Git hook called located at ‘etc/git/pre-push’:

  cp etc/git/pre-push .git/hooks/pre-push

When pushing a commit on behalf of somebody else, please add a Signed-off-by
line at the end of the commit log message (e.g. with ‘git am --signoff’).
This improves tracking of who did what.

For anything else, please post to guix-patches@gnu.org and leave time for a
review, without committing anything.  If you didn’t receive any reply
after two weeks, and if you’re confident, it’s OK to commit.

That last part is subject to being adjusted, allowing individuals to commit
directly on non-controversial changes on parts they’re familiar with.

* Using emacs-debbugs

Bug reports and patches are tracked using debbugs. If you are on emacs, you
can use emacs-debbugs.

List all open bug reports on guix-patches with

C-u M-x debbugs-gnu <RET> <RET> guix-patches <RET> n y

path: HACKING


code:
# GNU Guix --- Functional package management for GNU
# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
# Copyright © 2013 Andreas Enge <andreas@enge.fr>
# Copyright © 2015, 2017 Alex Kost <alezost@gmail.com>
# Copyright © 2016, 2018 Mathieu Lirzin <mthl@gnu.org>
# Copyright © 2016, 2017, 2018 Mark H Weaver <mhw@netris.org>
# Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
# Copyright © 2017 Leo Famulari <leo@famulari.name>
# Copyright © 2017 Ricardo Wurmus <rekado@elephly.net>
# Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
# Copyright © 2017 Arun Isaac <arunisaac@systemreboot.net>
# Copyright © 2018 Nils Gillmann <ng0@n0.is>
# Copyright © 2018 Julien Lepiller <julien@lepiller.eu>
# Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
#
# This file is part of GNU Guix.
#
# GNU Guix is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or (at
# your option) any later version.
#
# GNU Guix is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

MSGMERGE_UPDATE = @MSGMERGE@ --update

bin_SCRIPTS = scripts/guix

# Handle substitution of fully-expanded Autoconf variables.
do_subst = $(SED)					\
  -e 's,[@]GUILE[@],$(GUILE),g'				\
  -e 's,[@]guilemoduledir[@],$(guilemoduledir),g'	\
  -e 's,[@]guileobjectdir[@],$(guileobjectdir),g'	\
  -e 's,[@]localedir[@],$(localedir),g'

scripts/guix: scripts/guix.in Makefile
	$(AM_V_at)rm -f $@ $@-t
	$(AM_V_at)$(MKDIR_P) "$(@D)"
	$(AM_V_GEN)$(do_subst) < "$(srcdir)/$@.in" > "$@-t"
	$(AM_V_at)chmod a+x,a-w "$@-t" && mv -f "$@-t" "$@"

nodist_noinst_SCRIPTS =				\
  pre-inst-env					\
  test-env

# Modules that are not compiled but are installed nonetheless, such as
# build-side modules with unusual dependencies.
MODULES_NOT_COMPILED =				\
  guix/man-db.scm

include gnu/local.mk
include po/doc/local.mk

MODULES =					\
  guix/base16.scm				\
  guix/base32.scm				\
  guix/base64.scm				\
  guix/cpio.scm					\
  guix/records.scm				\
  guix/pki.scm					\
  guix/progress.scm				\
  guix/combinators.scm				\
  guix/memoization.scm				\
  guix/utils.scm				\
  guix/sets.scm					\
  guix/modules.scm				\
  guix/download.scm				\
  guix/discovery.scm				\
  guix/git-download.scm				\
  guix/hg-download.scm				\
  guix/monads.scm				\
  guix/monad-repl.scm				\
  guix/gexp.scm					\
  guix/profiles.scm				\
  guix/serialization.scm			\
  guix/nar.scm					\
  guix/derivations.scm				\
  guix/grafts.scm				\
  guix/inferior.scm				\
  guix/describe.scm				\
  guix/channels.scm				\
  guix/gnu-maintenance.scm			\
  guix/self.scm					\
  guix/upstream.scm				\
  guix/licenses.scm				\
  guix/glob.scm					\
  guix/git.scm					\
  guix/graph.scm				\
  guix/cache.scm				\
  guix/cve.scm					\
  guix/workers.scm				\
  guix/zlib.scm					\
  guix/build-system.scm				\
  guix/build-system/android-ndk.scm		\
  guix/build-system/ant.scm			\
  guix/build-system/cargo.scm			\
  guix/build-system/cmake.scm			\
  guix/build-system/dub.scm			\
  guix/build-system/emacs.scm			\
  guix/build-system/font.scm			\
  guix/build-system/go.scm			\
  guix/build-system/meson.scm			\
  guix/build-system/minify.scm			\
  guix/build-system/asdf.scm			\
  guix/build-system/glib-or-gtk.scm		\
  guix/build-system/gnu.scm			\
  guix/build-system/guile.scm			\
  guix/build-system/haskell.scm			\
  guix/build-system/perl.scm			\
  guix/build-system/python.scm			\
  guix/build-system/ocaml.scm			\
  guix/build-system/waf.scm			\
  guix/build-system/r.scm			\
  guix/build-system/ruby.scm			\
  guix/build-system/scons.scm			\
  guix/build-system/texlive.scm			\
  guix/build-system/trivial.scm			\
  guix/ftp-client.scm				\
  guix/http-client.scm				\
  guix/gnupg.scm				\
  guix/elf.scm					\
  guix/profiling.scm				\
  guix/store.scm				\
  guix/cvs-download.scm				\
  guix/svn-download.scm				\
  guix/i18n.scm					\
  guix/ui.scm					\
  guix/status.scm				\
  guix/build/android-ndk-build-system.scm	\
  guix/build/ant-build-system.scm		\
  guix/build/download.scm			\
  guix/build/download-nar.scm			\
  guix/build/cargo-build-system.scm		\
  guix/build/cmake-build-system.scm		\
  guix/build/dub-build-system.scm		\
  guix/build/emacs-build-system.scm		\
  guix/build/meson-build-system.scm		\
  guix/build/minify-build-system.scm		\
  guix/build/font-build-system.scm		\
  guix/build/go-build-system.scm		\
  guix/build/asdf-build-system.scm		\
  guix/build/git.scm				\
  guix/build/hg.scm				\
  guix/build/glib-or-gtk-build-system.scm	\
  guix/build/gnu-build-system.scm		\
  guix/build/gnu-dist.scm			\
  guix/build/guile-build-system.scm		\
  guix/build/perl-build-system.scm		\
  guix/build/python-build-system.scm		\
  guix/build/ocaml-build-system.scm		\
  guix/build/r-build-system.scm			\
  guix/build/ruby-build-system.scm		\
  guix/build/scons-build-system.scm		\
  guix/build/texlive-build-system.scm		\
  guix/build/waf-build-system.scm		\
  guix/build/haskell-build-system.scm		\
  guix/build/store-copy.scm			\
  guix/build/utils.scm				\
  guix/build/union.scm				\
  guix/build/profiles.scm			\
  guix/build/compile.scm			\
  guix/build/pull.scm				\
  guix/build/rpath.scm				\
  guix/build/cvs.scm				\
  guix/build/svn.scm				\
  guix/build/syscalls.scm                       \
  guix/build/gremlin.scm			\
  guix/build/debug-link.scm			\
  guix/build/emacs-utils.scm			\
  guix/build/java-utils.scm			\
  guix/build/lisp-utils.scm			\
  guix/build/graft.scm				\
  guix/build/bournish.scm			\
  guix/build/qt-utils.scm			\
  guix/build/make-bootstrap.scm			\
  guix/search-paths.scm				\
  guix/packages.scm				\
  guix/import/print.scm				\
  guix/import/utils.scm				\
  guix/import/gnu.scm				\
  guix/import/snix.scm				\
  guix/import/cabal.scm				\
  guix/import/cran.scm				\
  guix/import/hackage.scm			\
  guix/import/elpa.scm				\
  guix/import/texlive.scm			\
  guix/import/gopkg.scm				\
  guix/scripts.scm				\
  guix/scripts/download.scm			\
  guix/scripts/perform-download.scm		\
  guix/scripts/build.scm			\
  guix/scripts/archive.scm			\
  guix/scripts/import.scm			\
  guix/scripts/package.scm			\
  guix/scripts/gc.scm				\
  guix/scripts/hash.scm				\
  guix/scripts/pack.scm				\
  guix/scripts/pull.scm				\
  guix/scripts/substitute.scm			\
  guix/scripts/authenticate.scm			\
  guix/scripts/refresh.scm			\
  guix/scripts/repl.scm				\
  guix/scripts/describe.scm			\
  guix/scripts/system.scm			\
  guix/scripts/system/search.scm		\
  guix/scripts/lint.scm				\
  guix/scripts/challenge.scm			\
  guix/scripts/import/cran.scm			\
  guix/scripts/import/gnu.scm			\
  guix/scripts/import/nix.scm			\
  guix/scripts/import/hackage.scm		\
  guix/scripts/import/elpa.scm			\
  guix/scripts/import/texlive.scm		\
  guix/scripts/import/gopkg.scm			\
  guix/scripts/environment.scm			\
  guix/scripts/publish.scm			\
  guix/scripts/edit.scm				\
  guix/scripts/size.scm				\
  guix/scripts/graph.scm			\
  guix/scripts/container.scm			\
  guix/scripts/container/exec.scm		\
  guix.scm					\
  $(GNU_SYSTEM_MODULES)

if HAVE_GUILE_JSON

MODULES +=					\
  guix/ci.scm					\
  guix/docker.scm	   			\
  guix/import/cpan.scm				\
  guix/import/crate.scm				\
  guix/import/gem.scm				\
  guix/import/github.scm   			\
  guix/import/gnome.scm				\
  guix/import/json.scm				\
  guix/import/opam.scm				\
  guix/import/pypi.scm				\
  guix/import/stackage.scm			\
  guix/scripts/import/crate.scm			\
  guix/scripts/import/gem.scm			\
  guix/scripts/import/json.scm  		\
  guix/scripts/import/opam.scm			\
  guix/scripts/import/pypi.scm			\
  guix/scripts/import/stackage.scm		\
  guix/scripts/weather.scm

endif

if HAVE_GUILE_SSH

MODULES +=					\
  guix/ssh.scm					\
  guix/scripts/copy.scm				\
  guix/store/ssh.scm

endif HAVE_GUILE_SSH

if BUILD_DAEMON_OFFLOAD

MODULES +=					\
  guix/scripts/offload.scm

endif BUILD_DAEMON_OFFLOAD

# Scheme implementation of the build daemon and related functionality.
STORE_MODULES =					\
  guix/store/database.scm			\
  guix/store/deduplication.scm

MODULES += $(STORE_MODULES)

# Internal modules with test suite support.
dist_noinst_DATA = guix/tests.scm guix/tests/http.scm

# Auxiliary files for packages.
AUX_FILES =						\
  gnu/packages/aux-files/emacs/guix-emacs.el		\
  gnu/packages/aux-files/linux-libre/4.18-arm.conf	\
  gnu/packages/aux-files/linux-libre/4.18-arm64.conf	\
  gnu/packages/aux-files/linux-libre/4.18-i686.conf	\
  gnu/packages/aux-files/linux-libre/4.18-x86_64.conf	\
  gnu/packages/aux-files/linux-libre/4.14-arm.conf	\
  gnu/packages/aux-files/linux-libre/4.14-i686.conf	\
  gnu/packages/aux-files/linux-libre/4.14-x86_64.conf	\
  gnu/packages/aux-files/linux-libre/4.9-i686.conf	\
  gnu/packages/aux-files/linux-libre/4.9-x86_64.conf	\
  gnu/packages/aux-files/linux-libre/4.4-i686.conf	\
  gnu/packages/aux-files/linux-libre/4.4-x86_64.conf	\
  gnu/packages/aux-files/run-in-namespace.c

# Templates, examples.
EXAMPLES =					\
  gnu/system/examples/bare-bones.tmpl		\
  gnu/system/examples/beaglebone-black.tmpl	\
  gnu/system/examples/desktop.tmpl		\
  gnu/system/examples/lightweight-desktop.tmpl	\
  gnu/system/examples/vm-image.tmpl

GOBJECTS = $(MODULES:%.scm=%.go) guix/config.go $(dist_noinst_DATA:%.scm=%.go)

nobase_dist_guilemodule_DATA =					\
  guix/store/schema.sql						\
  $(MODULES) $(MODULES_NOT_COMPILED) $(AUX_FILES) $(EXAMPLES)	\
  $(MISC_DISTRO_FILES)
nobase_nodist_guilemodule_DATA = guix/config.scm
nobase_nodist_guileobject_DATA = $(GOBJECTS)

# Handy way to remove the .go files without removing all the rest.
clean-go:
	-$(RM) -f $(GOBJECTS)
	@find . -name '*.go' -print | \
	  if test -t 1; then \
	    xargs -r echo -e "\033[31mwarning:\033[0m stray .go files:"; \
	  else \
	    xargs -r echo "warning: stray .go files:"; \
	  fi

# Test extensions; has to be unconditional.
TEST_EXTENSIONS = .scm .sh

if CAN_RUN_TESTS

SCM_TESTS =					\
  tests/base16.scm				\
  tests/base32.scm				\
  tests/base64.scm				\
  tests/cpio.scm				\
  tests/pki.scm					\
  tests/print.scm				\
  tests/sets.scm				\
  tests/modules.scm				\
  tests/gnu-maintenance.scm			\
  tests/substitute.scm				\
  tests/builders.scm				\
  tests/derivations.scm				\
  tests/glob.scm				\
  tests/grafts.scm				\
  tests/ui.scm					\
  tests/status.scm				\
  tests/records.scm				\
  tests/upstream.scm				\
  tests/combinators.scm				\
  tests/discovery.scm				\
  tests/utils.scm				\
  tests/build-utils.scm				\
  tests/packages.scm				\
  tests/snix.scm				\
  tests/hackage.scm				\
  tests/cran.scm				\
  tests/elpa.scm				\
  tests/texlive.scm				\
  tests/store.scm				\
  tests/monads.scm				\
  tests/gexp.scm				\
  tests/nar.scm					\
  tests/union.scm				\
  tests/profiles.scm				\
  tests/search-paths.scm			\
  tests/syscalls.scm				\
  tests/inferior.scm				\
  tests/gremlin.scm				\
  tests/debug-link.scm				\
  tests/bournish.scm				\
  tests/lint.scm				\
  tests/publish.scm				\
  tests/scripts.scm				\
  tests/size.scm				\
  tests/graph.scm				\
  tests/challenge.scm				\
  tests/cache.scm				\
  tests/cve.scm					\
  tests/workers.scm				\
  tests/zlib.scm				\
  tests/file-systems.scm			\
  tests/uuid.scm				\
  tests/system.scm				\
  tests/services.scm				\
  tests/scripts-build.scm			\
  tests/containers.scm				\
  tests/pack.scm				\
  tests/import-utils.scm			\
  tests/store-database.scm			\
  tests/store-deduplication.scm

if HAVE_GUILE_JSON

SCM_TESTS += 					\
  tests/pypi.scm				\
  tests/opam.scm				\
  tests/cpan.scm				\
  tests/gem.scm					\
  tests/crate.scm

endif

SH_TESTS =					\
  tests/guix-build.sh				\
  tests/guix-download.sh			\
  tests/guix-gc.sh				\
  tests/guix-hash.sh				\
  tests/guix-pack.sh				\
  tests/guix-package.sh				\
  tests/guix-package-net.sh			\
  tests/guix-system.sh				\
  tests/guix-archive.sh				\
  tests/guix-authenticate.sh			\
  tests/guix-environment.sh			\
  tests/guix-environment-container.sh		\
  tests/guix-graph.sh				\
  tests/guix-describe.sh			\
  tests/guix-lint.sh

TESTS = $(SCM_TESTS) $(SH_TESTS)

AM_TESTS_ENVIRONMENT = abs_top_srcdir="$(abs_top_srcdir)" GUILE_AUTO_COMPILE=0

SCM_LOG_DRIVER =				\
  $(top_builddir)/test-env --quiet-stderr	\
  $(GUILE) --no-auto-compile -e main		\
      $(top_srcdir)/build-aux/test-driver.scm

AM_SCM_LOG_DRIVER_FLAGS = --brief=yes

SH_LOG_COMPILER = $(top_builddir)/test-env $(SHELL)
AM_SH_LOG_FLAGS = -x -e

# Make sure `tests/guix-gc.sh' runs last, after all the others.  Otherwise it
# could end up removing files from the store while they are being used by
# other instances of the daemon.
tests/guix-gc.log:							\
  $(patsubst %.sh,%.log,$(filter-out tests/guix-gc.sh,$(SH_TESTS)))	\
  $(SCM_TESTS:%.scm=%.log)

else !CAN_RUN_TESTS

TESTS =
SH_TESTS =
SCM_TESTS =

# Automake always generates a 'check' target, so better not override it.
check-local:
	@echo
	@echo "Cannot run tests because file name limits would be exceeded." >&2
	@echo "Look for 'length' in the 'config.log' file for details." >&2
	@echo
	@exit 1

endif !CAN_RUN_TESTS

check-system: $(GOBJECTS)
	$(AM_V_at)$(top_builddir)/pre-inst-env			\
	   $(GUILE) --no-auto-compile				\
	   -e '(@@ (run-system-tests) run-system-tests)'	\
	   $(top_srcdir)/build-aux/run-system-tests.scm

# Public key used to sign substitutes from hydra.gnu.org & co.
dist_pkgdata_DATA =				\
  hydra.gnu.org.pub				\
  berlin.guixsd.org.pub

# Bash completion file.
dist_bashcompletion_DATA = etc/completion/bash/guix	\
  etc/completion/bash/guix-daemon

# Zsh completion file.
dist_zshcompletion_DATA = etc/completion/zsh/_guix

# Fish completion file.
dist_fishcompletion_DATA = etc/completion/fish/guix.fish

# SELinux policy
dist_selinux_policy_DATA = etc/guix-daemon.cil

EXTRA_DIST +=						\
  HACKING						\
  ROADMAP						\
  TODO							\
  CODE-OF-CONDUCT					\
  .dir-locals.el					\
  scripts/guix.in					\
  etc/guix-install.sh					\
  build-aux/build-self.scm				\
  build-aux/compile-all.scm				\
  build-aux/hydra/evaluate.scm				\
  build-aux/hydra/gnu-system.scm			\
  build-aux/hydra/guix.scm				\
  build-aux/hydra/guix-modular.scm			\
  build-aux/cuirass/gnu-system.scm			\
  build-aux/cuirass/guix-modular.scm			\
  build-aux/cuirass/hydra-to-cuirass.scm		\
  build-aux/check-available-binaries.scm		\
  build-aux/check-final-inputs-self-contained.scm	\
  build-aux/compile-as-derivation.scm			\
  build-aux/generate-authors.scm			\
  build-aux/test-driver.scm				\
  build-aux/update-guix-package.scm			\
  build-aux/update-NEWS.scm				\
  build-aux/run-system-tests.scm			\
  d3.v3.js						\
  graph.js						\
  tests/test.drv					\
  tests/signing-key.pub					\
  tests/signing-key.sec					\
  tests/cve-sample.xml					\
  build-aux/config.rpath				\
  bootstrap						\
  release.nix						\
  $(TESTS)

if !BUILD_DAEMON_OFFLOAD

EXTRA_DIST +=					\
  guix/scripts/offload.scm

endif !BUILD_DAEMON_OFFLOAD

CLEANFILES =					\
  $(bin_SCRIPTS)				\
  $(GOBJECTS)					\
  $(SCM_TESTS:tests/%.scm=%.log)

# Unset 'GUILE_LOAD_COMPILED_PATH' altogether while compiling.  Otherwise, if
# $GUILE_LOAD_COMPILED_PATH contains $(moduledir), we may find .go files in
# there that are newer than the local .scm files (for instance because the
# user ran 'make install' recently).  When that happens, we end up loading
# those previously-installed .go files, which may be stale, thereby breaking
# the whole thing.  Likewise, set 'XDG_CACHE_HOME' to avoid loading possibly
# stale files from ~/.cache/guile/ccache.
%.go: make-go ; @:
make-go: $(MODULES) guix/config.scm $(dist_noinst_DATA)
	$(AM_V_at)echo "Compiling Scheme modules..." ;			\
	unset GUILE_LOAD_COMPILED_PATH ;				\
	XDG_CACHE_HOME=/nowhere						\
	host=$(host) srcdir="$(top_srcdir)"				\
	$(top_builddir)/pre-inst-env					\
	$(GUILE) -L "$(top_builddir)" -L "$(top_srcdir)"		\
	  --no-auto-compile 						\
	  -s "$(top_srcdir)"/build-aux/compile-all.scm $^

SUFFIXES = .go

# Make sure source files are installed first, so that the mtime of
# installed compiled files is greater than that of installed source
# files.  See
# <http://lists.gnu.org/archive/html/guile-devel/2010-07/msg00125.html>
# for details.
guix_install_go_files = install-nobase_nodist_guileobjectDATA
$(guix_install_go_files): install-nobase_dist_guilemoduleDATA

# The above trick doesn't work for 'config.go' because both 'config.scm' and
# 'config.go' are listed in $(nobase_nodist_guileobject_DATA).  Thus, give it
# special treatment.
install-data-hook: set-bootstrap-executable-permissions
	touch "$(DESTDIR)$(guileobjectdir)/guix/config.go"

# Assuming Guix is already installed and the daemon is up and running, this
# rule builds from $(srcdir), creating and building derivations.
as-derivation:
	$(AM_V_at)echo "Building Guix in Guix..." ;		\
	$(GUILE) --no-auto-compile				\
	  "$(top_srcdir)/build-aux/compile-as-derivation.scm"	\
	  "$(abs_top_srcdir)"

SUBDIRS = po/guix po/packages
BUILT_SOURCES =

include doc/local.mk

if BUILD_DAEMON

include nix/local.mk

endif BUILD_DAEMON

ACLOCAL_AMFLAGS = -I m4

# Pass an explicit '--localstatedir' so that configure does not error out if
# it finds an existing installation with a different localstatedir.  Inherit
# 'ac_cv_guix_test_root' so that "make check" in $(distdir) does not have to
# repopulate the whole store, and to make sure $(GUIX_TEST_ROOT) is short
# enough for shebangs.
AM_DISTCHECK_CONFIGURE_FLAGS =			\
  --localstatedir="$$dc_install_base/var"	\
  --with-libgcrypt-prefix="$(LIBGCRYPT_PREFIX)"	\
  --with-libgcrypt-libdir="$(LIBGCRYPT_LIBDIR)"	\
  --with-nix-prefix="$(NIX_PREFIX)"		\
  --enable-daemon				\
  ac_cv_guix_test_root="$(GUIX_TEST_ROOT)"

# The self-contained tarball.  Add 'glibc-utf8-locales' along with glibc just
# so 'etc/profile' defines 'GUIX_LOCPATH' pointing to a valid set of locales.
guix-binary.%.tar.xz:
	$(AM_V_GEN)GUIX_PACKAGE_PATH=					\
	tarball=`$(top_builddir)/pre-inst-env guix pack -K -C xz	\
	  -s "$*" --localstatedir guix glibc-utf8-locales		\
	  -e  '(@@ (gnu packages commencement) glibc-final)'` ;		\
	cp "$$tarball" "$@.tmp" ; mv "$@.tmp" "$@"

dist-hook: $(distdir)/ChangeLog gen-AUTHORS gen-tarball-version
dist-hook: assert-no-store-file-names

distcheck-hook: assert-binaries-available assert-final-inputs-self-contained

EXTRA_DIST += $(top_srcdir)/.version
BUILT_SOURCES += $(top_srcdir)/.version
$(top_srcdir)/.version:
	echo $(VERSION) > "$@-t" && mv "$@-t" "$@"

gen-tarball-version:
	echo $(VERSION) > "$(distdir)/.tarball-version"

gen-ChangeLog $(distdir)/ChangeLog:
	$(AM_V_GEN)if test -d .git; then		\
	  $(top_srcdir)/build-aux/gitlog-to-changelog	\
	    > $(distdir)/cl-t;				\
	  rm -f $(distdir)/ChangeLog;			\
	  mv $(distdir)/cl-t $(distdir)/ChangeLog;	\
	fi

gen-AUTHORS:
	$(AM_V_GEN)if test -d .git; then			\
	  rm -f "$(distdir)/AUTHORS";				\
	  $(top_builddir)/pre-inst-env "$(GUILE)"		\
	    "$(top_srcdir)/build-aux/generate-authors.scm"	\
	    "$(top_srcdir)" "$(distdir)/AUTHORS";		\
	fi

#
# Release management.
#

releasedir = release-$(PACKAGE_VERSION)

PACKAGE_FULL_TARNAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)

# List of source tarballs produced.  This must be kept in sync with the
# 'dist-' options of 'AM_INIT_AUTOMAKE' in 'configure.ac'.
SOURCE_TARBALLS =					\
  $(foreach ext,tar.gz,$(PACKAGE_FULL_TARNAME).$(ext))

# Systems supported by Guix.
SUPPORTED_SYSTEMS ?= x86_64-linux i686-linux armhf-linux aarch64-linux

# Guix binary tarballs.
BINARY_TARBALLS =							\
  $(foreach system,$(SUPPORTED_SYSTEMS),guix-binary.$(system).tar.xz)

# Systems supported by GuixSD.
GUIXSD_SUPPORTED_SYSTEMS ?= x86_64-linux i686-linux

# Systems for which we build GuixSD VMs.
GUIXSD_VM_SYSTEMS ?= x86_64-linux

# Prefix of the GuixSD installation image file name.
GUIXSD_IMAGE_BASE = guixsd-install-$(PACKAGE_VERSION)

# Prefix of the GuixSD VM image file name.
GUIXSD_VM_IMAGE_BASE = guixsd-vm-image-$(PACKAGE_VERSION)

# The release process works in several phases:
#
#   0. We assume the developer created a 'vX.Y' tag.
#   1. Build the source tarball.
#   2. Update the 'guix' package so that it corresponds to the 'vX.Y' tag.
#   3. Build the binary tarballs for that 'guix' package.
#   4. Update the 'guix' package again.
#   5. Build the GuixSD installation images.  The images will run 'guix'
#      corresponding to 'vX.Y' + 1 commit, and they will install 'vX.Y'.
#
# This 'release' target takes care of everything and copies the resulting
# files to $(releasedir).
#
# XXX: Depend on 'dist' rather than 'distcheck' to work around the Gettext
# issue described at <https://savannah.gnu.org/bugs/index.php?51027>.
release: dist
	cd po; git checkout .
	@if ! git diff-index --quiet HEAD; then			\
	  echo "There are uncommitted changes; stopping." >&2 ;	\
	  exit 1 ;						\
	fi
	$(MKDIR_P) "$(releasedir)"
	rm -f "$(releasedir)"/*
	mv $(SOURCE_TARBALLS) "$(releasedir)"
	$(top_builddir)/pre-inst-env "$(GUILE)"			\
	   $(top_srcdir)/build-aux/update-guix-package.scm	\
	   "`git rev-parse HEAD`" "$(PACKAGE_VERSION)"
	git add $(top_srcdir)/gnu/packages/package-management.scm
	git commit -m "gnu: guix: Update to $(PACKAGE_VERSION)."
	rm -f $(BINARY_TARBALLS)
	$(MAKE) $(BINARY_TARBALLS)
	for system in $(SUPPORTED_SYSTEMS) ; do					\
	  mv "guix-binary.$$system.tar.xz"					\
	      "$(releasedir)/guix-binary-$(PACKAGE_VERSION).$$system.tar.xz" ;	\
	done
	$(top_builddir)/pre-inst-env "$(GUILE)"			\
	   $(top_srcdir)/build-aux/update-guix-package.scm	\
	   "`git rev-parse HEAD`"
	git add $(top_srcdir)/gnu/packages/package-management.scm
	git commit -m "gnu: guix: Update to `git rev-parse HEAD | cut -c1-7`."
	for system in $(GUIXSD_SUPPORTED_SYSTEMS) ; do					\
	  image=`$(top_builddir)/pre-inst-env						\
	    guix system disk-image							\
	    --file-system-type=iso9660							\
            --system=$$system								\
	    gnu/system/install.scm` ;							\
	  if [ ! -f "$$image" ] ; then							\
	    echo "failed to produced GuixSD installation image for $$system" >&2 ;	\
	    exit 1 ;									\
	  fi ;										\
	  xz < "$$image" > "$(releasedir)/$(GUIXSD_IMAGE_BASE).$$system.iso.xz.tmp" ;	\
	  mv "$(releasedir)/$(GUIXSD_IMAGE_BASE).$$system.iso.xz.tmp"			\
	     "$(releasedir)/$(GUIXSD_IMAGE_BASE).$$system.iso.xz" ;			\
	done
	for system in $(GUIXSD_VM_SYSTEMS) ; do						\
	  image=`$(top_builddir)/pre-inst-env						\
	    guix system vm-image							\
	    --system=$$system								\
	    gnu/system/examples/vm-image.tmpl` ;					\
	  if [ ! -f "$$image" ] ; then							\
	    echo "failed to produced GuixSD VM image for $$system" >&2 ;		\
	    exit 1 ;									\
	  fi ;										\
	  xz < "$$image" > "$(releasedir)/$(GUIXSD_VM_IMAGE_BASE).$$system.xz.tmp" ;	\
	  mv "$(releasedir)/$(GUIXSD_VM_IMAGE_BASE).$$system.xz.tmp"			\
	     "$(releasedir)/$(GUIXSD_VM_IMAGE_BASE).$$system.xz" ;			\
	done
	@echo
	@echo "Congratulations!  All the release files are now in $(releasedir)."
	@echo

update-guix-package:
	git rev-parse HEAD
	$(top_builddir)/pre-inst-env "$(GUILE)"			\
	   $(top_srcdir)/build-aux/update-guix-package.scm	\
	   "`git rev-parse HEAD`"

# Location of a checkout of <git://git.savannah.gnu.org/guix/maintenance.git>.
# Package data from this checkout is used by 'update-NEWS.scm'.
GUIX_MAINTENANCE_DIRECTORY ?= $(top_srcdir)/../guix-maintenance

update-NEWS: $(GOBJECTS)
	$(top_builddir)/pre-inst-env "$(GUILE)"				\
	  $(top_srcdir)/build-aux/update-NEWS.scm			\
	  $(top_srcdir)/NEWS "$(GUIX_MAINTENANCE_DIRECTORY)/data"

# Make sure we're not shipping a file that embeds a local /gnu/store file name.
assert-no-store-file-names: $(distdir)/ChangeLog
	$(AM_V_at)if grep -r --exclude=*.texi --exclude=*.info			\
	     --exclude=*.info-[0-9] --exclude=*.dot				\
	     --exclude=*.eps --exclude-dir=bootstrap				\
		 --exclude=guix-manual.pot --exclude=guix-manual.*.po		\
	     --exclude=guix-prettify.el						\
	     --exclude=ChangeLog						\
	     -E "$(storedir)/[a-z0-9]{32}-" $(distdir) ;			\
	then									\
	  echo "error: store file names embedded in the distribution" >&2 ;	\
	  exit 1 ;								\
	fi

# Make sure hydra.gnu.org has the important binaries.
assert-binaries-available: $(GOBJECTS)
	$(AM_V_at)$(top_builddir)/pre-inst-env "$(GUILE)"			\
	  "$(top_srcdir)/build-aux/check-available-binaries.scm"

# Make sure the final inputs don't refer to bootstrap tools.
assert-final-inputs-self-contained: $(GOBJECTS)
	$(AM_V_at)$(top_builddir)/pre-inst-env "$(GUILE)"			\
	  "$(top_srcdir)/build-aux/check-final-inputs-self-contained.scm"

# Compute the Hydra jobs and write them in the target file.
hydra-jobs.scm: $(GOBJECTS)
	$(AM_V_at)$(MKDIR_P) "`dirname "$@"`"
	$(AM_V_GEN)$(top_builddir)/pre-inst-env "$(GUILE)"		\
	  "$(top_srcdir)/build-aux/hydra/evaluate.scm"			\
	  "$(top_srcdir)/build-aux/hydra/gnu-system.scm" > "$@.tmp"
	$(AM_V_at)mv "$@.tmp" "$@"

# Compute the Cuirass jobs and write them in the target file.
cuirass-jobs.scm: $(GOBJECTS)
	$(AM_V_at)$(MKDIR_P) "`dirname "$@"`"
	$(AM_V_GEN)$(top_builddir)/pre-inst-env "$(GUILE)"		\
	  "$(top_srcdir)/build-aux/hydra/evaluate.scm"			\
	  "$(top_srcdir)/build-aux/cuirass/gnu-system.scm" 		\
	  cuirass > "$@.tmp"
	$(AM_V_at)mv "$@.tmp" "$@"

.PHONY: gen-ChangeLog gen-AUTHORS gen-tarball-version
.PHONY: assert-no-store-file-names assert-binaries-available
.PHONY: assert-final-inputs-self-contained
.PHONY: clean-go make-go as-derivation
.PHONY: update-guix-package update-NEWS release

## -------------- ##
## Silent rules.  ##
## -------------- ##

AM_V_DL = $(AM_V_DL_$(V))
AM_V_DL_ = $(AM_V_DL_$(AM_DEFAULT_VERBOSITY))
AM_V_DL_0 = @echo "  DL      " $@;

AM_V_DOT = $(AM_V_DOT_$(V))
AM_V_DOT_ = $(AM_V_DOT_$(AM_DEFAULT_VERBOSITY))
AM_V_DOT_0 = @echo "  DOT     " $@;

AM_V_HELP2MAN = $(AM_V_HELP2MAN_$(V))
AM_V_HELP2MAN_ = $(AM_V_HELP2MAN_$(AM_DEFAULT_VERBOSITY))
AM_V_HELP2MAN_0 = @echo "  HELP2MAN" $@;

AM_V_PO4A = $(AM_V_PO4A_$(V))
AM_V_PO4A_ = $(AM_V_PO4A_$(AM_DEFAULT_VERBOSITY))
AM_V_PO4A_0 = @echo "  PO4A" $@;

AM_V_POXREF = $(AM_V_POXREF_$(V))
AM_V_POXREF_ = $(AM_V_POXREF_$(AM_DEFAULT_VERBOSITY))
AM_V_POXREF_0 = @echo "  POXREF" $@;