2
0
mirror of https://github.com/kazhala/dotbare synced 2024-11-04 06:00:45 +00:00
See CHANGELOG.md
This commit is contained in:
Kevin Zhuang 2020-07-01 18:01:30 +10:00 committed by GitHub
commit 53adb47597
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1107 additions and 545 deletions

12
.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
scripts/*
!scripts/fadd
!scripts/fbackup
!scripts/fcheckout
!scripts/fedit
!scripts/finit
!scripts/flog
!scripts/freset
!scripts/fstash
!scripts/fstat
!scripts/funtrack
!scripts/fupgrade

View File

@ -2,7 +2,32 @@
Noteble changes are documentated in this file.
## 1.0.0
## 1.2.0
### Added
- `dotbare` now accept verbose type of argument e.g. `dotbare fadd --file` `dotbare fcheckout --branch`.
More information please refer to each commands help manual
- Added support for handling files with spaces
- Improved unittest with mocking
- A more reliable `dotbare fupgrade` behavior
- Added version flag for `dotbare`, `dotbare --version` or `dotbare -v`
### Changed
- `dotbare fcheckout -a` has now been renamed to `dotbare fcheckout -s` or `dotbare fcheckout --select`
- `dotbare fstash -f` has now been renamed to `dotbare fstash -s` or `dotbare fstash --select`
- `dotbare funtrack -s` has now been renamed to `dotbare funtrack -t` or `dotbare funtrack --temp`
- `dotbare funtrack -S` has now been renamed to `dotbare funtrack -r` or `dotbare funtrack --resume`
- dryrun information no longer will display if `-y` or `--yes` flag has been passed
### Removed
- Removed `-a` flag of `dotbare freset`. It's not working as intended because I misunderstand it, the intended
behavior is actually achieved by `dotbare fcheckout -a`, use `dotbare fcheckout -a` instead.
(Edit: `dotbare fcheckout -a` is now `dotbare fcheckout -s` or `dotbare fcheckout --select`)
## 1.1.0
### Added
@ -21,3 +46,5 @@ Noteble changes are documentated in this file.
- Removed global .gitignore manipulation during migration, not needed. Added .gitignore tips to README and
let user handle it
## 1.0.0

251
README.md
View File

@ -8,8 +8,8 @@
## Introduction
dotbare is a command line utility to help you manage your dotfiles. It wraps around git bare
repository and heavily utilise [fzf](https://github.com/junegunn/fzf) for better user experience.
It is inspired by [forgit](https://github.com/wfxr/forgit), a git wrapper that utilise fzf for interactive experience.
repository and heavily utilises [fzf](https://github.com/junegunn/fzf) for an interactive experience.
It is inspired by [forgit](https://github.com/wfxr/forgit), a git wrapper using fzf.
dotbare uses a different implementation approach and focuses on managing and interacting with your dotfiles.
Don't worry about migration if you have a symlink/GNU stow setup, you can easily integrate dotbare with them.
@ -20,19 +20,19 @@ Pros:
- Customizable
- Easy migration
- Flat learning curve
- Manage dotfiles in any directory
- Manage dotfiles anywhere in your system
- Integration with symlink/GNU stow setup
You could find out how git bare repository could be used for managing dotfiles [here](https://www.atlassian.com/git/tutorials/dotfiles).
Or a [video](https://www.youtube.com/watch?v=tBoLDpTWVOM&t=288s) explanation that helped me to get started. If you currently
is using symlink/GNU stow setup, checkout how to integrate dotbare with them [here](#migrating-from-a-generic-symlink-setup-or-gnu-stow).
Or a [video](https://www.youtube.com/watch?v=tBoLDpTWVOM&t=288s) explanation that helped me to get started. If you are currently
using a symlink/GNU stow setup, checkout how to integrate dotbare with them [here](#migrating-from-a-generic-symlink-setup-or-gnu-stow).
![Demo](https://user-images.githubusercontent.com/43941510/82142379-4a1e7500-987f-11ea-8d35-8588a413efd3.png)
## Why
It has always been a struggle for me to get started with managing dotfiles using version control,
as some other tools like "GNU stow" really scares me off with all the symlinks, until I found
as some tools like "GNU stow" really scares me off with all the symlinks, until I found
out about using git bare repository for managing dotfiles, zero symlinks, minimal setup
required and you keep your dotfiles at the location they should be.
@ -80,6 +80,7 @@ with minimal set up required.
- [finit: initialise/migrating dotbare](#finit)
- [funtrack: untrack files](#funtrack)
- [fupgrade: update dotbare](#fupgrade)
- [Custom scripts](#custom-scripts)
- [Tips and Tricks](#tips-and-tricks)
- [Testing](#testing)
- [Contributing](#contributing)
@ -92,7 +93,7 @@ with minimal set up required.
### zsh
dotbare should work with any zsh plugin manager, below is only demonstration
dotbare should work with any zsh plugin manager, below is only demonstration.
#### zinit
@ -138,7 +139,7 @@ antigen bundle kazhala/dotbare
dotbare comes with a `dotbare.plugin.bash` which will enable both bash command line
completion for dotbare commands and adding dotbare to your PATH. If you don't want the completion,
simply follow the instructions in [others](#others) and add dotbare to your PATH.
follow the instructions in [others](#others) which simply add dotbare to your PATH.
- Clone the repository (change ~/.dotbare to the location of your preference)
@ -179,8 +180,11 @@ simply follow the instructions in [others](#others) and add dotbare to your PATH
### Dependencies
- Required dependency
- git
- [fzf](https://github.com/junegunn/fzf)
- bash(You don't need to run bash, but dotbare does require you have bash in your system)
- Optional dependency
- [tree](https://linux.die.net/man/1/tree) (Will provide a directory tree view when finding directory)
@ -194,7 +198,7 @@ simply follow the instructions in [others](#others) and add dotbare to your PATH
1. init git bare repository
Note: by default, `dotbare finit` will set up a bare repo in \$HOME/.cfg, to customize
Note: by default, `dotbare finit` will set up a bare repository in \$HOME/.cfg, to customize
location and various other settings, checkout [customization](#customization)
```sh
@ -203,9 +207,9 @@ simply follow the instructions in [others](#others) and add dotbare to your PATH
2. add dotfiles you want to track
```sh
# Treat dotbare as normal `git` commands.
Treat dotbare as normal `git` commands.
```sh
dotbare fadd -f
# or
dotbare add [FIELNAME]
@ -243,7 +247,7 @@ simply follow the instructions in [others](#others) and add dotbare to your PATH
export DOTBARE_TREE="$HOME"
```
4. remove the original alias and use dotbare the same except with _super power_
4. remove the original alias and use `dotbare`
5. optionally you could alias config to dotbare so you keep your muscle memory
@ -253,10 +257,6 @@ simply follow the instructions in [others](#others) and add dotbare to your PATH
#### Migrating from a generic symlink setup or GNU stow
> If you already have a symlink setup either custom or with GNU stow.
> You could either integrate dotbare with your current set up or
> do a complete migration.
##### Keep your current setup but integrate dotbare
1. follow the steps in [install](#install) to install dotbare
@ -276,21 +276,27 @@ simply follow the instructions in [others](#others) and add dotbare to your PATH
##### Complete migration
I haven't used GNU stow or any symlink setup, but I do recommend keep your current setup
and integrate with dotbare. If you are really happy with `dotbare`, as long as your remote
repository resembles the structure of your home holder (reference what I mean in my [repo](https://github.com/kazhala/dotfiles.git)),
simply run the command below.
**NOTE**: There's an open [issue](https://github.com/kazhala/dotbare/issues/12) where if you have more than 100 dotfiles
tracked, this method would cause a crash during migration. Please don't use this method before the issue get resolved.
While bare method is great and easy, I recommend keeping your current GNU stow/symlink setup and integrate it with dotbare instead of a migration.
If you are really happy with `dotbare`, as long as your remote repository resembles the structure of your home holder
(reference what I mean in my [repo](https://github.com/kazhala/dotfiles.git)), simply run the command below.
**Disclaimer**: I have not done nearly enough test on this as I don't personally use GNU stow or symlink setup, migrate this way with caution.
I recommend you test this migration in docker, see [Test-it-in-docker](#test-it-in-docker).
```sh
# Disclaimer: I have not test this with GNU stow, migrate in this way with caution.
# I recommend you test this migration in docker, see #Test-it-in-docker
# dotbare will replace all symlinks with the original file and a bare repository will be created at $DOTBARE_DIR
dotbare finit -u [URL]
```
#### Migrating dotbare to a new system
1. follow the steps in [install](#install) to install dotbare
2. Optionally set env variable to customize dotbare location. Checkout [customization](#customization)
2. Optionally set env variable to customize dotbare location
> Checkout [customization](#customization)
```sh
export DOTBARE_DIR="$HOME/.cfg"
@ -305,8 +311,8 @@ dotbare finit -u [URL]
#### Test it in docker
I strongly suggest you give dotbare a try in docker, especially
when it comes to first time migration.
When you are about to do migrations, I strongly suggest you give the migration a try in docker first.
The dotbare image is based on alpine linux.
```sh
docker pull kazhala/dotbare:latest
@ -327,8 +333,8 @@ This is the location of the bare repository, dotbare will look for this director
and query git information or it will create this directory when initializing dotbare.
Change this to location or rename the directory to your liking.
If you are using symlink/GNU stow setup, set this variable point to your .git folder
in your working directory of your dotfiles.
If you are using symlink/GNU stow setup, set this variable point to the .git folder
within your dotfile directory.
```sh
# Default
@ -340,7 +346,7 @@ DOTBARE_DIR="$HOME/.cfg"
This is the working tree for the git bare repository, meaning this is where the version
control will take place. I don't recommend changing this one unless **ALL** of your config
file is in something like \$XDG_CONFIG_HOME or if you are using symlink/GNU stow setup,
set this variable to point to the folder contains your actual dotfiles.
set this variable to point to the folder containing your dotfiles.
```sh
# Default
@ -352,8 +358,7 @@ DOTBARE_TREE="$HOME"
This variable is used to determine where to store the backup of your files. It is used
mainly by `dotbare fbackup` which will back up all of your tracked dotfiles into this location.
It is also used by `dotbare finit -u [URL]`, when there is checkout conflict, dotbare will
automatically backup conflicted files to this location. You probably shouldn't change this
location.
automatically backup conflicted files to this location.
```sh
# Default
@ -381,7 +386,7 @@ to set [here](https://github.com/junegunn/fzf/blob/97a725fbd0e54cbc07e4d72661ea2
# Default
DOTBARE_KEY="
--bind=alt-a:toggle-all # toggle all selection
--bind=alt-j:jump # label jump mode, sort of like easymotion
--bind=alt-j:jump # label jump mode, sort of like vim-easymotion
--bind=alt-0:top # set cursor back to top
--bind=alt-s:toggle-sort # toggle sorting
--bind=alt-t:toggle-preview # toggle preview
@ -396,81 +401,86 @@ fzf behavior from your normal system fzf settings.
```sh
# Default is unset
# More settings checkout fzf man page and their wiki
# You could also take a look at my fzf config
# https://github.com/kazhala/dotfiles/blob/5507a2dea4f4a420e6d65a423abaa247521f89a8/.zshrc#L56
```
## Commands
> dotbare doesn't have a man page yet, will come later, for help, type dotbare [COMMAND] -h
> dotbare doesn't have a man page yet (it is planned tho), for help, type dotbare [COMMAND] -h
### Checkout all available scripts and their help manual
```sh
# run dotbare without any arguments
# run dotbare without any arguments will display all available `f` scripts
dotbare
# or checkout help for dotbare
dotbare -h
dotbare help
# for normal git help
dotbare --help
# for normal git help
dotbare help
```
### fedit
List all tracked dotfiles and edit the selected file through \$EDITOR, it also support
edit commits through interactive rebase.
Select files/commits through fzf and edit selected files/commits in \$EDITOR.
Editing commits will perform a interactive rebase.
- Default: list all tracked files and open \$EDITOR to edit it. Support multi selection.
- -m: list all modified files and open \$EDITOR to edit it. Support multi selection.
- -c: list all commits and open interactive rebase to edit commits.
- Default: list all tracked files and open \$EDITOR to edit the selected files. Support multi selection.
- `-h, --help`: show the help message of `dotbare fedit` and exit.
- `-m, --modified`: list all modified files and open \$EDITOR to edit the selected files. Support multi selection.
- `-c, --commit`: list all commits and edit the selected commit through interactive rebase.
![fedit](https://user-images.githubusercontent.com/43941510/82388905-0d6c9c80-9a7e-11ea-845f-21338c2d3a1f.png)
### fadd
Stage modified files, stage new file or directory interactive by through fzf.
Select files/directories or modified files through fzf and stage the selected files/directories.
- Default: list all modified files and stage selected files. Support multi selection.
- -f: list all files in current directory and stage selected files. Support multi selection. (Used for staging new files to index)
- -d: list all directory under current directory and stage selected directory. Support multi selection. (Used for staging new files to index)
- `-h, --help`: show the help message of `dotbare fadd` and exit.
- `-f, --file`: list all files in current directory and stage selected files. Support multi selection. (Used for staging new files to index).
- `-d, --dir`: list all directory under current directory and stage selected directory. Support multi selection. (Used for staging new files to index).
![fadd demo](https://user-images.githubusercontent.com/43941510/82388994-4e64b100-9a7e-11ea-953a-621d85347c57.png)
### freset
Reset/unstage file, reset HEAD back to certain commits and reset certain file back to certain
commits. Also supports reset HEAD back to certain commits either `--soft`, `--hard`, `--mixed`, as well
as reset a file back to certain commits. More information on differences [here](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt-emgitresetemltmodegtltcommitgt).
Select staged files or commits through fzf and then reset(unstage) staged files or reset HEAD back to certain commits.
Also supports reset HEAD back to certain commits using either `--soft`, `--hard`, `--mixed` flags.
More information on differences between flags [here](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt-emgitresetemltmodegtltcommitgt).
- Default: list all staged files and unstage the selected files. Support multi selection.
- -a: list all tracked files and then prompt commits selection. Reset selected file back to the selected commits. (Default: `--mixed`)
- -c: list all commits and then reset HEAD back to the selected commits. (Default: `--mixed`)
- -S: use `--soft` flag instead of `--mixed` flag
- -H: use `--hard` flag instead of `--mixed` flag
- `-h, --help`: show the help message of `dotbare freset` and exit.
- `-c, --commit`: list all commits and then reset HEAD back to the selected commits. (Default: `--mixed`, put all changes into modified state).
- `-S, --soft`: use `--soft` flag instead of `--mixed` flag, reset HEAD to certain commit without modifying working tree.
- `-H, --hard`: use `--hard` flag instead of `--mixed` flag, reset HEAD to certain commit discard all changes from the working tree.
- `-y, --yes`: acknowledge all actions that will be taken and skip confirmation.
### fcheckout
Checkout files/commit/branch interactively.
Checkout files/commit/branch interactively through fzf.
- Default: list all modified files and reset selected files back to HEAD. Support multi selection. (Discard all changes)
Note: if your file is staged, you will need to unstage first before running fcheckout to make it work.
- -a: list all tracked files and then prompt commit selection, checkout selected file in the version of selected commit.
- -b: list all branch and switch to selected branch.
- -c: list all commits and checkout selected commit.
**Note**: if your file is staged, you will need to unstage first before running fcheckout to make it work.
- `-h, --help`: show the help message of `dotbare fcheckout` and exit.
- `-s, --select`: list all tracked files and select a commit to checkout the selected files. Support multi selection.
- `-b, --branch`: list all branch and switch/checkout the selected branch.
- `-c, --commit`: list all commits and checkout selected commit.
- `-y, --yes`: acknowledge all actions that will be taken and skip confirmation.
![fcheckout demo](https://user-images.githubusercontent.com/43941510/82389569-e2834800-9a7f-11ea-92b5-ed20c8f2ecda.png)
### flog
Interactive log viewer that will prompt you with a menu after selecting a commit. Allows
Interactive log viewer that will prompt you with a menu after selecting a commit. The action menu contains options including
edit, reset, revert and checkout the selected commits.
- Default: list all commits and then prompt menu to select actions.
- -r: revert the selected commit
- -R: reset HEAD back to the selected commit
- -e: edit selected commit through interactive rebase
- -c: checkout selected commit
- Default: list all commits and then prompt menu to select action to perform.
- `-h, --help`: show the help message of `dotbare flog` and exit.
- `-r, --revert`: revert the selected commit and skip action menu.
- `-R, --reset`: reset HEAD back to the selected commit and skip action menu.
- `-e, --edit`: edit selected commit through interactive rebase and skip action menu.
- `-c, --checkout`: checkout selected commit and skip action menu.
- `-y, --yes`: acknowledge all actions that will be taken and skip confirmation.
![flog demo](https://user-images.githubusercontent.com/43941510/82389843-810fa900-9a80-11ea-9653-544816eb9eb8.png)
@ -478,39 +488,44 @@ edit, reset, revert and checkout the selected commits.
View and manage stash interactively.
- Default: list all stash and apply the selected stash. (Default: `apply`)
- -f: list modified files and only stash selected files. Support multi selection.
- -d: list all stash and delete selected stash. Support multi selection.
- -p: use `pop` instead of `apply`. (`pop` would remove the stash while `apply` preserve the stash)
- Default: list all stashes and apply the selected stash. (Default: `apply`).
- `-h, --help`: show the help message of `dotbare fstash` and exit.
- `-s, --select`: list modified files and stash the selected files. Support multi selection.
- `-d, --delete`: list all stashes and delete selected stash. Support multi selection.
- `-p, --pop`: use `pop` instead of `apply`. (`pop` would remove the stash while `apply` preserve the stash).
![fstash demo](https://user-images.githubusercontent.com/43941510/82390106-275bae80-9a81-11ea-8c7c-6573bb1ecada.png)
### fbackup
Backup all of the tracked dotfiles to \$DOTBARE_BACKUP directory. This is used also by
`dotbare finit -u [URL]` for backing up conflicted checkout files.
Backup files to \$DOTBARE_BACKUP directory. This is particular useful when untracking files
or migrating to new machines. This is used by `dotbare finit -u [URL]` for backing up conflicted checkout files.
- Default: backup all tracked dotfiles to \$DOTBARE_BACKUP directory. (Default: use `cp`)
- -s: list all tracked files and only backup selected files. Support multi selection.
- -p PATH: specify path to files and then backup. (This is mainly used by `dotbare finit -u [URL]`)
- -m: use `mv` instead of `cp` to backup. (This is mainly used by `dotbare finit -u [URL]`)
- Default: backup all tracked files to \$DOTBARE_BACKUP directory. (Default: use `cp` command).
- `-h, --help`: show the help message of `dotbare fbackup` and exit.
- `-s, --select`: list all tracked files and only backup the selected files. Support multi selection.
- `-p PATH, --path PATH`: specify path to files to backup. (This is mainly used by `dotbare finit -u [URL]`).
- `-m, --move`: use `mv` instead of the default `cp` command to backup. (This is mainly used by `dotbare finit -u [URL]`).
### fstat
Interactively toggle stage/unstage of files. This is less used compare to `dotbare fadd`,
it might get deprecated.
Display interactive git status menu. Toggle file stage/unstage status interactively.
- `-h, --help`: show the help message of `dotbare fstat` and exit.
### finit
Initialise dotbare with a bare repository or add -u [URL] flag for migrating current
dotfiles to a new system.
Initialise dotbare with a bare repository or add -u [URL] flag for migrating existing dotfiles from
remote git repo to current system.
Note: do not use this command if you are using symlink/GNU stow.
Note: do not use this command if you are using symlink/GNU stow and want to keep your current setup.
- Default: initialise a git bare repository at \$DOTBARE_DIR
- -u URL: migrate existing bare repository from remote to current system.
- -s: if you have defined submodules in your bare repo (i.e. containes .gitmodule), add -s
- Default: init the bare repository at \$DOTBARE_DIR.
- `-h, --help`: show the help message of `dotbare finit` and exit.
- `-u URL, --url URL`: migrate existing dotfiles from remote git repo to current system.
- `-s, --submodule`: if you have defined submodules in your bare repo (i.e. containes .gitmodule), add -s
flag to clone submodules as well during migration.
- `-y, --yes`: acknowledge all actions that will be taken and skip confirmation.
### funtrack
@ -519,39 +534,54 @@ for files and then later on resume tracking changes.
**Note: This command has severe limitations.**
By default, selected files are permanently untracked starting from next commit.
It will not remove it from history. And if your other system pull down the new commit,
the untracked files on the other system will actually get removed by git. This is a limitation
with git, to overcome this, after untracking the files, run `dotbare fbackup` to backup the files.
By default, selected files are permanently untracked from git. Selected files will be
remove from index while keeping the file in your current system. However, when your other
machines pull down the changes, the untracked files will be deleted by git. This is a limitation
with git, to overcome this, after untracking the files, run `dotbare fbackup` to backup all files on
other machines before pulling down the changesto avoid any file loss.
After pulling new changes, move the deleted files from backup back to their original position.
More discussions [here](https://stackoverflow.com/questions/1274057/how-to-make-git-forget-about-a-file-that-was-tracked-but-is-now-in-gitignore).
`dotbare funtrack` does come with capabilities to temporarily untrack files, which will not
actually remove the untracked files from other system. However, this is **NOT** recommended
remove the untracked files from other system. However, this is **NOT** recommended
way to untrack files, explained [here](https://www.git-scm.com/docs/git-update-index#_notes).
- Default: list all tracked files and permanently untrack the selected files. Support multi selection.
- -s: list all tracked files and temporarily untrack changes of the selected files. Support multi selection.
- -S: list all tracked files and resume tracking changes of the selected files.
- `-h, --help`: show the help message of `dotbare funtrack` and exit.
- `-t, --temp`: list all tracked files and temporarily untrack changes of the selected files. Support multi selection.
- `-r, --resume`: list all tracked files and resume tracking changes of the selected files.
- `-y, --yes`: acknowledge all actions that will be taken and skip confirmation.
### fupgrade
Update dotbare to the latest version in master. It basically just pull down changes from master,
except you don't have to cd into dotbare directory, you can run this command any where.
Update dotbare to the latest master. It will perform a `git pull --rebase --stat` and also
performing a auto-stash if needed (copied the method from OMZ). This is useful if you are not
using a plugin manager.
- `-h, --help`: show the help message of `dotbare fstat` and exit.
## Custom scripts
`dotbare` may not contains all the functionalities of your need, feel free to open up feature request. You could also
define your custom scripts under the scripts folder in `dotbare`. The `.gitignore` are configured to ignore everything except the scripts used by `dotbare` default,
so you can name your scripts any name you want. You can then track your custom scripts using `dotbare` to ensure the scripts are available in all of your machines.
Feel free to open pull request for your script, I'm happy to review and discuss for merging.
A dedicated wiki page will be setup to document API for helper functions.
## Tips and Tricks
- Most commands related to files support multi selection (default fzf setting is TAB)
- Most commands related to commits and branches doesn't support multi selection
- Most commands related to files support multi selection (default fzf setting is TAB for multi select).
- Most commands related to commits and branches doesn't support multi selection.
- Checkout fzf [doc](https://github.com/junegunn/fzf/blob/97a725fbd0e54cbc07e4d72661ea2bd2bb7c01c1/man/man1/fzf.1#L648)
for more default fzf keybinds information.
- Alias dotbare to shorter words to type less
- Alias dotbare to shorter words to type less.
```sh
alias db=dotbare
alias dots=dotbare
```
- Create keybinds for dotbare (e.g. bind ctrl-g to launch fedit and edit files)
- Create keybinds for dotbare (e.g. bind ctrl-g to launch fedit and edit files).
```sh
# zsh example
@ -581,31 +611,43 @@ except you don't have to cd into dotbare directory, you can run this command any
echo ".cfg" >> $HOME/.gitignore
```
- Define a custom vim command to select dotfiles using [fzf.vim](https://github.com/junegunn/fzf.vim)
```vim
command! Dots call fzf#run(fzf#wrap({
\ 'source': 'dotbare ls-files --full-name --directory "${DOTBARE_TREE}" | awk -v home="$HOME/" "{print home \$0}"',
\ 'sink': 'e',
\ 'options': [ '--multi', '--preview', 'cat {}' ]
\ }))
```
## Testing
dotbare is unit tested on a _best effort_ due the nature of fzf which require human input.
Mock test are coming if I could make it work.
`dotbare` is unit tested using [bats](https://github.com/bats-core/bats-core). A very weird mock tests are implemented using PATH override method.
This will be improved later and documented in a dedicated README in tests folder for more readability and extensibility.
Some functions may have a lot more coverage than others, so please fire up issues if something went wrong.
dotbare uses [bats](https://github.com/bats-core/bats-core) to test individual functions.
Not all functions have 100% coverage and lots of user interaction cannot be effectively tested, please fire up issues if something went wrong.
I've added AWSCodeBuild to CI/CD just for my personal practice, if you are interested in what's happening in AWSCodeBuild
I've added AWSCodeBuild to CI/CD to build the docker image. It is mainly for my personal practice. If you are interested in what's happening in AWSCodeBuild
you could checkout my cloudformation [template](https://github.com/kazhala/AWSCloudFormationStacks/blob/master/CICD_dotbare.yaml).
## Contributing
Please help me out by pointing out things that I could improve, I've only been
scripting for a few months and are still adapting many new things every day. PR are always welcome
> A CONTRIBUTING.md is coming.
Please help me out by pointing out things that I could improve.
I've only been scripting for a few months and are still learning many new things every day. PR are always welcome
and please fire up issues if something went wrong.
Leave a star if possible :)
Leave a star :)
## Coming up
- [ ] Improve unit test with mocking
- [x] Improve unit test with mocking
- [x] Support submodules during migration
- [ ] Command line completion for dotbare in zsh
- [x] Command line completion for dotbare in bash
- [ ] Command line completion for git commands
- [ ] Man page
- [x] Installation method
@ -619,6 +661,7 @@ for it. I hope you find it useful and enjoy it, thanks!
- credit to [forgit](https://github.com/wfxr/forgit) for inspiration.
- credit to [fzf](https://github.com/junegunn/fzf) for fzf.
- credit to [OMZ](https://github.com/ohmyzsh/ohmyzsh) for upgrading method.
- credit to [this](https://www.atlassian.com/git/tutorials/dotfiles) post for step by step guide of setting up git bare repo.
- credit to [this](https://www.youtube.com/watch?v=tBoLDpTWVOM&t=288s) video for introducing git bare repo.

55
dotbare
View File

@ -5,7 +5,6 @@
# @params
# Globals
# ${mydir}: string, directory of the executing script, used for sourcing helpers
# ${action_command}: string, determine which script to call
# Arguments
# action_command: sub commands dotbare should run
# General git command: log, status etc
@ -17,54 +16,52 @@ mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "${mydir}"/helper/set_variable.sh
function usage() {
echo -e "Usage: dotbare [-h] [COMMANDS] [OPTIONS] ...\n"
echo -e "Interactively manage dotfiles with the help of fzf and git bare repo"
echo -e "To see all dotbare specific COMMANDS, run dotbare without any arguments\n"
echo -e "dotbare is just a wrapper around git hence all git commands will function"
echo -e "normally, just replace git with dotbare (e.g. dotbare commit -m 'message')."
echo -e "dotbare added couple useful scripts starting with 'f' prefix to help you"
echo -e "manage your interact with your git bare repo a little easier with the help of fzf\n"
echo -e "Usage: dotbare [-h] [-v] [COMMANDS] [OPTIONS] ...\n"
echo -e "Interactively manage dotfiles with the help of fzf and git bare repository."
echo -e "To see all dotbare specific COMMANDS, run dotbare without any arguments.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -h, --help\t\tshow this help message and exit."
echo -e " -v, --version\t\tshow dotbare current version.\n"
echo -e "Available commands:"
echo -e " Any git commands, treat dotbare as git"
echo -e " fadd \t\tstage modified file interactively"
echo -e " freset \t\tunstage file or reset commit interactively"
echo -e " funtrack \t\tuntrack file interactively"
echo -e " fstash \t\tmanage stash interactively"
echo -e " fcheckout \t\tcheckout branch/files/commits interactively"
echo -e " fstat \t\tstage/unstage interactively"
echo -e " fedit \t\tselect files/commits and edit interactively"
echo -e " flog \t\tmanage commits interactively"
echo -e " fbackup \t\tperform backup for tracked dotfiles"
echo -e " fupgrade \t\tupdate dotbare to the latest version"
echo -e " finit \t\tinitialise/migrate dotbare"
echo -e " help \t\tshow this help message and exit"
echo -e " All git commands are available, treat dotbare as git."
echo -e " fadd \t\tstage files/directories interactively."
echo -e " freset \t\treset(unstage) files or commit interactively."
echo -e " funtrack \t\tuntrack files interactively."
echo -e " fstash \t\tmanage stash interactively."
echo -e " fcheckout \t\tcheckout branch/files/commit interactively."
echo -e " fstat \t\tinteractive menu to toggle stage/unstage."
echo -e " fedit \t\tinteractively select files/commit and edit."
echo -e " flog \t\tmanage commits interactively."
echo -e " fbackup \t\tperform backup for tracked files."
echo -e " fupgrade \t\tupdate dotbare to the latest master."
echo -e " finit \t\tinitialise dotbare or migrate dotfiles to a new machine."
}
# if no argument, display all possible actions
if [[ $# -eq 0 ]]; then
if [[ "$#" -eq 0 ]]; then
find "${mydir}"/scripts/* -type f -print0 \
| xargs -I __ -0 basename __ \
| fzf --no-multi --header='Available commands' --preview="dotbare {} -h" \
| xargs -I __ dotbare __ -h
| fzf --no-multi --header='Available commands' --preview="${mydir}/dotbare {} -h" \
| xargs -I __ "${mydir}"/dotbare __ -h
exit 0
fi
# shellcheck disable=SC2199
[[ "$@" == 'add --all' ]] && \
[[ "$*" == 'add --all' ]] && \
echo 'If you intend to stage all modified file, run dotbare add -u' && \
echo "dotbare disabled add --all option as this will stage every single file in ${DOTBARE_TREE}" && \
exit 1
case "$1" in
help|-h)
--help|-h)
usage
exit 0
;;
-v|--version)
echo "Current dotbare version: ${DOTBARE_VERSION}"
exit 0
;;
*)
if [[ -x "${mydir}/scripts/$1" ]]; then
# run the scripts
exec "${mydir}/scripts/$1" "${@:2}"
fi
;;

View File

@ -1,3 +1,5 @@
# shellcheck disable=SC2207
mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
[[ :$PATH: != *:"${mydir}":* ]] && export PATH="$PATH:${mydir}"
@ -17,16 +19,25 @@ _dotbare_completions()
}
}')
options=$(
"${mydir}"/dotbare -h \
| awk '{
if ($0 ~ /^ -.*/) {
gsub(/,/, " ", $0)
gsub(/^ /, "", $0)
gsub(/\t\t/, " ", $0)
print $0
}
}'
)
if [[ $curr == -* ]]; then
# shellcheck disable=SC2207
suggestions=($(compgen -W "-h" -- "${curr}"))
suggestions=($(compgen -W "${options}" -- "${curr}"))
else
# shellcheck disable=SC2207
suggestions=($(compgen -W "${subcommands}" -- "${curr}"))
fi
elif [[ "${COMP_WORDS[1]}" == "fbackup" && "${prev}" == '-p' ]]; then
# shellcheck disable=SC2207
COMPREPLY=($(compgen -d -- "${curr}"))
return
@ -36,15 +47,17 @@ _dotbare_completions()
fbackup)
options=$("${mydir}"/dotbare fbackup -h \
| awk -v selected="${selected[*]}" '{
gsub(/,/, " ", $0)
if (selected ~ $1) {
next
} else if ($0 ~ / -p PATH/) {
gsub(/^ -p PATH/, "-p ", $0)
} else if ($0 ~ /^ -p PATH/) {
gsub(/^ -p PATH --path PATH/, "-p", $0)
gsub(/\t/, " ", $0)
print $0
} else if ($0 ~ / -*/) {
} else if ($0 ~ /^ -*/) {
gsub(/^ /, "", $0)
gsub(/\t/, " ", $0)
$2=""
print $0
}
}')
@ -52,15 +65,17 @@ _dotbare_completions()
finit)
options=$("${mydir}"/dotbare finit -h \
| awk -v selected="${selected[*]}" '{
gsub(/,/, " ", $0)
if (selected ~ $1) {
next
} else if ($0 ~ / -u URL/) {
gsub(/^ -u URL/, "-u ", $0)
} else if ($0 ~ /^ -u URL/) {
gsub(/^ -u URL --url URL/, "-u", $0)
gsub(/\t/, " ", $0)
print $0
} else if ($0 ~ / -*/) {
} else if ($0 ~ /^ -*/) {
gsub(/^ /, "", $0)
gsub(/\t/, " ", $0)
$2=""
print $0
}
}')
@ -68,22 +83,23 @@ _dotbare_completions()
f*)
options=$("${mydir}"/dotbare "${COMP_WORDS[1]}" -h \
| awk -v selected="${selected[*]}" '{
gsub(/,/, " ", $0)
if (selected ~ $1) {
next
} else if ($0 ~ / -*/) {
} else if ($0 ~ /^ -*/) {
gsub(/^ /, "", $0)
gsub(/\t/, " ", $0)
$2=""
print $0
}
}')
;;
esac
# shellcheck disable=SC2207
suggestions=($(compgen -W "${options}" -- "${curr}"))
fi
if [[ "${#suggestions[*]}" -eq 1 ]]; then
COMPREPLY=( "${suggestions[0]%% *}" )
COMPREPLY=("${suggestions[@]%% *}")
else
for i in "${!suggestions[@]}"; do
suggestions[$i]="$(printf '%*s' "-$COLUMNS" "${suggestions[$i]}")"

