├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── buildspec.yml
├── dotbare
├── dotbare.plugin.bash
├── dotbare.plugin.zsh
├── helper
├── get_confirmation.sh
├── git_query.sh
├── preview.sh
├── search_file.sh
└── set_variable.sh
├── pkg
├── completion
│ ├── bash
│ │ └── dotbare
│ └── zsh
│ │ └── _dotbare
├── dotbare.aur
└── dotbare.brew
├── scripts
├── fadd
├── fbackup
├── fcheckout
├── fedit
├── fgrep
├── finit
├── flog
├── freset
├── fstash
├── fstat
├── funtrack
└── fupgrade
└── tests
├── Dockerfile
├── README.md
├── dotbare.bats
├── fadd.bats
├── fbackup.bats
├── fcheckout.bats
├── fedit.bats
├── fgrep.bats
├── finit.bats
├── flog.bats
├── freset.bats
├── fstash.bats
├── fstat.bats
├── funtrack.bats
├── fupgrade.bats
├── fzf
├── git
├── set_variable.bats
├── shellcheck.sh
└── tree
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [push, pull_request]
4 |
5 | env:
6 | COLUMNS: 80
7 |
8 | defaults:
9 | run:
10 | shell: bash
11 | working-directory: .
12 |
13 | jobs:
14 | ubuntu:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 | - run: sudo apt-get install shellcheck -y
19 | - run: ./tests/shellcheck.sh
20 | - uses: actions/setup-node@v2
21 | with:
22 | node-version: "13"
23 | - run: npm install -g bats
24 | - run: ./dotbare finit -u https://github.com/kazhala/dotfiles.git
25 | - run: bats tests
26 | - run: rm -rf "$HOME"/.cfg
27 | - run: ./dotbare finit -y
28 | - run: bats tests
29 | macos:
30 | runs-on: macos-latest
31 | steps:
32 | - uses: actions/checkout@v2
33 | - run: brew install shellcheck
34 | - run: ./tests/shellcheck.sh
35 | - run: brew install bats
36 | - run: ./dotbare finit -u https://github.com/kazhala/dotfiles.git
37 | - run: bats tests
38 | - run: rm -rf "$HOME"/.cfg
39 | - run: ./dotbare finit -y
40 | - run: bats tests
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | scripts/*
2 | !scripts/fadd
3 | !scripts/fbackup
4 | !scripts/fcheckout
5 | !scripts/fedit
6 | !scripts/finit
7 | !scripts/flog
8 | !scripts/freset
9 | !scripts/fstash
10 | !scripts/fstat
11 | !scripts/funtrack
12 | !scripts/fupgrade
13 | !scripts/fgrep
14 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | Noteble changes are documentated in this file.
4 |
5 | ## dev
6 |
7 | ### Fixed
8 |
9 | - unnecessary argument for zsh completion [#26](https://github.com/kazhala/dotbare/issues/26)
10 |
11 | ### Added
12 |
13 | - common basic zsh widgets such as `dotbare fedit` [#24](https://github.com/kazhala/dotbare/issues/24)
14 | - new zsh widget `dotbare-transform` (Not documented yet, will add to documendation in next release)
15 | - transform a generic `git` command to a `dotbare` command; e.g. `git log` -> `dotbare -g flog`
16 | - Bind this widget to keys of your choice (e.g. `ctrl-u`): `bindkey "^u" dotbare-transform`
17 |
18 | ## 1.3.1 (25/08/2020)
19 |
20 | ### Fixed
21 |
22 | - dotbare with no args fails [#23](https://github.com/kazhala/dotbare/issues/23)
23 | - some typos in help manual
24 |
25 | ## 1.3.0 (04/08/2020)
26 |
27 | ### Added
28 |
29 | - hide preview window on small window (when \$COLUMNS less than 80)
30 | - If using default keybinds, use `alt-t` to re-open the preview
31 | - verbose flag completion for bash
32 | - `dotbare` can now be used as a generic fuzzy git tool, using `-g` or `--git flag`
33 | - Sort of like a replacement for `forgit`, bascially just dynamiclly switching
34 | `DOTBARE_DIR` and `DOTBARE_TREE` to the current git directory.
35 | - Seems kind of wierd to make `dotbare` also a fuzzy git client, but since it's literally
36 | like a few lines of changes, I figured why not ..
37 | - options for `fgrep` to configure search behavior in fzf
38 | - `-c, --col`: pass in argument to specify which column to start searching in fzf (`dotbare fgrep --col 2`), by default `fgrep` starts the search from column 3, column 1 is the file name, column2 is the line number and starting from column 3 is the actual content.
39 | - `-f, --full`: configure the fzf search to include all columns, same as using `dotbare fgrep --col 1` which includes the file name, line number and the actual content.
40 | - dedicated completion file to use for package installation
41 |
42 | ### CHANGED
43 |
44 | - update the fzf header to make more sense, some wording issues
45 |
46 | ### Fixed
47 |
48 | - bash completion raising unexpected git error
49 |
50 | ## 1.2.3 (17/07/2020)
51 |
52 | ### Added
53 |
54 | - zsh completion for dotbare commands
55 | - zsh completion for git commands
56 | - bash completion for git commands
57 | - fgrep: grep words within tracked dotfiles and edit them through EDITOR
58 | - More info is documented in wiki
59 |
60 | ### Changed
61 |
62 | - adjusted how help messages are printed to reduce some calls
63 |
64 | ### Fixed
65 |
66 | - bash completion awk panic on version 4.0+ bash on MacOS
67 |
68 | ## 1.2.2 (11/07/2020)
69 |
70 | ### Fixed
71 |
72 | - dotbare crash when migrating a dotfile repo with over 100 files [#12](https://github.com/kazhala/dotbare/issues/12)
73 | - dotbare fbackup crash when using cp command on symlink
74 |
75 | ## 1.2.1 (09/07/2020)
76 |
77 | ### Added
78 |
79 | - dynamic preview function, detect bats, hightlight etc to provide syntax hightlighting when previewing files.
80 | - custom preview ENV variable (DOTBARE_PREVIEW)
81 | - Note: has to be this format `export DOTBARE_PREVIEW='cat -n {}'`, the `{}` is
82 | used in preview functions to subsitute for the filepath.
83 | - support for fancy diff tools like "diff-so-fancy" or "delta"
84 | - This is optional, only takes effect if installed and set as `git config core.pager`
85 | - Also configurable through DOTBARE_DIFF_PAGER, these are documentated in the README.
86 |
87 | ## 1.2.0 (01/07/2020)
88 |
89 | ### Added
90 |
91 | - `dotbare` now accept verbose type of argument e.g. `dotbare fadd --file` `dotbare fcheckout --branch`.
92 | More information please refer to each commands help manual
93 | - support for handling files with spaces
94 | - improved unittest with mocking
95 | - more reliable `dotbare fupgrade` behavior
96 | - version flag for `dotbare`, `dotbare --version` or `dotbare -v`
97 |
98 | ### Changed
99 |
100 | - `dotbare fcheckout -a` has now been renamed to `dotbare fcheckout -s` or `dotbare fcheckout --select`
101 | - `dotbare fstash -f` has now been renamed to `dotbare fstash -s` or `dotbare fstash --select`
102 | - `dotbare funtrack -s` has now been renamed to `dotbare funtrack -t` or `dotbare funtrack --temp`
103 | - `dotbare funtrack -S` has now been renamed to `dotbare funtrack -r` or `dotbare funtrack --resume`
104 | - dryrun information no longer will display if `-y` or `--yes` flag has been passed
105 |
106 | ### Removed
107 |
108 | - removed `-a` flag of `dotbare freset`. It's not working as intended because I misunderstand it, the intended
109 | behavior is actually achieved by `dotbare fcheckout -a`, use `dotbare fcheckout -a` instead.
110 | (Edit: `dotbare fcheckout -a` is now `dotbare fcheckout -s` or `dotbare fcheckout --select`)
111 |
112 | ## 1.1.0 (28/06/2020)
113 |
114 | ### Added
115 |
116 | - zsh plugin [#4](https://github.com/kazhala/dotbare/pull/4)
117 | - bash plugin
118 | - drop-in functionality [#6](https://github.com/kazhala/dotbare/pull/6)
119 | - User can now place custom fzf scripts into scripts folder
120 | - bash completion capabilities [#7](https://github.com/kazhala/dotbare/pull/7)
121 | - option to clone submodule [#8](https://github.com/kazhala/dotbare/issues/8)
122 |
123 | ### Fixed
124 |
125 | - ambiguous argument error [#3](https://github.com/kazhala/dotbare/pull/3)
126 |
127 | ### Removed
128 |
129 | - removed global .gitignore manipulation during migration, not needed. Added .gitignore tips to README and
130 | let user handle it
131 |
132 | ## 1.0.0 (20/05/2020)
133 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to dotbare
2 |
3 | Thanks for stopping by! Happy to see you willing to improve `dotbare`.
4 |
5 | `dotbare` has lots of improvement that could be made ranging from code efficiency,
6 | functionality and possibility some best practice for safer code or portability.
7 |
8 | ## Efficiency
9 |
10 | If you find some weird implementations that could be shorten or done better, feel free
11 | to make a PR for it, I'm willing to learn how to improve and done better. For example,
12 | before v1.2.3, the help message from `dotbare` were actually printed through multiple
13 | invocations of `echo -e` which were very very unnecessary.
14 |
15 | ```sh
16 | # Before
17 | echo -e "usage: ...\n"
18 | echo -e "foo boo\n"
19 | echo -e "Optional arguments: ...\n"
20 |
21 | # After
22 | echo -e "usage: ...
23 |
24 | foo boo
25 |
26 | Optional arguments: ..."
27 | ```
28 |
29 | ## Functionality
30 |
31 | `dotbare` was originally implemented to fill my own need with some extra that I think
32 | others may use. There are two ways to improve functionality, adding new "f" scripts
33 | or maybe adding extra flags for existing scripts.
34 |
35 | ### New scripts
36 |
37 | Checkout [wiki](https://github.com/kazhala/dotbare/wiki/Custom-Scripts) about how
38 | to create custom scripts as well as how to use the API from `dotbare` helper methods.
39 |
40 | Feel free to open pull request for your script, I'm happy to review and discuss for merging.
41 |
42 | Just make sure that they are indeed a separate category than all of the existing "f" scripts,
43 | otherwise you may want to add extra flags to existing "f" scripts.
44 |
45 | Before you could commit your custom scripts to the fork of `dotbare`, you need to add an
46 | entry to `.gitignore` because it's written to ignore everything in the scripts folder.
47 |
48 | ```sh
49 | # ignore everything in scripts folder except the !scripts/fadd etc
50 | scripts/*
51 | !scripts/fadd
52 | !scripts/fbackup
53 | ....
54 | !scripts/your new script
55 | ```
56 |
57 | ### Adding arguments
58 |
59 | Existing "f" scripts could be extended through adding flags. For example maybe `dotbare fgrep`
60 | could take a `--dryrun` option, instead of populating result in fzf, just print the result
61 | to terminal.
62 |
63 | After adding the new flag, don't forget to add the flag to `usage` function as well as `dotbare.plugin.zsh`
64 | completion definitions.
65 |
66 | ## Helper functions
67 |
68 | When making changes or extending helper functions like `git_query.sh`, make sure the changes are
69 | backward compatible.
70 |
71 | ## Testing
72 |
73 | There is no requirements for the changes to be unit tested, bash unit test is nasty.
74 |
75 | Just make sure you have thoroughly tested manually and pass shellcheck.
76 |
77 | If you are interested, checkout [here](https://github.com/kazhala/dotbare/blob/master/tests/README.md) to see how the unit test are implemented and
78 | use current unit tests as reference.
79 |
80 | ## Finally
81 |
82 | Thanks for your interest in improving `dotbare`!
83 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM bash:latest
2 | RUN apk add --no-cache git
3 | RUN apk add --no-cache vim
4 | RUN apk add --no-cache fzf
5 | ADD ./ /root/dotbare
6 | RUN echo "source /root/dotbare/dotbare.plugin.bash" >> "$HOME"/.bashrc
7 | WORKDIR /root
8 | ENTRYPOINT ["bash"]
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Kevin Zhuang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # dotbare
2 |
3 | 
4 | 
5 | 
6 | 
7 |
8 | ## Introduction
9 |
10 | `dotbare` is a command line utility to help manage dotfiles and or as a generic fuzzy git client. As a dotfile management tool,
11 | it wraps around git bare repository, query git information from it and display them through [fzf](https://github.com/junegunn/fzf) for an
12 | interactive experience. It is originally inspired by [forgit](https://github.com/wfxr/forgit), a git wrapper using fzf.
13 | `dotbare` uses a different implementation approach and focuses on managing and interacting with system dotfiles. Because
14 | of the flexible implementation of `dotbare`, it can easily integrate with symlink/GNU stow setup or even as a generic
15 | fuzzy git client to use in any git repository.
16 |
17 | As a generic fuzzy git client (using `--git` flag), `dotbare` dynamically determine the top level `.git` folder and process git information
18 | and perform git operation in the current working tree.
19 |
20 | You could find out how git bare repository could be used for managing dotfiles [here](https://www.atlassian.com/git/tutorials/dotfiles).
21 | Or a [video](https://www.youtube.com/watch?v=tBoLDpTWVOM&t=288s) explanation that helped me to get started. If you are currently
22 | using a symlink/GNU stow setup, checkout how to integrate `dotbare` with them [here](#migrating-from-a-generic-symlink-setup-or-gnu-stow).
23 |
24 | Select and edit dotfiles.
25 | 
26 | Stage and unstage dotfiles.
27 | 
28 | Interactive log viewer.
29 | 
30 | For more capabilities and commands, checkout [wiki](https://github.com/kazhala/dotbare/wiki/Commands).
31 |
32 | ## Why
33 |
34 | It has always been a struggle for me to get started with managing dotfiles using version control,
35 | as tools like "GNU stow" really scares me off with all the symlinks, until I found
36 | out about using git bare repository for managing dotfiles, zero symlinks, minimal setup
37 | required while keeping dotfiles at the location they should be.
38 |
39 | However, it has always lack some interactive experience as it does not provide any auto
40 | completion on git commands nor file paths by default. It is also a pain when migrating the setup over
41 | to another system as you will have to manually resolve all the git checkout issues.
42 |
43 | `dotbare` solves the above problems by providing a series of scripts starts with a prefix f
44 | (e.g. `dotbare fadd`, `dotbare flog` etc) that will enable a interactive experience by processing
45 | all the git information and display it through fzf. In addition, `dotbare` also comes with command line completion
46 | that you could choose to either to complete `git` commands or `dotbare` commands.
47 | `dotbare` also comes with the ability to integrate with GNU stow or any symlink set up as long as you are using git.
48 | It is easy to migrate to any system with minimal set up required. In addition, with a simple flag `--git`, you can
49 | now also use `dotbare` as a generic fuzzy git client to manage any git repository.
50 |
51 | ## Install
52 |
53 | ### zsh
54 |
55 | `dotbare` should work with any zsh plugin manager, below is only demonstration. Checkout [wiki](https://github.com/kazhala/dotbare/wiki/Completion#zsh)
56 | about how to enable completion for zsh.
57 |
58 | #### zinit
59 |
60 | ```sh
61 | zinit light kazhala/dotbare
62 | ```
63 |
64 | #### Fig
65 |
66 | [Fig](https://fig.io) adds apps, shortcuts, and autocomplete to your existing terminal.
67 |
68 | Install `dotbare` in just one click.
69 |
70 |
71 |
72 |
73 | #### oh-my-zsh
74 |
75 | - Clone the repository in to [oh-my-zsh](https://github.com/ohmyzsh/ohmyzsh) plugins directory.
76 |
77 | ```sh
78 | git clone https://github.com/kazhala/dotbare.git $HOME/.oh-my-zsh/custom/plugins/dotbare
79 | ```
80 |
81 | - Activate the plugin in `~/.zshrc`.
82 |
83 | ```zsh
84 | plugins=( [plugins...] dotbare [plugins...] )
85 | ```
86 |
87 | #### Antigen
88 |
89 | ```sh
90 | antigen bundle kazhala/dotbare
91 | ```
92 |
93 | #### Manual
94 |
95 | - Clone the repository (change ~/.dotbare to the location of your preference).
96 |
97 | ```sh
98 | git clone https://github.com/kazhala/dotbare.git ~/.dotbare
99 | ```
100 |
101 | - Put below into `.zshrc`.
102 |
103 | ```sh
104 | source ~/.dotbare/dotbare.plugin.zsh
105 | ```
106 |
107 | ### bash
108 |
109 | `dotbare` comes with a `dotbare.plugin.bash` which contains the command line completion
110 | function for both `git` and `dotbare`, checkout [wiki](https://github.com/kazhala/dotbare/wiki/Completion#bash)
111 | about how to enable it.
112 |
113 | - Clone the repository (change ~/.dotbare to the location of your preference).
114 |
115 | ```sh
116 | git clone https://github.com/kazhala/dotbare.git ~/.dotbare
117 | ```
118 |
119 | - Put below into `.bashrc` or `.bash_profile`.
120 |
121 | ```sh
122 | source ~/.dotbare/dotbare.plugin.bash
123 | ```
124 |
125 | ### others
126 |
127 | 1. Clone the repository (change ~/.dotbare to the location of your preference).
128 |
129 | ```sh
130 | git clone https://github.com/kazhala/dotbare.git ~/.dotbare
131 | ```
132 |
133 | 2. Add `dotbare` to your PATH.
134 |
135 | ```sh
136 | # This is only an example command for posix shell
137 | # If you are on fish, use the fish way to add dotbare to your path
138 | export PATH=$PATH:$HOME/.dotbare
139 | ```
140 |
141 | Or you could create a alias which point to dotbare executable.
142 |
143 | ```sh
144 | alias dotbare="$HOME/.dotbare/dotbare"
145 | ```
146 |
147 | ## Getting started
148 |
149 | ### Dependencies
150 |
151 | You will need git on the system for obvious reasons..and because `dotbare` is written in bash,
152 | it will require you to have bash in the system (You don't need to run bash, just need to be in the system).
153 |
154 | #### Required dependency
155 |
156 | - [fzf](https://github.com/junegunn/fzf)
157 |
158 | #### Optional dependency
159 |
160 | - [tree](https://linux.die.net/man/1/tree) (Provide a directory tree view when finding directory)
161 |
162 | ```sh
163 | # if you are on macos
164 | brew install tree
165 | ```
166 |
167 | - [bat](https://github.com/sharkdp/bat) or [highlight](http://www.andre-simon.de/doku/highlight/en/highlight.php) or [coderay](https://github.com/rubychan/coderay)
168 | or [rougify](https://github.com/rouge-ruby/rouge) (Syntax highlighting when previewing files, otherwise cat will be used)
169 | - [delta](https://github.com/dandavison/delta) or [diff-so-fancy](https://github.com/so-fancy/diff-so-fancy)
170 | or any diff tools of your choice (Fancy git diff preview like in the screen shot)
171 |
172 | ### Setup
173 |
174 | 1. init git bare repository.
175 |
176 | Note: by default, `dotbare finit` will set up a bare repository in \$HOME/.cfg, to customize
177 | location and various other settings, checkout [customization](#customization)
178 |
179 | ```sh
180 | dotbare finit
181 | ```
182 |
183 | 2. add dotfiles you want to track.
184 |
185 | Treat `dotbare` as normal `git` commands.
186 |
187 | ```sh
188 | dotbare fadd -f
189 | # or
190 | dotbare add [FILENAME]
191 |
192 | # add entire repository like .config directory
193 | dotbare fadd -d
194 | # or
195 | dotbare add [DIRECTORY]
196 | ```
197 |
198 | 3. commit changes and push to remote.
199 |
200 | ```sh
201 | dotbare commit -m "First commit"
202 | dotbare remote add origin [URL]
203 | dotbare push -u origin master
204 | ```
205 |
206 | ### Migration
207 |
208 | #### Migrating from normal git bare repository
209 |
210 | 1. follow the steps in [install](#install) to install `dotbare`.
211 | 2. check your current alias of git bare reference.
212 |
213 | ```sh
214 | # Below is an example alias, check yours for reference
215 | alias config=/usr/bin/git --git-dir=$HOME/.cfg --work-tree=$HOME
216 | ```
217 |
218 | 3. set env variable for `dotbare`.
219 |
220 | ```sh
221 | export DOTBARE_DIR="$HOME/.cfg"
222 | export DOTBARE_TREE="$HOME"
223 | ```
224 |
225 | 4. remove the original alias and use `dotbare`.
226 |
227 | 5. optionally you could alias `config` to `dotbare` so you keep your muscle memory.
228 |
229 | ```sh
230 | alias config=dotbare
231 | ```
232 |
233 | #### Migrating from a generic symlink setup or GNU stow
234 |
235 | ##### Keep your current setup but integrate dotbare
236 |
237 | 1. follow the steps in [install](#install) to install `dotbare`.
238 | 2. set environment variable so that `dotbare` knows where to look for git information.
239 |
240 | ```sh
241 | # e.g. I have all my dotfiles stored in folder $HOME/.myworld and symlinks all of them to appropriate location.
242 | # export DOTBARE_DIR="$HOME/.myworld/.git"
243 | # export DOTBARE_TREE="$HOME/.myworld"
244 | export DOTBARE_DIR=
245 | export DOTBARE_TREE=
246 | ```
247 |
248 | 3. Run `dotbare` anywhere in your system.
249 |
250 | Note: with this method, you do not run `dotbare finit -u [URL]` when migrating to new system,
251 | you will do your normal migration steps and then do the above steps.
252 |
253 | ##### Complete migration
254 |
255 | While bare method is great and easy, I recommend keeping your current symlink/GNU stow setup and integrate it with `dotbare` instead of a migration.
256 | If you are really happy with `dotbare`, as long as your remote repository resembles the structure of your home holder
257 | (reference what I mean in my [repo](https://github.com/kazhala/dotfiles.git)), simply run the command below.
258 |
259 | **Disclaimer**: I have not done nearly enough test on this as I don't personally use symlink/GNU stow setup, migrate this way with caution.
260 | I recommend you test this migration in docker, see [Test-it-in-docker](#test-it-in-docker).
261 |
262 | ```sh
263 | # dotbare will replace all symlinks with the original file and a bare repository will be created at $DOTBARE_DIR
264 | dotbare finit -u [URL]
265 | ```
266 |
267 | #### Migrating dotbare to a new system
268 |
269 | 1. follow the steps in [install](#install) to install `dotbare`.
270 | 2. Optionally set env variable to customize `dotbare` location (checkout [customization](#customization)).
271 |
272 | ```sh
273 | export DOTBARE_DIR="$HOME/.cfg"
274 | export DOTBARE_TREE="$HOME"
275 | ```
276 |
277 | 3. give `dotbare` your remote URL and let it handle the rest.
278 |
279 | ```sh
280 | dotbare finit -u https://github.com/kazhala/dotfiles.git
281 | ```
282 |
283 | #### Test it in docker
284 |
285 | When you are about to do migrations, I strongly suggest you give the migration a try in docker first.
286 | The `dotbare` image is based on alpine linux.
287 |
288 | ```sh
289 | docker pull kazhala/dotbare:latest
290 | docker container run -it --rm --name dotbare kazhala/dotbare:latest
291 | ```
292 |
293 | 
294 |
295 | ## Customization
296 |
297 | `dotbare` could be customized through modification of env variables.
298 |
299 | Note: customization of fzf is not covered here, checkout their [wiki](https://github.com/junegunn/fzf/wiki).
300 |
301 | ### DOTBARE_DIR
302 |
303 | This is the location of the bare repository, `dotbare` will look for this directory
304 | and query git information or it will create this directory when initializing `dotbare`.
305 | Change this to location or rename the directory to your liking.
306 |
307 | If you are using symlink/GNU stow setup, set this variable point to the .git folder
308 | within your dotfile directory.
309 |
310 | ```sh
311 | # Default value
312 | export DOTBARE_DIR="$HOME/.cfg"
313 | ```
314 |
315 | ### DOTBARE_TREE
316 |
317 | This is the working tree for the git bare repository, meaning this is where the version
318 | control will take place. I don't recommend changing this one unless **ALL** of your config
319 | file is in something like \$XDG_CONFIG_HOME. If you are using symlink/GNU stow setup,
320 | set this variable to point to the folder containing all of your dotfiles.
321 |
322 | ```sh
323 | # Default value
324 | export DOTBARE_TREE="$HOME"
325 | ```
326 |
327 | ### DOTBARE_BACKUP
328 |
329 | This variable is used to determine where to store the backup of your files. It is used
330 | mainly by `dotbare fbackup` which will back up all of your tracked dotfiles into this location.
331 | It is also used by `dotbare finit -u [URL]`, when there is checkout conflict, `dotbare` will
332 | automatically backup conflicted files to this location.
333 |
334 | ```sh
335 | # Default value
336 | export DOTBARE_BACKUP="${XDG_DATA_HOME:-$HOME/.local/share}/dotbare"
337 | ```
338 |
339 | ### EDITOR
340 |
341 | This is probably already set in your ENV. `dotbare` uses this variable to determine
342 | which editor to use when running `dotbare fedit`.
343 |
344 | ```sh
345 | # Default value
346 | export EDITOR="vim"
347 | ```
348 |
349 | ### DOTBARE_KEY
350 |
351 | This variable set default keybinds for fzf in `dotbare`. You could checkout a list of keybinds
352 | to set [here](https://github.com/junegunn/fzf/blob/97a725fbd0e54cbc07e4d72661ea2bd2bb7c01c1/man/man1/fzf.1#L648).
353 |
354 | ```sh
355 | # Default value
356 | export DOTBARE_KEY="
357 | --bind=alt-a:toggle-all # toggle all selection
358 | --bind=alt-j:jump # label jump mode, sort of like vim-easymotion
359 | --bind=alt-0:top # set cursor back to top
360 | --bind=alt-s:toggle-sort # toggle sorting
361 | --bind=alt-t:toggle-preview # toggle preview
362 | "
363 | ```
364 |
365 | ### DOTBARE_FZF_DEFAULT_OPTS
366 |
367 | Customize fzf settings for dotbare. This is useful when you want a different
368 | fzf behavior from your normal system fzf settings.
369 |
370 | ```sh
371 | # By default this variable is not set
372 | # More settings checkout fzf man page and their wiki
373 | # Example: if you want your preview window for dotbare to be bigger
374 | export DOTBARE_FZF_DEFAULT_OPTS="--preview-window=right:65%"
375 | ```
376 |
377 | ### DOTBARE_PREVIEW
378 |
379 | This variable determines the preview command for file previews. By default, the preview is automatically determined
380 | using fall back (bat -> highlight -> coderay -> rougify -> cat). Set this variable to control the preview command if
381 | you have a specific preference or if you want extra flags/settings. Reference [here](https://github.com/kazhala/dotbare/blob/master/helper/preview.sh).
382 |
383 | ```sh
384 | # By default this value is not set, dotbare uses a fall back method to determine which command to use.
385 | # Make sure to have "{}" included when customizing it, the preview script substitute "{}" for actual filename.
386 | # Example: enable line number for cat command
387 | export DOTBARE_PREVIEW="cat -n {}"
388 | ```
389 |
390 | ### DOTBARE_DIFF_PAGER
391 |
392 | This variable controls the diff output pager in previews like `dotbare flog`, `dotbare fadd` etc. It will read the value
393 | of `git config core.pager` to determine the pager to use. If you have a specific preference for `dotbare` or have not set
394 | the global pager in git config, you could use this variable to customize the diff preview.
395 |
396 | ```sh
397 | # By default this value uses fall back (git config core.pager -> cat)
398 | export DOTBARE_DIFF_PAGER="delta --diff-so-fancy --line-numbers"
399 | ```
400 |
401 | ## Usage
402 |
403 | All usage and commands are documented in **[wiki](https://github.com/kazhala/dotbare/wiki/Commands)**.
404 |
405 | - [Commands](https://github.com/kazhala/dotbare/wiki/Commands)
406 | - [Completion](https://github.com/kazhala/dotbare/wiki/Completion)
407 | - [Custom Scripts and API](https://github.com/kazhala/dotbare/wiki/Custom-Scripts)
408 | - [Tips and Tricks](https://github.com/kazhala/dotbare/wiki/Tips-and-Tricks)
409 |
410 | ## Changes
411 |
412 | Latest changes are documented in [CHANGELOG](https://github.com/kazhala/dotbare/blob/master/CHANGELOG.md).
413 |
414 | ## Testing
415 |
416 | `dotbare` is unit tested using [bats](https://github.com/bats-core/bats-core). Mock tests are implemented using PATH override method.
417 | This is documented [here](https://github.com/kazhala/dotbare/blob/master/tests/README.md) for better readability and extensibility.
418 |
419 | Not all functions have 100% coverage and lots of user interaction cannot be effectively tested, please fire up issues if something went wrong.
420 |
421 | 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
422 | you could checkout my cloudformation [template](https://github.com/kazhala/AWSCloudFormationStacks/blob/master/CICD_dotbare.yaml).
423 |
424 | ## Contributing
425 |
426 | Checkout out [CONTRIBUTING.md](https://github.com/kazhala/dotbare/blob/master/CONTRIBUTING.md) to see how you could contribute to `dotbare`. PRs are
427 | welcome and I'm happy to improve/extend `dotbare`'s functionality.
428 |
429 | Don't forget to leave a star :)
430 |
431 | ## Background
432 |
433 | `dotbare` was initially part of my personal scripts, I had a hard time sharing those scripts
434 | and as the number of scripts grows, I feel like is more appropriate to make a dedicated project
435 | for it. I hope you find it useful and enjoy it, thanks!
436 |
437 | ## Credit
438 |
439 | - credit to [forgit](https://github.com/wfxr/forgit) for inspiration.
440 | - credit to [fzf](https://github.com/junegunn/fzf) for fzf and the preview script from fzf.vim.
441 | - credit to [OMZ](https://github.com/ohmyzsh/ohmyzsh) for upgrading method.
442 | - credit to [this](https://www.atlassian.com/git/tutorials/dotfiles) post for step by step guide of setting up git bare repo.
443 | - credit to [this](https://www.youtube.com/watch?v=tBoLDpTWVOM&t=288s) video for introducing git bare repo.
444 |
445 | ## Demo
446 |
447 | You could find some more demo [here](https://github.com/kazhala/dotbare/issues/1)
448 | [](https://asciinema.org/a/332231)
449 |
--------------------------------------------------------------------------------
/buildspec.yml:
--------------------------------------------------------------------------------
1 | version: 0.2
2 |
3 | env:
4 | parameter-store:
5 | LOGIN_PASSWORD: /dotbare/dockerpassword
6 | LOGIN_USERNAME: /dotbare/dockerusername
7 |
8 | phases:
9 | install:
10 | commands:
11 | - echo Installing shellcheck ...
12 | - apt-get update -y
13 | - apt-get install shellcheck -y
14 | pre_build:
15 | commands:
16 | - echo Login to dockerhub
17 | - 'echo $LOGIN_PASSWORD | docker login --username $LOGIN_USERNAME --password-stdin'
18 | build:
19 | commands:
20 | - echo Checking script compliance ...
21 | - ./tests/shellcheck.sh
22 | - echo Building docker url image ...
23 | - docker image build --build-arg MIGRATE=url -t kazhala/dotbare:testurl -f tests/Dockerfile .
24 | - echo Running bats unittest ...
25 | - docker container run -i --rm --name dotbare kazhala/dotbare:testurl
26 | - echo Building docker bare image ...
27 | - docker image build --build-arg MIGRATE=bare -t kazhala/dotbare:testbare -f tests/Dockerfile .
28 | - echo Running bats unittest ...
29 | - docker container run -i --rm --name dotbare kazhala/dotbare:testbare
30 | - echo Building docker image ...
31 | - |-
32 | DOTBARE_VERSION=$(./dotbare --version | awk -F ": v" '{print $2}')
33 | - docker image build -t kazhala/dotbare:$DOTBARE_VERSION .
34 | - docker image tag kazhala/dotbare:$DOTBARE_VERSION kazhala/dotbare:latest
35 | post_build:
36 | commands:
37 | - echo Deploying docker image ...
38 | - docker image push kazhala/dotbare:latest
39 | - docker image push kazhala/dotbare:$DOTBARE_VERSION
40 |
--------------------------------------------------------------------------------
/dotbare:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Main entry script for dotbare, used to route command to appropriate scripts
4 | #
5 | # @params
6 | # Globals
7 | # ${mydir}: string, directory of the executing script, used for sourcing helpers
8 | # Arguments
9 | # action_command: sub commands dotbare should run
10 | # General git command: log, status etc
11 | # dotbare specific commands: fadd | frm | fpop | freset | fcheckout | help etc
12 | # option flags:
13 | # check sub commands for available option flags
14 |
15 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
16 | source "${mydir}"/helper/set_variable.sh
17 |
18 | function usage() {
19 | echo -e "Usage: dotbare [-h] [-v] [COMMANDS] [OPTIONS] ...
20 |
21 | Interactively manage dotfiles with the help of fzf and git bare repository.
22 | To see all dotbare specific COMMANDS, run dotbare without any arguments.
23 |
24 | Optional arguments:
25 | -h, --help\t\tshow this help message and exit.
26 | -v, --version\t\tshow dotbare current version.
27 | -g, --git\t\tuse dotbare as a generic fuzzy git tool and operate in current git directory.
28 |
29 | Available commands:
30 | All git commands are available, treat dotbare as git.
31 | fadd \t\tstage files/directories interactively.
32 | fbackup \t\tperform backup for tracked files.
33 | fcheckout \t\tcheckout branch/files/commit interactively.
34 | fedit \t\tinteractively select files/commit and edit.
35 | fgrep \t\tgrep within tracked files.
36 | finit \t\tinitialise dotbare or migrate dotfiles to a new machine.
37 | flog \t\tmanage commits interactively.
38 | freset \t\treset(unstage) files or commit interactively.
39 | fstash \t\tmanage stash interactively.
40 | fstat \t\tinteractive menu to toggle stage/unstage.
41 | funtrack \t\tuntrack files interactively.
42 | fupgrade \t\tupdate dotbare to the latest master."
43 | }
44 |
45 | function list_dotbare_commands() {
46 | find "${mydir}"/scripts/* -type f -print0 \
47 | | xargs -I __ -0 basename __ \
48 | | fzf --no-multi --header='Available commands' --preview="${mydir}/dotbare {} -h" \
49 | | xargs -I __ "${mydir}"/dotbare __ -h
50 | }
51 |
52 | function execute_dotbare() {
53 | [[ "$#" -eq 0 ]] \
54 | && list_dotbare_commands \
55 | && exit 0
56 |
57 | if [[ -x "${mydir}/scripts/$1" ]]; then
58 | exec "${mydir}/scripts/$1" "${@:2}"
59 | fi
60 | }
61 |
62 | # if no argument, display all possible actions
63 | if [[ "$#" -eq 0 ]]; then
64 | list_dotbare_commands
65 | exit 0
66 | fi
67 |
68 | [[ "$*" == 'add --all' ]] && \
69 | echo 'If you intend to stage all modified file, run dotbare add -u' && \
70 | echo "dotbare disabled add --all option as this will stage every single file in ${DOTBARE_TREE}" && \
71 | exit 1
72 |
73 | case "$1" in
74 | --help|-h)
75 | usage
76 | exit 0
77 | ;;
78 | -v|--version)
79 | echo "Current dotbare version: ${DOTBARE_VERSION}"
80 | exit 0
81 | ;;
82 | -g|--git)
83 | if git rev-parse --is-inside-work-tree &>/dev/null; then
84 | DOTBARE_TREE=$(git rev-parse --show-toplevel)
85 | DOTBARE_DIR="${DOTBARE_TREE}/.git"
86 | shift
87 | case "$1" in
88 | fbackup|finit|fupgrade)
89 | echo "dotbare $1 is not supported when using dotbare as a generic fuzzy git tool" >&2
90 | exit 1
91 | ;;
92 | *)
93 | execute_dotbare "$@"
94 | ;;
95 | esac
96 | else
97 | echo "Not in a git directory" >&2
98 | exit 1
99 | fi
100 | ;;
101 | *)
102 | execute_dotbare "$@"
103 | ;;
104 | esac
105 |
106 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" "$@"
107 |
--------------------------------------------------------------------------------
/dotbare.plugin.bash:
--------------------------------------------------------------------------------
1 | # shellcheck disable=SC2207
2 |
3 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4 | [[ :$PATH: != *:"${mydir}":* ]] && export PATH="$PATH:${mydir}"
5 |
6 | __dotbare_completion()
7 | {
8 | local IFS=$'\n' subcommands curr prev options verbose_options suggestions
9 | curr="${COMP_WORDS[$COMP_CWORD]}"
10 | prev="${COMP_WORDS[$COMP_CWORD-1]}"
11 |
12 | if [[ "$COMP_CWORD" -eq "1" ]]; then
13 | subcommands=$(
14 | "${mydir}"/dotbare -h \
15 | | awk '{
16 | if ($0 ~ /^ f.*/) {
17 | gsub(/^ /, "", $0)
18 | gsub(/\t\t/, " ", $0)
19 | print $0
20 | }
21 | }'
22 | )
23 | options=$(
24 | "${mydir}"/dotbare -h \
25 | | awk '{
26 | if ($0 ~ /^ -.*/) {
27 | gsub(/,/, " ", $0)
28 | gsub(/^ /, "", $0)
29 | gsub(/\t\t/, " ", $0)
30 | $2=""
31 | print $0
32 | }
33 | }'
34 | )
35 | verbose_options=$("${mydir}"/dotbare -h | awk '$0 ~ /^ -.*/ {print $2}')
36 | if [[ "${curr}" == --* ]]; then
37 | suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
38 | elif [[ "${curr}" == -* ]]; then
39 | suggestions=($(compgen -W "${options}" -- "${curr}"))
40 | else
41 | suggestions=($(compgen -W "${subcommands}" -- "${curr}"))
42 | fi
43 |
44 | elif [[ "${COMP_CWORD}" -eq 2 && "${prev}" == "-g" || "${prev}" == "--git" ]]; then
45 | subcommands=$(
46 | "${mydir}"/dotbare -h \
47 | | awk '{
48 | if ($0 ~ /^ f.*/) {
49 | if ($0 ~ /^ f(backup|init|upgrade).*/) {
50 | next
51 | }
52 | gsub(/^ /, "", $0)
53 | gsub(/\t\t/, " ", $0)
54 | print $0
55 | }
56 | }'
57 | )
58 | suggestions=($(compgen -W "${subcommands}" -- "${curr}"))
59 |
60 | elif [[ "${COMP_WORDS[1]}" == "-g" || "${COMP_WORDS[1]}" == "--git" ]] && [[ "${COMP_CWORD}" -gt 2 ]]; then
61 | if [[ "${curr}" == --* && "${prev}" != "-h" && "${prev}" != "--help" ]]; then
62 | verbose_options=$(
63 | "${mydir}"/dotbare "${COMP_WORDS[2]}" -h 2> /dev/null \
64 | | awk '{
65 | if ($0 ~ /^ -p PATH/) {
66 | next
67 | } else if ($0 ~ /^ -u URL/) {
68 | next
69 | } else if ($0 ~ /^ -*/) {
70 | print $2
71 | }
72 | }'
73 | )
74 | suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
75 | elif [[ "${prev}" != "-h" && "${prev}" != "--help" ]]; then
76 | options=$(
77 | "${mydir}"/dotbare "${COMP_WORDS[2]}" -h 2> /dev/null \
78 | | awk '{
79 | gsub(/,/, " ", $0)
80 | if ($0 ~ /^ -p PATH/) {
81 | next
82 | } else if ($0 ~ /^ -u URL/) {
83 | next
84 | } else if ($0 ~ /^ -*/) {
85 | gsub(/^ /, "", $0)
86 | gsub(/\t/, " ", $0)
87 | $2=""
88 | print $0
89 | }
90 | }'
91 | )
92 | suggestions=($(compgen -W "${options}" -- "${curr}"))
93 | else
94 | return
95 | fi
96 |
97 | elif [[ "${COMP_WORDS[1]}" == "fbackup" ]] && [[ "${prev}" == "-p" || "${prev}" == "--path" ]]; then
98 | COMPREPLY=($(compgen -d -- "${curr}"))
99 | return
100 | elif [[ "${COMP_WORDS[1]}" == "finit" ]] && [[ "${prev}" == "-u" || "${prev}" == "--url" ]]; then
101 | return
102 | elif [[ "${curr}" == --* && "${prev}" != "-h" && "${prev}" != "--help" ]]; then
103 | verbose_options=$(
104 | "${mydir}"/dotbare "${COMP_WORDS[1]}" -h 2> /dev/null \
105 | | awk '{
106 | if ($0 ~ /^ -p PATH/) {
107 | print "--path"
108 | } else if ($0 ~ /^ -u URL/) {
109 | print "--url"
110 | } else if ($0 ~ /^ -c COL/) {
111 | print "--col"
112 | } else if ($0 ~ /^ -*/) {
113 | print $2
114 | }
115 | }'
116 | )
117 | suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
118 | elif [[ "${prev}" != "-h" && "${prev}" != "--help" ]]; then
119 | options=$(
120 | "${mydir}"/dotbare "${COMP_WORDS[1]}" -h 2> /dev/null \
121 | | awk '{
122 | gsub(/,/, " ", $0)
123 | if ($0 ~ /^ -p PATH/) {
124 | gsub(/^ -p PATH --path PATH/, "-p", $0)
125 | gsub(/\t/, " ", $0)
126 | print $0
127 | } else if ($0 ~ /^ -u URL/) {
128 | gsub(/^ -u URL --url URL/, "-u", $0)
129 | gsub(/\t/, " ", $0)
130 | print $0
131 | } else if ($0 ~ /^ -c COL/) {
132 | gsub(/^ -c COL --col COL/, "-c", $0)
133 | gsub(/\t/, " ", $0)
134 | print $0
135 | } else if ($0 ~ /^ -*/) {
136 | gsub(/^ /, "", $0)
137 | gsub(/\t/, " ", $0)
138 | $2=""
139 | print $0
140 | }
141 | }'
142 | )
143 | suggestions=($(compgen -W "${options}" -- "${curr}"))
144 | fi
145 |
146 | if [[ "${#suggestions[*]}" -eq 1 ]]; then
147 | COMPREPLY=("${suggestions[@]%% *}")
148 | else
149 | for i in "${!suggestions[@]}"; do
150 | suggestions[$i]="$(printf '%*s' "-$COLUMNS" "${suggestions[$i]}")"
151 | done
152 | COMPREPLY=("${suggestions[@]}")
153 | fi
154 | }
155 |
156 | _dotbare_completion_cmd() {
157 | local complete_name="${1:-dotbare}"
158 | complete -F __dotbare_completion "${complete_name}"
159 | }
160 |
161 | _dotbare_completion_git() {
162 | local complete_name="${1:-dotbare}"
163 | complete -F _git "${complete_name}"
164 | }
165 |
--------------------------------------------------------------------------------
/dotbare.plugin.zsh:
--------------------------------------------------------------------------------
1 | 0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
2 | _path="${0:h}"
3 |
4 | if [[ -z "${path[(r)$_path]}" ]]; then
5 | path+=( "${_path}" )
6 | fi
7 |
8 | __dotbare_completion() {
9 | local context state state_descr line ret curcontext
10 | local -A opt_args
11 | ret=1
12 | curcontext="${curcontext}"
13 |
14 | _arguments -C \
15 | '(- : *)'{-h,--help}'[show help information]' \
16 | '(- : *)'{-v,--version}'[display dotbare version]' \
17 | '(-g --git)'{-g,--git}'[use dotbare as a generic fuzzy git tool and operate in current git directory]' \
18 | '1:cmds:->cmds' \
19 | '*::options:->options' \
20 | && ret=0
21 |
22 | case "${state}" in
23 | cmds)
24 | local subcommands
25 | subcommands=(
26 | 'fadd:stage files'
27 | 'fbackup:backup files'
28 | 'fcheckout:checkout file/branch/commit'
29 | 'fedit:edit files'
30 | 'fgrep:grep within tracked files'
31 | 'finit:init/migrate dotbare'
32 | 'flog:interactive log viewer'
33 | 'freset:reset files/commit'
34 | 'fstash:stage management'
35 | 'fstat:toggle stage/unstage of files'
36 | 'funtrack:untrack files'
37 | 'fupgrade:update dotbare'
38 | )
39 | _describe 'command' subcommands \
40 | && ret=0
41 | ;;
42 | options)
43 | case "${line[1]}" in
44 | fadd)
45 | _arguments \
46 | '(- : *)'{-h,--help}'[show help information]' \
47 | '(-f --file -d --dir -h --help)'{-f,--file}'[select files from PWD and stage]' \
48 | '(-d --dir -f --file -h --help)'{-d,--dir}'[select directory from PWD and stage]' \
49 | && ret=0
50 | ;;
51 | fbackup)
52 | _arguments \
53 | '(- : *)'{-h,--help}'[show help information]' \
54 | '(-s --select -p --path -h --help)'{-s,--select}'[select tracked files to backup]' \
55 | '(-p --path -s --select -h --help)'{-p,--path}'[sepcify path of files to backup]:filename:_files' \
56 | '(-m --move -h --help)'{-m,--move}'[use mv cmd instead of cp cmd]' \
57 | && ret=0
58 | ;;
59 | fcheckout)
60 | _arguments \
61 | '(- : *)'{-h,--help}'[show help information]' \
62 | '(-s --select -b --branch -c --commit -h --help)'{-s,--select}'[select files and then checkout them in selected commits]' \
63 | '(-b --branch -s --select -c --commit -h --help)'{-b,--branch}'[checkout branch]' \
64 | '(-c --commit -b --branch -s --select -h --help)'{-c,--commit}'[checkout commit]' \
65 | '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
66 | && ret=0
67 | ;;
68 | fedit)
69 | _arguments \
70 | '(- : *)'{-h,--help}'[show help information]' \
71 | '(-m --modified -c --commit -h --help)'{-m,--modified}'[edit modified files]' \
72 | '(-c --commit -m --modified -h --help)'{-c,--commit}'[edit commits]' \
73 | && ret=0
74 | ;;
75 | fgrep)
76 | _arguments \
77 | '(- : *)'{-h,--help}'[show help information]' \
78 | '(-f --full -c --col)'{-f,--full}'[include all columns during fzf search, as if using "--col 1"]' \
79 | '(-f --full -c --col)'{-c,--col}'[specify a column number to start searching in fzf]: :->cols' \
80 | && ret=0
81 | ;;
82 | finit)
83 | _arguments \
84 | '(- : *)'{-h,--help}'[show help information]' \
85 | '(-u --url -h --help)'{-u,--url}'[migrate remote dotfiles to current system]: :->url' \
86 | '(-s --submodule -h --help)'{-s,--submodule}'[clone submodules during migration]' \
87 | '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
88 | && ret=0
89 | ;;
90 | flog)
91 | _arguments \
92 | '(- : *)'{-h,--help}'[show help information]' \
93 | '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-r,--revert}'[revert the selected commit and skip action menu]' \
94 | '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-R,--reset}'[reset the selected commit and skip action menu]' \
95 | '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-e,--edit}'[edit the selected commit and skip action menu]' \
96 | '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-c,--checkout}'[checkout the selected commit and skip action menu]' \
97 | '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
98 | && ret=0
99 | ;;
100 | freset)
101 | _arguments \
102 | '(- : *)'{-h,--help}'[show help information]' \
103 | '(-c --commit -h --help)'{-c,--commit}'[reset HEAD to certain commit]' \
104 | '(-S --soft -H --hard -h --help)'{-S,--soft}'[reset commit using --soft flag]' \
105 | '(-H --hard -S --soft -h --help)'{-H,--hard}'[reset commit using --hard flag]' \
106 | '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
107 | && ret=0
108 | ;;
109 | fstash)
110 | _arguments \
111 | '(- : *)'{-h,--help}'[show help information]' \
112 | '(-s --select -d --delete -p --pop -h --help)'{-s,--select}'[list modified files and stash the selected files]' \
113 | '(-s --select -d --delete -p --pop -h --help)'{-d,--delete}'[list stash and delete the selected stash]' \
114 | '(-s --select -d --delete -p --pop -h --help)'{-p,--pop}'[use "stash pop" instead of "stash apply"]' \
115 | && ret=0
116 | ;;
117 | fstat)
118 | _arguments \
119 | '(- : *)'{-h,--help}'[show help information]' \
120 | && ret=0
121 | ;;
122 | funtrack)
123 | _arguments \
124 | '(- : *)'{-h,--help}'[show help information]' \
125 | '(-t --temp -r --resume -h --help)'{-t,--temp}'[temporarily ignore changes of the selected files]' \
126 | '(-t --temp -r --resume -h --help)'{-r,--resume}'[resume tracking changes of the selected files]' \
127 | '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
128 | && ret=0
129 | ;;
130 | fupgrade)
131 | _arguments \
132 | '(- : *)'{-h,--help}'[show help information]' \
133 | && ret=0
134 | ;;
135 | esac
136 | ;;
137 | esac
138 |
139 | return "${ret}";
140 | }
141 |
142 | _dotbare_completion_cmd() {
143 | local compdef_name="dotbare"
144 | compdef __dotbare_completion "${compdef_name}"
145 | }
146 |
147 | _dotbare_completion_git() {
148 | local compdef_name="dotbare"
149 | compdef "${compdef_name}"=git
150 | }
151 |
152 | _widget_dotbare_fadd() { dotbare fadd; }
153 | _widget_dotbare_fedit() { dotbare fedit; }
154 | _widget_dotbare_fcheckout() { dotbare fcheckout; }
155 | _widget_dotbare_freset() { dotbare freset; }
156 | _widget_dotbare_flog() { dotbare flog; }
157 | _widget_dotbare_fgrep() { dotbare fgrep; }
158 | _widget_dotbare_fstat() { dotbare fstat; }
159 |
160 | zle -N dotbare-fadd _widget_dotbare_fadd
161 | zle -N dotbare-fedit _widget_dotbare_fedit
162 | zle -N dotbare-fcheckout _widget_dotbare_fcheckout
163 | zle -N dotbare-freset _widget_dotbare_reset
164 | zle -N dotbare-flog _widget_dotbare_flog
165 | zle -N dotbare-fgrep _widget_dotbare_fgrep
166 | zle -N dotbare-fstat _widget_dotbare_fstat
167 |
168 | _widget_git_transform_dotbare() {
169 | local dotbare_cmd new_cmd
170 | dotbare_cmd=$(alias | grep dotbare | cut -d'=' -f1 | head -n 1)
171 | [[ -z "${dotbare_cmd}" ]] && dotbare_cmd="dotbare"
172 | dotbare_cmd="${dotbare_cmd} -g"
173 | BUFFER=$(echo "$BUFFER" \
174 | | awk -v dotbare="${dotbare_cmd}" '{
175 | if ($1 == "git") {
176 | $1=dotbare
177 | if ($2 ~ /(log|add|reset|checkout|status|stash|grep|untrack|stat)/) {
178 | if ($2 == "status"){
179 | $2="stat"
180 | }
181 | $2="f"$2
182 | }
183 | }
184 | print $0
185 | }'
186 | )
187 | zle end-of-line
188 | }
189 |
190 | zle -N dotbare-transform _widget_git_transform_dotbare
191 |
--------------------------------------------------------------------------------
/helper/get_confirmation.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # confirmaiton helper
4 |
5 | #######################################
6 | # Helper function to get user confirmation
7 | # Globals:
8 | # None
9 | # Locals:
10 | # ${confirm}: user confirmation status
11 | # Arguments:
12 | # $1: confirmation message to show during confirm
13 | # Outputs:
14 | # ${confirm}: y or n indicating user response
15 | #######################################
16 | function get_confirmation() {
17 | local confirm
18 | local message="${1:-Confirm?}"
19 | while [ "${confirm}" != 'y' ] && [ "${confirm}" != 'n' ]; do
20 | read -r -p "${message}(y/n): " confirm
21 | done
22 | echo "${confirm}"
23 | }
24 |
--------------------------------------------------------------------------------
/helper/git_query.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # helper functions to obtain git related information
4 |
5 | #######################################
6 | # let user select a commit interactively
7 | # credit to forgit for the git log format
8 | # Arguments:
9 | # $1: the helper message to display in the fzf header
10 | # $2: files to show diff against HEAD
11 | # Outputs:
12 | # the selected commit 6 char code
13 | # e.g. b60b330
14 | #######################################
15 | # TODO: line33 "${files[*]}" cannot handle space in file names, but "${files[@]}" won't get properly
16 | # processed by git for whatever reason just in this preview situation but works every where else, HELP needed.
17 | # although this won't affect any real functionality or break the code, it will just print a error message in preview.
18 | function get_commit() {
19 | local header="${1:-select a commit}"
20 | local files=("${@:2}")
21 | if [[ "${#files[@]}" -eq 0 ]]; then
22 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
23 | log --color=always --format='%C(auto)%h%d %s %C(black)%C(bold)%cr' \
24 | | fzf --header="${header}" --no-multi \
25 | --preview "echo {} \
26 | | awk '{print \$1}' \
27 | | xargs -I __ git --git-dir=${DOTBARE_DIR} --work-tree=${DOTBARE_TREE} \
28 | show --color=always __ \
29 | | ${DOTBARE_DIFF_PAGER}" \
30 | | awk '{print $1}'
31 | else
32 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
33 | log --oneline --color=always --decorate=short \
34 | | fzf --header="${header}" --no-multi --preview "echo {} \
35 | | awk '{print \$1}' \
36 | | xargs -I __ git --git-dir=${DOTBARE_DIR} --work-tree=${DOTBARE_TREE} \
37 | diff --color=always __ ${files[*]} \
38 | | ${DOTBARE_DIFF_PAGER}" \
39 | | awk '{print $1}'
40 | fi
41 | }
42 |
43 | #######################################
44 | # let user select a branch interactively
45 | # Arguments:
46 | # $1: the helper message to display in the fzf header
47 | # Outputs:
48 | # the selected branch name
49 | # e.g. master
50 | #######################################
51 | function get_branch() {
52 | local header="${1:-select a branch}"
53 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" branch -a \
54 | | awk '{
55 | if ($0 ~ /\*.*\(HEAD.*/) {
56 | gsub(/\* /, "", $0)
57 | print "\033[32m" $0 "\033[0m"
58 | } else if (match($1, "\\*") != 0) {
59 | print "\033[32m" $2 "\033[0m"
60 | } else if ($0 ~ /^[ \t]+remotes\/.*/) {
61 | gsub(/[ \t]+/, "", $0)
62 | print "\033[31m" $0 "\033[0m"
63 | } else {
64 | gsub(/^[ \t]+/, "", $0)
65 | print $0
66 | }
67 | }' \
68 | | fzf --no-multi --header="${header}" \
69 | --preview="echo {} \
70 | | awk '{
71 | if (\$0 ~ /.*HEAD.*/) {
72 | print \"HEAD\"
73 | } else {
74 | print \$0
75 | }
76 | }' \
77 | | xargs -I __ git --git-dir=${DOTBARE_DIR} --work-tree=${DOTBARE_TREE} \
78 | log --color=always --color=always --format='%C(auto)%h%d %s %C(black)%C(bold)%cr' __"
79 | }
80 |
81 | #######################################
82 | # let user select a dotbare tracked file interactively
83 | # Arguments:
84 | # $1: the helper message to display in the fzf header
85 | # $2: print option, values (full|raw)
86 | # $3: if exist, don't do multi selection, do single
87 | # Outputs:
88 | # the selected file path
89 | # e.g.$HOME/.config/nvim/init.vim
90 | #######################################
91 | function get_git_file() {
92 | local mydir
93 | local header="${1:-select tracked file}"
94 | local print_opt="${2:-full}"
95 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
96 | set_fzf_multi "$3"
97 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
98 | ls-files --full-name --directory "${DOTBARE_TREE}" \
99 | | fzf --header="${header}" \
100 | --preview "${mydir}/../helper/preview.sh ${DOTBARE_TREE}/{}" \
101 | | awk -v home="${DOTBARE_TREE}" -v print_opt="${print_opt}" '{
102 | if (print_opt == "full") {
103 | print home "/" $0
104 | } else {
105 | print $0
106 | }
107 | }'
108 | }
109 |
110 | #######################################
111 | # let user select a modified file interactively
112 | # Arguments:
113 | # $1: the helper message to display in the fzf header
114 | # $2: display mode of modified files.
115 | # default: true
116 | # all: display all modified, include staged and unstaged
117 | # staged: display only staged files
118 | # unstaged: display only unstaged files
119 | # $3: output_format
120 | # default: name
121 | # name: formatted name of the file
122 | # raw: raw file name with status
123 | # $4: if exists, don't do multi selection, do single
124 | # Outputs:
125 | # the selected file path
126 | # e.g.$HOME/.config/nvim/init.vim
127 | #######################################
128 | function get_modified_file() {
129 | local header="${1:-select a modified file}"
130 | local display_mode="${2:-all}"
131 | local output_format="${3:-name}"
132 | set_fzf_multi "$4"
133 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
134 | status --porcelain \
135 | | awk -v display_mode="${display_mode}" '{
136 | if ($0 ~ /^[A-Za-z][A-Za-z].*$/) {
137 | print "\033[32m" substr($0, 1, 1) "\033[31m" substr($0, 2) "\033[0m"
138 | } else if ($0 ~ /^[A-Za-z][ \t].*$/) {
139 | if (display_mode == "all" || display_mode == "staged") {
140 | print "\033[32m" $0 "\033[0m"
141 | }
142 | } else {
143 | if (display_mode == "all" || display_mode == "unstaged") {
144 | print "\033[31m" $0 "\033[0m"
145 | }
146 | }
147 | }' \
148 | | fzf --header="${header}" --preview "echo {} \
149 | | awk '{sub(\$1 FS,\"\");print \$0}' \
150 | | xargs -I __ git --git-dir=${DOTBARE_DIR} --work-tree=${DOTBARE_TREE} \
151 | diff HEAD --color=always -- ${DOTBARE_TREE}/__ \
152 | | ${DOTBARE_DIFF_PAGER}" \
153 | | awk -v home="${DOTBARE_TREE}" -v format="${output_format}" '{
154 | if (format == "name") {
155 | $1=""
156 | gsub(/^[ \t]/, "", $0)
157 | gsub(/"/, "", $0)
158 | print home "/" $0
159 | } else {
160 | print $0
161 | }
162 | }'
163 | }
164 |
165 | #######################################
166 | # let user select a stash interactively
167 | # Arguments:
168 | # $1: the help message to display in header
169 | # $2: if exists, don't do multi select, only allow single selection
170 | # Outputs:
171 | # the selected stash identifier
172 | # e.g. stash@{0}
173 | #######################################
174 | function get_stash() {
175 | local header="${1:-select a stash}"
176 | set_fzf_multi "$2"
177 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
178 | stash list \
179 | | fzf --header="${header}" --preview "echo {} \
180 | | awk '{
181 | gsub(/:/, \"\", \$1)
182 | print \$1
183 | }' \
184 | | xargs -I __ git --git-dir=${DOTBARE_DIR} --work-tree=${DOTBARE_TREE} \
185 | stash show -p __ --color=always \
186 | | ${DOTBARE_DIFF_PAGER}" \
187 | | awk '{
188 | gsub(/:/, "", $1)
189 | print $1
190 | }'
191 | }
192 |
193 | #######################################
194 | # Using git grep to find word within
195 | # all tracked files in the bare repo.
196 | # Arguments:
197 | # $1: the help message to display in header
198 | # $2: the fzf delimiter to start searching, default is 3
199 | # $3: if exists, don't do multi select, only allow single selection
200 | # Outputs:
201 | # the selected file name with it's line number and line, separated by ":"
202 | # e.g. .bash_profile:1:echo hello
203 | #######################################
204 | function grep_words() {
205 | local header="${1:-select matches to edit}"
206 | local delimiter="${2:-3}"
207 | set_fzf_multi "$2"
208 | cd "${DOTBARE_TREE}" || exit
209 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
210 | grep --line-number -- . \
211 | | fzf --delimiter : --nth "${delimiter}".. --header="${header}" \
212 | --preview "${mydir}/../helper/preview.sh ${DOTBARE_TREE}/{}" \
213 | | awk -F ":" -v home="${DOTBARE_TREE}" '{
214 | print home "/" $1 ":" $2
215 | }'
216 | }
217 |
--------------------------------------------------------------------------------
/helper/preview.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # dynamic preview command for dotbare
4 | # borrowed and modified from fzf.vim
5 | #
6 | # @params
7 | # Globals
8 | # reverse_seq: reverse highlight sequence for easier print
9 | # reset_seq: reset highlight sequence for eaiser print
10 | # input_option: the array containing informaiton from cmd argument
11 | # preview_file: the file path to be previewed
12 | # preview_center: the center/highlight line of the preview, if not set, display entire file
13 | # preview_lines: total lines to be previed, used to determine the first line and last line to be printed
14 | # preview_first: the first line number of the file to be printed
15 | # preview_last: the last line number of the file to be printed
16 | # file_mime: mime of the file, used to display information for binary file
17 | # Arguments
18 | # $1: The filename and line info to be previewed
19 | # Format: filepath[:lineno][:ignored]
20 | # Example
21 | # preview "$HOME/.bashrc:15"
22 |
23 | #######################################
24 | # display the preview of the file
25 | # construct argument for the action, execute and exit
26 | # Arguments:
27 | # $1: the file path to be previewed
28 | # $2: the first line number to be previewd, optional
29 | # $3: the center/highlight line in the preview, optional
30 | # $4: the last line number to be previewed, optional
31 | # Note:
32 | # if the line number information such as $2 $3 $4 is not given, the entire
33 | # file will be printed.
34 | # Otherwise only the $2-$4 parts of the file will be printed and $3 will be highlighted
35 | #######################################
36 | function display_preview() {
37 | local fallback_cmd preview_cmd preview_file preview_first preview_last preview_center
38 | preview_file="$1"
39 | preview_first="$2"
40 | preview_center="$3"
41 | preview_last="$4"
42 | fallback_cmd="highlight -O ansi -l {} || coderay {} || rougify {} || cat {}"
43 | preview_cmd=${DOTBARE_PREVIEW:-${fallback_cmd}}
44 | preview_cmd=${preview_cmd//{\}/$(printf %q "${preview_file}")}
45 |
46 | if [[ -z "${preview_first}" ]] || [[ -z "${preview_center}" ]] || [[ -z "${preview_last}" ]]; then
47 | if [[ -z "${DOTBARE_PREVIEW}" ]] && command -v bat > /dev/null; then
48 | bat --color=always --pager=never "${preview_file}"
49 | exit $?
50 | fi
51 | eval "${preview_cmd}" 2> /dev/null
52 | exit 0
53 | else
54 | if [ -z "${DOTBARE_PREVIEW}" ] && command -v bat > /dev/null; then
55 | bat --color=always --pager=never \
56 | --line-range="${preview_first}":"${preview_last}" --highlight-line="${preview_center}" "${preview_file}"
57 | exit $?
58 | fi
59 | eval "${preview_cmd}" 2> /dev/null \
60 | | awk "NR >= ${preview_first} && NR <= ${preview_last} { \
61 | if (NR == ${preview_center}) \
62 | { gsub(/\x1b[[0-9;]*m/, \"&${reverse_seq}\"); printf(\"${reverse_seq}%s\n${reset_seq}\", \$0); } \
63 | else \
64 | printf(\"${reset_seq}%s\n\", \$0); \
65 | }"
66 | exit 0
67 | fi
68 | }
69 |
70 | reverse_seq="\x1b[7m"
71 | reset_seq="\x1b[m"
72 |
73 | IFS=':' read -r -a input_option <<< "$1"
74 | preview_file=${input_option[0]}
75 | preview_center=${input_option[1]}
76 |
77 | # potential fix for windows? Although I don't think dotbare will be usable in windows yet
78 | if [[ $1 =~ ^[A-Z]:\\ ]]; then
79 | preview_file=$preview_file:${input_option[1]}
80 | preview_center=${input_option[2]}
81 | fi
82 |
83 | preview_file="${preview_file/#\~\//$HOME/}"
84 | if [ ! -r "${preview_file}" ]; then
85 | echo "File not found ${preview_file}"
86 | exit 1
87 | fi
88 |
89 | # if binary, display binary info and exit
90 | file_mime=$(file --dereference --mime "${preview_file}")
91 | [[ "${file_mime}" =~ binary ]] \
92 | && echo "${file_mime}" \
93 | && exit 0
94 |
95 | # if no line number was given, just preview the entire file
96 | [[ -z "${preview_center}" ]] && display_preview "${preview_file}"
97 |
98 | # if invalid line number was given, just preview the entire file
99 | [[ -n "${preview_center}" && ! "${preview_center}" =~ ^[0-9] ]] && display_preview "${preview_file}"
100 |
101 | # get the size of the termianl window and determine the first line and last line
102 | preview_center=${preview_center/[^0-9]*/}
103 |
104 | if [ -n "${FZF_PREVIEW_LINES}" ]; then
105 | preview_lines="${FZF_PREVIEW_LINES}"
106 | else
107 | if [ -r /dev/tty ]; then
108 | preview_lines=$(stty size < /dev/tty | awk '{print $1}')
109 | else
110 | preview_lines=40
111 | fi
112 | fi
113 |
114 | preview_first=$((preview_center-preview_lines/3))
115 | preview_first=$((preview_first < 1 ? 1 : preview_first))
116 | preview_last=$((preview_first+preview_lines-1))
117 |
118 | display_preview "${preview_file}" "${preview_first}" "${preview_center}" "${preview_last}"
119 |
--------------------------------------------------------------------------------
/helper/search_file.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # search local file or directory taking consideration of optional dependency
4 |
5 | #######################################
6 | # search local file
7 | # Arguments:
8 | # $1: string, f or d, search file or directory
9 | # Outputs:
10 | # A user selected file path
11 | #######################################
12 | function search_file() {
13 | local search_type="$1" mydir
14 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
15 | if [[ "${search_type}" == "f" ]]; then
16 | find . -maxdepth 1 -type f | sed "s|\./||g" | fzf --multi --preview "${mydir}/preview.sh {}"
17 | elif [[ "${search_type}" == "d" ]]; then
18 | if command -v tree &>/dev/null; then
19 | find . -maxdepth 1 -type d | awk '{if ($0 != "." && $0 != "./.git"){gsub(/^\.\//, "", $0);print $0}}' | fzf --multi --preview "tree -L 1 -C --dirsfirst {}"
20 | else
21 | find . -maxdepth 1 -type d | awk '{if ($0 != "." && $0 != "./.git"){gsub(/^\.\//, "", $0);print $0}}' | fzf --multi
22 | fi
23 | fi
24 | }
25 |
--------------------------------------------------------------------------------
/helper/set_variable.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # check env variables and set default variables
4 | #
5 | # @params
6 | # Globals
7 | # ${DOTBARE_DIR}: location of the bare repo
8 | # ${DOTBARE_TREE}: which folder is the bare repo tracking
9 | # ${DOTBARE_BACKUP}: backup directory for all tracked files
10 | # ${DOTBARE_KEY}: default key bindings
11 | # ${FZF_DEFAULT_OPTS}: update FZF_DEFAULT_OPTS to reflect dotbare changes
12 | # ${DOTBARE_FZF_DEFAULT_OPTS}: user custom setting for dotbare
13 | # ${EDITOR}: default editor to use
14 |
15 | export DOTBARE_DIR="${DOTBARE_DIR:-$HOME/.cfg/}"
16 | export DOTBARE_TREE="${DOTBARE_TREE:-$HOME}"
17 | export DOTBARE_BACKUP="${DOTBARE_BACKUP:-${XDG_DATA_HOME:-$HOME/.local/share}/dotbare}"
18 | export DOTBARE_VERSION="v1.3.1"
19 |
20 | export DOTBARE_DIFF_PAGER="${DOTBARE_DIFF_PAGER:-$(git config core.pager || echo 'cat')}"
21 |
22 | export EDITOR="${EDITOR:-vim}"
23 | if [[ -z "${DOTBARE_KEY}" ]]; then
24 | DOTBARE_KEY="
25 | --bind=alt-a:toggle-all
26 | --bind=alt-w:jump
27 | --bind=alt-0:top
28 | --bind=alt-s:toggle-sort
29 | --bind=alt-t:toggle-preview
30 | "
31 | fi
32 |
33 | [[ -z "${FZF_DEFAULT_OPTS}" ]] && export FZF_DEFAULT_OPTS='--cycle'
34 |
35 | FZF_DEFAULT_OPTS="
36 | $FZF_DEFAULT_OPTS
37 | --ansi
38 | --cycle
39 | --exit-0
40 | $DOTBARE_FZF_DEFAULT_OPTS
41 | $DOTBARE_KEY
42 | "
43 |
44 | [[ -z "${COLUMNS}" ]] \
45 | && COLUMNS=$(stty size < /dev/tty | cut -d' ' -f2)
46 | [[ "${COLUMNS}" -lt 80 ]] \
47 | && FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS --preview-window=hidden"
48 |
49 | #######################################
50 | # determine to set multi selection or not
51 | # Globals:
52 | # ${FZF_DEFAULT_OPTS}: fzf options
53 | # Arguments:
54 | # $1: if exists, disable multi, set single
55 | #######################################
56 | function set_fzf_multi() {
57 | local no_multi="$1"
58 | if [[ -z "${no_multi}" ]]; then
59 | export FZF_DEFAULT_OPTS="${FZF_DEFAULT_OPTS} --multi"
60 | else
61 | export FZF_DEFAULT_OPTS="${FZF_DEFAULT_OPTS} --no-multi"
62 | fi
63 | }
64 |
--------------------------------------------------------------------------------
/pkg/completion/bash/dotbare:
--------------------------------------------------------------------------------
1 | # shellcheck disable=SC2207
2 |
3 | _dotbare_completion()
4 | {
5 | local IFS=$'\n' subcommands curr prev options verbose_options suggestions
6 | curr="${COMP_WORDS[$COMP_CWORD]}"
7 | prev="${COMP_WORDS[$COMP_CWORD-1]}"
8 |
9 | if [[ "$COMP_CWORD" -eq "1" ]]; then
10 | subcommands=$(
11 | dotbare -h \
12 | | awk '{
13 | if ($0 ~ /^ f.*/) {
14 | gsub(/^ /, "", $0)
15 | gsub(/\t\t/, " ", $0)
16 | print $0
17 | }
18 | }'
19 | )
20 | options=$(
21 | dotbare -h \
22 | | awk '{
23 | if ($0 ~ /^ -.*/) {
24 | gsub(/,/, " ", $0)
25 | gsub(/^ /, "", $0)
26 | gsub(/\t\t/, " ", $0)
27 | $2=""
28 | print $0
29 | }
30 | }'
31 | )
32 | verbose_options=$(dotbare -h | awk '$0 ~ /^ -.*/ {print $2}')
33 | if [[ "${curr}" == --* ]]; then
34 | suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
35 | elif [[ "${curr}" == -* ]]; then
36 | suggestions=($(compgen -W "${options}" -- "${curr}"))
37 | else
38 | suggestions=($(compgen -W "${subcommands}" -- "${curr}"))
39 | fi
40 |
41 | elif [[ "${COMP_CWORD}" -eq 2 && "${prev}" == "-g" || "${prev}" == "--git" ]]; then
42 | subcommands=$(
43 | dotbare -h \
44 | | awk '{
45 | if ($0 ~ /^ f.*/) {
46 | if ($0 ~ /^ f(backup|init|upgrade).*/) {
47 | next
48 | }
49 | gsub(/^ /, "", $0)
50 | gsub(/\t\t/, " ", $0)
51 | print $0
52 | }
53 | }'
54 | )
55 | suggestions=($(compgen -W "${subcommands}" -- "${curr}"))
56 |
57 | elif [[ "${COMP_WORDS[1]}" == "-g" || "${COMP_WORDS[1]}" == "--git" ]] && [[ "${COMP_CWORD}" -gt 2 ]]; then
58 | if [[ "${curr}" == --* && "${prev}" != "-h" && "${prev}" != "--help" ]]; then
59 | verbose_options=$(
60 | dotbare "${COMP_WORDS[2]}" -h 2> /dev/null \
61 | | awk '{
62 | if ($0 ~ /^ -p PATH/) {
63 | next
64 | } else if ($0 ~ /^ -u URL/) {
65 | next
66 | } else if ($0 ~ /^ -*/) {
67 | print $2
68 | }
69 | }'
70 | )
71 | suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
72 | elif [[ "${prev}" != "-h" && "${prev}" != "--help" ]]; then
73 | options=$(
74 | dotbare "${COMP_WORDS[2]}" -h 2> /dev/null \
75 | | awk '{
76 | gsub(/,/, " ", $0)
77 | if ($0 ~ /^ -p PATH/) {
78 | next
79 | } else if ($0 ~ /^ -u URL/) {
80 | next
81 | } else if ($0 ~ /^ -*/) {
82 | gsub(/^ /, "", $0)
83 | gsub(/\t/, " ", $0)
84 | $2=""
85 | print $0
86 | }
87 | }'
88 | )
89 | suggestions=($(compgen -W "${options}" -- "${curr}"))
90 | else
91 | return
92 | fi
93 |
94 | elif [[ "${COMP_WORDS[1]}" == "fbackup" ]] && [[ "${prev}" == "-p" || "${prev}" == "--path" ]]; then
95 | COMPREPLY=($(compgen -d -- "${curr}"))
96 | return
97 | elif [[ "${COMP_WORDS[1]}" == "finit" ]] && [[ "${prev}" == "-u" || "${prev}" == "--url" ]]; then
98 | return
99 | elif [[ "${curr}" == --* && "${prev}" != "-h" && "${prev}" != "--help" ]]; then
100 | verbose_options=$(
101 | dotbare "${COMP_WORDS[1]}" -h 2> /dev/null \
102 | | awk '{
103 | if ($0 ~ /^ -p PATH/) {
104 | print "--path"
105 | } else if ($0 ~ /^ -u URL/) {
106 | print "--url"
107 | } else if ($0 ~ /^ -c COL/) {
108 | print "--col"
109 | } else if ($0 ~ /^ -*/) {
110 | print $2
111 | }
112 | }'
113 | )
114 | suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
115 | elif [[ "${prev}" != "-h" && "${prev}" != "--help" ]]; then
116 | options=$(
117 | dotbare "${COMP_WORDS[1]}" -h 2> /dev/null \
118 | | awk '{
119 | gsub(/,/, " ", $0)
120 | if ($0 ~ /^ -p PATH/) {
121 | gsub(/^ -p PATH --path PATH/, "-p", $0)
122 | gsub(/\t/, " ", $0)
123 | print $0
124 | } else if ($0 ~ /^ -u URL/) {
125 | gsub(/^ -u URL --url URL/, "-u", $0)
126 | gsub(/\t/, " ", $0)
127 | print $0
128 | } else if ($0 ~ /^ -c COL/) {
129 | gsub(/^ -c COL --col COL/, "-c", $0)
130 | gsub(/\t/, " ", $0)
131 | print $0
132 | } else if ($0 ~ /^ -*/) {
133 | gsub(/^ /, "", $0)
134 | gsub(/\t/, " ", $0)
135 | $2=""
136 | print $0
137 | }
138 | }'
139 | )
140 | suggestions=($(compgen -W "${options}" -- "${curr}"))
141 | fi
142 |
143 | if [[ "${#suggestions[*]}" -eq 1 ]]; then
144 | COMPREPLY=("${suggestions[@]%% *}")
145 | else
146 | for i in "${!suggestions[@]}"; do
147 | suggestions[$i]="$(printf '%*s' "-$COLUMNS" "${suggestions[$i]}")"
148 | done
149 | COMPREPLY=("${suggestions[@]}")
150 | fi
151 | }
152 |
153 | complete -F _dotbare_completion dotbare
154 |
--------------------------------------------------------------------------------
/pkg/completion/zsh/_dotbare:
--------------------------------------------------------------------------------
1 | #compdef dotbare
2 |
3 | _dotbare() {
4 | local context state state_descr line ret curcontext
5 | local -A opt_args
6 | ret=1
7 | curcontext="${curcontext}"
8 |
9 | _arguments -C \
10 | '(- : *)'{-h,--help}'[show help information]' \
11 | '(- : *)'{-v,--version}'[display dotbare version]' \
12 | '(-g --git)'{-g,--git}'[use dotbare as a generic fuzzy git tool and operate in current git directory]' \
13 | '1:cmds:->cmds' \
14 | '*::options:->options' \
15 | && ret=0
16 |
17 | case "${state}" in
18 | cmds)
19 | local subcommands
20 | subcommands=(
21 | 'fadd:stage files'
22 | 'fbackup:backup files'
23 | 'fcheckout:checkout file/branch/commit'
24 | 'fedit:edit files'
25 | 'fgrep:grep within tracked files'
26 | 'finit:init/migrate dotbare'
27 | 'flog:interactive log viewer'
28 | 'freset:reset files/commit'
29 | 'fstash:stage management'
30 | 'fstat:toggle stage/unstage of files'
31 | 'funtrack:untrack files'
32 | 'fupgrade:update dotbare'
33 | )
34 | _describe 'command' subcommands \
35 | && ret=0
36 | ;;
37 | options)
38 | case "${line[1]}" in
39 | fadd)
40 | _arguments \
41 | '(- : *)'{-h,--help}'[show help information]' \
42 | '(-f --file -d --dir -h --help)'{-f,--file}'[select files from PWD and stage]' \
43 | '(-d --dir -f --file -h --help)'{-d,--dir}'[select directory from PWD and stage]' \
44 | && ret=0
45 | ;;
46 | fbackup)
47 | _arguments \
48 | '(- : *)'{-h,--help}'[show help information]' \
49 | '(-s --select -p --path -h --help)'{-s,--select}'[select tracked files to backup]' \
50 | '(-p --path -s --select -h --help)'{-p,--path}'[sepcify path of files to backup]:filename:_files' \
51 | '(-m --move -h --help)'{-m,--move}'[use mv cmd instead of cp cmd]' \
52 | && ret=0
53 | ;;
54 | fcheckout)
55 | _arguments \
56 | '(- : *)'{-h,--help}'[show help information]' \
57 | '(-s --select -b --branch -c --commit -h --help)'{-s,--select}'[select files and then checkout them in selected commits]' \
58 | '(-b --branch -s --select -c --commit -h --help)'{-b,--branch}'[checkout branch]' \
59 | '(-c --commit -b --branch -s --select -h --help)'{-c,--commit}'[checkout commit]' \
60 | '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
61 | && ret=0
62 | ;;
63 | fedit)
64 | _arguments \
65 | '(- : *)'{-h,--help}'[show help information]' \
66 | '(-m --modified -c --commit -h --help)'{-m,--modified}'[edit modified files]' \
67 | '(-c --commit -m --modified -h --help)'{-c,--commit}'[edit commits]' \
68 | && ret=0
69 | ;;
70 | fgrep)
71 | _arguments \
72 | '(- : *)'{-h,--help}'[show help information]' \
73 | '(-f --full -c --col)'{-f,--full}'[include all columns during fzf search, as if using "--col 1"]' \
74 | '(-f --full -c --col)'{-c,--col}'[specify a column number to start searching in fzf]: :->cols' \
75 | && ret=0
76 | ;;
77 | finit)
78 | _arguments \
79 | '(- : *)'{-h,--help}'[show help information]' \
80 | '(-u --url -h --help)'{-u,--url}'[migrate remote dotfiles to current system]: :->url' \
81 | '(-s --submodule -h --help)'{-s,--submodule}'[clone submodules during migration]' \
82 | '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
83 | && ret=0
84 | ;;
85 | flog)
86 | _arguments \
87 | '(- : *)'{-h,--help}'[show help information]' \
88 | '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-r,--revert}'[revert the selected commit and skip action menu]' \
89 | '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-R,--reset}'[reset the selected commit and skip action menu]' \
90 | '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-e,--edit}'[edit the selected commit and skip action menu]' \
91 | '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-c,--checkout}'[checkout the selected commit and skip action menu]' \
92 | '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
93 | && ret=0
94 | ;;
95 | freset)
96 | _arguments \
97 | '(- : *)'{-h,--help}'[show help information]' \
98 | '(-c --commit -h --help)'{-c,--commit}'[reset HEAD to certain commit]' \
99 | '(-S --soft -H --hard -h --help)'{-S,--soft}'[reset commit using --soft flag]' \
100 | '(-H --hard -S --soft -h --help)'{-H,--hard}'[reset commit using --hard flag]' \
101 | '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
102 | && ret=0
103 | ;;
104 | fstash)
105 | _arguments \
106 | '(- : *)'{-h,--help}'[show help information]' \
107 | '(-s --select -d --delete -p --pop -h --help)'{-s,--select}'[list modified files and stash the selected files]' \
108 | '(-s --select -d --delete -p --pop -h --help)'{-d,--delete}'[list stash and delete the selected stash]' \
109 | '(-s --select -d --delete -p --pop -h --help)'{-p,--pop}'[use "stash pop" instead of "stash apply"]' \
110 | && ret=0
111 | ;;
112 | fstat)
113 | _arguments \
114 | '(- : *)'{-h,--help}'[show help information]' \
115 | && ret=0
116 | ;;
117 | funtrack)
118 | _arguments \
119 | '(- : *)'{-h,--help}'[show help information]' \
120 | '(-t --temp -r --resume -h --help)'{-t,--temp}'[temporarily ignore changes of the selected files]' \
121 | '(-t --temp -r --resume -h --help)'{-r,--resume}'[resume tracking changes of the selected files]' \
122 | '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
123 | && ret=0
124 | ;;
125 | fupgrade)
126 | _arguments \
127 | '(- : *)'{-h,--help}'[show help information]' \
128 | && ret=0
129 | ;;
130 | esac
131 | ;;
132 | esac
133 |
134 | return "${ret}";
135 | }
136 |
137 | _dotbare "$@"
138 |
--------------------------------------------------------------------------------
/pkg/dotbare.aur:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | SCRIPT_DIR=/opt/dotbare
4 | ${SCRIPT_DIR}/dotbare "$@"
5 |
--------------------------------------------------------------------------------
/pkg/dotbare.brew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | SCRIPT_DIR=/usr/local/Cellar/dotbare/1.3.1
4 | ${SCRIPT_DIR}/dotbare "$@"
5 |
--------------------------------------------------------------------------------
/scripts/fadd:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Stage the selected file to git bare repo
4 | #
5 | # @params
6 | # Globals
7 | # ${mydir}: string, current directory of the executing script
8 | # ${stage_type}: modified, new file, or directory to stage
9 | # ${selected_files}: bash array of user selected files to stage
10 | # Arguments
11 | # -h|--help: show help message
12 | # -f|--file: select a file in PWD to stage
13 | # -d|--dir: select a directory in PWD to stage
14 |
15 | set -e
16 | set -f
17 |
18 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
19 | source "${mydir}"/../helper/search_file.sh
20 | source "${mydir}"/../helper/set_variable.sh
21 | source "${mydir}"/../helper/git_query.sh
22 |
23 | function usage() {
24 | echo -e "Usage: dotbare fadd [-h] [-f] [-d] ...
25 |
26 | Select files/directories or modified files through fzf.
27 | Stage the selected file to the dotfile gitbare repo.
28 |
29 | Default: list all modified files and stage the selected files.
30 |
31 | Optional arguments:
32 | -h, --help\t\tshow this help message and exit.
33 | -f, --file\t\tselect files in current directory and stage the selected files.
34 | -d, --dir\t\tselect folders in current directory and stage the selected folders."
35 | }
36 |
37 | #######################################
38 | # stage file
39 | # Arguments:
40 | # $1: array of files to stage
41 | #######################################
42 | function stage_file() {
43 | local files=("$@")
44 | [[ "${#files[@]}" -eq 0 ]] && exit 1
45 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" add "${files[@]}"
46 | }
47 |
48 | stage_type="modified"
49 | selected_files=()
50 |
51 | while [[ "$#" -gt 0 ]]; do
52 | case "$1" in
53 | -f|--file)
54 | stage_type="file"
55 | shift
56 | ;;
57 | -d|--dir)
58 | stage_type="dir"
59 | shift
60 | ;;
61 | -h|--help)
62 | usage
63 | exit 0
64 | ;;
65 | *)
66 | echo "Invalid option: $1" >&2
67 | usage
68 | exit 1
69 | ;;
70 | esac
71 | done
72 |
73 | while IFS= read -r line; do
74 | selected_files+=("${line}")
75 | done < <(
76 | if [[ "${stage_type}" == "file" ]]; then
77 | search_file 'f'
78 | elif [[ "${stage_type}" == "dir" ]]; then
79 | search_file 'd'
80 | else
81 | get_modified_file "select files to stage" "unstaged"
82 | fi
83 | )
84 |
85 | stage_file "${selected_files[@]}"
86 |
--------------------------------------------------------------------------------
/scripts/fbackup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # backup all tracked files
4 | #
5 | # @params
6 | # Globals
7 | # ${mydir}: current dir of the script
8 | # ${backup_type}: types of backup, individual or all
9 | # ${selected_files}: selected files to backup
10 | # ${action_command}: actions to run, cp|mv
11 | # Arguments
12 | # -h|--help: show help message and exit
13 | # -s|--select: select individual files through fzf and backup
14 | # -p PATH|--path PATH: pass in path and backup
15 | # -m|--move: use mv to backup instead of cp
16 |
17 | set -e
18 | set -f
19 |
20 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
21 | source "${mydir}"/../helper/set_variable.sh
22 | source "${mydir}"/../helper/git_query.sh
23 |
24 | function usage() {
25 | echo -e "Usage: dotbare fbackup [-h] [-m] [-s] [-p PATH] ...
26 |
27 | Backup files to ${DOTBARE_BACKUP}.
28 | This is useful when untracking files or migrating to new machines.
29 |
30 | Default: backup all tracked files using cp command to ${DOTBARE_BACKUP} directory.
31 |
32 | optional arguments:
33 | -h, --help\t\tshow this help message and exit.
34 | -s, --select\t\tlist all tracked files and only backup the selected files.
35 | -p PATH, --path PATH\tspecify path of files to backup.
36 | -m, --move\t\tuse 'mv' instead of the default 'cp' command to backup."
37 | }
38 |
39 | #######################################
40 | # backup passed in files while preserving directory info
41 | # Arguments:
42 | # $1: files to backup, separate by \n
43 | # $2: action command (cp|mv)
44 | #######################################
45 | function dotbare_backup() {
46 | local selected_files="$1"
47 | local action_command="${2:-cp}"
48 | while IFS= read -r line; do
49 | dir_name=$(dirname "${line}")
50 | [[ ! -d "${DOTBARE_BACKUP}/${dir_name}" ]] && mkdir -p "${DOTBARE_BACKUP}/${dir_name}"
51 | [[ "${action_command}" == "cp" ]] \
52 | && cp -av "${line}" "${DOTBARE_BACKUP}/${line}" \
53 | && continue
54 | # Purposly didn't use the -v flag because in finit, error message were
55 | # directed to /dev/null but the cp/mv info will still be printed, causing confusion.
56 | [[ "${action_command}" == "mv" ]] \
57 | && mv "${line}" "${DOTBARE_BACKUP}/${line}" \
58 | && echo "${line} -> ${DOTBARE_BACKUP}/${line}"
59 | done <<< "${selected_files}"
60 | exit 0
61 | }
62 |
63 | backup_type="all"
64 | action_command='cp'
65 | selected_files=""
66 |
67 | while [[ "$#" -gt 0 ]]; do
68 | case "$1" in
69 | -s|--select)
70 | backup_type="select"
71 | shift
72 | ;;
73 | -p|--path)
74 | [[ -z "$2" ]] && echo "Invalid option: $1" >&2 && usage && exit 1
75 | selected_files="$2"
76 | shift
77 | shift
78 | ;;
79 | -m|--move)
80 | action_command="mv"
81 | shift
82 | ;;
83 | -h|--help)
84 | usage
85 | exit 0
86 | ;;
87 | *)
88 | echo "Invalid option: $1" >&2
89 | usage
90 | exit 1
91 | ;;
92 | esac
93 | done
94 |
95 |
96 | [[ -n "${selected_files}" ]] && dotbare_backup "${selected_files}" "${action_command}"
97 |
98 | cd "${DOTBARE_TREE}"
99 | if [[ "${backup_type}" == 'select' ]]; then
100 | selected_files=$(get_git_file "select files to backup" "raw")
101 | else
102 | selected_files=$(git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
103 | ls-files --full-name --directory "${DOTBARE_TREE}")
104 | fi
105 |
106 | [[ -z "${selected_files}" ]] && exit 1
107 | dotbare_backup "${selected_files}" "${action_command}"
108 |
--------------------------------------------------------------------------------
/scripts/fcheckout:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # checkout files/commit/branches using fzf
4 | #
5 | # @params
6 | # Globals
7 | # ${mydir}: current directory of the script, used for imports
8 | # ${action_type}: what type of git commands to use (branch|select|commit|modified)
9 | # ${selected_branch}: selected_branch to switch
10 | # ${selected_files}: selected_files to checkout
11 | # ${selected_commit}: selected commit to checkout
12 | # ${confirm}: confirm status of the user
13 | # Arguments
14 | # -h|--help: show help message
15 | # -s|--select: search all files instead of just the modified files
16 | # -b|--branch: search branch and checkout branch
17 | # -c|--commit: search commit and checkout commit
18 |
19 | set -e
20 | set -f
21 |
22 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
23 | source "${mydir}"/../helper/set_variable.sh
24 | source "${mydir}"/../helper/get_confirmation.sh
25 | source "${mydir}"/../helper/git_query.sh
26 |
27 | function usage() {
28 | echo -e "Usage: dotbare fcheckout [-h] [-s] [-b] [-c] [-y] ...
29 |
30 | Select files/commit/branch through fzf and checkout the selected objects.
31 | Files: checkout the version in HEAD or in a specific commit (reset files content back to the selected commit).
32 | Branch: switch to the selected branch.
33 | Commit: switch to a specific commit.
34 |
35 | Default: list all modified files and reset selected files back to HEAD.
36 |
37 | Optional arguments:
38 | -h, --help\t\tshow this help message and exit.
39 | -s, --select\t\tlist all tracked files and select a commit to checkout the selected files.
40 | -b, --branch\t\tlist all branch and checkout/switch the selected branch.
41 | -c, --commit\t\tlist all commits and checkout selected commit.
42 | -y, --yes\t\tacknowledge all actions that will be taken and skip confirmation."
43 | }
44 |
45 | action_type="modified"
46 | selected_files=()
47 | confirm=""
48 | selected_commit=""
49 | selected_branch=""
50 |
51 | while [[ "$#" -gt 0 ]]; do
52 | case "$1" in
53 | -s|--select)
54 | action_type="select"
55 | shift
56 | ;;
57 | -b|--branch)
58 | action_type="branch"
59 | shift
60 | ;;
61 | -c|--commit)
62 | action_type="commit"
63 | shift
64 | ;;
65 | -y|--yes)
66 | confirm="y"
67 | shift
68 | ;;
69 | -h|--help)
70 | usage
71 | exit 0
72 | ;;
73 | *)
74 | echo "Invalid option: $1" >&2
75 | usage
76 | exit 1
77 | ;;
78 | esac
79 | done
80 |
81 | if [[ "${action_type}" == "branch" ]]; then
82 | # checkout branch
83 | selected_branch=$(get_branch 'select a branch to checkout')
84 | [[ -z "${selected_branch}" ]] && exit 1
85 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" checkout "${selected_branch}"
86 | elif [[ "${action_type}" == "commit" ]]; then
87 | # checkout commit
88 | selected_commit=$(get_commit 'select a commit to checkout')
89 | [[ -z "${selected_commit}" ]] && exit 1
90 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" checkout "${selected_commit}"
91 | elif [[ "${action_type}" == "modified" ]]; then
92 | # checkout modified file back to version in HEAD
93 | while IFS= read -r line; do
94 | selected_files+=("${line}")
95 | done < <(get_modified_file 'select files to checkout version in HEAD')
96 | [[ "${#selected_files[@]}" -eq 0 ]] && exit 1
97 | [[ -z "${confirm}" ]] && echo "(dryrun) dotbare checkout --" "${selected_files[@]}"
98 | [[ -z "${confirm}" ]] && confirm=$(get_confirmation "Confirm?")
99 | [[ "${confirm}" != 'y' ]] && exit 1
100 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" checkout -- "${selected_files[@]}"
101 | elif [[ "${action_type}" == "select" ]]; then
102 | # checkout selected files to a selected commit
103 | while IFS= read -r line; do
104 | selected_files+=("${line}")
105 | done < <(get_git_file 'select files to checkout to previous commit')
106 | [[ "${#selected_files[@]}" -eq 0 ]] && exit 1
107 | # continue select a commit and then checkout the file back to the selected commit
108 | selected_commit=$(get_commit 'select the target commit' "${selected_files[@]}")
109 | [[ -z "${selected_commit}" ]] && exit 1
110 | [[ -z "${confirm}" ]] && echo "(dryrun) dotbare checkout ${selected_commit} --" "${selected_files[@]}"
111 | [[ -z "${confirm}" ]] && confirm=$(get_confirmation "Confirm?")
112 | [[ "${confirm}" != 'y' ]] && exit 0
113 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" checkout "${selected_commit}" "${selected_files[@]}"
114 | fi
115 |
--------------------------------------------------------------------------------
/scripts/fedit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # interactive menu to select file/commit to edit
4 | #
5 | # @params
6 | # Globals
7 | # ${mydir}: current directory of the script
8 | # ${edit_type}: which type to edit, all files, modified files, commit
9 | # ${selected_commit}: selected commit to edit
10 | # ${selected_files}: arrays of selected file to edit
11 | # Arguments
12 | # -m|--modified: display modified file only
13 | # -c|--commit: edit commit using interactive rebase
14 | # -h|--help: show helpe message and exit
15 |
16 | set -e
17 | set -f
18 |
19 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
20 | source "${mydir}"/../helper/set_variable.sh
21 | source "${mydir}"/../helper/git_query.sh
22 |
23 | function usage() {
24 | echo -e "Usage: dotbare fedit [-h] [-m] [-c] ...
25 |
26 | Select files/commits through fzf and edit selected files/commits in EDITOR.
27 |
28 | Default: list all tracked dotfiles and edit the selected files.
29 |
30 | Optional arguments:
31 | -h, --help\t\tshow this help message and exit.
32 | -m, --modified\tonly list and edit selected modified files.
33 | -c, --commit\t\tlist commit and edit the selected commit through interactive rebase."
34 | }
35 |
36 | edit_type="all"
37 | selected_files=()
38 | selected_commit=""
39 |
40 | while [[ "$#" -gt 0 ]]; do
41 | case "$1" in
42 | -m|--modified)
43 | edit_type="modified"
44 | shift
45 | ;;
46 | -c|--commit)
47 | edit_type="commit"
48 | shift
49 | ;;
50 | -h|--help)
51 | usage
52 | exit 0
53 | ;;
54 | *)
55 | echo "Invalid option: $1" >&2
56 | usage
57 | exit 1
58 | ;;
59 | esac
60 | done
61 |
62 | if [[ "${edit_type}" == "commit" ]]; then
63 | selected_commit=$(get_commit "select a commit to edit")
64 | [[ -z "${selected_commit}" ]] && exit 1
65 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" rebase -i "${selected_commit}"~
66 | else
67 | while IFS= read -r line; do
68 | selected_files+=("${line}")
69 | done < <(
70 | if [[ "${edit_type}" == "modified" ]]; then
71 | get_modified_file "select files to edit"
72 | else
73 | get_git_file "select files to edit"
74 | fi
75 | )
76 | [[ "${#selected_files[@]}" -eq 0 ]] && exit 1
77 | exec "${EDITOR}" "${selected_files[@]}"
78 | fi
79 |
--------------------------------------------------------------------------------
/scripts/fgrep:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Grep for words within all dotfiles
4 | #
5 | # @params
6 | # Globals
7 | # mydir: path to this current script
8 | # selected_lines: selected lines to edit
9 | # fzf_search_delimiter: the col to start searching in fzf
10 | # Arguments
11 | # -h|--help: show help message and exit
12 | # -c COL| --col COL: use a different delimiter in fzf search
13 | # -f|--full: include file name in fzf searching, as if using --col 1
14 |
15 | set -e
16 | set -f
17 |
18 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
19 | source "${mydir}"/../helper/set_variable.sh
20 | source "${mydir}"/../helper/git_query.sh
21 |
22 | function usage() {
23 | echo -e "Usage: dotbare fgrep [-h] [-c] [-f] ...
24 |
25 | Grep words within tracked files and select to edit matches.
26 |
27 | Default: start searching from 3rd column (excluding the file name during search).
28 |
29 | Optional arguments:
30 | -h, --help\t\tshow this help message and exit.
31 | -c COL, --col COL\tspecify the column number to start searching.
32 | -f, --full\t\tinclude all column during search, as if using '--col 1'."
33 | }
34 |
35 | selected_lines=()
36 | fzf_search_delimiter=3
37 |
38 | while [[ "$#" -gt 0 ]]; do
39 | case "$1" in
40 | -c|--col)
41 | fzf_search_delimiter="$2"
42 | shift
43 | shift
44 | ;;
45 | -f|--full)
46 | fzf_search_delimiter=1
47 | shift
48 | ;;
49 | -h|--help)
50 | usage
51 | exit 0
52 | ;;
53 | *)
54 | echo "Invalid option: $1" >&2
55 | usage
56 | exit 1
57 | ;;
58 | esac
59 | done
60 |
61 | while IFS= read -r line; do
62 | case "${EDITOR}" in
63 | vim|nvim|nano)
64 | # line number = "${line##*:}"
65 | # file name = "${line%%:*}"
66 | selected_lines+=(+"${line##*:}" "${line%%:*}")
67 | ;;
68 | *)
69 | selected_lines+=("${line}")
70 | ;;
71 | esac
72 | done < <(grep_words "select matches to edit" "${fzf_search_delimiter}")
73 |
74 | [[ "${#selected_lines[@]}" -eq 0 ]] && exit 1
75 |
76 | "${EDITOR}" "${selected_lines[@]}"
77 |
--------------------------------------------------------------------------------
/scripts/finit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # init or migrate the git bare repo
4 | #
5 | # @params
6 | # Globals
7 | # ${mydir}: current dir of the script
8 | # ${confirm}: confirm status of the user
9 | # ${post_hooks}: array of post checkout actions to perform
10 | # ${remote_url}; remote_url to clone and migrate
11 | # Arguments
12 | # -h|--help: show help message and exit
13 | # -u URL|--url URL: specify remote dotfiles url to init
14 | # -s|--select: clone submodules after checkout
15 | # -y|--yes: confirm action by default and skip confirmation
16 |
17 | set -e
18 | set -f
19 |
20 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
21 | source "${mydir}"/../helper/set_variable.sh
22 | source "${mydir}"/../helper/get_confirmation.sh
23 |
24 | function usage() {
25 | echo -e "Usage: dotbare finit [-h] [-y] [-s] [-u URL] ...
26 |
27 | Init the git bare repository if doesn't exist or migrate existing dotfiles to current system.
28 | The bare repository will be initialised under \$DOTBARE_DIR, default to \$HOME/.cfg if not set.
29 | It will track \$DOTBARE_TREE, default to \$HOME if not set.
30 |
31 | Migration example:
32 | dotbare finit -u URL --submodule
33 |
34 | Default: init the bare repository at $DOTBARE_DIR.
35 |
36 | Optional arguments:
37 | -h, --help\t\tshow this help message and exit.
38 | -u URL, --url URL\tmigrate existing dotfiles from remote git repo to current system.
39 | -s, --submodule\tclone submodules during migration.
40 | -y, --yes\t\tacknowledge all actions that will be taken and skip confirmation."
41 | }
42 |
43 | remote_url=""
44 | post_hooks=()
45 | confirm=""
46 |
47 | while [[ "$#" -gt 0 ]]; do
48 | case "$1" in
49 | -s|--submodule)
50 | [[ ! "${post_hooks[*]}" =~ submodule ]] && \
51 | post_hooks+=("submodule")
52 | shift
53 | ;;
54 | -u|--url)
55 | [[ -z "$2" ]] && echo "Invalid option: $1" >&2 && usage && exit 1
56 | remote_url="$2"
57 | shift
58 | shift
59 | ;;
60 | -y|--yes)
61 | confirm='y'
62 | shift
63 | ;;
64 | -h|--help)
65 | usage
66 | exit 0
67 | ;;
68 | *)
69 | echo "Invalid option: $1" >&2
70 | usage
71 | exit 1
72 | ;;
73 | esac
74 | done
75 |
76 | if [[ -z "${remote_url}" ]]; then
77 | echo "git bare repository will be initialised at ${DOTBARE_DIR}"
78 | echo "git bare repository will be tracking ${DOTBARE_TREE}"
79 | [[ -z "${confirm}" ]] && confirm=$(get_confirmation)
80 | [[ "${confirm}" != 'y' ]] && exit 1
81 |
82 | if [[ -d "${DOTBARE_DIR}" ]]; then
83 | echo "${DOTBARE_DIR} already exist"
84 | exit 1
85 | else
86 | git init --bare "${DOTBARE_DIR}"
87 | git --git-dir "${DOTBARE_DIR}" --work-tree "${DOTBARE_TREE}" \
88 | config --local status.showUntrackedFiles no
89 | fi
90 | else
91 | [[ ! -d "${DOTBARE_TREE}" ]] && mkdir -p "${DOTBARE_TREE}"
92 | cd "${DOTBARE_TREE}"
93 | git clone --bare "${remote_url}" "${DOTBARE_DIR}"
94 |
95 | set +e
96 | while ! git --git-dir "${DOTBARE_DIR}" --work-tree "${DOTBARE_TREE}" checkout 2> /dev/null; do
97 | echo "Resolving conflicts ..."
98 | git --git-dir "${DOTBARE_DIR}" --work-tree "${DOTBARE_TREE}" checkout 2>&1 \
99 | | awk '{
100 | if ($0 ~ /[\t].*/) {
101 | gsub(/^[\t]/, "", $0)
102 | print $0
103 | }
104 | }' \
105 | | xargs -I __ "${mydir}"/fbackup -p __ -m 2> /dev/null
106 | if git --git-dir "${DOTBARE_DIR}" --work-tree "${DOTBARE_TREE}" checkout 2> /dev/null; then
107 | echo "All conflicts resolved"
108 | break
109 | fi
110 | done
111 | set -e
112 |
113 | git --git-dir "${DOTBARE_DIR}" --work-tree "${DOTBARE_TREE}" \
114 | config --local status.showUntrackedFiles no
115 | echo "File checkout succeeded"
116 |
117 | for hook in "${post_hooks[@]}"; do
118 | case "${hook}" in
119 | submodule)
120 | echo "Cloning submodules ..."
121 | git --git-dir "${DOTBARE_DIR}" --work-tree "${DOTBARE_TREE}" \
122 | submodule update --init --recursive
123 | ;;
124 | esac
125 | done
126 |
127 | echo "Migration completed"
128 | exit 0
129 | fi
130 |
--------------------------------------------------------------------------------
/scripts/flog:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # git log interactive viewer
4 | #
5 | # @params
6 | # Globals
7 | # ${mydir}: current dir of the script
8 | # ${selected_action}: action to take on the selected commit
9 | # ${selected_commit}: user selected commit
10 | # ${confirm}: confirm status of user
11 | # Arguments
12 | # -h|--help: display help message
13 | # -r|--revert: revert the selected commit
14 | # -R|--reset: reset HEAD back to the selected commit
15 | # -e|--edit: edit commmit (interactive rebase)
16 | # -c|--checkout: checkout selected commmit
17 | # -y|--yes: confirm action by default and skip confirmation
18 |
19 | set -e
20 | set -f
21 |
22 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
23 | source "${mydir}"/../helper/set_variable.sh
24 | source "${mydir}"/../helper/git_query.sh
25 | source "${mydir}"/../helper/get_confirmation.sh
26 |
27 | function usage() {
28 | echo -e "Usage: dotbare flog [-h] [-r] [-R] [-e] [-c] [-y] ...
29 |
30 | Interactive log viewer with action menu.
31 | Action menu contains options including revert|reset|edit|checkout|exit.
32 |
33 | Default: list all commits and prompt a menu to select action to perform.
34 |
35 | Optional arguments:
36 | -h, --help\t\tshow this help message and exit.
37 | -r, --revert\t\trevert the selected commit and skip action menu.
38 | -R, --reset\t\treset HEAD back to selected commit and skip action menu.
39 | -e, --edit\t\tedit selected commit through interactive rebase and skip action menu.
40 | -c, --checkout\tcheckout selected commit and skip action menu.
41 | -y, --yes\t\tacknowledge all actions that will be taken and skip confirmation."
42 | }
43 |
44 | #######################################
45 | # draw action menu for selected commit
46 | # Arguments:
47 | # $1: selected commit hash, used to display commit message in fzf header
48 | # $2: selected action, if selected, skip menu, return action
49 | # Outputs:
50 | # ${selected_action}: user selected action
51 | #######################################
52 | function draw_menu() {
53 | local selected_commit="$1"
54 | local selected_action="$2"
55 | local menu header message
56 | if [[ -n "$selected_action" ]]; then
57 | echo "${selected_action}"
58 | else
59 | menu="revert: revert the selected commit\n"
60 | menu="${menu}reset: reset HEAD to the selected commit using --mixed flag\n"
61 | menu="${menu}edit: edit selected commit through interactive rebase\n"
62 | menu="${menu}checkout: checkout the selected commit\n"
63 | menu="${menu}exit: quit dotbare flog"
64 | message=$(
65 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
66 | log --format=%B -n 1 "${selected_commit}"
67 | )
68 | header="commit ${selected_commit}: ${message}"
69 | selected_action=$(echo -e "${menu}" \
70 | | fzf --no-multi --header="${header}" \
71 | | awk -F ":" '{
72 | print $1
73 | }'
74 | )
75 | echo "${selected_action}"
76 | fi
77 | }
78 |
79 | selected_action=""
80 | selected_commit=""
81 | confirm=""
82 |
83 | while [[ "$#" -gt 0 ]]; do
84 | case "$1" in
85 | -r|--revert)
86 | selected_action="revert"
87 | shift
88 | ;;
89 | -R|--reset)
90 | selected_action="reset"
91 | shift
92 | ;;
93 | -e|--edit)
94 | selected_action="edit"
95 | shift
96 | ;;
97 | -c|--checkout)
98 | selected_action="checkout"
99 | shift
100 | ;;
101 | -y|--yes)
102 | confirm='y'
103 | shift
104 | ;;
105 | -h|--help)
106 | usage
107 | exit 0
108 | ;;
109 | *)
110 | echo "Invalid option: $1" >&2
111 | usage
112 | exit 1
113 | ;;
114 | esac
115 | done
116 |
117 | while :; do
118 | selected_commit=$(get_commit)
119 | [[ -z "${selected_commit}" ]] && exit 1
120 | selected_action=$(draw_menu "${selected_commit}" "${selected_action}")
121 | [[ -n "${selected_action}" ]] && break
122 | done
123 |
124 | if [[ "${selected_action}" != 'exit' ]]; then
125 | if [[ "${selected_action}" == "reset" ]] && [[ -z "${confirm}" ]]; then
126 | echo "(dryrun) reset HEAD to ${selected_commit}"
127 | elif [[ -z "${confirm}" ]]; then
128 | echo "(dryrun) ${selected_action} ${selected_commit}"
129 | fi
130 | [[ -z "${confirm}" ]] && confirm=$(get_confirmation)
131 | [[ "${confirm}" != 'y' ]] && exit 1
132 | fi
133 |
134 | case "${selected_action}" in
135 | revert)
136 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
137 | revert "${selected_commit}"
138 | ;;
139 | reset)
140 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
141 | reset "${selected_commit}"
142 | ;;
143 | edit)
144 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
145 | rebase -i "${selected_commit}"~
146 | ;;
147 | checkout)
148 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
149 | checkout "${selected_commit}"
150 | ;;
151 | exit)
152 | exit 0
153 | ;;
154 | *)
155 | exit 1
156 | ;;
157 | esac
158 |
--------------------------------------------------------------------------------
/scripts/freset:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # unstage the selected staged file
4 | # or reset the commit to certain point
5 | #
6 | # @params
7 | # Globals
8 | # ${mydir}: current directory of the script
9 | # ${reset_type}: reset type, modified files or commit
10 | # ${reset_option}: git reset flag, --mixed | --soft | --hard
11 | # ${selected_files}: selected file to reset
12 | # ${selected_commit}: selected commit to reset
13 | # ${confirm}: confirmation status of the user
14 | # Arguments
15 | # -h|--help: show help message and quit
16 | # -c|--commit: reset commit
17 | # -S|--soft: use --soft flag
18 | # -H|--hard: use --hard flag
19 | # -y|--yes: confirm action by default and skip confirmation
20 |
21 | set -e
22 | set -f
23 |
24 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
25 | source "${mydir}"/../helper/set_variable.sh
26 | source "${mydir}"/../helper/get_confirmation.sh
27 | source "${mydir}"/../helper/git_query.sh
28 |
29 | function usage() {
30 | echo -e "Usage: dotbare freset [-h] [-c] [-S] [-H] [-y] ...
31 |
32 | Reset(unstage) the selected staged files.
33 | Reset the HEAD to certain commits by using -c flag.
34 |
35 | Default: unstage the selected files.
36 |
37 | Optional arguments:
38 | -h, --help\t\tshow this help message and exit.
39 | -c, --commit\t\treset HEAD to certain commit, default --mixed flag, reset HEAD to certain commit put all changes into modified state.
40 | -S, --soft\t\treset commit using --soft flag, reset HEAD to certain commit without modify working tree.
41 | -H, --hard\t\treset commit using --hard flag, reset HEAD to certain commit discard all changes from the working tree.
42 | -y, --yes\t\tacknowledge all actions that will be taken and skip confirmation."
43 | }
44 |
45 | reset_option="--mixed"
46 | reset_type="modified"
47 | selected_files=()
48 | confirm=""
49 | selected_commit=""
50 |
51 | while [[ "$#" -gt 0 ]]; do
52 | case "$1" in
53 | -c|--commit)
54 | reset_type="commit"
55 | shift
56 | ;;
57 | -S|--soft)
58 | reset_option="--soft"
59 | shift
60 | ;;
61 | -H|--hard)
62 | reset_option="--hard"
63 | shift
64 | ;;
65 | -y|--yes)
66 | confirm='y'
67 | shift
68 | ;;
69 | -h|--help)
70 | usage
71 | exit 0
72 | ;;
73 | *)
74 | echo "Invalid option: $1" >&2
75 | usage
76 | exit 1
77 | ;;
78 | esac
79 | done
80 |
81 | if [[ "${reset_type}" == "commit" ]]; then
82 | selected_commit=$(get_commit "select the target commit")
83 | [[ -z "${selected_commit}" ]] && exit 1
84 | [[ -z "${confirm}" ]] && confirm=$(get_confirmation "Reset HEAD to ${selected_commit} ${reset_option}?")
85 | [[ "${confirm}" != 'y' ]] && exit 1
86 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" reset "${selected_commit}" "${reset_option}"
87 | else
88 | while IFS= read -r line; do
89 | selected_files+=("${line}")
90 | done < <(get_modified_file 'select files to unstage' 'staged')
91 | [[ "${#selected_files[@]}" -eq 0 ]] && exit 1
92 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" reset "${selected_files[@]}"
93 | fi
94 |
--------------------------------------------------------------------------------
/scripts/fstash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # stash operation using fzf
4 | #
5 | # @params
6 | # Globals
7 | # ${mydir}: current dir of the script, source purpose
8 | # ${stash_command}: stash command, pop, apply or file/delete to stash file or delete stash
9 | # ${selected_files}: selected files to stash
10 | # ${selected_stash}: selected stash to apply
11 | # ${confirm}: user confirm status
12 | # Arguments
13 | # -h|--help: show help message
14 | # -s|--select: select individual files and stash
15 | # -d|--delete: delete selected stash
16 | # -p|--pop: use pop instead of apply on the selected stash
17 |
18 | set -e
19 | set -f
20 |
21 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
22 | source "${mydir}"/../helper/set_variable.sh
23 | source "${mydir}"/../helper/get_confirmation.sh
24 | source "${mydir}"/../helper/git_query.sh
25 |
26 | function usage() {
27 | echo -e "Usage: dotbare fstash [-h] [-s] [-d] [-p] ...
28 |
29 | View and manage stash interactively.
30 |
31 | Default: list all stashes and apply the selected stash.
32 |
33 | Optional arguments:
34 | -h, --help\t\tshow this help message and exit.
35 | -s, --select\t\tlist modified files and stash the selected files.
36 | -d, --delete\t\tlist all stashes and delete the selected stash from stash list.
37 | -p, --pop\t\tuse 'stash pop' instead of 'stash apply'."
38 | }
39 |
40 | stash_command="apply"
41 | selected_files=()
42 | selected_stash=""
43 | confirm=""
44 |
45 | while [[ "$#" -gt 0 ]]; do
46 | case "$1" in
47 | -p|--pop)
48 | stash_command="pop"
49 | shift
50 | ;;
51 | -s|--select)
52 | stash_command="select"
53 | shift
54 | ;;
55 | -d|--delete)
56 | stash_command="delete"
57 | shift
58 | ;;
59 | -y|--yes)
60 | confirm="y"
61 | shift
62 | ;;
63 | -h|--help)
64 | usage
65 | exit 0
66 | ;;
67 | *)
68 | echo "Invalid option: $1" >&2
69 | usage
70 | exit 1
71 | ;;
72 | esac
73 | done
74 |
75 | if [[ "${stash_command}" == "select" ]]; then
76 | while IFS= read -r line; do
77 | selected_files+=("${line}")
78 | done < <(get_modified_file "select files to add to a stash")
79 | [[ "${#selected_files[@]}" -eq 0 ]] && exit 1
80 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" stash -- "${selected_files[@]}"
81 | elif [[ "${stash_command}" == "delete" ]]; then
82 | selected_stash=$(get_stash "select stash to delete")
83 | [[ -z "${selected_stash}" ]] && exit 1
84 | [[ -z "${confirm}" ]] && \
85 | while IFS= read -r line; do
86 | echo "(dryrun) drop ${line}"
87 | done <<< "${selected_stash}"
88 | [[ -z "${confirm}" ]] && confirm=$(get_confirmation)
89 | [[ "${confirm}" != 'y' ]] && exit 1
90 | while IFS= read -r line; do
91 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" stash drop "${line}"
92 | done <<< "${selected_stash}"
93 | else
94 | selected_stash=$(get_stash "select stash to apply" "true")
95 | [[ -z "${selected_stash}" ]] && exit 1
96 | [[ -z "${confirm}" ]] && echo "(dryrun) ${stash_command} ${selected_stash}"
97 | [[ -z "${confirm}" ]] && confirm=$(get_confirmation)
98 | [[ "${confirm}" != 'y' ]] && exit 1
99 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" stash "${stash_command}" "${selected_stash}"
100 | fi
101 |
--------------------------------------------------------------------------------
/scripts/fstat:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # interactive git status menu
4 | # toggle stage and unstage
5 | #
6 | # @params
7 | # Globals
8 | # ${mydir}: current directory of where the script is running
9 | # ${selected_files}: raw selected file (with current git status prepend)
10 | # ${selected_filenames}: bash array of names for the selected_files
11 | # ${stage_file}: determine if current operation should be staging file or unstage
12 | # Arguments
13 | # -h|--help: show help message and exit
14 |
15 | set -e
16 | set -f
17 |
18 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
19 | source "${mydir}"/../helper/set_variable.sh
20 | source "${mydir}"/../helper/git_query.sh
21 |
22 | function usage() {
23 | echo -e "Usage: dotbare fstat [-h] ...
24 |
25 | Display interactive git status menu.
26 | Toggle file stage/unstage interactively.
27 |
28 | Optional arguments:
29 | -h, --help\t\tshow this help message and exit."
30 | }
31 |
32 | while [[ "$#" -gt 0 ]]; do
33 | case "$1" in
34 | -h|--help)
35 | usage
36 | exit 0
37 | ;;
38 | *)
39 | echo "Invalid option: $1" >&2
40 | usage
41 | exit 1
42 | ;;
43 | esac
44 | done
45 |
46 | while :; do
47 | # reset all variable and arrays for each loop
48 | selected_files=()
49 | selected_filenames=()
50 | stage_file=""
51 |
52 | while IFS= read -r line; do
53 | selected_files+=("${line}")
54 | done < <(get_modified_file "select files to stage/unstage" "all" "raw")
55 | [[ "${#selected_files[@]}" -eq 0 ]] && break
56 |
57 | # check if current operation should stage file or unstage file
58 | # if any file start with M but has char immediately follow it, new changes are made, stage file
59 | # if any file start with a space or tab, the file is not staged, stage file
60 | # otherwise, we unstage
61 | stage_file=$(printf '%s\n' "${selected_files[@]}" | awk '{
62 | if ($0 ~ /^[A-Za-z][A-Za-z].*$/) {
63 | print "stage"
64 | } else if ($0 ~ /^[ \t].*$/) {
65 | print "stage"
66 | }
67 | }')
68 |
69 | while IFS= read -r line; do
70 | selected_filenames+=("${line}")
71 | done < <(
72 | printf '%s\n' "${selected_files[@]}" \
73 | | awk -v home="${DOTBARE_TREE}" '{
74 | $1=""
75 | gsub(/^[ \t]/, "", $0)
76 | gsub(/"/, "", $0)
77 | print home "/" $0
78 | }'
79 | )
80 |
81 | if [[ -z "${stage_file}" ]]; then
82 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" reset --quiet HEAD "${selected_filenames[@]}"
83 | else
84 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" add "${selected_filenames[@]}"
85 | fi
86 | done
87 |
--------------------------------------------------------------------------------
/scripts/funtrack:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # untrack selected files
4 | #
5 | # @params
6 | # Globals
7 | # ${mydir}: current dir of the script
8 | # ${track_type}: determine method to use for untrack, possible values: untrack, temp, resume
9 | # ${confirm}: user confirm status
10 | # ${selected_files}: arrays of user selected_files for operation
11 | # Arguments
12 | # -h|--help: display help message and exit
13 | # -t|--temp: temporarily untrack files
14 | # -r|--resume: resume track of temp untracked files
15 | # -y|--yes: confirm action by default and skip confirmation
16 |
17 | set -e
18 | set -f
19 |
20 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
21 | source "${mydir}"/../helper/set_variable.sh
22 | source "${mydir}"/../helper/git_query.sh
23 | source "${mydir}"/../helper/get_confirmation.sh
24 |
25 | function usage() {
26 | echo -e "Usage: dotbare funtrack [-h] [-t] [-r] [-y] ...
27 |
28 | Untrack selected files from git.
29 |
30 | Default: list all tracked files and permanently untrack the selected files (using git rm --cached filename).
31 |
32 | Files will be remove from index while keeping the file in your current system.
33 | However, when your other computers pull down the changes, the untracked files will be deleted.
34 | Make sure to run dotbare fbackup before pulling down the changes.
35 |
36 | Alternatively use the -t flag (using git update-index --assume-unchanged [path]) to temporarily
37 | untrack a file but keeping the files when other computers pull down the changes.
38 | More information please refer to dotbare's github.
39 |
40 | Optional arguments:
41 | -h, --help\t\tshow this help message and exit.
42 | -t, --temp\t\tlist all tracked files and temporarily ignore changes of the selected files.
43 | -r, --resume\t\tlist all tracked files and resume tracking changes of the selected files.
44 | -y, --yes\t\tacknowledge all actions that will be taken and skip confirmation."
45 | }
46 |
47 | track_type="untrack"
48 | selected_files=()
49 | confirm=""
50 |
51 | while [[ "$#" -gt 0 ]]; do
52 | case "$1" in
53 | -t|--temp)
54 | track_type="temp"
55 | shift
56 | ;;
57 | -r|--resume)
58 | track_type="retrack"
59 | shift
60 | ;;
61 | -y|--yes)
62 | confirm='y'
63 | shift
64 | ;;
65 | -h|--help)
66 | usage
67 | exit 0
68 | ;;
69 | *)
70 | echo "Invalid option: $1" >&2
71 | usage
72 | exit 1
73 | ;;
74 | esac
75 | done
76 |
77 | while IFS= read -r line; do
78 | selected_files+=("${line}")
79 | done < <(get_git_file "select files to untrack")
80 | [[ "${#selected_files[@]}" -eq 0 ]] && exit 1
81 |
82 | if [[ "${track_type}" == "temp" ]]; then
83 | [[ -z "${confirm}" ]] && echo "(dryrun) dotbare update-index --assume-unchanged" "${selected_files[@]}"
84 | [[ -z "${confirm}" ]] && confirm=$(get_confirmation "Files will be temporarily stop being tracked for changes, continue?")
85 | [[ "${confirm}" != 'y' ]] && exit 1
86 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" update-index --assume-unchanged "${selected_files[@]}"
87 | echo -e " "
88 | echo "Selected files are temporarily untracked by git, use dotbare funtrack -r to continue tracking changes."
89 | echo "Although dotbare funtrack -t won't delete the files on other machines, it is not the recommended way to untrack files."
90 | echo "dotbare funtrack -t is using git update-index --assume-unchanged under the hood"
91 | echo "Please refer to git update-index official documentation for more details or visit dotbare's github page"
92 | elif [[ "${track_type}" == "retrack" ]]; then
93 | [[ -z "${confirm}" ]] && echo "(dryrun) dotbare update-index --no-assume-unchanged" "${selected_files[@]}"
94 | [[ -z "${confirm}" ]] && confirm=$(get_confirmation "Files will resume being tracked by git, continue?")
95 | [[ "${confirm}" != 'y' ]] && exit 1
96 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" update-index --no-assume-unchanged "${selected_files[@]}"
97 | echo " "
98 | echo "Selected files are being resumed for tracking by git."
99 | echo "Although dotbare funtrack -t won't delete the files on other machines, it is not the recommended way to untrack files."
100 | echo "dotbare funtrack -t is using git update-index --assume-unchanged under the hood"
101 | echo "Please refer to git update-index official documentation for more details or visit dotbare's github page"
102 | else
103 | [[ -z "${confirm}" ]] && echo "(dryrun) dotbare rm --cached" "${selected_files[@]}"
104 | [[ -z "${confirm}" ]] && confirm=$(get_confirmation "Untrack the selected files?")
105 | [[ "${confirm}" != 'y' ]] && exit 1
106 | git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" rm --cached "${selected_files[@]}"
107 | echo -e " "
108 | echo "Selected files are being untracked by git, make sure to run dotbare fbackup on your other systems."
109 | echo "When other systems pull down this change, selected files will be deleted on other systems."
110 | echo "This is the default behavior of git rm --cached."
111 | echo "Please refer to git rm official documentation for more details or visit dotbare's github page"
112 | fi
113 |
--------------------------------------------------------------------------------
/scripts/fupgrade:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # update dotbare to latest master
4 |
5 | set -f
6 |
7 | mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
8 |
9 | function usage() {
10 | echo -e "Usage: dotbare fupgrade [-h] ...
11 |
12 | Upgrade dotbare to the latest master.
13 |
14 | Optional arguments:
15 | -h, --help\t\tshow this help message and exit."
16 | }
17 |
18 | while [[ "$#" -gt 0 ]]; do
19 | case "$1" in
20 | -h|--help)
21 | usage
22 | exit 0
23 | ;;
24 | *)
25 | echo "Invalid option: $1" >&2
26 | usage
27 | exit 1
28 | ;;
29 | esac
30 | done
31 |
32 | # rip from omz
33 | # auto stash on rebase
34 | resetAutoStash=$(git config --bool rebase.autoStash 2>&1)
35 | git config rebase.autoStash true
36 |
37 | # change directory to dotbare folder
38 | cd "${mydir}/.." || exit
39 |
40 | echo "Updating dotbare ..."
41 | if git pull --rebase --stat origin master; then
42 | echo "dotbare updated successfully"
43 | else
44 | echo "Something went wrong, please try again or fire up an issue at https://github.com/kazhala/dotbare"
45 | fi
46 |
47 | # reset autostack to original value
48 | case "$resetAutoStash" in
49 | "")
50 | git config --unset rebase.autoStash
51 | ;;
52 | *)
53 | git config rebase.autoStash "${resetAutoStash}"
54 | ;;
55 | esac
56 |
--------------------------------------------------------------------------------
/tests/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM bats/bats:latest
2 | RUN apk add --no-cache git
3 | RUN apk add --no-cache fzf
4 | ENV COLUMNS=80
5 | ADD ./ /root/dotbare
6 | RUN echo "source /root/dotbare/dotbare.plugin.bash" >> "$HOME"/.bashrc
7 | WORKDIR /root/dotbare
8 | ARG MIGRATE='url'
9 | RUN [ "$MIGRATE" = 'url' ] && ./dotbare finit -u https://github.com/kazhala/dotfiles.git || :
10 | RUN [ "$MIGRATE" = 'bare' ] && ./dotbare finit -y || :
11 | ENTRYPOINT ["bats", "tests"]
12 |
--------------------------------------------------------------------------------
/tests/README.md:
--------------------------------------------------------------------------------
1 | # Testing dotbare
2 |
3 | `dotbare` is unit tested using the [bats](https://github.com/bats-core/bats-core) testing
4 | frame work. Interaction with `fzf` are mocked using the PATH override method.
5 |
6 | Refer to bats homepage for usage of bats and their test basics.
7 |
8 | ## Mocking
9 |
10 | One of the challenge when testing `dotbare` is interaction with `fzf`, `git` and some
11 | other shell functions. `fzf` is the most pain because it does require human interaction.
12 |
13 | Using the PATH override method, at the very least, we can assert if fzf is invoked with
14 | right arguments.
15 |
16 | ### How it works
17 |
18 | There is a executable file called fzf in the test folder as well as git, tree etc. Before
19 | running test that requires fzf invokations, append the test folder path to the front of
20 | PATH variable.
21 |
22 | ```sh
23 | #!/usr/bin/env bats
24 |
25 | stage_selected_dir() {
26 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
27 | bash "${BATS_TEST_DIRNAME}"/../dotbare fadd --dir
28 | }
29 | ```
30 |
31 | This way the executable will be executed by `dotbare` instead of the real `fzf`.
32 |
33 | ### The fzf executable
34 |
35 | I'm sure there might be more elegant way of doing this, if you have suggestions please
36 | help me improve it. Currently for better readability in all the bats test file, I added
37 | bunch of `if` statement in the `fzf` executable to assert if `fzf` is being called
38 | correctly.
39 |
40 | ```sh
41 | if [[ "$*" =~ '--multi --preview ' ]] && [[ "$*" =~ "tree -L 1 -C --dirsfirst {}" ]]; then
42 | # dotbare fadd --dir -- "./fadd.bats" @test "fadd stage selected dir"
43 | echo "fadd_stage_dir"
44 | fi
45 | ```
46 |
47 | When the executable is being called, it will check for it's arguments and echo out a shorter
48 | word indicating the correct argument is passed.
49 |
50 | ```sh
51 | #!/usr/bin/env bats
52 |
53 | @test "fadd stage selected dir" {
54 | run stage_selected_dir
55 | # we could assert if fzf is actually being invoked correctly
56 | # in this case, it's supposed to search directory and using tree to provide preview
57 | [[ "${output}" =~ "add fadd_stage_dir" ]]
58 | }
59 | ```
60 |
61 | ## Full example
62 |
63 | > You could always checkout more examples in tests folder
64 |
65 | The fzf executable
66 |
67 | ```sh
68 | if [[ "$*" =~ '--header=select a commit' ]] && [[ "$*" =~ "show --color" ]]; then
69 | # dotbare flog --reset -y -- "./flog.bats" @test "flog reset"
70 | echo "--flog_reset"
71 | fi
72 | ```
73 |
74 | The bats unit test file.
75 |
76 | ```sh
77 | #!/usr/bin/env bats
78 |
79 | help() {
80 | bash "${BATS_TEST_DIRNAME}"/../dotbare flog -h
81 | }
82 | reset() {
83 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
84 | bash "${BATS_TEST_DIRNAME}"/../dotbare flog --reset -y
85 | }
86 |
87 | @test "flog help" {
88 | run help
89 | [ "${status}" -eq 0 ]
90 | [ "${lines[0]}" = "Usage: dotbare flog [-h] [-r] [-R] [-e] [-c] [-y] ..." ]
91 | }
92 | @test "flog reset" {
93 | run reset
94 | [[ "${output}" =~ "reset --flog_reset" ]]
95 | }
96 | ```
97 |
--------------------------------------------------------------------------------
/tests/dotbare.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | help() {
4 | bash "${BATS_TEST_DIRNAME}"/../dotbare -h
5 | }
6 |
7 | addall() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare add --all
9 | }
10 |
11 | routing() {
12 | "${BATS_TEST_DIRNAME}"/../dotbare fadd -h
13 | }
14 |
15 | routing2() {
16 | "${BATS_TEST_DIRNAME}"/../dotbare flog -h
17 | }
18 |
19 | normal_git() {
20 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
21 | "${BATS_TEST_DIRNAME}"/../dotbare add -h
22 | }
23 |
24 | invalid_command() {
25 | "${BATS_TEST_DIRNAME}"/../dotbare hello
26 | }
27 |
28 | version() {
29 | "${BATS_TEST_DIRNAME}"/../dotbare --version
30 | }
31 |
32 | no_argument() {
33 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
34 | "${BATS_TEST_DIRNAME}"/../dotbare
35 | }
36 |
37 | generic_git_operation_block_finit() {
38 | "${BATS_TEST_DIRNAME}"/../dotbare --git finit
39 | }
40 |
41 | generic_git_operation_block_fbackup() {
42 | "${BATS_TEST_DIRNAME}"/../dotbare --git fbackup
43 | }
44 |
45 | generic_git_operation_block_fupgrade() {
46 | "${BATS_TEST_DIRNAME}"/../dotbare --git fupgrade
47 | }
48 |
49 | generic_git_operation_init() {
50 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
51 | "${BATS_TEST_DIRNAME}"/../dotbare --git init
52 | }
53 |
54 | generic_git_operation_fadd() {
55 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
56 | "${BATS_TEST_DIRNAME}"/../dotbare --git fadd
57 | }
58 |
59 | @test "main generic git fadd" {
60 | run generic_git_operation_fadd
61 | [ "${status}" -eq 0 ]
62 | [[ "${output}" =~ "--git-dir=rev-parse --show-toplevel/.git --work-tree=rev-parse --show-toplevel" ]]
63 | [[ "${output}" =~ "fadd_stage_modified" ]]
64 | }
65 |
66 | @test "main generic git commands" {
67 | run generic_git_operation_init
68 | [ "${status}" -eq 0 ]
69 | [[ "${output}" =~ "--git-dir=rev-parse --show-toplevel/.git --work-tree=rev-parse --show-toplevel" ]]
70 | [[ "${output}" =~ "init" ]]
71 | }
72 |
73 | @test "main generic git flag block finit" {
74 | run generic_git_operation_block_finit
75 | [ "${status}" -eq 1 ]
76 | [ "${output}" = "dotbare finit is not supported when using dotbare as a generic fuzzy git tool" ]
77 | }
78 |
79 | @test "main generic git flag block fbackup" {
80 | run generic_git_operation_block_fbackup
81 | [ "${status}" -eq 1 ]
82 | [ "${output}" = "dotbare fbackup is not supported when using dotbare as a generic fuzzy git tool" ]
83 | }
84 |
85 | @test "main generic git flag block fupgrade" {
86 | run generic_git_operation_block_fupgrade
87 | [ "${status}" -eq 1 ]
88 | [ "${output}" = "dotbare fupgrade is not supported when using dotbare as a generic fuzzy git tool" ]
89 | }
90 |
91 | @test "main help" {
92 | run help
93 | [ "${status}" -eq 0 ]
94 | [ "${lines[0]}" = "Usage: dotbare [-h] [-v] [COMMANDS] [OPTIONS] ..." ]
95 | }
96 |
97 | @test "main version" {
98 | run version
99 | [ "${status}" -eq 0 ]
100 | [[ "${output}" =~ "Current dotbare version: ${DOTBARE_VERSION}" ]]
101 | }
102 |
103 | @test "main disable add --all" {
104 | run addall
105 | [ "${status}" -eq 1 ]
106 | [ "${lines[0]}" = "If you intend to stage all modified file, run dotbare add -u" ]
107 | }
108 |
109 | @test "main routing" {
110 | run routing
111 | [ "${status}" -eq 0 ]
112 | [ "${lines[0]}" = "Usage: dotbare fadd [-h] [-f] [-d] ..." ]
113 | }
114 |
115 | @test "main routing2" {
116 | run routing2
117 | [ "${status}" -eq 0 ]
118 | [ "${lines[0]}" = "Usage: dotbare flog [-h] [-r] [-R] [-e] [-c] [-y] ..." ]
119 | }
120 |
121 | @test "main git command" {
122 | run normal_git
123 | [ "${status}" -eq 0 ]
124 | [[ "${output}" =~ "add -h" ]]
125 | }
126 |
127 | @test "main invliad command" {
128 | run invalid_command
129 | [ "${status}" -eq 1 ]
130 | }
131 |
132 | @test "main no argument" {
133 | run no_argument
134 | [[ "${output}" =~ "Available commands" ]]
135 | }
136 |
--------------------------------------------------------------------------------
/tests/fadd.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | help() {
4 | bash "${BATS_TEST_DIRNAME}"/../dotbare fadd -h
5 | }
6 |
7 | invalid_option() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare fadd -p
9 | }
10 |
11 | no_file_selected() {
12 | cd "${BATS_TEST_DIRNAME}"
13 | bash "${BATS_TEST_DIRNAME}"/../dotbare fadd -d
14 | }
15 |
16 | stage_selected_file() {
17 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
18 | bash "${BATS_TEST_DIRNAME}"/../dotbare fadd -f
19 | }
20 |
21 | stage_selected_dir() {
22 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
23 | bash "${BATS_TEST_DIRNAME}"/../dotbare fadd --dir
24 | }
25 |
26 | stage_modified_file() {
27 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
28 | bash "${BATS_TEST_DIRNAME}"/../dotbare fadd
29 | }
30 |
31 | @test "fadd help" {
32 | run help
33 | [ "${status}" -eq 0 ]
34 | [ "${lines[0]}" = "Usage: dotbare fadd [-h] [-f] [-d] ..." ]
35 | }
36 |
37 | @test "fadd invalid option" {
38 | run invalid_option
39 | [ "${status}" -eq 1 ]
40 | [ "${lines[0]}" = "Invalid option: -p" ]
41 | }
42 |
43 | @test "fadd no file selected" {
44 | run no_file_selected
45 | [ "${status}" -eq 1 ]
46 | }
47 |
48 | @test "fadd stage selected file" {
49 | run stage_selected_file
50 | [[ "${output}" =~ "add fadd_stage_file" ]]
51 | }
52 |
53 | @test "fadd stage selected dir" {
54 | run stage_selected_dir
55 | [[ "${output}" =~ "add fadd_stage_dir" ]]
56 | }
57 |
58 | @test "fadd stage modified file" {
59 | run stage_modified_file
60 | [[ "${output}" =~ "add" ]]
61 | [[ "${output}" =~ "fadd_stage_modified" ]]
62 | }
63 |
--------------------------------------------------------------------------------
/tests/fbackup.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | setup() {
4 | export DOTBARE_BACKUP="$HOME/.local/share/dotbare_test"
5 | export DOTBARE_DIR="${HOME}/.cfg/"
6 | }
7 |
8 | teardown() {
9 | [ -d "${DOTBARE_BACKUP}" ] && rm -r "${DOTBARE_BACKUP}"
10 | unset DOTBARE_BACKUP
11 | }
12 |
13 | help() {
14 | bash "${BATS_TEST_DIRNAME}"/../dotbare fbackup -h
15 | }
16 |
17 | invalid_option() {
18 | bash "${BATS_TEST_DIRNAME}"/../dotbare fbackup -f
19 | }
20 |
21 | backup() {
22 | bash "${BATS_TEST_DIRNAME}"/../dotbare fbackup
23 | }
24 |
25 | individual_backup() {
26 | cd "${BATS_TEST_DIRNAME}"
27 | bash "${BATS_TEST_DIRNAME}"/../dotbare fbackup -p fadd.bats
28 | }
29 |
30 | move_file() {
31 | touch bats_test.txt
32 | bash "${BATS_TEST_DIRNAME}"/../dotbare fbackup --path bats_test.txt -m
33 | }
34 |
35 | @test "fbackup help" {
36 | run help
37 | [ "${status}" -eq 0 ]
38 | [ "${lines[0]}" = "Usage: dotbare fbackup [-h] [-m] [-s] [-p PATH] ..." ]
39 | }
40 |
41 | @test "fbackup invalid option" {
42 | run invalid_option
43 | [ "${status}" -eq 1 ]
44 | [ "${lines[0]}" = 'Invalid option: -f' ]
45 | }
46 |
47 | @test "fbackup backup all files" {
48 | if ! "${BATS_TEST_DIRNAME}"/../dotbare log &>/dev/null; then
49 | run backup
50 | [ "${status}" -eq 1 ]
51 | else
52 | run backup
53 | [ "${status}" -eq 0 ]
54 | [ -f "${DOTBARE_BACKUP}"/.bashrc ]
55 | fi
56 | }
57 |
58 | @test "fbackup backup individual file" {
59 | run individual_backup
60 | [ "${status}" -eq 0 ]
61 | [ -f "${DOTBARE_BACKUP}"/fadd.bats ]
62 | }
63 |
64 | @test "fbackup move file" {
65 | run move_file
66 | [ "${status}" -eq 0 ]
67 | [ -f "${DOTBARE_BACKUP}"/bats_test.txt ]
68 | [ ! -f "${BATS_TEST_DIRNAME}"/bats_test.txt ]
69 | }
70 |
--------------------------------------------------------------------------------
/tests/fcheckout.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | setup() {
4 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
5 | }
6 |
7 | help() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout -h
9 | }
10 |
11 | invalid_option() {
12 | bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout -p
13 | }
14 |
15 | checkout_branch() {
16 | bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout --branch
17 | }
18 |
19 | checkout_commit() {
20 | bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout -c
21 | }
22 |
23 | checkout_modified_file() {
24 | bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout -y
25 | }
26 |
27 | checkout_selected_file() {
28 | bash "${BATS_TEST_DIRNAME}"/../dotbare fcheckout --yes -s
29 | }
30 |
31 | @test "fcheckout help" {
32 | run help
33 | [ "${status}" -eq 0 ]
34 | [ "${lines[0]}" = "Usage: dotbare fcheckout [-h] [-s] [-b] [-c] [-y] ..." ]
35 | }
36 |
37 | @test "fcheckout invalid option" {
38 | run invalid_option
39 | [ "${status}" -eq 1 ]
40 | [ "${lines[0]}" = "Invalid option: -p" ]
41 | }
42 |
43 | @test "fcheckout branch" {
44 | run checkout_branch
45 | [[ "${output}" =~ "checkout fcheckout_branch" ]]
46 | }
47 |
48 | @test "fcheckout commit" {
49 | run checkout_commit
50 | [[ "${output}" =~ "checkout fcheckout_commit" ]]
51 | }
52 |
53 | @test "fcheckout modified" {
54 | run checkout_modified_file
55 | [[ "${output}" =~ "checkout" ]]
56 | [[ "${output}" =~ "fcheckout_modified" ]]
57 | }
58 |
59 | @test "fcheckout select" {
60 | run checkout_selected_file
61 | [[ "${output}" =~ "checkout" ]]
62 | [[ "${output}" =~ "fcheckout_select_gitfile" ]]
63 | [[ "${output}" =~ "fcheckout_select_commitdiff" ]]
64 | }
65 |
--------------------------------------------------------------------------------
/tests/fedit.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | help() {
4 | bash "${BATS_TEST_DIRNAME}"/../dotbare fedit -h
5 | }
6 |
7 | invalid_option() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare fedit -p
9 | }
10 |
11 | no_file_selected() {
12 | cd "${BATS_TEST_DIRNAME}"
13 | bash "${BATS_TEST_DIRNAME}"/../dotbare fedit -m
14 | }
15 |
16 | edit_commits() {
17 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
18 | bash "${BATS_TEST_DIRNAME}"/../dotbare fedit --commit
19 | }
20 |
21 | edit_files() {
22 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
23 | export EDITOR="echo"
24 | bash "${BATS_TEST_DIRNAME}"/../dotbare fedit
25 | }
26 |
27 | @test "fedit help" {
28 | run help
29 | [ "${status}" -eq 0 ]
30 | [ "${lines[0]}" = "Usage: dotbare fedit [-h] [-m] [-c] ..." ]
31 | }
32 |
33 | @test "fedit invalid option" {
34 | run invalid_option
35 | [ "${status}" -eq 1 ]
36 | [ "${lines[0]}" = "Invalid option: -p" ]
37 | }
38 |
39 | @test "fedit no file selected" {
40 | run no_file_selected
41 | [ "${status}" -eq 1 ]
42 | }
43 |
44 | @test "fedit edit commits" {
45 | run edit_commits
46 | [[ "${output}" =~ "rebase -i" ]]
47 | [[ "${output}" =~ "fedit_commits" ]]
48 | }
49 |
50 | @test "fedit edit files" {
51 | run edit_files
52 | [[ "${output}" =~ "fedit_files" ]]
53 | }
54 |
--------------------------------------------------------------------------------
/tests/fgrep.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | help() {
4 | bash "${BATS_TEST_DIRNAME}"/../dotbare fgrep -h
5 | }
6 |
7 | invalid_option() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare fgrep -p
9 | }
10 |
11 | edit_lines() {
12 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
13 | export EDITOR="echo"
14 | bash "${BATS_TEST_DIRNAME}"/../dotbare fgrep
15 | }
16 |
17 | full_deli() {
18 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
19 | export EDITOR="echo"
20 | bash "${BATS_TEST_DIRNAME}"/../dotbare fgrep --full
21 | }
22 |
23 | option_deli() {
24 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
25 | export EDITOR="echo"
26 | bash "${BATS_TEST_DIRNAME}"/../dotbare fgrep --col 2
27 | }
28 |
29 | @test "fgrep option delimiter" {
30 | run option_deli
31 | [[ "${output}" =~ "--nth 2.. --header=select matches to edit" ]]
32 | }
33 |
34 | @test "fgrep full delimiter" {
35 | run full_deli
36 | [[ "${output}" =~ "--nth 1.. --header=select matches to edit" ]]
37 | }
38 |
39 | @test "fgrep help" {
40 | run help
41 | [ "${status}" -eq 0 ]
42 | [ "${lines[0]}" = "Usage: dotbare fgrep [-h] [-c] [-f] ..." ]
43 | }
44 |
45 | @test "fgrep invalid option" {
46 | run invalid_option
47 | [ "${status}" -eq 1 ]
48 | [ "${lines[0]}" = "Invalid option: -p" ]
49 | }
50 |
51 | @test "fgrep edit lines" {
52 | run edit_lines
53 | [[ "${output}" =~ "--nth 3.. --header=select matches to edit" ]]
54 | }
55 |
--------------------------------------------------------------------------------
/tests/finit.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | setup() {
4 | export DOTBARE_DIR="$HOME/.local/share/dotbare_test/.cfg"
5 | export DOTBARE_TREE="$HOME/.local/share/dotbare_test"
6 | }
7 |
8 | teardown() {
9 | if [[ "${DOTBARE_DIR}" == "$HOME/.local/share/dotbare_test/.cfg" ]] && \
10 | [[ "${DOTBARE_TREE}" == "$HOME/.local/share/dotbare_test" ]]; then
11 | rm -rf "${DOTBARE_TREE}"
12 | fi
13 | unset DOTBARE_DIR
14 | unset DOTBARE_TREE
15 | }
16 |
17 | help() {
18 | bash "${BATS_TEST_DIRNAME}"/../dotbare finit -h
19 | }
20 |
21 | init() {
22 | bash "${BATS_TEST_DIRNAME}"/../dotbare finit --yes
23 | }
24 |
25 | migration() {
26 | bash "${BATS_TEST_DIRNAME}"/../dotbare finit -u https://github.com/kazhala/dotfiles.git
27 | }
28 |
29 | submodule() {
30 | bash "${BATS_TEST_DIRNAME}"/../dotbare finit -u https://github.com/kazhala/dotfiles.git -s --submodule
31 | }
32 |
33 | @test "finit help" {
34 | run help
35 | [ "${status}" -eq 0 ]
36 | [ "${lines[0]}" = "Usage: dotbare finit [-h] [-y] [-s] [-u URL] ..." ]
37 | }
38 |
39 | @test "finit init dotbare" {
40 | [[ -d "${DOTBARE_DIR}" ]] && rm -rf "${DOTBARE_DIR}"
41 | run init
42 | [ "${status}" -eq 0 ]
43 | run init
44 | [ "${status}" -eq 1 ]
45 | [[ "${output}" =~ "${DOTBARE_DIR} already exist" ]]
46 | }
47 |
48 | @test "finit migration" {
49 | [[ -d "${DOTBARE_DIR}" ]] && rm -rf "${DOTBARE_DIR}"
50 | run migration
51 | [ "${status}" -eq 0 ]
52 | [[ "${output}" =~ "Migration completed" ]]
53 | }
54 |
55 | @test "finit submodule" {
56 | [[ -d "${DOTBARE_DIR}" ]] && rm -rf "${DOTBARE_DIR}"
57 | run submodule
58 | [ "${status}" -eq 0 ]
59 | result=$(echo "${output}" | tr "\n" " ")
60 | [[ "${result}" =~ "Cloning submodules ... Migration completed" ]]
61 | }
62 |
--------------------------------------------------------------------------------
/tests/flog.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | help() {
4 | bash "${BATS_TEST_DIRNAME}"/../dotbare flog -h
5 | }
6 |
7 | invalid_option() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare flog -p
9 | }
10 |
11 | menu() {
12 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
13 | bash "${BATS_TEST_DIRNAME}"/../dotbare flog
14 | }
15 |
16 | reset() {
17 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
18 | bash "${BATS_TEST_DIRNAME}"/../dotbare flog --reset -y
19 | }
20 |
21 | @test "flog help" {
22 | run help
23 | [ "${status}" -eq 0 ]
24 | [ "${lines[0]}" = "Usage: dotbare flog [-h] [-r] [-R] [-e] [-c] [-y] ..." ]
25 | }
26 |
27 | @test "flog invalid option" {
28 | run invalid_option
29 | [ "${status}" -eq 1 ]
30 | [ "${lines[0]}" = "Invalid option: -p" ]
31 | }
32 |
33 | @test "flog menu" {
34 | run menu
35 | [ "${status}" -eq 0 ]
36 | }
37 |
38 | @test "flog reset" {
39 | run reset
40 | [[ "${output}" =~ "reset --flog_reset" ]]
41 | }
42 |
--------------------------------------------------------------------------------
/tests/freset.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | help() {
4 | bash "${BATS_TEST_DIRNAME}"/../dotbare freset -h
5 | }
6 |
7 | invalid_option() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare freset -p
9 | }
10 |
11 | no_selection_made() {
12 | bash "${BATS_TEST_DIRNAME}"/../dotbare freset
13 | }
14 |
15 | select_commit() {
16 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
17 | bash "${BATS_TEST_DIRNAME}"/../dotbare freset --commit -y
18 | }
19 |
20 | select_files() {
21 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
22 | bash "${BATS_TEST_DIRNAME}"/../dotbare freset
23 | }
24 |
25 | @test "freset help" {
26 | run help
27 | [ "${status}" -eq 0 ]
28 | [ "${lines[0]}" = "Usage: dotbare freset [-h] [-c] [-S] [-H] [-y] ..." ]
29 | }
30 |
31 | @test "freset invalid option" {
32 | run invalid_option
33 | [ "${status}" -eq 1 ]
34 | [ "${lines[0]}" = "Invalid option: -p" ]
35 | }
36 |
37 | @test "freset no selection made" {
38 | run no_selection_made
39 | [ "${status}" -eq 1 ]
40 | }
41 |
42 | @test "freset select commit" {
43 | run select_commit
44 | [[ "${output}" =~ "reset freset_commit --mixed" ]]
45 | }
46 |
47 | @test "freset select files" {
48 | run select_files
49 | [[ "${output}" =~ "reset" ]]
50 | [[ "${output}" =~ "freset_file" ]]
51 | }
52 |
--------------------------------------------------------------------------------
/tests/fstash.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | setup() {
4 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
5 | }
6 |
7 | help() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare fstash -h
9 | }
10 |
11 | invalid_option() {
12 | bash "${BATS_TEST_DIRNAME}"/../dotbare fstash -w
13 | }
14 |
15 | stash_file() {
16 | bash "${BATS_TEST_DIRNAME}"/../dotbare fstash -s
17 | }
18 |
19 | stash_delete() {
20 | bash "${BATS_TEST_DIRNAME}"/../dotbare fstash --delete --yes
21 | }
22 |
23 | stash_apply() {
24 | bash "${BATS_TEST_DIRNAME}"/../dotbare fstash --yes
25 | }
26 |
27 | @test "fstash help" {
28 | run help
29 | [ "${status}" -eq 0 ]
30 | [ "${lines[0]}" = "Usage: dotbare fstash [-h] [-s] [-d] [-p] ..." ]
31 | }
32 |
33 | @test "fstash invalid option" {
34 | run invalid_option
35 | [ "${status}" -eq 1 ]
36 | [ "${lines[0]}" = "Invalid option: -w" ]
37 | }
38 |
39 | @test "fstash stash select file" {
40 | run stash_file
41 | [[ "${output}" =~ "stash" ]]
42 | [[ "${output}" =~ "fstash_select" ]]
43 | }
44 |
45 | @test "fstash stash delete" {
46 | run stash_delete
47 | [[ "${output}" =~ "stash drop fstash_delete" ]]
48 | }
49 |
50 | @test "fstash apply stash" {
51 | run stash_apply
52 | [[ "${output}" =~ "stash apply fstash_apply" ]]
53 | }
54 |
--------------------------------------------------------------------------------
/tests/fstat.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | help() {
4 | bash "${BATS_TEST_DIRNAME}"/../dotbare fstat -h
5 | }
6 |
7 | invalid_option() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare fstat -p
9 | }
10 |
11 | no_modify() {
12 | bash "${BATS_TEST_DIRNAME}"/../dotbare fstat
13 | }
14 |
15 | @test "fstat help" {
16 | run help
17 | [ "${status}" -eq 0 ]
18 | [ "${lines[0]}" = "Usage: dotbare fstat [-h] ..." ]
19 | }
20 |
21 | @test "fstat invalid option" {
22 | run invalid_option
23 | [ "${status}" -eq 1 ]
24 | [ "${lines[0]}" = "Invalid option: -p" ]
25 | }
26 |
27 | @test "fstat run no modify file" {
28 | run no_modify
29 | [ "${status}" -eq 0 ]
30 | }
31 |
--------------------------------------------------------------------------------
/tests/funtrack.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | setup() {
4 | export PATH="${BATS_TEST_DIRNAME}:$PATH"
5 | }
6 |
7 | help() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare funtrack -h
9 | }
10 |
11 | invalid_option() {
12 | bash "${BATS_TEST_DIRNAME}"/../dotbare funtrack -p
13 | }
14 |
15 | untrack_file() {
16 | bash "${BATS_TEST_DIRNAME}"/../dotbare funtrack --yes
17 | }
18 |
19 | temp_untrack() {
20 | bash "${BATS_TEST_DIRNAME}"/../dotbare funtrack --yes -t
21 | }
22 |
23 | resume_track() {
24 | bash "${BATS_TEST_DIRNAME}"/../dotbare funtrack --yes --resume
25 | }
26 |
27 | @test "funtrack help" {
28 | run help
29 | [ "${status}" -eq 0 ]
30 | [ "${lines[0]}" = "Usage: dotbare funtrack [-h] [-t] [-r] [-y] ..." ]
31 | }
32 |
33 | @test "funtrack invalid option" {
34 | run invalid_option
35 | [ "${status}" -eq 1 ]
36 | [ "${lines[0]}" = "Invalid option: -p" ]
37 | }
38 |
39 | @test "funtrack untrack file" {
40 | run untrack_file
41 | [[ "${output}" =~ "rm --cached" ]]
42 | [[ "${output}" =~ "funtrack_file" ]]
43 | }
44 |
45 | @test "funtrack temp untrack" {
46 | run temp_untrack
47 | [[ "${output}" =~ "update-index --assume-unchanged" ]]
48 | [[ "${output}" =~ "funtrack_file" ]]
49 | }
50 |
51 | @test "funtrack resume track" {
52 | run resume_track
53 | [[ "${output}" =~ "update-index --no-assume-unchanged" ]]
54 | [[ "${output}" =~ "funtrack_file" ]]
55 | }
56 |
--------------------------------------------------------------------------------
/tests/fupgrade.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | help() {
4 | bash "${BATS_TEST_DIRNAME}"/../dotbare fupgrade -h
5 | }
6 |
7 | invalid_option() {
8 | bash "${BATS_TEST_DIRNAME}"/../dotbare fupgrade -p
9 | }
10 |
11 | upgrade() {
12 | bash "${BATS_TEST_DIRNAME}"/../dotbare fupgrade
13 | }
14 |
15 | @test "fupgrade help" {
16 | run help
17 | [ "${status}" -eq 0 ]
18 | [ "${lines[0]}" = "Usage: dotbare fupgrade [-h] ..." ]
19 | }
20 |
21 | @test "fupgrade invliad option" {
22 | run invalid_option
23 | [ "${status}" -eq 1 ]
24 | [ "${lines[0]}" = "Invalid option: -p" ]
25 | }
26 |
27 | @test "fupgrade upgrade" {
28 | skip
29 | run upgrade
30 | [ "${status}" -eq 0 ]
31 | [ "${lines[0]}" = "Updating dotbare ..." ]
32 | }
33 |
--------------------------------------------------------------------------------
/tests/fzf:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # This script is for mocking fzf for testing,
4 | # it will stop fzf for goin into a interactive mode
5 | #
6 | # usage:
7 | # export PATH="${BATS_TEST_DIRNAME}:$PATH"
8 |
9 | if [[ "$*" =~ '--multi --preview ' ]] && [[ "$*" =~ "tree -L 1 -C --dirsfirst {}" ]]; then
10 | # dotbare fadd --dir -- "./fadd.bats" @test "fadd stage selected dir"
11 | echo "fadd_stage_dir"
12 | elif [[ "$*" =~ '--multi --preview' ]] && [[ "$*" =~ "preview.sh {}" ]]; then
13 | # dotbare fadd -f -- "./fadd.bats" @test "fadd stage selected file"
14 | echo "fadd_stage_file"
15 | elif [[ "$*" =~ '--header=select files to stage' ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
16 | # dotbare fadd -- "./fadd.bats" @test "fadd stage modified files"
17 | echo "-- fadd_stage_modified"
18 | elif [[ "$*" =~ "--no-multi --header=select a branch to checkout" ]]; then
19 | # dotbare fcheckout --branch -- "./fcheckout.bats" @test "fcheckout branch"
20 | echo "fcheckout_branch"
21 | elif [[ "$*" =~ "--header=select a commit to checkout" ]] && [[ "$*" =~ "show --color" ]]; then
22 | # dotbare fcheckout --c -- "./fcheckout.bats" @test "fcheckout commit"
23 | echo "fcheckout_commit"
24 | elif [[ "$*" =~ "--header=select files to checkout version in HEAD" ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
25 | # dotbare fcheckout -y -- "./fcheckout.bats" @test "fcheckout modified"
26 | echo "-- fcheckout_modified"
27 | elif [[ "$*" =~ '--header=select the target commit' ]] && [[ "$*" =~ "diff --color" ]]; then
28 | # dotbare fcheckout --yes -s -- "./fcheckout.bats" @test "fcheckout select"
29 | echo "fcheckout_select_commitdiff"
30 | elif [[ "$*" =~ '--header=select files to checkout' ]] && [[ "$*" =~ "preview.sh ${DOTBARE_TREE}/{}" ]]; then
31 | # dotbare fcheckout --yes -s -- "./fcheckout.bats" @test "fcheckout select"
32 | echo "fcheckout_select_gitfile"
33 | elif [[ "$*" =~ "--header=select a commit to edit --no-multi" ]] && [[ "$*" =~ "show --color=always" ]]; then
34 | # dotbare fedit --commit -- "./fedit.bats" @test "fedit edit commits"
35 | echo "fedit_commits"
36 | elif [[ "$*" =~ "--header=select files to edit" ]]; then
37 | # dotbare fedit -- "./fedit.bats" @test "fedit edit files"
38 | echo "fedit_files"
39 | elif [[ "$*" =~ '--header=select the target commit --no-multi' ]] && [[ "$*" =~ "show --color" ]]; then
40 | # dotbare freset --commit -y -- "./freset.bats" @test "freset select commit"
41 | echo "freset_commit"
42 | elif [[ "$*" =~ "--header=select files to unstage" ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
43 | # dotbare freset -- "./freset.bats" @test "freset select files"
44 | echo "-- freset_file"
45 | elif [[ "$*" =~ "--no-multi --header=commit --flog_reset" ]]; then
46 | # dotbare flog -- "./flog.bats" @test "flog checkout routing"
47 | echo "exit"
48 | elif [[ "$*" =~ '--header=select a commit' ]] && [[ "$*" =~ "show --color" ]]; then
49 | # dotbare flog --reset -y -- "./flog.bats" @test "flog reset"
50 | echo "--flog_reset"
51 | elif [[ "$*" =~ "--header=select files to untrack" ]] && [[ "$*" =~ "preview.sh ${DOTBARE_TREE}/{}" ]]; then
52 | # dotbare funtrack -- "./funtrack.bats" @test "funtrack untrack file"
53 | echo "funtrack_file"
54 | elif [[ "$*" =~ '--header=select files to add to a stash' ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
55 | # dotbare fstash -s -- "./fstash.bats" @test "fstash stash select file"
56 | echo "-- fstash_select"
57 | elif [[ "$*" =~ '--header=select stash to delete' ]] && [[ "$*" =~ "show -p __ --color=always" ]]; then
58 | # dotbare fstash --delete -- "./fstash.bats" @test "fstash stash delete"
59 | echo "fstash_delete"
60 | elif [[ "$*" =~ '--header=select stash to apply' ]] && [[ "$*" =~ "show -p __ --color=always" ]]; then
61 | # dotbare fstash -- "./fstash.bats" @test "fstash apply stash"
62 | echo "fstash_apply"
63 | else
64 | echo "$@"
65 | fi
66 |
--------------------------------------------------------------------------------
/tests/git:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # This script is for mocking git during unit test,
4 | # used to mock all the git calls.
5 | #
6 | # usage:
7 | # export PATH="${BATS_TEST_DIRNAME}:$PATH"
8 |
9 | echo "$@"
10 |
--------------------------------------------------------------------------------
/tests/set_variable.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | setup() {
4 | source "${BATS_TEST_DIRNAME}"/../helper/set_variable.sh
5 | }
6 |
7 | @test "env check env var" {
8 | [ "${DOTBARE_DIR}" = "$HOME/.cfg/" ]
9 | [ "${DOTBARE_TREE}" = "$HOME" ]
10 | [ "${DOTBARE_BACKUP}" = "$HOME/.local/share/dotbare" ]
11 | }
12 |
13 | @test "env check fzf var" {
14 | [ -n "${DOTBARE_KEY}" ]
15 | [ -n "${FZF_DEFAULT_OPTS}" ]
16 | [ -n "${DOTBARE_VERSION}" ]
17 | }
18 |
--------------------------------------------------------------------------------
/tests/shellcheck.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # run shellcheck against all scripts
4 |
5 | set -e
6 |
7 | mydir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8 | cd "${mydir}"/../
9 |
10 | scripts=()
11 | while IFS= read -r -d $'\0' line; do
12 | scripts+=("$line")
13 | done < <(
14 | find \
15 | dotbare \
16 | helper/* \
17 | scripts/* \
18 | tests/shellcheck.sh \
19 | -type f \
20 | -print0
21 | )
22 |
23 | shellcheck -e SC1091,SC1090 "${scripts[@]}"
24 | shellcheck -e SC1091 --shell=bash "dotbare.plugin.bash"
25 | shellcheck --shell=bash "pkg/completion/bash/dotbare"
26 | # \shellcheck does not have zsh support yet, hence using bash for now
27 | shellcheck -e SC2034,SC2277,SC2269 --shell=bash "dotbare.plugin.zsh"
28 | shellcheck -e SC2034,SC2269 --shell=bash "pkg/completion/zsh/_dotbare"
29 |
30 | exit $?
31 |
--------------------------------------------------------------------------------
/tests/tree:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # This script is for mocking tree during unit test,
4 | # just that we don't need install tree during different
5 | # test environment.
6 | #
7 | # usage:
8 | # export PATH="${BATS_TEST_DIRNAME}:$PATH"
9 |
10 | echo "$@"
11 |
--------------------------------------------------------------------------------