Fist commit

This commit is contained in:
Yorick Barbanneau 2019-11-10 02:01:43 +01:00
commit 1d9cd3a9c4
2 changed files with 429 additions and 0 deletions

114
README.md Normal file
View file

@ -0,0 +1,114 @@
dotinstall - manage dotfiles
----------------------------
`dotinstall` is another little script made for install or uninstall dotfiles by
creating symbolic link. You need to provide a boostrap script for it.
## How to use
```
dotinstall bootstrap
```
The script can use git to retrieve a repository :
```
dotinstall https://git.example.com/user/repo.git
```
You can uninstall the dotfiles by adding the `uninstall` keyword before the
bootstrap file :
```
dotinstall uninstall bootstrap
```
## Boostrap file syntax
`bootstrap` is a simple bash script sourced by `dotinstall`. The `bootstrap`
file contains instructions and can call functions and use variables from
dotinstall:
### functions
#### bin_check
This function check if binary file is avaible in the `PATH`.
- **input** : list of executable separated by spaces"
- **return** : no value, but exit the entire script if a executable is not
found with exit code 128
```
bin_check "ls mv git"
```
#### conf_process_dirs
Process a directory that contains others directories an symblink them to the
destination folder :
- **input** :
- `$1` : source directory
- `$2` : destination directory
- **return** : no value, exit the funtion if there is an error on path
```
conf_process_dirs "${repository}/config" "${HOME}/.config"
```
#### conf_process_files
Process a directory than contains files and symblink them to the destination
folder :
- **input** :
- `$1` : source directory
- `$2` : destination directory
- **return** : no value, exit the funtion if there is an error on path
```
conf_process_dirs "${repository}/zshrc" "${HOME}"
```
#### bin_install
Symblink an executable file to the `~/.local/bin` folder.
- **input** :
- `$1` : source file
- **return** : no value, exit the function if the source file not exist or is
not executable.
```
bin_install "bin/check_mails.sh
```
#### service_install
Install a systemd service as user, can be useful for timers for example :
- **input** :
- `$1` : source file
- `$2` : 1 if service must be activated
- **return** : no value, but exit the function if source file is not found or
the service can't be activated
```
service_install "services/myservice.service" 1
```
### Avaible variables
- `$repository` : the root folder of the repository
- `OVERWRITE_DIRECTORY` : if `1`, the script will erase a directory and replace
it with a symblink if needed. For example if `~/.vim/` exist, but your
boostrap file need to create a symblink from `~/.config/dotrepo/conf/vim`
to `~/.vim`, it will be erased fist. If 0, an error message will be
displayed.
- `OVERWRITE_FILE` : do the same with file
## Licence
This softeware is licenced under the GNU-GPL 3 licence, you can found a copy of
the licence [here](https://www.gnu.org/licenses/gpl-3.0.en.html).

315
src/dotinstall.sh Executable file
View file

@ -0,0 +1,315 @@
#!/usr/bin/env bash
# Personnal Dotfiles install script
BIN_DIRECTORY="${HOME}/.local/bin/"
LIB_DIRECTORY="${HOME}/.local/lib/"
SYD_DIRECTORY="${HOME}/.config/systemd/user"
DOTREPO="${HOME}/.config/dotrepo/"
# DEFAULT VALUES
OVERWRITE_DIRECTORY=0
OVERWRITE_FILE=0
repository=""
install=1
usage ()
{
printf "\nUSAGE\n"
printf "\n"
printf "%s <bootstrap_file>\n" "$0"
printf "boostrap_file : file contain variables\n"
}
die ()
{
# Exit script
# $1 : error message before quit
# $2 : exit code - default 99
# $3 : 1 if print usage
[ -z $2 ] && $2=99
printf "\e[31mFATAL : %s\e[0m\n" "$1"
[ $3 == 1 ] && usage
exit $2
}
error ()
{
# print error message in red
# $@ : message
printf "\e[31m%s\e[0m\n" "$*"
}
private:get_bootstrap_path ()
{
# this function return the absolute path of the bootstrap file
# $* : path of bootstrap file
# If the path begin with /, this is an absolute part
if [[ "$*" =~ ^/[[:graph:]]*$ ]]
then
repository="$(dirname $*)"
return
fi
local relative_path="$*"
local current_path="$(pwd)"
while [[ $relative_path =~ ^../[[:graph:]]*$ ]]
do
printf "We found ..\n"
relative_path="${relative_path##../}"
current_path="${current_path%/*}"
done
repository="$(dirname "${current_path}/${relative_path}")"
}
private:remove_symblink()
{
# Remove a symblink
# $* source
printf " -> Remove symblink %s : " "$symblink"
if [ -L "$*" ]
then
local ret;
ret=$(rm "$*" 2>&1)
[ $? -ne 0 ] && { error "can't remove : $ret"; return; }
elif [ ! -f "$*" ]
then
error "$* not exist"
return
else
error "$* is not a symblink"
fi
printf "\e[32mdone\e[0m\n"
}
private:create_symblink ()
{
# Create a symblink
# $1: source
# $2: destination
local source="$1"
local dest="$2"
printf " -> Create a symblink from %s : " "$source"
# If dest is a symbolic link, delete it.
if [ -L "$dest" ]
then
rm -rf "$dest"
# If source is a directory
elif [ -d "$source" ]
then
if [ -d "$dest" ]
then
if [ $OVERWRITE_DIRECTORY -ne 0 ]
then
error "can't overwrite destination"
return
else
rm -rf $dest
fi
elif [ -e $dest ]
then
error "destination exist but is not a directory"
return
fi
# If source is a file
elif [ -f "$source" ]
then
if [ -f "$dest" ]
then
if [ $OVERWRITE_FILE -ne 0 ]
then
error "can't overwrite destination"
return
else
rm -rf "$dest"
fi
elif [ -e "$dest" ]
then
error "$dest exist but is not a file"
return
fi
fi
ln -s "$source" "$dest"
printf "\e[32mdone\e[0m\n"
}
private:clone_repository ()
{
# Clone a git repository and test if it has a bootstrap file
# $* url
# return : local directory
local ret
ret=$(git clone -q "$1" "${2}" 2>&1)
[[ $? -ne 0 ]] && die "Can't clone_repository : $ret" 20 0
}
process_dirs () {
# Process a directory than contains subdir, create symblink from each subdir
# to the destination.
#
# $1: source directory
# $2: destination directory
local dest="${repository}/$1"
printf "\nProcess directory %s\n" "$1"
[ ! -d "$dest" ] && { error " -> source is not a directory"; return; }
[ ! -d "$dest" ] && { error " -> destination is not a directory"; return; }
while read d
do
if [ $install -eq 1 ]
then
private:create_symblink "$d" "${2}/$(basename "$d")"
else
local symblink="${2}/$(basename ${d})"
private:remove_symblink "$symblink"
fi
done < <(ls -d -1 "${dest}"/*/)
}
process_files () {
# Process a directory than contains config files, create symblink from each
# files to the destination.
# $1: source directory
# $2: destination directory
local dest="${repository}/$1"
printf "Process files from directory %s:\n" "$1"
[ ! -d "$dest" ] && { error " -> source is not a directory"; return; }
[ ! -d "$dest" ] && { error " -> destination is not a directory"; return; }
while read d
do
if [ $install -eq 1 ]
then
private:create_symblink "$d" "$2/$(basename "$d")"
else
local symblink="${2}/$(basename ${d})"
private:remove_symblink "$symblink"
fi
done < <(ls -1 "$dest")
}
install_service ()
{
# Install an user service with systemd and activate it
# $1 file
# $2 1 to Activate the service
local source="${repository}/$1"
local ret
[ ! -f "$source" ] && { error "$1 not found"; return; }
local basename=$(basename "$source")
if [ $install -eq 1 ]
then
printf "\nInstall service %s :\n" "$source"
private:create_symblink "$source" "${SYD_DIRECTORY}/${basename}"
# activate service
if [ $2 ]
then
printf " -> Activate $basename : "
ret=$(systemctl --user enable ${basename} 2>&1)
[[ $? -ne 0 || ! $(systemctl --user is-enabled $basename) ]] && { error "$ret"; return; }
printf "\e[32mdone\e[0m\n"
fi
else
printf "\nUninstall service %s :\n" "$source"
#Deactivate service
if [ $1 ]
then
printf " -> Deactivate $basename : "
ret=$(systemctl --user disable ${basename} 2>&1)
[[ $? -ne 0 ]] && { error "$ret"; return; }
printf "\e[32mdone\e[0m\n"
fi
fi
}
check_bin ()
{
# Check if an executable exist
# $1 executables separated with spaces
printf "Checking required programs :\n"
for p in $1
do
printf " -> %s:" "$p"
command -v $p >/dev/null 2>&1 || die "not found" 128
printf " \e[32mfound\e[0m\n"
done
}
install_bin ()
{
# Install a binary / script file as executable
# Via a symbolic link
# $1 : path to script
local source="${repository}/${1}"
local dest="${BIN_DIRECTORY}/$(basename $1)"
printf "\nProcess executable :\n"
[ ! -f "$source" ] && { error "$source is not a file"; return; }
[ ! -x "$source" ] && { error "$source not executable "; return; }
if [ $install -eq 1 ]
then
private:create_symblink "$source" "$dest"
else
private:remove_symblink "$dest"
fi
}
## create bin directory
[ ! -d $BIN_DIRECTORY ] && mkdir -p $BIN_DIRECTORY || printf "bin exist\n"
# Test parameters : we need to know if it's a git repo or a file
[[ $1 == "uninstall" || $1 == "-u" ]] && { install=0; printf "Activate uninstall mode\n"; shift; }
echo $install
[ "$*" = "" ] && die "You must specify a bootstrap file" 10 1
if [[ $* =~ ^https://.*\.git$ || $* =~ ^ssh://.*\.git$ ]]
then
bin_check "git"
# Check
localdir="${DOTREPO}/$(basename $* .git)"
[ -d "$localdir" ] && die "destination folder for git repository already exist" 21 0
private:clone_repository "$*" "$localdir"
if [ -f "${localdir}/bootstrap" ]
then
$0 "${localdir}/bootstrap"
exit $?
else
die "Can't find a \`boostrap\` file in ${repo}" 22 0
fi
else
[ ! -f "$*" ] && die "$* does not exist" 10 1
private:get_bootstrap_path "$*"
# Include bootstrap
source $*
fi
exit 0