View File

@ -11,10 +11,13 @@
# the selected commit 6 char code
# e.g. b60b330
#######################################
# TODO: line33 "${files[*]}" cannot handle space in file names, but "${files[@]}" won't get properly
# processed by git for whatever reason just in this preview situation but works every where else, HELP needed.
# although this won't affect any real functionality or break the code, it will just print a error message in preview.
function get_commit() {
local header="${1:-select a commit}"
local files="$2"
if [[ -z "${files}" ]]; then
local files=("${@:2}")
if [[ "${#files[@]}" -eq 0 ]]; then
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
log --oneline --color=always --decorate=short \
| fzf --no-multi --header="${header}" \
@ -29,7 +32,7 @@ function get_commit() {
| fzf --no-multi --header="${header}" --preview "echo {} \
| awk '{print \$1}' \
| xargs -I __ /usr/bin/git --git-dir=${DOTBARE_DIR} --work-tree=${DOTBARE_TREE} \
diff --color=always __ $files" \
diff --color=always __ ${files[*]}" \
| awk '{print $1}'
fi
}
@ -89,7 +92,7 @@ function get_git_file() {
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
ls-files --full-name --directory "${DOTBARE_TREE}" \
| fzf --header="${header}" \
--preview "head -50 ${DOTBARE_TREE}/{}" \
--preview "cat ${DOTBARE_TREE}/{}" \
| awk -v home="${DOTBARE_TREE}" -v print_opt="${print_opt}" '{
if (print_opt == "full") {
print home "/" $0
@ -138,12 +141,15 @@ function get_modified_file() {
}
}' \
| fzf --header="${header}" --preview "echo {} \
| awk '{print \$2}' \
| awk '{sub(\$1 FS,\"\");print \$0}' \
| xargs -I __ /usr/bin/git --git-dir=${DOTBARE_DIR} --work-tree=${DOTBARE_TREE} \
diff HEAD --color=always -- ${DOTBARE_TREE}/__" \
| awk -v home="${DOTBARE_TREE}" -v format="${output_format}" '{
if (format == "name") {
print home "/" $2
$1=""
gsub(/^[ \t]/, "", $0)
gsub(/"/, "", $0)
print home "/" $0
} else {
print $0
}

View File

@ -12,7 +12,7 @@
function search_file() {
local search_type="$1"
if [[ "${search_type}" == "f" ]]; then
find . -maxdepth 1 -type f | sed "s|\./||g" | fzf --multi --preview "head -200 {}"
find . -maxdepth 1 -type f | sed "s|\./||g" | fzf --multi --preview "cat {}"
elif [[ "${search_type}" == "d" ]]; then
if tree --version &>/dev/null; then
find . -maxdepth 1 -type d | awk '{if ($0 != "." && $0 != "./.git"){gsub(/^\.\//, "", $0);print $0}}' | fzf --multi --preview "tree -L 1 -C --dirsfirst {}"

View File

@ -4,7 +4,7 @@
#
# @params
# Globals
# ${DOTBARE_DIR}: location of the bare repo
# ${DOTBARE_DIR}: location of the bare repo
# ${DOTBARE_TREE}: which folder is the bare repo tracking
# ${DOTBARE_BACKUP}: backup directory for all tracked files
# ${DOTBARE_KEY}: defualt key bindings
@ -15,6 +15,7 @@
export DOTBARE_DIR="${DOTBARE_DIR:-$HOME/.cfg/}"
export DOTBARE_TREE="${DOTBARE_TREE:-$HOME}"
export DOTBARE_BACKUP="${DOTBARE_BACKUP:-${XDG_DATA_HOME:-$HOME/.local/share}/dotbare}"
export DOTBARE_VERSION="v1.2.0"
export EDITOR="${EDITOR:-vim}"
if [[ -z "${DOTBARE_KEY}" ]]; then

View File

@ -6,11 +6,11 @@
# Globals
# ${mydir}: string, current directory of the executing script
# ${stage_type}: modified, new file, or directory to stage
# ${selected_files}: user selected files to stage
# ${selected_files}: bash array of user selected files to stage
# Arguments
# -h: show help message
# -f: select a file in PWD to stage
# -d: select a directory in PWD to stage
# -h|--help: show help message
# -f|--file: select a file in PWD to stage
# -d|--dir: select a directory in PWD to stage
set -e
set -f
@ -22,57 +22,61 @@ source "${mydir}"/../helper/git_query.sh
function usage() {
echo -e "Usage: dotbare fadd [-h] [-f] [-d] ...\n"
echo -e "Stage the selected file to the dotfile gitbare repo\n"
echo -e "Select files/directories or modified files through fzf."
echo -e "Stage the selected file to the dotfile gitbare repo.\n"
echo -e "Default: list all modified files and stage the selected files.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -f\t\tselect a file in current directory and stage it"
echo -e " -d\t\tselect a entire folder to stage"
echo -e " -h, --help\t\tshow this help message and exit."
echo -e " -f, --file\t\tselect files in current directory and stage the selected files."
echo -e " -d, --dir\t\tselect folders in current directory and stage the selected folders."
}
#######################################
# stage file
# Arguments:
# $1: files to stage
# $1: array of files to stage
#######################################
function stage_file() {
local file=$1
if [[ -z "${file}" ]]; then
exit 1
else
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" add ${file}
fi
local files=("$@")
[[ "${#files[@]}" -eq 0 ]] && exit 1
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" add "${files[@]}"
}
stage_type="modified"
selected_files=()
while getopts ":fhd" opt
do
case "$opt" in
f)
while [[ "$#" -gt 0 ]]; do
case "$1" in
-f|--file)
stage_type="file"
shift
;;
d)
-d|--dir)
stage_type="dir"
shift
;;
h)
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
*)
echo "Invalid option: $1" >&2
usage
exit 1
;;
esac
done
if [[ "${stage_type}" == "file" ]]; then
selected_files=$(search_file 'f' | tr '\n' ' ')
elif [[ "${stage_type}" == "dir" ]]; then
selected_files=$(search_file 'd' | tr '\n' ' ')
else
selected_files=$(get_modified_file 'select files to stage' "unstaged" | tr '\n' ' ')
fi
stage_file "${selected_files}"
while IFS= read -r line; do
selected_files+=("${line}")
done < <(
if [[ "${stage_type}" == "file" ]]; then
search_file 'f'
elif [[ "${stage_type}" == "dir" ]]; then
search_file 'd'
else
get_modified_file "select files to stage" "unstaged"
fi
)
stage_file "${selected_files[@]}"

View File

@ -9,10 +9,10 @@
# ${selected_files}: selected files to backup
# ${action_command}: actions to run, cp|mv
# Arguments
# -h: show help message and exit
# -s: select individual files through fzf and backup
# -p: pass in path and backup
# -m: use mv to backup instead of cp
# -h|--help: show help message and exit
# -s|--select: select individual files through fzf and backup
# -p PATH|--path PATH: pass in path and backup
# -m|--move: use mv to backup instead of cp
set -e
set -f
@ -23,14 +23,14 @@ source "${mydir}"/../helper/git_query.sh
function usage() {
echo -e "Usage: dotbare fbackup [-h] [-m] [-s] [-p PATH] ...\n"
echo -e "Backup files to ${DOTBARE_BACKUP}"
echo -e "This is useful when untracking files or migrating on new machines\n"
echo -e "Default: backup every tracked files using cp to ${DOTBARE_BACKUP} directory\n"
echo -e "Backup files to ${DOTBARE_BACKUP}."
echo -e "This is useful when untracking files or migrating to new machines.\n"
echo -e "Default: backup all tracked files using cp command to ${DOTBARE_BACKUP} directory.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -s\t\tselect individual file through fzf and backup"
echo -e " -p PATH\tsepcify path to backup"
echo -e " -m\t\tuse mv command for backup instead of default cp"
echo -e " -h, --help\t\tshow this help message and exit."
echo -e " -s, --select\t\tlist all tracked files and only backup the selected files."
echo -e " -p PATH, --path PATH\tsepcify path of files to backup."
echo -e " -m, --move\t\tuse 'mv' instead of the default 'cp' command to backup."
}
#######################################
@ -52,23 +52,30 @@ function dotbare_backup() {
backup_type="all"
action_command='cp'
while getopts ":hsp:m" opt; do
case "$opt" in
s)
backup_type='individual'
selected_files=""
while [[ "$#" -gt 0 ]]; do
case "$1" in
-s|--select)
backup_type="select"
shift
;;
p)
selected_files="${OPTARG}"
-p|--path)
[[ -z "$2" ]] && echo "Invalid option: $1" >&2 && usage && exit 1
selected_files="$2"
shift
shift
;;
m)
-m|--move)
action_command="mv"
shift
;;
h)
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
echo "Invalid option: $1" >&2
usage
exit 1
;;
@ -79,7 +86,7 @@ done
[[ -n "${selected_files}" ]] && dotbare_backup "${selected_files}" "${action_command}"
cd "${DOTBARE_TREE}"
if [[ "${backup_type}" == 'individual' ]]; then
if [[ "${backup_type}" == 'select' ]]; then
selected_files=$(get_git_file "select files to backup" "raw")
else
selected_files=$(/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \

View File

@ -5,16 +5,16 @@
# @params
# Globals
# ${mydir}: current directory of the script, used for imports
# ${action_type}: what type of git commands to use, branch, commit files, modified files
# ${action_type}: what type of git commands to use (branch|select|commit|modified)
# ${selected_branch}: selected_branch to switch
# ${selected_files}: selected_files to checkout to the version in HEAD
# ${selected_files}: selected_files to checkout
# ${selected_commit}: selected commit to checkout
# ${confirm}: confirm status of the user
# Arguments
# -h: show help message
# -a: search all files instead of just the modified files
# -b: search branch and checkout branch
# -c: search commit and checkout commit
# -h|--help: show help message
# -s|--select: search all files instead of just the modified files
# -b|--branch: search branch and checkout branch
# -c|--commit: search commit and checkout commit
set -e
set -f
@ -25,39 +25,50 @@ source "${mydir}"/../helper/get_confirmation.sh
source "${mydir}"/../helper/git_query.sh
function usage() {
echo -e "Usage: dotbare fcheckout [-h] [-a] [-b] [-c] ...\n"
echo -e "Checkout files/commit/branch using fzf\n"
echo -e "Default: checkout files back to HEAD (Reset changes back to HEAD)\n"
echo -e "Usage: dotbare fcheckout [-h] [-s] [-b] [-c] [-y] ...\n"
echo -e "Select files/commit/branch through fzf and checkout the selected objects."
echo -e "Files: checkout the version in HEAD or in a specific commit (reset files content back to the selected commit)."
echo -e "Branch: switch to the selected branch."
echo -e "Commit: switch to a specific commit.\n"
echo -e "Default: list all modified files and reset selected files back to HEAD.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -a\t\tsearch all files and select a commit to checkout for selected files"
echo -e " -b\t\tlist all branch and checkout/switch the selected branch"
echo -e " -c\t\tlist all commits and checkout selected commit"
echo -e " -h, --help\t\tshow this help message and exit."
echo -e " -s, --select\t\tlist all tracked files and select a commit to checkout the selected files."
echo -e " -b, --branch\t\tlist all branch and checkout/switch the selected branch."
echo -e " -c, --commit\t\tlist all commits and checkout selected commit."
echo -e " -y, --yes\t\tacknowledge all actions that will be taken and skip confirmation."
}
action_type="modified"
selected_files=()
confirm=""
selected_commit=""
selected_branch=""
while getopts ":habcy" opt
do
case "$opt" in
a)
action_type="allfiles"
while [[ "$#" -gt 0 ]]; do
case "$1" in
-s|--select)
action_type="select"
shift
;;
b)
-b|--branch)
action_type="branch"
shift
;;
c)
-c|--commit)
action_type="commit"
shift
;;
y)
-y|--yes)
confirm="y"
shift
;;
h)
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
echo "Invalid option: $1" >&2
usage
exit 1
;;
@ -66,36 +77,35 @@ done
if [[ "${action_type}" == "branch" ]]; then
# checkout branch
selected_branch=$(get_branch 'Select a branch to checkout')
[[ -z "${selected_branch}" ]] && exit 0
selected_branch=$(get_branch 'select a branch to checkout')
[[ -z "${selected_branch}" ]] && exit 1
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" checkout "${selected_branch}"
exit 0
elif [[ "${action_type}" == "commit" ]]; then
# checkout commit
selected_commit=$(get_commit 'Select a commit to checkout')
[[ -z "${selected_commit}" ]] && exit 0
selected_commit=$(get_commit 'select a commit to checkout')
[[ -z "${selected_commit}" ]] && exit 1
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" checkout "${selected_commit}"
exit 0
else
# checkout files (reset file changes back to HEAD)
if [[ "${action_type}" == "modified" ]]; then
selected_files=$(get_modified_file 'select a file to checkout version in HEAD' | tr '\n' ' ')
[[ -z "${selected_files}" ]] && exit 0
echo "(dryrun) dotbare checkout -- ${selected_files}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation "Confirm?")
[[ "${confirm}" != 'y' ]] && exit 1
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" checkout -- ${selected_files}
elif [[ "${action_type}" == "allfiles" ]]; then
selected_files=$(get_git_file 'select a file to checkout' | tr '\n' ' ')
[[ -z "${selected_files}" ]] && exit 0
# continue select a commit and then checkout the file back to the selected commit
selected_commit=$(get_commit 'select the target commit' "${selected_files}")
[[ -z "${selected_commit}" ]] && exit 0
echo "(dryrun) dotbare checkout ${selected_commit} -- ${selected_files}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation "Confirm?")
[[ "${confirm}" != 'y' ]] && exit 0
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" checkout "${selected_commit}" ${selected_files}
fi
elif [[ "${action_type}" == "modified" ]]; then
# checkout modified file back to version in HEAD
while IFS= read -r line; do
selected_files+=("${line}")
done < <(get_modified_file 'select a file to checkout version in HEAD')
[[ "${#selected_files[@]}" -eq 0 ]] && exit 1
[[ -z "${confirm}" ]] && echo "(dryrun) dotbare checkout --" "${selected_files[@]}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation "Confirm?")
[[ "${confirm}" != 'y' ]] && exit 1
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" checkout -- "${selected_files[@]}"
elif [[ "${action_type}" == "select" ]]; then
# checkout selected files to a selected commit
while IFS= read -r line; do
selected_files+=("${line}")
done < <(get_git_file 'select a file to checkout')
[[ "${#selected_files[@]}" -eq 0 ]] && exit 1
# continue select a commit and then checkout the file back to the selected commit
selected_commit=$(get_commit 'select the target commit' "${selected_files[@]}")
[[ -z "${selected_commit}" ]] && exit 1
[[ -z "${confirm}" ]] && echo "(dryrun) dotbare checkout ${selected_commit} --" "${selected_files[@]}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation "Confirm?")
[[ "${confirm}" != 'y' ]] && exit 0
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" checkout "${selected_commit}" "${selected_files[@]}"
fi

View File

@ -7,11 +7,11 @@
# ${mydir}: current directory of the script
# ${edit_type}: which type to edit, all files, modified files, commit
# ${selected_commit}: selected commit to edit
# ${selected_files}: selected file to edit
# ${selected_files}: arrays of selected file to edit
# Arguments
# -m: display modified file only
# -c: edit commit using interactive rebase
# -h: show helpe message and exit
# -m|--modified: display modified file only
# -c|--commit: edit commit using interactive rebase
# -h|--help: show helpe message and exit
set -e
set -f
@ -22,30 +22,34 @@ source "${mydir}"/../helper/git_query.sh
function usage() {
echo -e "Usage: dotbare fedit [-h] [-m] [-c] ...\n"
echo -e "Select files/commits through fzf and edit selected files/commits\n"
echo -e "Default: list all dotfiles and edit the selected files\n"
echo -e "Select files/commits through fzf and edit selected files/commits in EDITOR.\n"
echo -e "Default: list all tracked dotfiles and edit the selected files.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -m\t\tonly display modified file"
echo -e " -c\t\tedit commit using interactive rebase instead"
echo -e " -h, --help\t\tshow this help message and exit."
echo -e " -m, --modified\tonly list and edit selected modified files."
echo -e " -c, --commit\t\tlist commit and edit the selected commit through interactive rebase."
}
edit_type='all'
edit_type="all"
selected_files=()
selected_commit=""
while getopts ":hmc" opt; do
case "$opt" in
m)
edit_type='modified'
while [[ "$#" -gt 0 ]]; do
case "$1" in
-m|--modified)
edit_type="modified"
shift
;;
c)
edit_type='commit'
-c|--commit)
edit_type="commit"
shift
;;
h)
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
echo "Invalid option: $1" >&2
usage
exit 1
;;
@ -53,16 +57,19 @@ while getopts ":hmc" opt; do
done
if [[ "${edit_type}" == "commit" ]]; then
selected_commit=$(get_commit "Select a commit to rename")
selected_commit=$(get_commit "select a commit to rename")
[[ -z "${selected_commit}" ]] && exit 1
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" rebase -i "${selected_commit}"~
else
if [[ "${edit_type}" == "modified" ]]; then
selected_files=$(get_modified_file "Select tracked files to edit")
else
selected_files=$(get_git_file "Select tracked files to edit")
fi
[[ -z "${selected_files}" ]] && exit 1
# shellcheck disable=SC2086
command "${EDITOR}" ${selected_files}
while IFS= read -r line; do
selected_files+=("${line}")
done < <(
if [[ "${edit_type}" == "modified" ]]; then
get_modified_file "select modified files to edit"
else
get_git_file "select tracked files to edit"
fi
)
[[ "${#selected_files[@]}" -eq 0 ]] && exit 1
exec "${EDITOR}" "${selected_files[@]}"
fi

View File

@ -1,17 +1,18 @@
#!/usr/bin/env bash
#
# init the git bare repo
# init or migrate the git bare repo
#
# @params
# Globals
# ${mydir}: current dir of the script
# ${confirm}: confirm status of the user
# ${post_hooks}: post checkout actions to perform
# ${post_hooks}: array of post checkout actions to perform
# ${remote_url}; remote_url to clone and migrate
# Arguments
# -h: show help message and exit
# -u: specify remote dotfiles url to init
# -s: clone submodules after checkout
# -y: confirm action by default and skip confirmation
# -h|--help: show help message and exit
# -u URL|--url URL: specify remote dotfiles url to init
# -s|--select: clone submodules after checkout
# -y|--yes: confirm action by default and skip confirmation
set -e
set -f
@ -22,39 +23,48 @@ source "${mydir}"/../helper/get_confirmation.sh
function usage() {
echo -e "Usage: dotbare finit [-h] [-y] [-s] [-u URL] ...\n"
echo -e "Init the git bare repository if doesn't exist"
echo -e "Init the git bare repository if doesn't exist or migrate existing dotfiles to current system."
# shellcheck disable=SC2016
echo -e 'The bare repository will be initialised under $DOTBARE_DIR, default to $HOME/.cfg if not set'
echo -e 'The bare repository will be initialised under $DOTBARE_DIR, default to $HOME/.cfg if not set.'
# shellcheck disable=SC2016
echo -e 'It will track $DOTBARE_TREE, default to $HOME if not set\n'
echo -e "Default: init the bare repository at $DOTBARE_DIR\n"
echo -e 'It will track $DOTBARE_TREE, default to $HOME if not set.\n'
echo -e "Migration example:"
echo -e "dotbare finit -u URL --submodule\n"
echo -e "Default: init the bare repository at $DOTBARE_DIR.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -u URL\tmigrate existing dotfiles from the git URL to current system"
echo -e " -s\t\tclone submodules after checkout"
echo -e " -y\t\tconfirm action by default and skip confirmation"
echo -e " -h, --help\t\tshow this help message and exit."
echo -e " -u URL, --url URL\tmigrate existing dotfiles from remote git repo to current system."
echo -e " -s, --submodule\tclone submodules during migration."
echo -e " -y, --yes\t\tacknowledge all actions that will be taken and skip confirmation."
}
remote_url=""
post_hooks=()
while getopts ":hu:ys" opt; do
case "$opt" in
s)
confirm=""
while [[ "$#" -gt 0 ]]; do
case "$1" in
-s|--submodule)
[[ ! "${post_hooks[*]}" =~ submodule ]] && \
post_hooks+=("submodule")
shift
;;
u)
remote_url="${OPTARG}"
-u|--url)
[[ -z "$2" ]] && echo "Invalid option: $1" >&2 && usage && exit 1
remote_url="$2"
shift
shift
;;
y)
-y|--yes)
confirm='y'
shift
;;
h)
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
echo "Invalid option: $1" >&2
usage
exit 1
;;
@ -62,7 +72,6 @@ while getopts ":hu:ys" opt; do
done
if [[ -z "${remote_url}" ]]; then
echo "modify DOTBARE_DIR and DOTBARE_TREE to customize location, more information run dotbare finit -h"
echo "git bare repository will be initialised at ${DOTBARE_DIR}"
echo "git bare repository will be tracking ${DOTBARE_TREE}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation)

View File

@ -9,12 +9,12 @@
# ${selected_commit}: user selected commit
# ${confirm}: confirm status of user
# Arguments
# -h: display help message
# -r: revert the selected commit
# -R: reset HEAD back to the selected commit
# -e: edit commmit (interactive rebase)
# -c: checkout selected commmit
# -y: confirm action by default and skip confirmation
# -h|--help: display help message
# -r|--revert: revert the selected commit
# -R|--reset: reset HEAD back to the selected commit
# -e|--edit: edit commmit (interactive rebase)
# -c|--checkout: checkout selected commmit
# -y|--yes: confirm action by default and skip confirmation
set -e
set -f
@ -25,17 +25,17 @@ source "${mydir}"/../helper/git_query.sh
source "${mydir}"/../helper/get_confirmation.sh
function usage() {
echo -e "Usage: dotbare flog [-h] [-r] [-R] [-e] [-c] ...\n"
echo -e "Interactive log viewer with action menu"
echo -e "Action menu contains command including revert|reset|edit|checkout|exit\n"
echo -e "Default: list all commits and prompt a menu for user to take action on the selected commit\n"
echo -e "Usage: dotbare flog [-h] [-r] [-R] [-e] [-c] [-y] ...\n"
echo -e "Interactive log viewer with action menu."
echo -e "Action menu contains options including revert|reset|edit|checkout|exit.\n"
echo -e "Default: list all commits and prompt a menu to select action to perform.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -r\t\trevert the selected commit"
echo -e " -R\t\treset HEAD back to selected commit"
echo -e " -e\t\tedit selected commit through interactive rebase"
echo -e " -c\t\tcheckout selected commit"
echo -e " -y\t\tconfirm action by default and skip confirmation"
echo -e " -h, --help\t\tshow this help message and exit."
echo -e " -r, --revert\t\trevert the selected commit and skip action menu."
echo -e " -R, --reset\t\treset HEAD back to selected commit and skip action menu."
echo -e " -e, --edit\t\tedit selected commit through interactive rebase and skip action menu."
echo -e " -c, --checkout\tcheckout selected commit and skip action menu."
echo -e " -y, --yes\t\tacknowledge all actions that will be taken and skip confirmation."
}
#######################################
@ -65,8 +65,7 @@ function draw_menu() {
header="commit ${selected_commit}: ${message}"
selected_action=$(echo -e "${menu}" \
| fzf --no-multi --header="${header}" \
| awk '{
gsub(/:/, "", $1)
| awk -F ":" '{
print $1
}'
)
@ -75,30 +74,37 @@ function draw_menu() {
}
selected_action=""
selected_commit=""
confirm=""
while getopts ":hrRecy" opt; do
case "$opt" in
r)
while [[ "$#" -gt 0 ]]; do
case "$1" in
-r|--revert)
selected_action="revert"
shift
;;
R)
-R|--reset)
selected_action="reset"
shift
;;
e)
-e|--edit)
selected_action="edit"
shift
;;
c)
-c|--checkout)
selected_action="checkout"
shift
;;
y)
-y|--yes)
confirm='y'
shift
;;
h)
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
echo "Invalid option: $1" >&2
usage
exit 1
;;
@ -113,9 +119,9 @@ while :; do
done
if [[ "${selected_action}" != 'exit' ]]; then
if [[ "${selected_action}" == "reset" ]]; then
if [[ "${selected_action}" == "reset" ]] && [[ -z "${confirm}" ]]; then
echo "(dryrun) reset HEAD to ${selected_commit}"
else
elif [[ -z "${confirm}" ]]; then
echo "(dryrun) ${selected_action} ${selected_commit}"
fi
[[ -z "${confirm}" ]] && confirm=$(get_confirmation)

View File

@ -6,18 +6,17 @@
# @params
# Globals
# ${mydir}: current directory of the script
# ${reset_type}: reset type, modified files, all files or commit
# ${reset_type}: reset type, modified files or commit
# ${reset_option}: git reset flag, --mixed | --soft | --hard
# ${selected_files}: selected file to unstage
# ${selected_files}: selected file to reset
# ${selected_commit}: selected commit to reset
# ${confirm}: confirmation status of the user
# Arguments
# -h: show help message and quit
# -a: select files and select a commit to reset the fiel back to selected commit
# -c: reset commit
# -S: use --soft flag
# -H: use --hard flag
# -y: confirm action by default and skip confirmation
# -h|--help: show help message and quit
# -c|--commit: reset commit
# -S|--soft: use --soft flag
# -H|--hard: use --hard flag
# -y|--yes: confirm action by default and skip confirmation
set -e
set -f
@ -28,46 +27,48 @@ source "${mydir}"/../helper/get_confirmation.sh
source "${mydir}"/../helper/git_query.sh
function usage() {
echo -e "Usage: dotbare freset [-h] [-a] [-c] [-S] [-H] ...\n"
echo -e "Reset/Unstage the selected staged file"
echo -e "Or reset the HEAD to certain commits by using -c flag\n"
echo -e "Default: unstage the selected files from\n"
echo -e "Usage: dotbare freset [-h] [-c] [-S] [-H] [-y] ...\n"
echo -e "Reset(unstage) the selected staged files."
echo -e "Reset the HEAD to certain commits by using -c flag.\n"
echo -e "Default: unstage the selected files.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -a\t\tselect files and then select a commit to reset the file back to the selected comit"
echo -e " -c\t\treset commit to certain commit, default --mixed flag, reset HEAD to certain commit put all changes into modified states"
echo -e " -S\t\treset commit using --soft flag, reset HEAD to certain commit without modify working tree"
echo -e " -H\t\treset commit using --hard flag, reset HEAD to certain commit dicard all changes from the working tree"
echo -e " -y\t\tconfirm action by default and skip confirmation"
echo -e " -h, --help\t\tshow this help message and exit."
echo -e " -c, --commit\t\treset commit to certain commit, default --mixed flag, reset HEAD to certain commit put all changes into modified state."
echo -e " -S, --soft\t\treset commit using --soft flag, reset HEAD to certain commit without modify working tree."
echo -e " -H, --hard\t\treset commit using --hard flag, reset HEAD to certain commit discard all changes from the working tree."
echo -e " -y, --yes\t\tacknowledge all actions that will be taken and skip confirmation."
}
reset_option="--mixed"
reset_type="modified"
selected_files=()
confirm=""
selected_commit=""
while getopts ":hacSHy" opt
do
case "$opt" in
a)
reset_type="allfiles"
;;
c)
while [[ "$#" -gt 0 ]]; do
case "$1" in
-c|--commit)
reset_type="commit"
shift
;;
S)
-S|--soft)
reset_option="--soft"
shift
;;
H)
-H|--hard)
reset_option="--hard"
shift
;;
y)
-y|--yes)
confirm='y'
shift
;;
h)
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
*)
echo "Invalid option: $1" >&2
usage
exit 1
;;
@ -75,23 +76,15 @@ do
done
if [[ "${reset_type}" == "commit" ]]; then
selected_commit=$(get_commit)
[[ -z "${selected_commit}" ]] && exit 0
selected_commit=$(get_commit "select the target commit for HEAD")
[[ -z "${selected_commit}" ]] && exit 1
[[ -z "${confirm}" ]] && confirm=$(get_confirmation "Reset HEAD to ${selected_commit} ${reset_option}?")
[[ "${confirm}" != 'y' ]] && exit 1
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" reset "${selected_commit}" "${reset_option}"
else
if [[ "${reset_type}" == "modified" ]]; then
selected_files=$(get_modified_file 'select files to unstage' 'staged' | tr '\n' ' ')
[[ -z "${selected_files}" ]] && exit 0
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" reset HEAD ${selected_files}
else
selected_files=$(get_git_file 'select a file to reset' | tr '\n' ' ')
[[ -z "${selected_files}" ]] && exit 0
selected_commit=$(get_commit "select the target commit" "${selected_files}")
[[ -z "${selected_commit}" ]] && exit 0
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" reset "${selected_commit}" ${selected_files}
fi
while IFS= read -r line; do
selected_files+=("${line}")
done < <(get_modified_file 'select files to unstage' 'staged')
[[ "${#selected_files[@]}" -eq 0 ]] && exit 1
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" reset "${selected_files[@]}"
fi

View File

@ -6,13 +6,14 @@
# Globals
# ${mydir}: current dir of the script, source purpose
# ${stash_command}: stash command, pop, apply or file/delete to stash file or delete stash
# ${selected_file}: selected files to stash
# ${selected_files}: selected files to stash
# ${selected_stash}: selected stash to apply
# ${confirm}: user confirm status
# Arguments
# -h: show help message
# -f: select individual files and stash
# -d: delete selected stash
# -p: use pop instead of apply on the selected stash
# -h|--help: show help message
# -s|--select: select individual files and stash
# -d|--delete: delete selected stash
# -p|--pop: use pop instead of apply on the selected stash
set -e
set -f
@ -23,55 +24,64 @@ source "${mydir}"/../helper/get_confirmation.sh
source "${mydir}"/../helper/git_query.sh
function usage() {
echo -e "Usage: dotbare fstash [-h] [-f] [-d] [-p] ...\n"
echo -e "save/apply/delect stash using fzf, also supports stashing individual file\n"
echo -e "Default: running fstash will apply the selected stash\n"
echo -e "Usage: dotbare fstash [-h] [-s] [-d] [-p] ...\n"
echo -e "View and manage stash interactively.\n"
echo -e "Default: list all stashes and apply the selected stash.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -f\t\tselect modified files through fzf and stash them"
echo -e " -d\t\tdelete the selected stash from stash list"
echo -e " -p\t\tuse pop instead of apply when retrieving stash"
echo -e " -h, --help\t\tshow this help message and exit."
echo -e " -s, --select\t\tlist modified files and stash the selected files."
echo -e " -d, --delete\t\tlist all stashes and delete the selected stash from stash list."
echo -e " -p, --pop\t\tuse 'stash pop' instead of 'stash apply'."
}
stash_command="apply"
selected_files=()
selected_stash=""
confirm=""
while getopts ":hdfpy" opt; do
case "$opt" in
p)
while [[ "$#" -gt 0 ]]; do
case "$1" in
-p|--pop)
stash_command="pop"
shift
;;
f)
stash_command="file"
-s|--select)
stash_command="select"
shift
;;
d)
-d|--delete)
stash_command="delete"
shift
;;
y)
confirm='y'
-y|--yes)
confirm="y"
shift
;;
h)
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
echo "Invalid option: $1" >&2
usage
exit 1
;;
esac
done
if [[ "${stash_command}" == "file" ]]; then
selected_file=$(get_modified_file "select files to add to a stash")
[[ -z "${selected_file}" ]] && exit 1
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" stash -- ${selected_file}
if [[ "${stash_command}" == "select" ]]; then
while IFS= read -r line; do
selected_files+=("${line}")
done < <(get_modified_file "select files to add to a stash")
[[ "${#selected_files[@]}" -eq 0 ]] && exit 1
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" stash -- "${selected_files[@]}"
elif [[ "${stash_command}" == "delete" ]]; then
selected_stash=$(get_stash "select stash to delete")
[[ -z "${selected_stash}" ]] && exit 1
while IFS= read -r line; do
echo "(dryrun) Drop ${line}"
done <<< "${selected_stash}"
[[ -z "${confirm}" ]] && \
while IFS= read -r line; do
echo "(dryrun) drop ${line}"
done <<< "${selected_stash}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation)
[[ "${confirm}" != 'y' ]] && exit 1
while IFS= read -r line; do
@ -80,5 +90,8 @@ elif [[ "${stash_command}" == "delete" ]]; then
else
selected_stash=$(get_stash "select stash to apply" "true")
[[ -z "${selected_stash}" ]] && exit 1
[[ -z "${confirm}" ]] && echo "(dryrun) ${stash_command} ${selected_stash}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation)
[[ "${confirm}" != 'y' ]] && exit 1
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" stash "${stash_command}" "${selected_stash}"
fi

View File

@ -1,15 +1,16 @@
#!/usr/bin/env bash
#
# interactive git status menu
# allow staging ustaging actions
# toggle stage and unstage
#
# @params
# Globals
# ${mydir}: current directory of where the script is running
# ${selected_files}: selected file to stage or unstage
# ${selected_files}: raw selected file (with current git status prepend)
# ${selected_filenames}: bash array of names for the selected_files
# ${stage_file}: determine if current operation should be staging file or unstage
# Arguments
# -h: show help message and exit
# -h|--help: show help message and exit
set -e
set -f
@ -20,20 +21,20 @@ source "${mydir}"/../helper/git_query.sh
function usage() {
echo -e "Usage: dotbare fstat [-h] ...\n"
echo -e "Display interactive git status menu"
echo -e "Stage, unstage, interactively\n"
echo -e "Display interactive git status menu."
echo -e "Toggle file stage/unstage interactively.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -h, --help\t\tshow this help message and exit."
}
while getopts ":h" opt; do
case "$opt" in
h)
while [[ "$#" -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
echo "Invalid option: $1" >&2
usage
exit 1
;;
@ -41,24 +42,43 @@ while getopts ":h" opt; do
done
while :; do
selected_files=$(get_modified_file "select a file" "all" "raw")
[[ -z "${selected_files}" ]] && break
# reset all variable and arrays for each loop
selected_files=()
selected_filenames=()
stage_file=""
while IFS= read -r line; do
selected_files+=("${line}")
done < <(get_modified_file "select files to stage/unstage" "all" "raw")
[[ "${#selected_files[@]}" -eq 0 ]] && break
# check if current operation should stage file or unstage file
stage_file=$(echo "${selected_files}" | awk '{
# if any file start with M but has char immediately follow it, new changes are made, stage file
# if any file start with a space or tab, the file is not staged, stage file
# otherwise, we unstage
stage_file=$(printf '%s\n' "${selected_files[@]}" | awk '{
if ($0 ~ /^[A-Za-z][A-Za-z].*$/) {
print "stage"
} else if ($0 ~ /^[ \t].*$/) {
print "stage"
}
}')
selected_files=$(echo "${selected_files}" | awk -v home="${DOTBARE_TREE}" '{
print home "/" $2
}')
while IFS= read -r line; do
selected_filenames+=("${line}")
done < <(
printf '%s\n' "${selected_files[@]}" \
| awk -v home="${DOTBARE_TREE}" '{
$1=""
gsub(/^[ \t]/, "", $0)
gsub(/"/, "", $0)
print home "/" $0
}'
)
if [[ -z "${stage_file}" ]]; then
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" reset --quiet HEAD ${selected_files}
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" reset --quiet HEAD "${selected_filenames[@]}"
else
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" add ${selected_files}
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" add "${selected_filenames[@]}"
fi
done

View File

@ -5,14 +5,14 @@
# @params
# Globals
# ${mydir}: current dir of the script
# ${track_type}: what method to use for untrack, untrack, update, retrack
# ${confirm}: use confirm status
# ${selected_files}: user selected_files for operation
# ${track_type}: determine method to use for untrack, possible values: untrack, temp, resume
# ${confirm}: user confirm status
# ${selected_files}: arrays of user selected_files for operation
# Arguments
# -h: display help message and exit
# -s: temporarily untrack files
# -S: resume track of temp untracked files
# -y: confirm action by default and skip confirmation
# -h|--help: display help message and exit
# -t|--temp: temporarily untrack files
# -r|--resume: resume track of temp untracked files
# -y|--yes: confirm action by default and skip confirmation
set -e
set -f
@ -23,82 +23,85 @@ source "${mydir}"/../helper/git_query.sh
source "${mydir}"/../helper/get_confirmation.sh
function usage() {
echo -e "Usage: dotbare funtrack [-h] [-s] [-S] ...\n"
echo -e "Untrack selected files from git\n"
echo -e "Default: the untrack will remove the file from index while"
echo -e "keeping the file in your current system (git rm --cached filename)"
echo -e "however, when your other computer pull down the changes, the file will be removed"
echo -e "make sure to run dotbare fbackup before pulling down the changes, alternativly"
echo -e "use the -s flag (git update-index --assume-unchanged [path])\n"
echo -e "Usage: dotbare funtrack [-h] [-t] [-r] [-y] ...\n"
echo -e "Untrack selected files from git.\n"
echo -e "Default: list all tracked files and permanently untrack the selected files (using git rm --cached filename).\n"
echo -e "Files will be remove from index while keeping the file in your current system."
echo -e "However, when your other computers pull down the changes, the untracked files will be deleted."
echo -e "Make sure to run dotbare fbackup before pulling down the changes.\n"
echo -e "Alternatively use the -t flag (using git update-index --assume-unchanged [path]) to temporarily"
echo -e "untrack a file but keeping the files when other computers pull down the changes."
echo -e "More information please refere to dotbare's github.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -s\t\ttemporarily ignore changes of selected files"
echo -e " \t\tuse -S flag to resume tracking changes of selected_files"
echo -e " -S\t\tresume tracking changes of selected files"
echo -e " -y\t\tconfirm action by default and skip confirmation"
echo -e " -h, --help\t\tshow this help message and exit."
echo -e " -t, --temp\t\tlist all tracked files and temporarily ignore changes of the selected files."
echo -e " -r, --resume\t\tlist all tracked files and resume tracking changes of the selected files."
echo -e " -y, --yes\t\tacknowledge all actions that will be taken and skip confirmation."
}
track_type="untrack"
selected_files=()
confirm=""
while getopts ":hsSy" opt
do
case "$opt" in
s)
track_type="update"
while [[ "$#" -gt 0 ]]; do
case "$1" in
-t|--temp)
track_type="temp"
shift
;;
S)
-r|--resume)
track_type="retrack"
shift
;;
y)
-y|--yes)
confirm='y'
shift
;;
h)
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
echo "Invalid option: $1" >&2
usage
exit 1
;;
esac
done
selected_files=$(get_git_file "select files to untrack" | tr "\n" " ")
[[ -z "${selected_files}" ]] && exit 1
while IFS= read -r line; do
selected_files+=("${line}")
done < <(get_git_file "select files to untrack")
[[ "${#selected_files[@]}" -eq 0 ]] && exit 1
if [[ "${track_type}" == "update" ]]; then
echo "(dryrun) dotbare update-index --assume-unchanged ${selected_files}"
if [[ "${track_type}" == "temp" ]]; then
[[ -z "${confirm}" ]] && echo "(dryrun) dotbare update-index --assume-unchanged" "${selected_files[@]}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation "Files will be temporarily stop being tracked for changes, continue?")
[[ "${confirm}" != 'y' ]] && exit 1
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" update-index --assume-unchanged ${selected_files}
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" update-index --assume-unchanged "${selected_files[@]}"
echo -e " "
echo "Selected files are temporarily untracked by git, use -S to continue tracking changes."
echo "dotbare funtrack -s is not the recommanded way to untrack files, although it won't delete"
echo "the files on other machines, please refer to git update-index official"
echo "documentation for more information"
echo "Selected files are temporarily untracked by git, use dotbare funtrack -r to continue tracking changes."
echo "Although dotbare funtrack -t won't delete the files on other machines, it is not the recommended way to untrack files."
echo "dotbare funtrack -t is using git update-index --assume-unchanged under the hood"
echo "Please refer to git update-index official documentation for more details or visit dotbare's github page"
elif [[ "${track_type}" == "retrack" ]]; then
echo "(dryrun) dotbare update-index --no-assume-unchanged ${selected_files}"
[[ -z "${confirm}" ]] && echo "(dryrun) dotbare update-index --no-assume-unchanged" "${selected_files[@]}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation "Files will resume being tracked by git, continue?")
[[ "${confirm}" != 'y' ]] && exit 1
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" update-index --no-assume-unchanged ${selected_files}
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" update-index --no-assume-unchanged "${selected_files[@]}"
echo " "
echo "Selected files are being resumed for track by git."
echo "dotbare funtrack -s not the recommanded way to untrack files, although it won't delete"
echo "the files on other machines, please refer to git update-index official"
echo "documentation for more information"
echo "Selected files are being resumed for tracking by git."
echo "Although dotbare funtrack -t won't delete the files on other machines, it is not the recommended way to untrack files."
echo "dotbare funtrack -t is using git update-index --assume-unchanged under the hood"
echo "Please refer to git update-index official documentation for more details or visit dotbare's github page"
else
echo "(dryrun) dotbare rm --cached ${selected_files}"
[[ -z "${confirm}" ]] && echo "(dryrun) dotbare rm --cached" "${selected_files[@]}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation "Untrack the selected files?")
[[ "${confirm}" != 'y' ]] && exit 1
# shellcheck disable=SC2086
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" rm --cached ${selected_files}
/usr/bin/git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" rm --cached "${selected_files[@]}"
echo -e " "
echo "Selected files are being untracked by git, make sure to run dotbare fbackup"
echo "on your other systems. When other system pull down this change, selected files"
echo "will be removed, this is the default behavior of git rm --cached, more information"
echo "refer to dotbare funtrack -h or README"
echo "Selected files are being untracked by git, make sure to run dotbare fbackup on your other systems."
echo "When other systems pull down this change, selected files will be deleted on other systems."
echo "This is the default behavior of git rm --cached."
echo "Please refer to git rm official documentation for more details or visit dotbare's github page"
fi

View File

@ -2,37 +2,52 @@
#
# update dotbare to latest master
set -e
set -f
mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
function usage() {
echo -e "Usage: dotbare fupgrade [-h] ...\n"
echo -e "Update dotbare to the latest version\n"
echo -e "Upgrade dotbare to the latest master.\n"
echo -e "optional arguments:"
echo -e " -h\t\tshow this help message and exit"
echo -e " -h, --help\t\tshow this help message and exit."
}
while getopts ":h" opt; do
case "$opt" in
h)
while [[ "$#" -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
*)
echo "Invalid option: ${OPTARG}" >&2
*)
echo "Invalid option: $1" >&2
usage
exit 1
;;
esac
done
# rip from omz
# auto stash on rebase
resetAutoStash=$(git config --bool rebase.autoStash 2>&1)
git config rebase.autoStash true
# change directory to dotbare folder
cd "${mydir}/.."
echo "Fetching latest changes ..."
git fetch
git checkout master &> /dev/null
git pull origin master
echo "Done"
exit 0
cd "${mydir}/.." || exit
echo "Updating dotbare ..."
if git pull --rebase --stat origin master; then
echo "dotbare updated successfully"
else
echo "Something went wrong, please try again or fire up an issue at https://github.com/kazhala/dotbare"
fi
# reset autostack to original value
case "$resetAutoStash" in
"")
git config --unset rebase.autoStash
;;
*)
git config rebase.autoStash "${resetAutoStash}"
;;
esac

View File

@ -12,6 +12,10 @@ routing() {
"${BATS_TEST_DIRNAME}"/../dotbare fadd -h
}
routing2() {
"${BATS_TEST_DIRNAME}"/../dotbare flog -h
}
normal_git() {
"${BATS_TEST_DIRNAME}"/../dotbare add -h
}
@ -20,10 +24,21 @@ invalid_command() {
"${BATS_TEST_DIRNAME}"/../dotbare hello
}
version() {
source "${BATS_TEST_DIRNAME}"/../helper/set_variable.sh
"${BATS_TEST_DIRNAME}"/../dotbare --version
}
@test "main help" {
run help
[ "${status}" -eq 0 ]
[ "${lines[0]}" = "Usage: dotbare [-h] [COMMANDS] [OPTIONS] ..." ]
[ "${lines[0]}" = "Usage: dotbare [-h] [-v] [COMMANDS] [OPTIONS] ..." ]
}
@test "main version" {
run version
[ "${status}" -eq 0 ]
[[ "${output}" =~ "Current dotbare version: ${DOTBARE_VERSION}" ]]
}
@test "main disable add --all" {
@ -38,6 +53,12 @@ invalid_command() {
[ "${lines[0]}" = "Usage: dotbare fadd [-h] [-f] [-d] ..." ]
}
@test "main routing2" {
run routing2
[ "${status}" -eq 0 ]
[ "${lines[0]}" = "Usage: dotbare flog [-h] [-r] [-R] [-e] [-c] [-y] ..." ]
}
@test "main git command" {
run normal_git
[ "${status}" -eq 129 ]

View File

@ -13,6 +13,21 @@ no_file_selected() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fadd -d
}
stage_selected_file() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
bash "${BATS_TEST_DIRNAME}"/../dotbare fadd -f
}
stage_selected_dir() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
bash "${BATS_TEST_DIRNAME}"/../dotbare fadd --dir
}
stage_modified_file() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
bash "${BATS_TEST_DIRNAME}"/../dotbare fadd
}
@test "fadd help" {
run help
[ "${status}" -eq 0 ]
@ -22,10 +37,28 @@ no_file_selected() {
@test "fadd invalid option" {
run invalid_option
[ "${status}" -eq 1 ]
[ "${lines[0]}" = "Invalid option: p" ]
[ "${lines[0]}" = "Invalid option: -p" ]
}
@test "fadd no file selected" {
run no_file_selected
[ "${status}" -eq 1 ]
}
@test "fadd stage selected file" {
run stage_selected_file
[ "${status}" -eq 128 ]
[[ "${output}" =~ "fadd_stage_file" ]]
}
@test "fadd stage selected dir" {
run stage_selected_dir
[ "${status}" -eq 128 ]
[[ "${output}" =~ "fadd_stage_dir" ]]
}
@test "fadd stage modified file" {
run stage_modified_file
[ "${status}" -eq 128 ]
[[ "${output}" =~ "fadd_add_modified" ]]
}

View File

@ -6,7 +6,7 @@ setup() {
}
teardown() {
[ -d "${DOTBARE_BACKUP}" ] && rm -r "$DOTBARE_BACKUP"
[ -d "${DOTBARE_BACKUP}" ] && rm -r "${DOTBARE_BACKUP}"
unset DOTBARE_BACKUP
}
@ -27,8 +27,14 @@ individual_backup() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fbackup -p fadd.bats
}
check_empty() {
bash "${BATS_TEST_DIRNAME}"/../dotbare log
move_file() {
touch bats_test.txt
bash "${BATS_TEST_DIRNAME}"/../dotbare fbackup --path bats_test.txt -m
}
select_file() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
bash "${BATS_TEST_DIRNAME}"/../dotbare fbackup --select
}
@test "fbackup help" {
@ -39,18 +45,17 @@ check_empty() {
@test "fbackup invalid option" {
run invalid_option
[ "${status}" -eq 1 ]
[ "${lines[0]}" = 'Invalid option: f' ]
[ "${lines[0]}" = 'Invalid option: -f' ]
}
@test "fbackup backup all files" {
run check_empty
if [ "${status}" -eq 0 ]; then
if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
run backup
[ "${status}" -eq 1 ]
else
run backup
[ "${status}" -eq 0 ]
[ -f "${DOTBARE_BACKUP}"/.bashrc ]
else
run backup
[ "${status}" -eq 1 ]
fi
}
@ -59,3 +64,17 @@ check_empty() {
[ "${status}" -eq 0 ]
[ -f "${DOTBARE_BACKUP}"/fadd.bats ]
}
@test "fbackup move file" {
run move_file
[ "${status}" -eq 0 ]
[ -f "${DOTBARE_BACKUP}"/bats_test.txt ]
[ ! -f "${BATS_TEST_DIRNAME}"/bats_test.txt ]
}
@test "fbackup select file" {
run select_file
[ "${status}" -eq 1 ]
[[ "${output}" =~ 'No such file or directory' ]]
[[ "${output}" =~ 'fbackup_select_file' ]]
}

View File

@ -1,5 +1,9 @@
#!/usr/bin/env bats
setup() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
}
help() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout -h
}
@ -8,14 +12,67 @@ invalid_option() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout -p
}
checkout_branch() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout --branch
}
checkout_commit() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout -c
}
checkout_modified_file() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout -y
}
checkout_selected_file() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout --yes -s
}
@test "fcheckout help" {
run help
[ "${status}" -eq 0 ]
[ "${lines[0]}" = "Usage: dotbare fcheckout [-h] [-a] [-b] [-c] ..." ]
[ "${lines[0]}" = "Usage: dotbare fcheckout [-h] [-s] [-b] [-c] [-y] ..." ]
}
@test "fchekcout invalid option" {
@test "fcheckout invalid option" {
run invalid_option
[ "${status}" -eq 1 ]
[ "${lines[0]}" = "Invalid option: p" ]
[ "${lines[0]}" = "Invalid option: -p" ]
}
@test "fcheckout branch" {
if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
skip
fi
run checkout_branch
[ "${status}" -eq 129 ]
[[ "${output}" =~ "fcheckout_branch" ]]
}
@test "fcheckout commit" {
if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
skip
fi
run checkout_commit
[ "${status}" -eq 129 ]
[[ "${output}" =~ "fcheckout_commit" ]]
}
@test "fcheckout modified" {
if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
skip
fi
run checkout_modified_file
[ "${status}" -eq 1 ]
[[ "${output}" =~ "fcheckout_modified" ]]
}
@test "fcheckout select" {
if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
skip
fi
run checkout_selected_file
[[ "${lines[0]}" =~ "fcheckout_select_commitdiff" ]]
[[ "${lines[1]}" =~ "fcheckout_select_gitfile" ]]
[ "${status}" -eq 1 ]
}

View File

@ -13,6 +13,16 @@ no_file_selected() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fedit -m
}
edit_commits() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
bash "${BATS_TEST_DIRNAME}"/../dotbare fedit --commit
}
edit_files() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
bash "${BATS_TEST_DIRNAME}"/../dotbare fedit
}
@test "fedit help" {
run help
[ "${status}" -eq 0 ]
@ -22,10 +32,25 @@ no_file_selected() {
@test "fedit invalid option" {
run invalid_option
[ "${status}" -eq 1 ]
[ "${lines[0]}" = "Invalid option: p" ]
[ "${lines[0]}" = "Invalid option: -p" ]
}
@test "fedit no file selected" {
run no_file_selected
[ "${status}" -eq 1 ]
}
@test "fedit edit commits" {
if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
skip
fi
run edit_commits
[ "${status}" -eq 128 ]
[[ "${output}" =~ "fedit_commits" ]]
}
@test "fedit edit files" {
run edit_files
[ "${status}" -eq 1 ]
[ -z "${output}" ]
}

View File

@ -1,15 +1,13 @@
#!/usr/bin/env bats
setup() {
export confirm='y'
export DOTBARE_DIR="$HOME/.local/share/dotbare_test/.cfg"
export DOTBARE_TREE="$HOME/.local/share/dotbare_test"
}
teardown() {
unset confirm
if [[ "${DOTBARE_DIR}" == "$HOME/.local/share/dotbare_test/.cfg" ]] \
&& [[ "${DOTBARE_TREE}" == "$HOME/.local/share/dotbare_test" ]]; then
if [[ "${DOTBARE_DIR}" == "$HOME/.local/share/dotbare_test/.cfg" ]] && \
[[ "${DOTBARE_TREE}" == "$HOME/.local/share/dotbare_test" ]]; then
rm -rf "${DOTBARE_TREE}"
fi
unset DOTBARE_DIR
@ -21,13 +19,17 @@ help() {
}
init() {
bash "${BATS_TEST_DIRNAME}"/../dotbare finit
bash "${BATS_TEST_DIRNAME}"/../dotbare finit --yes
}
migration() {
bash "${BATS_TEST_DIRNAME}"/../dotbare finit -u https://github.com/kazhala/dotfiles.git
}
submodule() {
bash "${BATS_TEST_DIRNAME}"/../dotbare finit -u https://github.com/kazhala/dotfiles.git -s --submodule
}
@test "finit help" {
run help
[ "${status}" -eq 0 ]
@ -35,15 +37,25 @@ migration() {
}
@test "finit init dotbare" {
[[ -d "${DOTBARE_DIR}" ]] && rm -rf "${DOTBARE_DIR}"
run init
[ "${status}" -eq 0 ]
run init
[ "${status}" -eq 1 ]
[ "${lines[3]}" = "${DOTBARE_DIR} already exist" ]
[[ "${output}" =~ "${DOTBARE_DIR} already exist" ]]
}
@test "finit migration" {
[[ -d "${DOTBARE_DIR}" ]] && rm -rf "${DOTBARE_DIR}"
run migration
[ "${status}" -eq 0 ]
[[ "${output}" =~ "Migration completed" ]]
}
@test "finit submodule" {
[[ -d "${DOTBARE_DIR}" ]] && rm -rf "${DOTBARE_DIR}"
run submodule
[ "${status}" -eq 0 ]
result=$(echo "${output}" | tr "\n" " ")
[[ "${result}" =~ "Cloning submodules ... Migration completed" ]]
}

View File

@ -8,14 +8,42 @@ invalid_option() {
bash "${BATS_TEST_DIRNAME}"/../dotbare flog -p
}
menu() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
bash "${BATS_TEST_DIRNAME}"/../dotbare flog
}
reset() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
bash "${BATS_TEST_DIRNAME}"/../dotbare flog --reset -y
}
@test "flog help" {
run help
[ "${status}" -eq 0 ]
[ "${lines[0]}" = "Usage: dotbare flog [-h] [-r] [-R] [-e] [-c] ..." ]
[ "${lines[0]}" = "Usage: dotbare flog [-h] [-r] [-R] [-e] [-c] [-y] ..." ]
}
@test "flog invalid option" {
run invalid_option
[ "${status}" -eq 1 ]
[ "${lines[0]}" = "Invalid option: p" ]
[ "${lines[0]}" = "Invalid option: -p" ]
}
@test "flog check routing" {
if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
skip
fi
run menu
[ "${status}" -eq 0 ]
}
@test "flog reset" {
if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
skip
fi
run reset
[ "${status}" -eq 129 ]
[[ "${output}" =~ "usage: git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]" ]]
[[ "${output}" =~ "flog_reset" ]]
}

View File

@ -8,14 +8,51 @@ invalid_option() {
bash "${BATS_TEST_DIRNAME}"/../dotbare freset -p
}
no_selection_made() {
bash "${BATS_TEST_DIRNAME}"/../dotbare freset
}
select_commit() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
bash "${BATS_TEST_DIRNAME}"/../dotbare freset --commit -y
}
select_files() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
bash "${BATS_TEST_DIRNAME}"/../dotbare freset
}
@test "freset help" {
run help
[ "${status}" -eq 0 ]
[ "${lines[0]}" = "Usage: dotbare freset [-h] [-a] [-c] [-S] [-H] ..." ]
[ "${lines[0]}" = "Usage: dotbare freset [-h] [-c] [-S] [-H] [-y] ..." ]
}
@test "freset invalid option" {
run invalid_option
[ "${status}" -eq 1 ]
[ "${lines[0]}" = "Invalid option: p" ]
[ "${lines[0]}" = "Invalid option: -p" ]
}
@test "freset no selection made" {
run no_selection_made
[ "${status}" -eq 1 ]
}
@test "freset select commit" {
if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
skip
fi
run select_commit
[ "${status}" -eq 129 ]
[[ "${output}" =~ "freset_commit" ]]
}
@test "freset select files" {
if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
skip
fi
run select_files
[ "${status}" -eq 128 ]
[[ "${output}" =~ "freset_file" ]]
}

View File

@ -1,5 +1,9 @@
#!/usr/bin/env bats
setup() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
}
help() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fstash -h
}
@ -9,22 +13,43 @@ invalid_option() {
}
stash_file() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fstash -f
bash "${BATS_TEST_DIRNAME}"/../dotbare fstash -s
}
stash_delete() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fstash --delete --yes
}
stash_apply() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fstash --yes
}
@test "fstash help" {
run help
[ "${status}" -eq 0 ]
[ "${lines[0]}" = "Usage: dotbare fstash [-h] [-f] [-d] [-p] ..." ]
[ "${lines[0]}" = "Usage: dotbare fstash [-h] [-s] [-d] [-p] ..." ]
}
@test "fstash invalid option" {
run invalid_option
[ "${status}" -eq 1 ]
[ "${lines[0]}" = "Invalid option: w" ]
[ "${lines[0]}" = "Invalid option: -w" ]
}
@test "fstash stash single file" {
@test "fstash stash select file" {
run stash_file
[ "${status}" -eq 1 ]
[[ "${output}" =~ "fstash_select" ]]
}
@test "fstash stash delete" {
run stash_delete
[ "${status}" -eq 1 ]
[[ "${output}" =~ "fstash_delete" ]]
}
@test "fstash apply stash" {
run stash_apply
[ "${status}" -eq 1 ]
[[ "${output}" =~ "fstash_apply" ]]
}

View File

@ -21,7 +21,7 @@ no_modify() {
@test "fstat invalid option" {
run invalid_option
[ "${status}" -eq 1 ]
[ "${lines[0]}" = "Invalid option: p" ]
[ "${lines[0]}" = "Invalid option: -p" ]
}
@test "fstat run no modify file" {

View File

@ -1,5 +1,9 @@
#!/usr/bin/env bats
setup() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
}
help() {
bash "${BATS_TEST_DIRNAME}"/../dotbare funtrack -h
}
@ -8,14 +12,44 @@ invalid_option() {
bash "${BATS_TEST_DIRNAME}"/../dotbare funtrack -p
}
untrack_file() {
bash "${BATS_TEST_DIRNAME}"/../dotbare funtrack --yes
}
temp_untrack() {
bash "${BATS_TEST_DIRNAME}"/../dotbare funtrack --yes -t
}
resume_track() {
bash "${BATS_TEST_DIRNAME}"/../dotbare funtrack --yes --resume
}
@test "funtrack help" {
run help
[ "${status}" -eq 0 ]
[ "${lines[0]}" = "Usage: dotbare funtrack [-h] [-s] [-S] ..." ]
[ "${lines[0]}" = "Usage: dotbare funtrack [-h] [-t] [-r] [-y] ..." ]
}
@test "funtrack invalid option" {
run invalid_option
[ "${status}" -eq 1 ]
[ "${lines[0]}" = "Invalid option: p" ]
[ "${lines[0]}" = "Invalid option: -p" ]
}
@test "funtrack untrack file" {
run untrack_file
[ "${status}" -eq 128 ]
[[ "${output}" =~ "funtrack_file" ]]
}
@test "funtrack temp untrack" {
run temp_untrack
[ "${status}" -eq 128 ]
[[ "${output}" =~ "fatal: Unable to mark file funtrack_file" ]]
}
@test "funtrack resume track" {
run resume_track
[ "${status}" -eq 128 ]
[[ "${output}" =~ "fatal: Unable to mark file funtrack_file" ]]
}

View File

@ -1,13 +1,5 @@
#!/usr/bin/env bats
setup() {
export DOTBARE_CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
}
teardown() {
git checkout "$DOTBARE_CURRENT_BRANCH"
}
help() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fupgrade -h
}
@ -29,11 +21,12 @@ upgrade() {
@test "fupgrade invliad option" {
run invalid_option
[ "${status}" -eq 1 ]
[ "${lines[0]}" = "Invalid option: p" ]
[ "${lines[0]}" = "Invalid option: -p" ]
}
@test "fupgrade upgrade" {
skip
run upgrade
[ "${status}" -eq 0 ]
[ "${lines[0]}" = "Fetching latest changes ..." ]
[ "${lines[0]}" = "Updating dotbare ..." ]
}

77
tests/fzf Executable file
View File

@ -0,0 +1,77 @@
#!/usr/bin/env bash
#
# This script is for mocking fzf for testing,
# it will stop fzf for goin into a interactive mode
#
# usage:
# export PATH="${BATS_TEST_DIRNAME}:$PATH"
# example:
# echo "commitdiff" when attempting to mock a local file search
# error code 128
# fatal: pathspec '$HOME/modifiedfile' did not match any files
# echo "-- modifiedfile" when attempting to mock a local file search
# error code 1 or code 128
# error: pathspec '$HOME/modifiedfile' did not match any file(s) known to git
# echo "--branch" when attempting to mock branch commit
# error code 129
# error: unknown option `commitshow'
# use something like tr "`" "'" to avoid any potential error bats would raise
if [[ "$*" =~ "--header=select a commit to checkout" ]] && [[ "$*" =~ "show --color" ]]; then
# dotbare fcheckout --c -- "./fcheckout.bats" @test "fcheckout commit"
echo "--fcheckout_commit"
elif [[ "$*" =~ '--no-multi --header=select the target commit for HEAD' ]] && [[ "$*" =~ "show --color" ]]; then
# dotbare freset --commit -y -- "./freset.bats" @test "freset select commit"
echo "--freset_commit"
elif [[ "$*" =~ "--no-multi --header=select a commit to rename" ]] && [[ "$*" =~ "show --color=always" ]]; then
# dotbare fedit --commit -- "./fedit.bats" @test "fedit edit commits"
echo "fedit_commits"
elif [[ "$*" =~ '--header=select a commit' ]] && [[ "$*" =~ "show --color" ]]; then
# dotbare flog --reset -y -- "./flog.bats" @test "flog reset"
echo "--flog_reset"
elif [[ "$*" =~ "--no-multi --header=select a branch to checkout" ]]; then
# dotbare fcheckout --branch -- "./fcheckout.bats" @test "fcheckout branch"
echo "--fcheckout_branch"
elif [[ "$*" =~ '--header=select a file to checkout' ]] && [[ "$*" =~ "cat ${DOTBARE_TREE}/{}" ]]; then
# dotbare fcheckout --yes -s -- "./fcheckout.bats" @test "fcheckout select"
echo "fcheckout_select_gitfile"
elif [[ "$*" =~ '--header=select files to backup' ]] && [[ "$*" =~ "cat ${DOTBARE_TREE}/{}" ]]; then
# dotbare fbackup --select -- "./fbackup.bats" @test "fbackup select file"
echo "fbackup_select_file"
elif [[ "$*" =~ "--header=select files to untrack" ]] && [[ "$*" =~ "cat ${DOTBARE_TREE}/{}" ]]; then
# dotbare funtrack -- "./funtrack.bats" @test "funtrack untrack file"
echo "funtrack_file"
elif [[ "$*" =~ '--multi --preview ' ]] && [[ "$*" =~ "tree -L 1 -C --dirsfirst {}" ]]; then
# dotbare fadd --dir -- "./fadd.bats" @test "fadd stage selected dir"
echo "fadd_stage_dir"
elif [[ "$*" =~ '--header=select the target commit' ]] && [[ "$*" =~ "diff --color" ]]; then
# dotbare fcheckout --yes -s -- "./fcheckout.bats" @test "fcheckout select"
echo "fcheckout_select_commitdiff"
elif [[ "$*" =~ '--multi --preview ' ]] && [[ "$*" =~ "cat {}" ]]; then
# dotbare fadd -f -- "./fadd.bats" @test "fadd stage selected file"
echo "fadd_stage_file"
elif [[ "$*" =~ '--header=select files to add to a stash' ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
# dotbare fstash -s -- "./fstash.bats" @test "fstash stash select file"
echo "-- fstash_select"
elif [[ "$*" =~ '--header=select stash to delete' ]] && [[ "$*" =~ "show -p __ --color=always" ]]; then
# dotbare fstash --delete -- "./fstash.bats" @test "fstash stash delete"
echo "fstash_delete"
elif [[ "$*" =~ '--header=select stash to apply' ]] && [[ "$*" =~ "show -p __ --color=always" ]]; then
# dotbare fstash -- "./fstash.bats" @test "fstash apply stash"
echo "fstash_apply"
elif [[ "$*" =~ "--header=select a file to checkout version in HEAD" ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
# dotbare fcheckout -y -- "./fcheckout.bats" @test "fcheckout modified"
echo "-- fcheckout_modified"
elif [[ "$*" =~ '--header=select files to stage' ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
# dotbare fadd -- "./fadd.bats" @test "fadd stage modified files"
echo "-- fadd_add_modified"
elif [[ "$*" =~ "--header=select files to unstage" ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
# dotbare freset -- "./freset.bats" @test "freset select files"
echo "-- freset_file"
elif [[ "$*" =~ "--header=select tracked files to edit" ]]; then
# dotbare fedit -- "./fedit.bats" @test "fedit edit files"
exit
elif [[ "$*" =~ "--no-multi --header=commit --flog_reset" ]]; then
# dotbare flog -- "./flog.bats" @test "flog checkout routing"
echo "exit"
fi

View File

@ -1,6 +1,8 @@
#!/usr/bin/env bats
source "${BATS_TEST_DIRNAME}"/../helper/set_variable.sh
setup() {
source "${BATS_TEST_DIRNAME}"/../helper/set_variable.sh
}
@test "env check env var" {
[ "${DOTBARE_DIR}" = "$HOME/.cfg/" ]
@ -11,4 +13,5 @@ source "${BATS_TEST_DIRNAME}"/../helper/set_variable.sh
@test "env check fzf var" {
[ -n "${DOTBARE_KEY}" ]
[ -n "${FZF_DEFAULT_OPTS}" ]
[ -n "${DOTBARE_VERSION}" ]
}

9
tests/tree Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
#
# This script is for mocking fzf for testing,
# it will stop fzf for goin into a interactive mode
#
# usage:
# export PATH="${BATS_TEST_DIRNAME}:$PATH"
echo "$@"