Compare commits

...

319 Commits

Author SHA1 Message Date
William Melody 8916c43efa Add `.github` configuration. 2023-06-27 16:59:08 -07:00
William Melody 9ea716f861
Use two-step homebrew install in README. 2020-10-06 23:13:23 -07:00
William Melody 9a929dc70f Update to version 3.6.4 2020-09-11 18:22:23 -07:00
William Melody 80699292a4 Use 'entries' terminology consistently. 2020-09-11 17:46:18 -07:00
William Melody 06ad3e8deb Add exit status to `list` and associated subcommands. 2020-09-11 17:40:47 -07:00
William Melody c74671613b Improve exit status documentation. 2020-09-11 17:22:02 -07:00
William Melody 0201480ffb Group helper variables and functions in Helpers section. 2020-09-11 17:01:29 -07:00
William Melody 0ce875c210 Use `sed -i` via a `_sed_i()` wrapper. 2020-09-11 17:01:29 -07:00
William Melody 6a58eb693d
Update README 2020-08-23 13:34:58 -07:00
William Melody 245188025a Improve `realpath` / `readlink` handling. 2020-08-16 10:14:48 -07:00
William Melody 39a182b47e Update Usage: ordering in `backups`. 2020-06-08 09:49:36 -07:00
William Melody bd7edba09b Improve spacing and comments in subcommands. 2020-06-08 09:42:58 -07:00
William Melody 5049abe817 Use alpha ordering for subcommand handling in `backup`. 2020-06-08 09:36:16 -07:00
William Melody 5c87ad62b0 Update version to 3.6.3 2020-06-07 18:07:12 -07:00
William Melody ca51f3f742 Remove extra newline. 2020-06-07 18:05:18 -07:00
William Melody ade1109cba Add missing `_warn` statements. 2020-06-07 17:22:20 -07:00
William Melody 3c383581c5 Update version to 3.6.2 2020-06-07 17:17:00 -07:00
William Melody 2346f6f814 Add missing `_download_from()` function. 2020-06-07 17:15:51 -07:00
William Melody 0715b9ec66 Update version to 3.6.1 2020-06-07 15:42:50 -07:00
William Melody 42a2a9f3d4 Use `__` prefix for variables in loops. 2020-06-07 15:42:11 -07:00
William Melody c11f22e558 Update error message in `_main()`. 2020-06-07 15:38:29 -07:00
William Melody 0d5f41537d Fix spacing in option parsing. 2020-06-07 15:13:23 -07:00
William Melody 0a98202f84 Remove additional `_debug()` statement. 2020-06-07 15:06:29 -07:00
William Melody 040593bd51 Improve `_load_subcommands()`. 2020-06-07 15:04:45 -07:00
William Melody 0b79763874 Update Make install instructions. 2020-06-07 14:59:31 -07:00
William Melody d6e3a8a128 Update version to 3.6.0 2020-06-07 14:57:43 -07:00
William Melody 0fa9b240c6 Remove extra space in `_load_subcommands()`. 2020-06-07 14:51:12 -07:00
William Melody 83bb517312 Update help and README.md for `subcommands`. 2020-06-07 14:49:59 -07:00
William Melody d396c5eefb Fix order in `$_SUBCOMMANDS`. 2020-06-07 14:44:57 -07:00
William Melody 8ab47640f0 Rename `commands` to `subcommands`. 2020-06-07 14:44:10 -07:00
William Melody c3be802faf Fix function name in `_debug` statement. 2020-06-07 14:41:35 -07:00
William Melody 768acb5d80 Rename `$_DEFINED_COMMANDS` to `$_DEFINED_SUBCOMMANDS`. 2020-06-07 14:41:05 -07:00
William Melody 379f99f4e1 Rename `_load_commands()` to `_load_subcommands()`. 2020-06-07 14:40:03 -07:00
William Melody 28fea3a599 Rename global variable to `$HOSTS_DEFAULT_SUBCOMMAND`. 2020-06-07 14:39:18 -07:00
William Melody bf65fbcad8 Replace `$_CMD` with `$_SUBCOMMAND`. 2020-06-07 14:37:10 -07:00
William Melody 5d4a9dfb28 Remove extra comments in `_main()`. 2020-06-07 14:36:21 -07:00
William Melody 0bd86e533d Move program functions to bottom of script. 2020-06-07 14:29:41 -07:00
William Melody a39c60aafa Use curly braces for all `$_ME` variable references. 2020-06-07 14:18:20 -07:00
William Melody 1da838faeb Remove extra comment. 2020-06-07 14:17:02 -07:00
William Melody 6e1d408ad5 Improve header formatting. 2020-06-07 14:14:13 -07:00
William Melody c381c8bd98 Add MIT license text to header.
resolves gh-10
2020-06-07 14:11:15 -07:00
William Melody 426f2ed602 Improve global variable comments. 2020-06-07 14:04:37 -07:00
William Melody 7596a2901f Improve variable names in `_print_entries()`. 2020-06-07 14:00:28 -07:00
William Melody 4e9ad74697 Improve alignment. 2020-06-07 13:57:07 -07:00
William Melody 051e8b3840 Don't use quotes when assigning empty strings. 2020-06-07 13:54:21 -07:00
William Melody f585447612 Improve variable handling in `_print_entries()`. 2020-06-07 13:51:00 -07:00
William Melody 4238e8bd81 Add `completions` help to README.md 2020-06-07 13:45:14 -07:00
William Melody a64c20bdd8 Rearrange commands in script. 2020-06-07 13:43:04 -07:00
William Melody 5865f92977 Remove version from default help output. 2020-06-07 13:40:11 -07:00
William Melody 2b81ea530f Remove unused utility functions. 2020-06-07 13:39:01 -07:00
William Melody 1e6af9b309 Improve comment in `$_SED_I_COMMAND` assignment. 2020-06-07 13:38:17 -07:00
William Melody 47b5d51fa3 Remove unused helper functions. 2020-06-07 13:36:33 -07:00
William Melody d775353c9a Use quotes when assigning function name. 2020-06-07 13:35:21 -07:00
William Melody 73ecc3119e Clean up program option parsing section. 2020-06-07 13:34:00 -07:00
William Melody d242aed463 Remove obsolete `$_COMMAND_ARGV` variable. 2020-06-07 13:31:46 -07:00
William Melody 9bf7f782c9 Use improved `_contains()`. 2020-06-07 13:26:27 -07:00
William Melody f0ebb08cd4 Use improved `_join()`. 2020-06-07 13:25:03 -07:00
William Melody 4aeab14d2d Remove obsolete `_command_argv_includes()`. 2020-06-07 13:23:54 -07:00
William Melody 952e2465b3 Add `_warn()` and use in `completions`. 2020-06-07 13:20:33 -07:00
William Melody 23d6a1c653 Move completion installation into the main script. 2020-06-07 13:20:12 -07:00
William Melody 17b2615820 Improve header, with note about LICENSE.
gh-10
2020-06-07 13:19:43 -07:00
William Melody 68b421f95a Combine Environment and Globals. 2020-06-07 12:45:07 -07:00
William Melody a09e7b2468 Improve section dividers. 2020-06-07 12:40:44 -07:00
William Melody dfbc83e12c Improve `_debug()`. 2020-06-07 12:34:55 -07:00
William Melody fff87648d4 Update version to 3.5.1 2020-05-17 11:39:26 -07:00
William Melody 8f6a700909 Improve formatting in tests. 2020-05-17 11:33:57 -07:00
William Melody 1d948837d0 Use `_exit_1` with non-help error messages. 2020-05-17 11:28:31 -07:00
William Melody 8f2553b5a3 Add $_ERROR_PREFIX to test_helper.bash. 2020-05-17 11:25:28 -07:00
William Melody 2f6290f3d4 Quote arguments to `help`. 2020-05-17 11:24:38 -07:00
William Melody 16a672d52a Improve code formatting. 2020-05-17 11:10:12 -07:00
William Melody 16a95406fe Replace `return 1` with message with `_return_1`. 2020-05-17 11:03:24 -07:00
William Melody 5a7d0cca91 Replace `_die()` with `_exit_1()`. 2020-05-17 11:01:25 -07:00
William Melody 40be65b7da `_verify_write_permissions()` doesn't accept arguments. 2020-05-17 10:57:33 -07:00
William Melody affd8d8657 Use brackets in `_verify_write_permissions()`. 2020-05-17 10:55:36 -07:00
William Melody 6e751065de Improve `backups` argument handling. 2020-05-17 10:54:03 -07:00
William Melody 3e326dad13 Unenable shellcheck SC2183 for printf format string. 2020-05-17 10:37:51 -07:00
William Melody 6bde3438c6 Don't use $/${} with arithmetic variables.
ShellCheck SC2004
https://github.com/koalaman/shellcheck/wiki/SC2004
2020-05-17 10:34:59 -07:00
William Melody ca43d92d85 Remove unused variable. 2020-05-17 10:33:15 -07:00
William Melody bc06de7476 Update version to 3.5.0 2020-04-22 12:15:15 -07:00
William Melody 9dab3606c6 Add exit status documentation to README.md 2020-04-22 12:08:02 -07:00
William Melody 88030b8a51 Return `1` from `show` when entry not found.
GH-9
2020-04-22 12:07:35 -07:00
William Melody 5112c3e6a0 Use consistent terminology in function documentation.
GH-9
2020-04-22 12:07:22 -07:00
William Melody 2f5f610e3c Reformat exit status documentation.
GH-9
2020-04-22 12:07:13 -07:00
William Melody 815def022e Remove .gitignore.
GH-9
2020-04-22 12:06:57 -07:00
William Melody 59bb99ea34 Merge branch 'sleepyghost01-feature/add-exit-codes'
* sleepyghost01-feature/add-exit-codes:
  Add exit code documentation
2020-04-22 12:05:37 -07:00
William Melody 40b76d2e26 Update version to 3.4.3 2020-04-16 11:48:00 -07:00
William Melody bc6b16c014 Improve `hosts-completion` script locations. 2020-04-16 11:46:45 -07:00
Amin Mousavi a67e4c997b Add exit code documentation
Problem:
It's not clear in documentation which exit code will return for each command specially commands that might return 1 when there's no action to do.

Solution:
- All possible documentation has been added.
- .ignorefile has been missed which could cause problem for other contribution so I add one by help of https://www.gitignore.io
2020-04-16 12:11:40 +02:00
William Melody 4088591bb2 Update version to 3.4.2 2020-04-14 13:21:03 -07:00
William Melody 972dc9a752 Improve README.md 2020-04-14 13:17:18 -07:00
William Melody 95807387a1 Improve README.md 2020-04-14 13:16:29 -07:00
William Melody 952d848157 Update version to 3.4.1 2020-04-14 13:06:40 -07:00
William Melody 89b016999d Remove duplicate heading in README.md 2020-04-14 13:05:47 -07:00
William Melody 91946962a6 Fix heading level in README.md 2020-04-14 13:03:37 -07:00
William Melody 886599394e Update version to 3.4.0 2020-04-14 10:13:31 -07:00
William Melody 45b39d1bc7 Update README.md 2020-04-14 10:10:20 -07:00
William Melody 6159d3e35a Update etc/README.md title. 2020-04-14 10:05:59 -07:00
William Melody 3d65bccdb5 Manage completion with `scripts/hosts-completion`. 2020-04-14 09:26:53 -07:00
William Melody 8cbbdc3550 Add scripts, update README.md and package.json. 2020-04-13 21:39:39 -07:00
William Melody 9cbc6ddafb Update version to 3.3.3 2020-04-13 16:49:08 -07:00
William Melody 809bb45121 Update heading in README.md 2020-04-13 16:37:45 -07:00
William Melody 638da3200e Reconfigure completion setup. 2020-04-13 16:36:58 -07:00
William Melody cd3d9ef2b5 Update version to 3.3.2 2020-04-13 15:07:41 -07:00
William Melody b7394fe2d5 Update completions. 2020-04-13 15:01:13 -07:00
William Melody b9a257f5d5 Add Travis status image to README.md 2020-04-12 19:09:30 -07:00
William Melody ace77c9926 Modify temp handling for better portability. 2020-04-12 19:04:39 -07:00
William Melody 56a27a040e Remove executable permissions from backups.bats. 2020-04-12 18:49:52 -07:00
William Melody e88cd0b16a Match variable space in duplicate detection. 2020-04-12 16:52:47 -07:00
William Melody 7b8b4db54b Escape newlines consistently. 2020-04-12 16:50:30 -07:00
William Melody 16c7484c17 Improve test failure messages. 2020-04-12 16:09:12 -07:00
William Melody c41b0ada74 Move documentation comment to more logical position. 2020-04-12 15:39:18 -07:00
William Melody b8c4ec06b9 Add .travis.yml 2020-04-12 15:34:56 -07:00
William Melody 5bb8add6de Update version to 3.3.1 2020-04-08 21:42:38 -07:00
William Melody 33c5aa1c3c Modify example in README.md 2020-04-08 21:36:52 -07:00
William Melody c14c1a5213 Avoid `less` in `backups show`. 2020-04-08 21:29:57 -07:00
William Melody c23a00bc49 Add walkthrough to README.md 2020-04-08 21:26:21 -07:00
William Melody fb67d7b510 Just use `diff` in `backups compare`. 2020-04-08 21:25:01 -07:00
William Melody 7fc3b994b4 Update version to 3.3.0 2020-04-08 18:01:24 -07:00
William Melody ce605e8c0c Add `delete` alias for `remove`. 2020-04-08 17:58:05 -07:00
William Melody d772e7c13e Avoid long lines in README.md 2020-04-08 17:47:53 -07:00
William Melody 7301dc38f1 Improve option parsing and command detection. 2020-04-08 17:44:51 -07:00
William Melody 5d9f876b13 Improve `add` formatting. 2020-04-08 17:27:11 -07:00
William Melody 902c996b3b Improve output formatting. 2020-04-08 16:43:07 -07:00
William Melody 3a810cf384 Update version to 3.2.5 2020-03-30 17:44:14 -07:00
William Melody 5916a18908 Avoid relying on `hosts` being in `$PATH`.
gh-8
2020-03-30 17:41:51 -07:00
William Melody b44b69f83d Use simpler homebrew install command in README.md. 2020-03-24 15:03:40 -07:00
William Melody 3ccfbb5bc1 Update version to 3.2.4 2020-03-23 17:54:20 -07:00
William Melody f67a88af94 Add URL to help text. 2020-03-23 17:52:58 -07:00
William Melody c864eff0ec Update version to 3.2.3 2020-03-18 12:04:42 -07:00
William Melody 925de9dca5 Update GitHub username.
alphabetum -> xwmx
2020-03-18 12:02:45 -07:00
William Melody 9f0c3d1773 Update keywords in package.json. 2020-03-17 11:01:11 -07:00
William Melody e9a7ecd6a7 Update version to 3.2.2 2020-03-16 22:36:18 -07:00
William Melody 85c1b7d436 Tweak keyword in package.json. 2020-03-16 22:35:43 -07:00
William Melody 0f3c59bd86 Rename `SED_COMMAND` variable to `_SED_I_COMMAND`. 2020-03-16 20:46:34 -07:00
William Melody 0a39dfe693 Add keywords to package.json. 2020-03-16 15:28:26 -07:00
William Melody d91a4406a7 Update version to 3.2.1 2020-03-16 15:07:52 -07:00
William Melody 92f0e97073 Link to the package name on npmjs.com. 2020-03-16 15:05:21 -07:00
William Melody 13171f4a01 Swap installation methods in README.md. 2020-03-16 15:05:21 -07:00
William Melody 916009280e Update bpkg URL in README.md. 2020-03-16 15:05:21 -07:00
William Melody e858faec05 Add npm install to README.md. 2020-03-16 15:05:21 -07:00
William Melody c6b84931a4 Update package name to 'hosts.sh'. 2020-03-16 15:05:21 -07:00
William Melody 75e68b0d17 Expand package.json. 2020-03-16 15:05:21 -07:00
William Melody 091e1c3809
Use non-mobile Wikipedia URL in README.md. 2020-03-15 20:37:05 -07:00
William Melody 774505abc0 Update version to 3.2.0 2020-03-15 18:55:34 -07:00
William Melody 659bbb4755 Use consistent argument name in documentation. 2020-03-15 18:51:42 -07:00
William Melody 0247826a41 Indicate in help text that `--skip-backup` is optional. 2020-03-15 18:49:03 -07:00
William Melody 09dad21311 Remove extra backslashes from README.md. 2020-03-15 18:46:59 -07:00
William Melody 4eed5251da Add `backups` command.
`backups` provides subcommands for managing backups of the hosts file.
2020-03-15 18:42:16 -07:00
William Melody ada8cb6019 Handle multiple hostnames with `block` and `unblock`. 2020-03-15 17:10:29 -07:00
William Melody ab2a193371 Update version to 3.1.3 2020-03-15 17:08:11 -07:00
William Melody 4be5105f67 Modify `sed` platform handling.
Use array for `sed -i` command so arguments are passed as expected. This
resolves an issue where a copy of the hosts file is created with quotes
appended to the filename.
2020-03-15 17:03:53 -07:00
William Melody bfbe08a65b Update version to 3.1.2 2020-03-15 11:45:39 -07:00
William Melody a2cddd9466 Update documentation in .shellcheckrc. 2020-03-15 11:40:13 -07:00
William Melody 4fae0d5526 Disable SC2206.
`IFS` and `noglob` are set, so we can ignore both SC2206 and SC2207.
2020-03-15 11:38:39 -07:00
William Melody c680c02007 Update grammar in comment. 2020-03-15 11:36:47 -07:00
William Melody a54793a9d0 Add .shellcheckrc and disable SC2207. 2020-03-15 11:32:09 -07:00
William Melody fa9ba543f5 Set `noglob` to disable filename expansion (globbing). 2020-03-15 11:30:08 -07:00
William Melody 850f210a4f Assign command parameters as quoted array.
Satisfies Shellcheck SC2206
https://github.com/koalaman/shellcheck/wiki/SC2206
2020-03-14 19:03:50 -07:00
William Melody fe48de86f1 Update version to 3.1.1 2019-11-21 19:28:51 -08:00
William Melody 2db235f68b Use portable `[[:digit:]]` in version tests.
`\d` is not portable so use `[[:digit]]`.
2019-11-21 19:26:49 -08:00
William Melody e10d116510 Handle platform-specific `sed -i` requirements.
`sed -i` on macOS requires an extension, but on Linux that extension can
cause errors. Use a platform check to only include the extension on
macOS.

resolves gh-5
2019-11-21 19:17:45 -08:00
William Melody 060306f28b Use { ..; } instead of (..) to avoid subshell overhead.
ShellCheck SC2235: https://github.com/koalaman/shellcheck/wiki/SC2235
2019-11-04 17:01:16 -08:00
William Melody 6b72e51651 Add tests for duplicate entry guard.
Deplicate entries are avoided by a guard in the `add` subcommand. Add
tests to ensure that duplicate entries are not created.
2019-05-28 18:22:34 -07:00
William Melody a475dc53aa
Add hosts file wikipedia link to README.md 2018-12-31 17:47:32 -08:00
William Melody 1ed6504bc2 Update version to 3.1.0 2018-08-14 11:31:02 -07:00
William Melody 14bfc65821 Fix 'enable' test names where needed. 2018-08-14 11:31:02 -07:00
William Melody 197ab087e6 Improve search tests.
Add tests for searching comments on disabled records and update test
names on search tests.
2018-08-14 11:31:02 -07:00
William Melody 789a0797c2 Improve search behavior.
Search comments in addition to IPs and hostnames.

Call grep twice, excluding commented lines first before searching.
2018-08-14 11:31:02 -07:00
William Melody b44f3b8fe0
Update description in README.md 2018-08-14 11:24:51 -07:00
William Melody 500d0f9b7f
Update description in README.md 2018-08-14 10:48:55 -07:00
William Melody af412412f2 Bump version to 3.0.1 2018-05-15 10:11:32 -07:00
{ɑβ} 899783e72d
Add link to AUR package in README.md 2018-05-15 10:06:02 -07:00
William Melody 5ee732006d Add comments about option parsing. 2018-05-15 08:37:24 -07:00
William Melody 647c4329c9 Update version to 3.0.0 2018-05-14 21:27:39 -07:00
William Melody 1738ba9ad3 Use double square brackets for option parsing `while` test. 2018-05-14 21:22:26 -07:00
William Melody 0c11a1939e Simplify `help` argument handling. 2018-05-14 21:19:36 -07:00
William Melody dfcb37b3b6 Remove unused option normalization.
This program only really accepts one short argument, `-h`, so this
extra complexity isn't necessary.
2018-05-14 20:45:35 -07:00
William Melody 79a5aa95fc Update boilerplate to latest from bash-boilerplate.
Source: https://github.com/alphabetum/bash-boilerplate
2018-05-14 20:22:35 -07:00
William Melody 7f3f6a95ab Simplify regular expression variable handling.
- Remove '_target' prefixes.
- Declare and assign separately.
2018-05-14 20:12:19 -07:00
William Melody 6da4b7475f Update coding style.
- Quote variables throughout.
- Use underscore prefixes to denote script-local variables and avoid
  identifier conflicts.
- Add spacing for better statement grouping.
2018-05-14 20:03:32 -07:00
William Melody d8f86743f4 Test `add` with multi-word comment. 2018-05-14 18:53:06 -07:00
William Melody 661fa3b114 Use updated `_join()` implementation.
Source: https://github.com/alphabetum/bash-boilerplate
2018-05-14 18:46:52 -07:00
William Melody dd25af8c99 Use updated `_load_commands()` implementation.
Source: https://github.com/alphabetum/bash-boilerplate
2018-05-14 18:42:21 -07:00
William Melody 2a5a18cf85 Bump version to 2.4.3
Fix misalignment between version numbers in package.json and
`$_VERSION`.
2018-05-09 10:36:18 -07:00
William Melody cfeb032707 Bump version to 2.4.2 2018-05-06 14:47:46 -07:00
William Melody a5bb823bac Improve setup / teardown of tmp test file.
Use a separate variable to identify tmp file during setup and teardown
operations.
2018-05-06 14:44:16 -07:00
William Melody 746780fbbe Use explicit escaping for backslashes in all contexts.
ShellCheck SC1117
https://github.com/koalaman/shellcheck/wiki/SC1117
2018-04-15 15:01:34 -07:00
William Melody 80edd464b6 Use explicit escaping for "\\n" newlines.
Backslash is literal, so explicitly escape it rather than rely on
fallback behavior.

ShellCheck SC1117
https://github.com/koalaman/shellcheck/wiki/SC1117
2018-04-15 14:55:26 -07:00
{ɑβ} b242081ef1
Add blocklists to README.md 2017-12-31 09:02:09 -08:00
William Melody 17a4eb1890 Use heading 3 for all command names in README.md. 2017-04-06 10:48:04 -07:00
William Melody d02f46a99e Bump version to 2.4.1. 2017-03-01 20:55:06 -08:00
William Melody d700037f18 Simplify header comment. 2017-03-01 20:54:08 -08:00
William Melody 32c5be4dcc Revert "Prefix `_debug` strings with '•' to avoid highlighting bugs."
This reverts commit 921afd7155.

The reverted commit did not succeed in fixing highlighting bugs.
2017-03-01 20:51:36 -08:00
William Melody 921afd7155 Prefix `_debug` strings with '•' to avoid highlighting bugs.
GitHub's syntax highlighting doesn't work well when strings contain
function names with parentheses, so add character to the beginning of
the string to see whether this makes it better.
2017-03-01 20:46:49 -08:00
William Melody f5d0f827e0 Bump version to 2.4.0. 2017-03-01 20:24:12 -08:00
William Melody d94af2c25b Update comments in "Globals" section. 2017-03-01 20:22:41 -08:00
William Melody db7ac727f1 Rename `$DEFAULT_COMMAND` to `$HOSTS_DEFAULT_COMMAND`. 2017-03-01 20:21:06 -08:00
William Melody 6c0254895f Support full `list` operations in `hosts` with no subcommand. 2017-03-01 20:18:26 -08:00
William Melody 05ba7bdc03 Quote argument to `unset`.
ShellCheck SC2184: Quote arguments to unset so they're not glob expanded.

https://github.com/koalaman/shellcheck/wiki/SC2184
2017-03-01 19:59:01 -08:00
William Melody 404ee19742 Add `_verify_write_permissions()` checks to `block` and `unblock`. 2017-03-01 19:32:49 -08:00
William Melody 3237818607 Expand documentation comment for `_verify_write_permissions()`. 2017-03-01 18:28:21 -08:00
William Melody b7b186267d Bump version to 2.3.1. 2017-03-01 16:29:36 -08:00
William Melody 7919b171fe Fix typo in README.md. 2017-03-01 16:26:58 -08:00
William Melody e0790f6a4c Bump version to 2.3.0. 2017-03-01 16:25:03 -08:00
William Melody c3cee7c65d Simplify README.md links. 2017-03-01 16:24:10 -08:00
William Melody 99b175f134 Add `--auto-sudo` option and expand option documentation.
Using `sudo` within a script is generally considered poor practice, so
by default an error message is printed when the user attempts to perform
a write operation without sufficient permissions.

One way to deal avoid this error message is to alias `hosts` to `sudo
hosts`, but this then requires `sudo` for all operations and not just
write operations.

The new `--auto-sudo` option flag provides a way to automatically invoke
a write command with `sudo` when the user doesn't have write
permissions.

In order to provide cleaner documentation for this option, include more
option documentation in README.md.
2017-03-01 16:18:05 -08:00
William Melody 0925735153 Bump version to 2.2.0. 2017-03-01 14:29:04 -08:00
William Melody 0bb87f92fe Expand help documentation in README.md
Output formatted to markdown with:

    for __command in "$(hosts commands --raw)"
    do
      printf "### \`hosts %s\`\n" "${__command}"
      printf "\n"
      printf "\`\`\`text\n"
      hosts help "${__command}"
      printf "\`\`\`\n"
      printf "\n"
    done
2017-03-01 14:02:17 -08:00
William Melody 347189c059 Add `search` usage to primary `help` output.
Update README.md to more accurately reflect `help` output.
2017-03-01 13:45:19 -08:00
William Melody 265a1c732e Add `block` and `unblock` functions.
`block` and `unblock` set the given <hostname> to the IPv4 and IPv6
loopback addresses.
2017-03-01 13:43:10 -08:00
William Melody e8fa0d8ac8 Fix typos in README.md. 2017-03-01 12:49:36 -08:00
William Melody b166d1b2ea Add missing `list` call in 'test/list.bats'. 2017-03-01 12:48:15 -08:00
William Melody 73ffcffb38 Add `hosts search` function.
`hosts search` wraps `hosts list`, providing a slightly more intuitive
interface.
2017-03-01 12:46:27 -08:00
William Melody 370e1f6688 Add autocomplete functions for bash and zsh. 2017-03-01 12:30:25 -08:00
William Melody e9f3dc5431 Add "Tests" section to README.md. 2017-03-01 12:15:16 -08:00
William Melody 703d665a32 Use `read` with `-r` option.
ShellCheck SC2162: read without -r mangle backslashes

https://github.com/koalaman/shellcheck/wiki/SC2162
2017-03-01 12:05:59 -08:00
William Melody 4194b25459 Use `HEREDOC` rather than `EOM` to define heredocs. 2017-03-01 11:42:26 -08:00
William Melody f4ebb9468a Rename "Readme.md" to "README.md". 2017-03-01 11:39:43 -08:00
William Melody 3ad43e7d95 Remove "Why" section from Readme.md. 2017-03-01 11:38:40 -08:00
William Melody f7675f360e Bump version to 2.1.6. 2016-03-24 17:32:26 -07:00
William Melody 149a51662e Handle blank arguments string when assigning to `$_RAW_OPTIONS`.
When `$*` is specified with quotes and braces as `"${*}"`, a blank
argument array results in an error in older versions of bash. Remove
the braces to avoid this error.
2016-03-24 17:30:30 -07:00
William Melody 187222614a Use braces in all variable references.
Braces are only required in certain cases, but the cognitive overhead in
keeping track of which cases require braces can be reduced by simply
always using them.

Example: `${NAME}`

Retain more widely-used braces `$NAME` convention in documentation.
2016-02-23 18:14:21 -08:00
William Melody 9782f78f22 Bump version to 2.1.5. 2016-01-26 20:42:26 -08:00
William Melody f7c7aef173 Update help/usage formatting. 2016-01-26 20:25:16 -08:00
William Melody f8564cfb2f Test argument with no match in remove.bats. 2016-01-26 20:17:55 -08:00
William Melody eb57a685c4 Expand list.bats. 2016-01-26 20:15:10 -08:00
William Melody 4330a73c3c Add remove.bats. 2016-01-26 19:35:04 -08:00
William Melody 73134c6b7b Remove unnecessary setup operations in enable.bats and disable.bats. 2016-01-26 19:17:36 -08:00
William Melody ee2a851bc9 Add show.bats. 2016-01-26 19:16:11 -08:00
William Melody 0bd1c32cd1 Use `version` command for tests that expect it in version.bats. 2016-01-26 19:08:04 -08:00
William Melody 4265bfe1f9 Add help tests to version.bats. 2016-01-26 19:07:05 -08:00
William Melody abfd442c3d Add help tests to file.bats. 2016-01-26 19:05:47 -08:00
William Melody f30981ec80 Add help tests to enabled.bats. 2016-01-26 19:05:10 -08:00
William Melody 481e593666 Add help tests to enable.bats. 2016-01-26 19:04:18 -08:00
William Melody c5fe3aedb2 Add help tests to disabled.bats. 2016-01-26 19:03:08 -08:00
William Melody 631c295ad1 Add help tests to disable.bats. 2016-01-26 19:02:07 -08:00
William Melody d88d819a19 Add help tests to add.bats. 2016-01-26 19:01:02 -08:00
William Melody 07108dc706 Add help tests to list.bats. 2016-01-26 19:00:02 -08:00
William Melody 09c375633f Add list.bats. 2016-01-26 18:58:32 -08:00
William Melody 5847cec598 Add enabled.bats. 2016-01-26 18:53:41 -08:00
William Melody 11fb3872e3 Add enable.bats. 2016-01-26 18:50:43 -08:00
William Melody 2f0a45bb5a Add disabled.bats. 2016-01-26 18:31:17 -08:00
William Melody 41a63ddf49 Add disable.bats. 2016-01-26 18:27:18 -08:00
William Melody 7b9e34ba53 Add add.bats. 2016-01-26 18:08:18 -08:00
William Melody b4c7370c10 Test number of `$lines` in hosts.bats test. 2016-01-26 17:49:05 -08:00
William Melody 7c961e1318 Add version.bats. 2016-01-25 19:27:49 -08:00
William Melody 6783e94f16 Fix typo in test_helper.bash comment. 2016-01-25 17:25:10 -08:00
William Melody 810e407c9e Fix copy/paste typos in help.bats. 2016-01-25 17:21:20 -08:00
William Melody 8faa7a0ab6 Add `_compare()` function to test_helper.bash. 2016-01-25 17:20:10 -08:00
William Melody 8e267fafd7 Edit hosts.bats test names to conform to project conventions. 2016-01-24 22:57:56 -08:00
William Melody 4e7cd2279e Add information about Bats to top of test_helper.bash. 2016-01-24 22:38:55 -08:00
William Melody 0c95e842ad Use /tmp directory for temp file generated with `mktemp`.
Moving to `mktemp` with files in /tmp makes it possible to remove the
local test/tmp directory.
2016-01-24 22:32:37 -08:00
William Melody 835d944bf9 Add help.bats with tests for the `help` subcommand. 2016-01-24 21:49:55 -08:00
William Melody 4cf3bc0a63 Test `file` output against `$HOSTS_PATH`. 2016-01-24 21:27:24 -08:00
William Melody ae9c4f0f4b Add tests for `file`. 2016-01-24 21:21:40 -08:00
William Melody 30ed049441 Add initial test structure with test 'hosts' file. 2016-01-24 21:14:32 -08:00
William Melody eeab6e8ba1 Alphabetize subcommands in Usage.
It's easier to find a subcommand in an alphabetical list.
2016-01-15 16:52:41 -08:00
William Melody 80a8e48c10 Use `if..then` in `show` to avoid non-zero exits.
The `[[ ... ]] && ...` conditional style results in non-zero exits when
the test is false. Moving this to a traditional `if..then` style avoids
this behavior while also being more explicit about the objective of the
code. `|| return 0` or `|| exit 0` could have been added as an
alternative way to avoid the non-zero exit behavior, but is not used in
this case because the traditional `if..then` style is more common.
2015-11-29 18:09:35 -08:00
William Melody 4d1adbdf52 Bump version to 2.1.4. 2015-11-25 18:03:19 -08:00
William Melody b1b644b97d Simplify description in Readme.md. 2015-11-24 16:16:09 -08:00
William Melody 8872349c16 Use fenced code blocks in Readme.md. 2015-11-24 16:15:45 -08:00
William Melody 21069fb68d Add quotes around strings in `list` command argument tests.
Quoting these strings more clearly communicates that these are not
variable or function names, and that the string itself is what is
being tested for.
2015-11-23 11:16:03 -08:00
William Melody 59e404f865 Add newlines around prompt section of `remove`.
The convention used in this project is to include newlines around
longer, grouped conditionals in order to provide better visual
separation.
2015-11-23 11:07:45 -08:00
William Melody 279573d2d0 Update regular expression comments in `remove`.
The regular expressions to which these comments apply were moved
around a few times without the comments being updated for these
changes.
2015-11-23 11:01:43 -08:00
William Melody e8e161f1e8 Bump version to 2.1.3. 2015-11-23 10:45:23 -08:00
William Melody 09d6d83093 Fix `--force` behavior in `remove`.
The `--force` option is passed to the function in `$_COMMAND_ARGV`,
which means that assigning arguments from positions in this array leads
to unexpected behavior depending on where in the argument list `--force`
is included. As a result, the `remove` function must parse the
arguments, removing the `--force` argument before assigning function
arguments to local variables.

resolves #2
2015-11-23 10:38:45 -08:00
William Melody a869da8e4e Clarify slicing example in `$_COMMAND_PARAMETERS` comment.
The example assignment should have balanced quotes to avoid any copy /
paste errors or reader confusion. Remove the 'not' since it's clearer if
this is used as a parenthetical example of slicing.
2015-10-19 16:50:48 -07:00
William Melody 0b955f41fa Bump version to 2.1.2. 2015-10-19 16:30:32 -07:00
William Melody e9b78ee15f Include debug statements in `add()` to print positional arguments. 2015-10-19 16:29:06 -07:00
William Melody b539cd6136 Use `unset` rather than slicing for bash 3.2 compatibility.
Use `unset` to remove the first element of `$_COMMAND_PARAMETERS` rather
than slicing because under bash 3.2 the resulting slice is treated as a
quoted string and doesn't easily get coaxed back into an array.
2015-10-19 16:26:21 -07:00
William Melody 6733260385 Bump version to 2.1.1 2015-09-15 11:33:39 -07:00
William Melody ab8934ae80 Default to 'N' in `remove` confirmation.
Rather than require a response, use 'N' as the default since this is a
destructive action.
2015-09-15 11:30:30 -07:00
William Melody 871e8fc131 Bump version to 2.1.0 2015-09-12 16:21:04 -07:00
William Melody db4df46caa Rename `search_term` to `search_string` in `enable` and `disable`.
`search_string` is slightly more descriptive, and it's the name that's
used in `remove`.
2015-09-12 16:18:53 -07:00
William Melody 1242d0b4bc Replace 'domain' with 'hostname' in regular expression variable names.
'hostname' is more accurate and consistent for this context.
2015-09-12 16:14:36 -07:00
William Melody 95fd43668a Assign `remove` regular expressions to variables.
Since the regular expressions are essentially repeated, with the only
difference being the capturing groups that have no impact on the delete
operations, assign them to a set of descriptive variables. This makes
things more organized and additionally provides some explanation for
what each regular expression is matching against.
2015-09-12 16:12:56 -07:00
William Melody ab9a08d954 Enhance `remove` to accept an IP and hostname pair.
This provides a mechanism for removing exact IP and hostname pairs.
The existing search string functionality should continue to function as
it did previously.
2015-09-12 15:41:28 -07:00
William Melody 1d1fa7ce9f Match IP at start of line in `disable`
The `disable` regular expressions avoid matching against commented lines
by excluding '#' characters at the beginning of the line. However, the
IP portion of the record is at the beginning of non-commented lines, so
in order to match these IPs the `target_regex_ip` needs to have the
search term checked against the beginning of the line. Therefore, the
`[^#]` at the beginning of `target_regex_ip` must be removed to make
`search_term` properly match these IPs.
2015-09-12 15:03:09 -07:00
William Melody b8811d42ba Bump version to 2.0.0 2015-09-12 14:16:43 -07:00
William Melody 84d77b8aec Export space and tab regular expression variables.
These variables are used within regular expressions, but as the program
evolves they are not always in constant use. Exporting these variables
silences ShellCheck warnings and makes them available to subshells.
2015-09-12 14:13:00 -07:00
William Melody a33b38b204 Make `sed` ops in `enable`/`disable` only match exact columns.
This is an application of the approach to `sed` calls that was included
in 94ca8bf

In order to make editing more precise, `sed` regular expressions only
match exact occurrences of the search string within each entry column.
2015-09-12 14:08:48 -07:00
William Melody 9cb7576bb5 Merge branch 'master' into exact-matches
* master:
  Exit with "Not found" message on failed search in `enable`/`disable`
  Bump version to 1.5.0
  Print confirmation feedback in `add` on success.
  Declare and assign separately to avoid masking return values.
  Add `brew tap` command to `brew install` in Readme.
2015-09-12 13:28:31 -07:00
William Melody 8465c2bdf8 Exit with "Not found" message on failed search in `enable`/`disable`
When the search string in `enable` or `disable` is not found, exit the
program and provide feedback rather than silently failing.
2015-09-12 13:19:17 -07:00
William Melody 62f200574d Bump version to 1.5.0 2015-09-11 19:51:02 -07:00
William Melody 590d75096f Print confirmation feedback in `add` on success. 2015-09-11 19:47:52 -07:00
William Melody 12d11c2dc3 Declare and assign separately to avoid masking return values.
ShellCheck SC2155
2015-09-11 19:43:56 -07:00
William Melody 5759ade2eb Add `brew tap` command to `brew install` in Readme. 2015-06-29 19:58:17 -07:00
William Melody 94ca8bfb57 Make `sed` operations in `remove` only match exact column matches.
In order to make editing more precise, sed regular expressions only
match exact occurrences of the search string within each entry column.

In order to properly handle tab and space separators in a portable
manner, a set of global variables are included that provide strings
of those characters.
2015-06-28 22:09:46 -07:00
William Melody 46dcff947c Bump version to 1.4.3 2015-06-28 22:08:29 -07:00
William Melody 41a84bd0ed Uppercase `$_USE_DEBUG` reference in `_debug`
This variable was uppercased in a09d0fc but this occurrence was missed.
2015-06-28 17:32:42 -07:00
William Melody 5a1ffa3498 Bump version 1.4.2
package.json was missed in c80287f
2015-06-27 20:51:45 -07:00
William Melody c80287f2bf Bump version to 1.4.2 2015-06-27 20:49:06 -07:00
William Melody fa920b0a97 Use `local` keyword more consistently. 2015-06-27 20:47:36 -07:00
William Melody a09d0fc893 Update boilerplate to reflect latest updates from source. 2015-06-27 20:43:19 -07:00
William Melody 8b0fc0fcfe Quote command names passed as arguments to `desc` 2015-06-27 20:33:11 -07:00
William Melody d2b92aec5a Prefer newlines instead of semicolons. 2015-06-27 20:31:26 -07:00
William Melody 66edbfd03c Update `_debug` and `_die` comments. 2015-06-27 20:21:58 -07:00
William Melody 3cfa2c8cf9 Use simpler `$IFS` setting. 2015-06-27 20:17:41 -07:00
William Melody 2693c62693 Bump version to 1.4.1 2015-06-25 17:19:23 -07:00
William Melody 02a87b0938 Add optional extension argument to `sed -i` calls
BSD sed requires the optional exention argument for the -i option, while
in GNU sed it's optional. Including a blank extension for portability.
2015-06-25 17:17:12 -07:00
William Melody 13d1428ee9 Add large ascii text of name to Readme 2015-05-20 20:31:05 -07:00
William Melody d5b6456766 Bump version to 1.4.0 2015-05-20 16:49:46 -07:00
William Melody db2b5ad074 Add expanded installtion instructions to Readme
Include command for manual and bpkg installation methods.
2015-05-20 16:48:08 -07:00
William Melody 371b644f6f Add package.json for bpkg 2015-05-20 16:47:32 -07:00
William Melody 87bce12994 Add basic Makefile
This simply installs the script to /usr/local/bin
2015-05-20 16:46:02 -07:00
William Melody 08d899fee5 Fix inert indentation typo. 2015-04-28 16:54:25 -07:00
William Melody 9a395fd017 Bump version to 1.3.0 2015-04-18 21:23:45 -07:00
William Melody 26ad499fee Spelling correction: formmatted_comment -> formatted_comment 2015-04-18 21:21:46 -07:00
William Melody 2c83de9dff Declare and assign separately to avoid masking return values.
ShellCheck SC2155

https://github.com/koalaman/shellcheck/wiki/SC2155
2015-04-18 21:17:46 -07:00
William Melody cb9e20e554 Use capitalized form of $_ME variable.
The capitalized version of this variable makes it easier to override,
even though this is not technically part of the external API. There is
no known downside of using the capitalized version of the variable.
2015-04-18 21:06:26 -07:00
William Melody e62bede843 Bump version to 1.2.0 2015-03-20 18:11:42 -07:00
William Melody c2ca24b459 Verify that matching records have been found in `remove` before removing 2015-03-20 18:10:51 -07:00
William Melody 312f5909fa Add ability to add an option comment when adding a record
This addition requires a number of changes including:

- the addition of a new `_join` function
- reformatting of the `add` function to facilitate the longer lines
2015-03-20 18:06:00 -07:00
William Melody 023aa0503f Add `enabled` and `disabled` to command list in `--help` 2015-03-20 17:23:31 -07:00
William Melody f10be24da7 Bump version to 1.1.0 2015-03-20 16:49:24 -07:00
William Melody 7e32a799c2 Add `enabled` and `disabled` commands.
Both of these are just aliases for the `list ( enabled | disabled )`
commands, providing a shorter way to access the same functionality.
2015-03-20 16:49:08 -07:00
William Melody 52529dd029 Correct typo in `help` usage + add info about `--force` in Readme 2015-03-19 17:14:04 -07:00
William Melody e6ee93da47 Add command information to Readme 2015-03-19 14:43:32 -07:00
William Melody 0830fa43b8 Simplify "strict mode" section in order to avoid too much noise
These comments can be found in the bash-boilerplate project and aren't
necessary here. Since the $DEFAULT_IFS doesn't appear to be used,
either, the $IFS setting can be reduced to a since simple assignment.
2015-03-19 14:30:51 -07:00
31 changed files with 4804 additions and 699 deletions

2
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,2 @@
github: xwmx
custom: https://paypal.me/WilliamMelody

84
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,84 @@
###############################################################################
# .github/workflows/tests.yml
#
# NOTE: GitHub Actions does not allocate a TTY, preventing detection of
# piped input using `[[ -t 0 ]]`.
#
# More information:
#
# https://github.com/actions/runner/issues/241
#
# faketty is a GitHub action that uses work-arounds to provide a tty:
#
# https://github.com/marketplace/actions/faketty
#
# Scripts used by faketty for each platform:
#
# linux: `faketty`
#
# ```bash
# #!/bin/bash
#
# script -q -e -c "$*"
# ```
#
# win32: `faketty.ps1`
#
# ```posh
# Invoke-Expression "$args"
# ```
#
# darwin: `faketty`
#
# requires: `brew install expect`
#
# ```bash
# #!/bin/bash
#
# unbuffer $*
# ```
###############################################################################
name: "hosts · Test Suite"
on:
pull_request:
branches: [ master ]
push:
branches: [ master ]
workflow_dispatch:
jobs:
test-macos-11:
name: "Test: macOS Big Sur 11.0"
runs-on: macos-11.0
steps:
- uses: actions/checkout@v3
- name: "Setup"
run: |
brew update
brew install bats-core
brew install expect
- name: "Set $TERM=xterm"
run: printf "TERM=xterm\\n" >> $GITHUB_ENV
- name: "Run bats tests"
run: unbuffer bats test
test-ubuntu-latest:
name: "Test: Ubuntu Latest"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: "Setup"
run: |
sudo apt-get update
sudo apt-get install bats -y
- name: "Install bats-core"
run: |
git clone https://github.com/bats-core/bats-core.git "${HOME}/bats-core" &&
cd "${HOME}/bats-core"
git checkout 2e2e5df6adf0b846b411b6b2f7bb654cbc3e2c4e
sudo ./install.sh /usr/local
- name: "Set $TERM=xterm"
run: printf "TERM=xterm\\n" >> $GITHUB_ENV
- name: "Run bats tests"
run: script -q -e -c "bats test"

22
.shellcheckrc Normal file
View File

@ -0,0 +1,22 @@
###############################################################################
# .shellcheckrc
#
# https://github.com/koalaman/shellcheck
# https://github.com/koalaman/shellcheck/wiki/Ignore
###############################################################################
# Disable SC2183
#
# Running into this: https://github.com/koalaman/shellcheck/issues/1310
# TODO: Check if resolved.
#
#https://github.com/koalaman/shellcheck/wiki/SC2183
disable=SC2183
# Disable SC2206 and SC2207
#
# `IFS` and `noglob` are set.
#
# https://github.com/koalaman/shellcheck/wiki/SC2206
# https://github.com/koalaman/shellcheck/wiki/SC2207
disable=SC2206,SC2207

10
Makefile Normal file
View File

@ -0,0 +1,10 @@
BIN ?= hosts
PREFIX ?= /usr/local
install:
install $(BIN) $(PREFIX)/bin
./$(BIN) completions install
uninstall:
rm -f $(PREFIX)/bin/$(BIN)
./$(BIN) completions uninstall

694
README.md Normal file
View File

@ -0,0 +1,694 @@
[![Build Status](https://img.shields.io/github/actions/workflow/status/xwmx/hosts/tests.yml?branch=master)](https://github.com/xwmx/hosts/actions)
__ __
/ /_ ____ _____/ /______
/ __ \/ __ \/ ___/ __/ ___/
/ / / / /_/ (__ ) /_(__ )
/_/ /_/\____/____/\__/____/
# Hosts
`hosts` is a command line program for managing
[hosts file](https://en.wikipedia.org/wiki/Hosts_\(file\)) entries.
`hosts` works with existing hosts files and entries, making it easier to add,
remove, comment, and search hosts file entries using simple, memorable
commands.
`hosts` is designed to be lightweight, easy to use, and contained in a
single, portable script that can be `curl`ed into any environment.
## Installation
### Homebrew
To install with [Homebrew](http://brew.sh/):
```bash
brew tap xwmx/taps
brew install hosts
```
### npm
To install with [npm](https://www.npmjs.com/package/hosts.sh):
```bash
npm install --global hosts.sh
```
### bpkg
To install with [bpkg](https://github.com/bpkg/bpkg):
```bash
bpkg install xwmx/hosts
```
### Make
To install with [Make](https://en.wikipedia.org/wiki/Make_(software)),
clone this repository, navigate to the clone's root directory, and run:
```bash
sudo make install
```
### Manual
To install as an administrator, copy and paste one of the following multi-line
commands:
```bash
# install using wget
sudo wget https://raw.github.com/xwmx/hosts/master/hosts -O /usr/local/bin/hosts &&
sudo chmod +x /usr/local/bin/hosts &&
sudo hosts completions install
# install using curl
sudo curl -L https://raw.github.com/xwmx/hosts/master/hosts -o /usr/local/bin/hosts &&
sudo chmod +x /usr/local/bin/hosts &&
sudo hosts completions install
```
###### User-only Installation
To install with just user permissions, simply add the `hosts` script to your
`$PATH`. If you already have a `~/bin` directory, for example, you can use
one of the following commands:
```bash
# download with wget
wget https://raw.github.com/xwmx/hosts/master/hosts -O ~/bin/hosts && chmod +x ~/bin/hosts
# download with curl
curl -L https://raw.github.com/xwmx/hosts/master/hosts -o ~/bin/hosts && chmod +x ~/bin/hosts
```
Installing with just user permissions doesn't install the completions, but
`hosts` works without them. If you have `sudo` access and want to install the
completion scripts, run the following command:
```bash
sudo hosts completions install
```
### Arch Linux
A package for Arch users is also
[available in the AUR](https://aur.archlinux.org/packages/hosts/).
### Tab Completion
Bash and Zsh tab completion is enabled when `hosts` is installed using
Homebrew, npm, bpkg, or Make. If you are installing `hosts` manually,
[completion can be enabled with a few commands](etc/README.md).
## Usage
### Listing Entries
`hosts` with no arguments lists the entries in the system's hosts file:
```bash
> hosts
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
```
`hosts` called with a string or regular expression will search for entries
that match.
```bash
> hosts localhost
127.0.0.1 localhost
::1 localhost
fe80::1%lo0 localhost
> hosts '\d\d\d'
127.0.0.1 localhost
255.255.255.255 broadcasthost
```
### Adding Entries
To add an entry, use `hosts add`:
```bash
> hosts add 127.0.0.1 example.com
Added:
127.0.0.1 example.com
```
Run `hosts` or `hosts list` to see the new entry in the list:
```bash
> hosts
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
127.0.0.1 example.com
```
### Removing Entries
To remove an entry, use `hosts remove`, which can take an IP
address, domain, or regular expression:
```bash
> hosts remove example.com
Removing the following entries:
127.0.0.1 example.com
Are you sure you want to proceed? [y/N] y
Removed:
127.0.0.1 example.com
```
### Blocking and Unblocking Domains
`hosts` provides easy commands for blocking and unblocking domains with IPv4
and IPv6 entries:
```bash
> hosts block example.com
Added:
127.0.0.1 example.com
Added:
fe80::1%lo0 example.com
Added:
::1 example.com
> hosts unblock example.com
Removed:
127.0.0.1 example.com
Removed:
fe80::1%lo0 example.com
Removed:
::1 example.com
```
### Enabling / Disabling Entries
All entries are enabled by default. Disabiling an entry comments it out
so it has no effect, but remains in the hosts file ready to be enabled
again.
```bash
> hosts
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
127.0.0.1 example.com
> hosts disable example.com
Disabling:
127.0.0.1 example.com
> hosts
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
Disabled:
---------
127.0.0.1 example.com
> hosts enable example.com
Enabling:
127.0.0.1 example.com
> hosts
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
127.0.0.1 example.com
```
### Backups
Create backups of your hosts file with `hosts backups create`:
```bash
> hosts backups create
Backed up to /etc/hosts--backup-20200101000000
```
List your backups with `hosts backups`. If you have existing hosts file
backups, `hosts` will include them:
```bash
> hosts backups
hosts--backup-20200101000000
hosts.bak
```
`hosts backups compare` will open your hosts file with `diff`:
```bash
> hosts backups compare hosts--backup-20200101000000
--- /etc/hosts 2020-01-01 00:00:00.000000000
+++ /etc/hosts--backup-20200101000000 2020-01-01 00:00:00.000000000
@@ -8,3 +8,4 @@
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
+127.0.0.1 example.com
```
View a backup with `hosts backups show`:
```bash
> hosts backups show hosts--backup-20200101000000
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
127.0.0.1 example.com
```
Restore a backup with `hosts backups restore`. Before a backup is
restored, a new one is created to avoid data loss:
```bash
> hosts backups restore hosts--backup-20200101000000
Backed up to /etc/hosts--backup-20200102000001
Restored from backup: hosts--backup-20200101000000
```
### Viewing and Editing `/etc/hosts` Directly
`hosts file` prints the raw contents of `/etc/hosts`:
```bash
> hosts file
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
```
`hosts edit` opens `/etc/hosts` in your editor:
```bash
> hosts edit
```
### `--auto-sudo`
When the `--auto-sudo` flag is used, all write operations that require
`sudo` will automatically rerun the command using `sudo` when the current user
does not have write permissions for the hosts file.
To have this option always enabled, add the following line to your shell
configuration (`.bashrc`, `.zshrc`, or similar):
```bash
alias hosts="hosts --auto-sudo"
```
## Help
```text
Usage:
hosts [<search string>]
hosts add <ip> <hostname> [<comment>]
hosts backups [create | (compare | delete | restore | show) <filename>]
hosts block <hostname>...
hosts completions (check | install [-d | --download] | uninstall)
hosts disable (<ip> | <hostname> | <search string>)
hosts disabled
hosts edit
hosts enable (<ip> | <hostname> | <search string>)
hosts enabled
hosts file
hosts list [enabled | disabled | <search string>]
hosts search <search string>
hosts show (<ip> | <hostname> | <search string>)
hosts subcommands [--raw]
hosts remove (<ip> | <hostname> | <search string>) [--force]
hosts unblock <hostname>...
hosts --auto-sudo
hosts -h | --help
hosts --version
Options:
--auto-sudo Run write commands with `sudo` automatically.
-h --help Display this help information.
--version Display version information.
Help:
hosts help [<command>]
```
For full usage, run:
```text
hosts help
```
For help with a particular command, try:
```text
hosts help <command name>
```
## Subcommands
<p align="center">
<a href="#hosts-1">(default)</a>
<a href="#hosts-add">add</a>
<a href="#hosts-backups">backups</a>
<a href="#hosts-block">block</a>
<a href="#hosts-completions">completions</a>
<a href="#hosts-disable">disable</a>
<a href="#hosts-disabled">disabled</a>
<a href="#hosts-edit">edit</a>
<a href="#hosts-enable">enable</a>
<a href="#hosts-enabled">enabled</a>
<a href="#hosts-file">file</a>
<a href="#hosts-help">help</a>
<a href="#hosts-list">list</a>
<a href="#hosts-remove">remove</a>
<a href="#hosts-search">search</a>
<a href="#hosts-show">show</a>
<a href="#hosts-subcommands">subcommands</a>
<a href="#hosts-unblock">unblock</a>
<a href="#hosts-version">version</a>
</p>
### `hosts`
```text
Usage:
hosts [<search string>]
Description:
List the existing IP / hostname pairs, optionally limited to a specified
state. When provided with a seach string, all matching enabled entries will
be printed.
Alias for `hosts list`
```
### `hosts add`
```text
Usage:
hosts add <ip> <hostname> [<comment>]
Description:
Add a given IP address and hostname pair, along with an optional comment.
Exit status:
0 Entry successfully added.
1 Invalid parameters or entry exists.
```
### `hosts backups`
```text
Usage:
hosts backups
hosts backups create
hosts backups compare <filename>
hosts backups delete <filename>
hosts backups restore <filename> [--skip-backup]
hosts backups show <filename>
Subcommands:
backups List available backups.
backups create Create a new backup of the hosts file.
backups compare Compare a backup file with the current hosts file.
backups delete Delete the specified backup.
backups restore Replace the contents of the hosts file with a
specified backup. The hosts file is automatically
backed up before being overwritten unless the
'--skip-backup' flag is specified.
backups show Show the contents of the specified backup file.
Description:
Manage backups.
Exit status:
0 Success.
1 Invalid parameters or backup not found.
```
### `hosts block`
```text
Usage:
hosts block <hostname>...
Description:
Block one or more hostnames by adding new entries assigned to `127.0.0.1`
for IPv4 and both `fe80::1%lo0` and `::1` for IPv6.
Exit status:
0 <hostname> successfully blocked.
1 Invalid parameters or entry exists.
```
#### Blocklists
- [jmdugan/blocklists](https://github.com/jmdugan/blocklists)
- [notracking/hosts-blocklists](https://github.com/notracking/hosts-blocklists)
### `hosts completions`
```text
Usage:
hosts completions (check | install [-d | --download] | uninstall)
Options:
-d, --download Download the completion scripts and install.
Description:
Manage completion scripts. For more information, visit:
https://github.com/xwmx/hosts/blob/master/etc/README.md
Exit status:
0 Completions successfully installed.
1 Invalid parameters or other error.
```
### `hosts disable`
```text
Usage:
hosts disable (<ip> | <hostname> | <search string>)
Description:
Disable one or more entries based on a given ip address, hostname, or
search string.
Exit status:
0 Entry successfully disabled.
1 Invalid parameters or entry not found.
```
### `hosts disabled`
```text
Usage:
hosts disabled
Description:
List all disabled entries. This is an alias for `hosts list disabled`.
Exit status:
0 One or more disabled entries found.
1 Invalid parameters or no disabled entries found.
```
### `hosts edit`
```text
Usage:
hosts edit
Description:
Open the /etc/hosts file in your $EDITOR.
```
### `hosts enable`
```text
Usage:
hosts enable (<ip> | <hostname> | <search string>)
Description:
Enable one or more disabled entries based on a given ip address, hostname,
or search string.
Exit status:
0 Entry successfully enabled.
1 Invalid parameters or entry not found.
```
### `hosts enabled`
```text
Usage:
hosts enabled
Description:
List all enabled entries. This is an alias for `hosts list enabled`.
Exit status:
0 One or more enabled entries found.
1 Invalid parameters or no enabled entries found.
```
### `hosts file`
```text
Usage:
hosts file
Description:
Print the entire contents of the /etc/hosts file.
```
### `hosts help`
```text
Usage:
hosts help [<command>]
Description:
Display help information for hosts or a specified command.
```
### `hosts list`
```text
Usage:
hosts list [enabled | disabled | <search string>]
Description:
List the existing IP / hostname pairs, optionally limited to a specified
state. When provided with a seach string, all matching enabled entries will
be printed.
Exit status:
0 One or more matching entries found.
1 Invalid parameters or entry not found.
```
### `hosts remove`
```text
Usage:
hosts remove (<ip> | <hostname> | <search string>) [--force]
hosts remove <ip> <hostname>
Options:
--force Skip the confirmation prompt.
Description:
Remove one or more entries based on a given IP address, hostname, or search
string. If an IP and hostname are both provided, only entries matching the
IP and hostname pair will be removed.
Exit status:
0 Entry successfully removed.
1 Invalid parameters or entry not found.
```
### `hosts search`
```text
Usage:
hosts search <search string>
Description:
Search entries for <search string>.
Exit status:
0 One or more matching entries found.
1 Invalid parameters or entry not found.
```
### `hosts show`
```text
Usage:
hosts show (<ip> | <hostname> | <search string>)
Description:
Print entries matching a given IP address, hostname, or search string.
Exit status:
0 One or more matching entries found.
1 Invalid parameters or entry not found.
```
### `hosts subcommands`
```text
Usage:
hosts subcommands [--raw]
Options:
--raw Display the subcommands list without formatting.
Description:
Display the list of available subcommands.
```
### `hosts unblock`
```text
Usage:
hosts unblock <hostname>...
Description:
Unblock one or more hostnames by removing the entries from the hosts file.
Exit status:
0 <hostname> successfully unblocked.
1 Invalid parameters or entry not found
```
### `hosts version`
```text
Usage:
hosts (version | --version)
Description:
Display the current program version.
```
## Tests
To run the [test suite](test), install [Bats](https://github.com/sstephenson/bats) and
run `bats test` in the project root directory.
---
<p align="center">
Copyright (c) 2015-present William Melody • See LICENSE for details.
</p>
<p align="center">
<a href="https://github.com/xwmx/hosts">github.com/xwmx/hosts</a>
</p>

View File

@ -1,52 +0,0 @@
# Hosts
A command line program with shortcuts for managing hosts file entries.
## Installation
To get started, add the `hosts` script to your path.
### Homebrew
To install with homebrew, use the following command:
brew install alphabetum/taps/hosts
## Usage
Usage:
hosts
hosts add <ip> <hostname>
hosts remove ( <ip> | <hostname> | <search string> ) [--force]
hosts list [enabled | disabled | <search string>]
hosts show ( <ip> | <hostname> | <search string> )
hosts disable ( <ip> | <hostname> | <search string> )
hosts enable ( <ip> | <hostname> | <search string> )
hosts edit
hosts file
For full usage, run:
hosts help
For help with a particular command, try:
hosts help <command name>
## Why
Although it's easy to just edit the hosts file manually, it's nice to
have a structured way to edit it and keep things a little organized.
## Acknowledgements
Based on prior work by:
- https://github.com/nddrylliog
- https://gist.github.com/nddrylliog/1368532
- https://github.com/dfeyer
- https://gist.github.com/dfeyer/1369760
Original idea and interface (since changed) via:
https://github.com/macmade/host-manager

113
etc/README.md Normal file
View File

@ -0,0 +1,113 @@
# `hosts` Tab Completion
## Homebrew
Installing via Homebrew with `brew install xwmx/taps/hosts` will also
install the completion scripts.
A one-time setup might be needed to [enable completion for all Homebrew
programs](https://docs.brew.sh/Shell-Completion).
## npm, bpkg, Make
When `hosts` is installed with `npm`, `bpkg`, or Make, an install hook will
check the environment and attempt to install completions. If it's successful,
you should see a message similar to:
```bash
Completion installed: /usr/local/etc/bash_completion.d/hosts
Completion installed: /usr/local/share/zsh/site-functions/_hosts
```
If completion is working after installing through any of these methods, then
you don't need to do anything else.
## `hosts completions`
The `hosts completions` subcommand can be used for installing and uninstalling
completion scripts. Depending on your configuration, you might need to use
`sudo` to install completion scripts easily:
```bash
> sudo hosts completions check
Completion scripts not found.
> sudo hosts completions install
Completion script installed: /usr/share/bash-completion/completions/hosts
Completion script installed: /usr/local/share/zsh/site-functions/_hosts
> sudo hosts completions check
Exists: /usr/share/bash-completion/completions/hosts
Exists: /usr/local/share/zsh/site-functions/_hosts
> sudo hosts completions uninstall
Completion script removed: /usr/share/bash-completion/completions/hosts
Completion script removed: /usr/local/share/zsh/site-functions/_hosts
```
If you installed `hosts` manually by downloading just the `hosts` script,
the completion scripts won't be immediately available for
`hosts completions install`. You can try installing the completions with
the `--download` flag, which will get the latest version from GitHub:
```bash
sudo hosts completions install --download
```
`hosts completions` will try to determine the completion script directories
from your environment. If `hosts completions` isn't able to install
the completion scripts, you can try installing them manually.
## Manual Installation
### bash
#### Linux
On a current Linux OS (in a non-minimal installation), bash completion should
be available.
Place the completion script in `/etc/bash_completion.d/`:
```bash
sudo curl -L https://raw.githubusercontent.com/xwmx/hosts/master/hosts-completion.bash -o /etc/bash_completion.d/hosts
```
#### macOS
If you aren't installing with homebrew, source the completion script in
`.bash_profile`:
```sh
if [[ -f /path/to/hosts-completion.bash ]]
then
source /path/to/hosts-completion.bash
fi
```
### zsh
Place the completion script in your `/path/to/zsh/completion` (typically
`~/.zsh/completion/`):
```bash
$ mkdir -p ~/.zsh/completion
$ curl -L https://raw.githubusercontent.com/xwmx/hosts/master/hosts-completion.zsh > ~/.zsh/completion/_hosts
```
Include the directory in your `$fpath` by adding in `~/.zshrc`:
```bash
fpath=(~/.zsh/completion $fpath)
```
Make sure `compinit` is loaded or do it by adding in `~/.zshrc`:
```bash
autoload -Uz compinit && compinit -i
```
Then reload your shell:
```bash
exec $SHELL -l
```

22
etc/hosts-completion.bash Normal file
View File

@ -0,0 +1,22 @@
__hosts_subcommands() {
local _commands
_commands=($(hosts commands --raw))
local _completions
_completions=(${_commands[@]})
local _current="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=()
for __command in "${_commands[@]}"
do
if [[ -n "${__command}" ]]
then
_completions+=("${__command}")
fi
done
COMPREPLY=($(compgen -W "${_completions[*]}" -- "${_current}"))
}
complete -F __hosts_subcommands hosts

26
etc/hosts-completion.zsh Normal file
View File

@ -0,0 +1,26 @@
#compdef hosts
__hosts_subcommands() {
local _commands
_commands=($(hosts commands --raw))
local _completions
_completions=(${_commands[@]})
for __command in "${_commands[@]}"
do
if [[ -n "${__command}" ]]
then
_completions+=("${__command}")
fi
done
if [[ "${?}" -eq 0 ]]
then
compadd -- "${_completions[@]}"
return 0
else
return 1
fi
}
__hosts_subcommands "$@"

2163
hosts

File diff suppressed because it is too large Load Diff

5
package-lock.json generated Normal file
View File

@ -0,0 +1,5 @@
{
"name": "hosts.sh",
"version": "3.6.4",
"lockfileVersion": 1
}

38
package.json Normal file
View File

@ -0,0 +1,38 @@
{
"name": "hosts.sh",
"version": "3.6.4",
"description": "A command line tool for managing hosts file entries.",
"global": true,
"install": "make install",
"bin": {
"hosts": "./hosts"
},
"directories": {
"test": "test"
},
"scripts": {
"test": "bats test",
"postinstall": "./hosts completions install",
"preuninstall": "./hosts completions uninstall"
},
"repository": {
"type": "git",
"url": "git+https://github.com/xwmx/hosts.git"
},
"author": "William Melody",
"license": "MIT",
"bugs": {
"url": "https://github.com/xwmx/hosts/issues"
},
"homepage": "https://github.com/xwmx/hosts#readme",
"keywords": [
"hosts",
"shell",
"command-line",
"terminal",
"hostname",
"bash",
"cli"
],
"dependencies": {}
}

182
test/add.bats Normal file
View File

@ -0,0 +1,182 @@
#!/usr/bin/env bats
load test_helper
# `hosts add` #################################################################
@test "\`add\` with no arguments exits with status 1." {
run "${_HOSTS}" add
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`add\` with no argument does not change the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" add
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "$(cat "${HOSTS_PATH}")" == "${_original}" ]]
}
@test "\`add\` with no arguments prints help information." {
run "${_HOSTS}" add
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts add <ip> <hostname> [<comment>]" ]]
}
# `hosts add <ip>` ############################################################
@test "\`add <ip>\` exits with status 1." {
run "${_HOSTS}" add 0.0.0.0
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`add <ip>\` does not change the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" add 0.0.0.0
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "$(cat "${HOSTS_PATH}")" == "${_original}" ]]
}
@test "\`add <ip>\` prints help information." {
run "${_HOSTS}" add 0.0.0.0
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Please include a hostname" ]]
[[ "${lines[1]}" == "Usage:" ]]
[[ "${lines[2]}" == " hosts add <ip> <hostname> [<comment>]" ]]
}
# `hosts add <ip> <hostname>` #################################################
@test "\`add <ip> <hostname>\` exits with status 0." {
run "${_HOSTS}" add 0.0.0.0 example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`add <ip> <hostname>\` adds the entry to the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" add 0.0.0.0 example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
_compare '0.0.0.0 example.com' "$(sed -n '11p' "${HOSTS_PATH}")"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(sed -n '11p' "${HOSTS_PATH}")" == "0.0.0.0 example.com" ]]
}
@test "\`add <ip> <hostname>\` prints feedback." {
run "${_HOSTS}" add 0.0.0.0 example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Added:" ]]
[[ "${lines[1]}" == "0.0.0.0 example.com" ]]
}
@test "\`add <ip> <hostname>\` doesn't add duplicate entry." {
_original="$(cat "${HOSTS_PATH}")"
{
run "${_HOSTS}" add 0.0.0.0 example.com
}
_modified="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" add 0.0.0.0 example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
_compare '0.0.0.0 example.com' "$(sed -n '11p' "${HOSTS_PATH}")"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(cat "${HOSTS_PATH}")" == "${_modified}" ]]
[[ "$(sed -n '11p' "${HOSTS_PATH}")" == "0.0.0.0 example.com" ]]
}
# `hosts add <ip> <hostname> [comment]` #######################################
@test "\`add <ip> <hostname> [comment]\` exits with status 0." {
run "${_HOSTS}" add 0.0.0.0 example.com 'Example multi-word comment.'
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`add <ip> <hostname> [comment]\` adds the entry to the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" add 0.0.0.0 example.com 'Example multi-word comment.'
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(sed -n '11p' "${HOSTS_PATH}")" == \
"0.0.0.0 example.com # Example multi-word comment." ]]
}
@test "\`add <ip> <hostname> [comment]\` doesn't add duplicate entry." {
_original="$(cat "${HOSTS_PATH}")"
{
run "${_HOSTS}" add 0.0.0.0 example.com
}
_modified="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" add 0.0.0.0 example.com 'Example multi-word comment.'
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
_compare '0.0.0.0 example.com' "$(sed -n '11p' "${HOSTS_PATH}")"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(cat "${HOSTS_PATH}")" == "${_modified}" ]]
[[ "$(sed -n '11p' "${HOSTS_PATH}")" == "0.0.0.0 example.com" ]]
[[ "$(sed -n '11p' "${HOSTS_PATH}")" != \
"0.0.0.0 example.com # Example multi-word comment." ]]
}
@test "\`add <ip> <hostname> [comment]\` doesn't add duplicate commented entry." {
_original="$(cat "${HOSTS_PATH}")"
{
run "${_HOSTS}" add 0.0.0.0 example.com 'Example multi-word comment.'
}
_modified="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" add 0.0.0.0 example.com 'Example multi-word comment.'
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
_compare '0.0.0.0 example.com' "$(sed -n '11p' "${HOSTS_PATH}")"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(cat "${HOSTS_PATH}")" == "${_modified}" ]]
[[ "$(sed -n '11p' "${HOSTS_PATH}")" == \
"0.0.0.0 example.com # Example multi-word comment." ]]
}
@test "\`add <ip> <hostname> [comment]\` prints feedback." {
run "${_HOSTS}" add 0.0.0.0 example.com 'Example multi-word comment.'
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Added:" ]]
[[ "${lines[1]}" == "0.0.0.0 example.com # Example multi-word comment." ]]
}
# help ########################################################################
@test "\`help add\` exits with status 0." {
run "${_HOSTS}" help add
[[ ${status} -eq 0 ]]
}
@test "\`help add\` prints help information." {
run "${_HOSTS}" help add
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts add <ip> <hostname> [<comment>]" ]]
}

257
test/backups.bats Normal file
View File

@ -0,0 +1,257 @@
#!/usr/bin/env bats
load test_helper
# `hosts backups` #############################################################
@test "\`backups\` with no backups and no arguments exits with status 0." {
run "${_HOSTS}" backups
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`backups\` with backups and no arguments exits with status 0." {
{
run "${_HOSTS}" backups create
}
run "${_HOSTS}" backups
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`backups\` with no backups and no arguments prints message." {
run "${_HOSTS}" backups
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
printf "\${_HOSTS_TEMP_PATH}: '%s'\\n" "${_HOSTS_TEMP_PATH}"
printf "\${HOSTS_PATH}: '%s'\\n" "${HOSTS_PATH}"
_expected="\
No backups found. Create a new backup:
hosts backups create"
[[ "${output}" == "${_expected}" ]]
}
@test "\`backups\` with backups and no arguments prints list of backups." {
{
run "${_HOSTS}" backups create
sleep 1
run "${_HOSTS}" backups create
}
run "${_HOSTS}" backups
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
printf "\${_HOSTS_TEMP_PATH}: '%s'\\n" "${_HOSTS_TEMP_PATH}"
printf "\${HOSTS_PATH}: '%s'\\n" "${HOSTS_PATH}"
[[ "${lines[0]}" =~ hosts--backup- ]]
[[ "${lines[1]}" =~ hosts--backup- ]]
}
# `hosts backups create` ######################################################
@test "\`backups create\` exits with status 0." {
run "${_HOSTS}" backups create
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`backups create\` creates backup." {
run "${_HOSTS}" backups create
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
printf "\${_backup_path}: '%s'\\n" "${_backup_path}"
[[ -e "${_backup_path}" ]]
}
@test "\`backups create\` prints message." {
run "${_HOSTS}" backups create
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${output} =~ 'Backed up to' ]]
}
# `hosts backups compare` #####################################################
@test "\`backups compare\` with valid backup exits with status 1 and prints." {
{
run "${_HOSTS}" backups create
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
_backup_basename="$(basename "${_backup_path}")"
run "${_HOSTS}" add 0.0.0.0 example.com
}
run "${_HOSTS}" backups compare "${_backup_basename}"
printf "\${output}: '%s'\\n" "${output}"
printf "\${lines[1]}: '%s'\\n" "${lines[1]}"
[[ ${status} -eq 1 ]]
[[ "${lines[2]}" == '@@ -8,4 +8,3 @@' ]]
}
@test "\`backups compare\` with missing backup exits with status 1" {
{
run "${_HOSTS}" backups create
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
_backup_basename="$(basename "${_backup_path}")"
run "${_HOSTS}" add 0.0.0.0 example.com
}
run "${_HOSTS}" backups compare
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
[[ "${lines[0]}" =~ 'Usage' ]]
}
@test "\`backups compare\` with invalid backup exits with status 1" {
{
run "${_HOSTS}" backups create
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
_backup_basename="$(basename "${_backup_path}")"
run "${_HOSTS}" add 0.0.0.0 example.com
}
run "${_HOSTS}" backups compare "invalid-backup-name"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
[[ ${output} =~ 'Backup not found' ]]
}
# `hosts backups delete` ######################################################
@test "\`backups delete\` with valid backup exits with status 0 and deletes backup" {
{
run "${_HOSTS}" backups create
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
[[ -e "${_backup_path}" ]]
_backup_basename="$(basename "${_backup_path}")"
}
run "${_HOSTS}" backups delete "${_backup_basename}"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
[[ ! -e "${_backup_path}" ]]
[[ ${output} =~ 'Backup deleted' ]]
}
@test "\`backups delete\` with invalid backup exits with status 1" {
{
run "${_HOSTS}" backups create
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
_backup_basename="$(basename "${_backup_path}")"
}
run "${_HOSTS}" backups delete "invalid-backup-name"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
[[ -e "${_backup_path}" ]]
[[ ${output} =~ 'Backup not found' ]]
}
# `hosts backups restore` #####################################################
@test "\`backups restore\` with valid backup exits with status 0 and restores" {
{
run "${_HOSTS}" backups create
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
_backup_basename="$(basename "${_backup_path}")"
run "${_HOSTS}" add 0.0.0.0 example.com
sleep 1
}
run "${_HOSTS}" backups restore "${_backup_basename}"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
printf "\${lines[0]}: '%s'\\n" "${lines[0]}"
[[ ${status} -eq 0 ]]
[[ "${lines[0]}" =~ 'Backed up to' ]]
[[ "${lines[1]}" =~ 'Restored from backup' ]]
_new_backup_path="$(echo "${lines[0]}" | sed -e 's/Backed up to \(.*\)/\1/')"
printf "\${_backup_path}: '%s'\\n" "${_backup_path}"
printf "\${_new_backup_path}: '%s'\\n" "${_new_backup_path}"
_new_backup_content="$(cat "${_new_backup_path}")"
_old_backup_content="$(cat "${_backup_path}")"
_current_content="$(cat "${HOSTS_PATH}")"
[[ "${_new_backup_content}" != "${_current_content}" ]]
[[ "${_old_backup_content}" == "${_current_content}" ]]
}
@test "\`backups restore --skip-backup\` with valid backup exits with status 0 and restores" {
{
run "${_HOSTS}" backups create
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
_backup_basename="$(basename "${_backup_path}")"
run "${_HOSTS}" add 0.0.0.0 example.com
_replaced_content="$(cat "${HOSTS_PATH}")"
sleep 1
}
run "${_HOSTS}" backups restore "${_backup_basename}" --skip-backup
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
printf "\${lines[0]}: '%s'\\n" "${lines[0]}"
[[ ${status} -eq 0 ]]
[[ "${lines[0]}" =~ 'Restored from backup' ]]
_old_backup_content="$(cat "${_backup_path}")"
_current_content="$(cat "${HOSTS_PATH}")"
[[ "${_replaced_content}" != "${_current_content}" ]]
[[ "${_old_backup_content}" == "${_current_content}" ]]
}
@test "\`backups restore\` with invalid backup exits with status 1" {
{
run "${_HOSTS}" backups create
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
_backup_basename="$(basename "${_backup_path}")"
}
run "${_HOSTS}" backups restore "invalid-backup-name"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
[[ ${output} =~ 'Backup not found' ]]
}
# `hosts backups show` ########################################################
@test "\`backups show\` with valid backup exits with status 0 and prints." {
{
run "${_HOSTS}" backups create
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
[[ -e "${_backup_path:-}" ]]
_backup_basename="$(basename "${_backup_path}")"
}
run "${_HOSTS}" backups show "${_backup_basename}"
printf "\${output}: '%s'\\n" "${output}"
printf "\${lines[6]}: '%s'\\n" "${lines[6]}"
[[ ${status} -eq 0 ]]
[[ "${lines[6]}" == '127.0.0.1 localhost' ]]
}
@test "\`backups show\` with invalid backup exits with status 1" {
{
run "${_HOSTS}" backups create
_backup_path="$(echo "${output}" | sed -e 's/Backed up to \(.*\)/\1/')"
_backup_basename="$(basename "${_backup_path}")"
}
run "${_HOSTS}" backups show "invalid-backup-name"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
[[ ${output} =~ 'Backup not found' ]]
}

118
test/block.bats Normal file
View File

@ -0,0 +1,118 @@
#!/usr/bin/env bats
load test_helper
# `hosts block` ###############################################################
@test "\`block\` with no arguments exits with status 1." {
run "${_HOSTS}" block
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`block\` with no argument does not change the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" block
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "$(cat "${HOSTS_PATH}")" == "${_original}" ]]
}
@test "\`block\` with no arguments prints help information." {
run "${_HOSTS}" block
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts block <hostname>..." ]]
}
# `hosts block <hostname>` ####################################################
@test "\`block <hostname>\` exits with status 0." {
run "${_HOSTS}" block example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`block <hostname>\` adds entries to the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" block example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
_compare '127.0.0.1 example.com' "$(sed -n '11p' "${HOSTS_PATH}")"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ 127.0.0.1[[:space:]]+example.com ]]
}
@test "\`block <hostname>\` prints feedback." {
run "${_HOSTS}" block example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Added:" ]]
[[ "${lines[1]}" =~ 127.0.0.1[[:space:]]+example.com ]]
[[ "${lines[2]}" == "Added:" ]]
[[ "${lines[3]}" =~ fe80\:\:1\%lo0[[:space:]]example.com ]]
[[ "${lines[4]}" == "Added:" ]]
[[ "${lines[5]}" =~ \:\:1[[:space:]]+example.com ]]
}
# `hosts block <hostname> <hostname2>` ########################################
@test "\`block <hostname> <hostname2>\` exits with status 0." {
run "${_HOSTS}" block example.com example2.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`block <hostname> <hostname2>\` adds entries to the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" block example.com example2.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
_compare '127.0.0.1 example.com' "$(sed -n '11p' "${HOSTS_PATH}")"
_compare '127.0.0.1 example2.com' "$(sed -n '11p' "${HOSTS_PATH}")"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ 127.0.0.1[[:space:]]+example.com ]]
[[ "$(sed -n '14p' "${HOSTS_PATH}")" =~ 127.0.0.1[[:space:]]+example2.com ]]
}
@test "\`block <hostname> <hostname2>\` prints feedback." {
run "${_HOSTS}" block example.com example2.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Added:" ]]
[[ "${lines[1]}" =~ 127.0.0.1[[:space:]]+example.com ]]
[[ "${lines[2]}" == "Added:" ]]
[[ "${lines[3]}" =~ fe80\:\:1\%lo0[[:space:]]+example.com ]]
[[ "${lines[4]}" == "Added:" ]]
[[ "${lines[5]}" =~ \:\:1[[:space:]]+example.com ]]
[[ "${lines[6]}" == "Added:" ]]
[[ "${lines[7]}" =~ 127.0.0.1[[:space:]]+example2.com ]]
[[ "${lines[8]}" == "Added:" ]]
[[ "${lines[9]}" =~ fe80\:\:1\%lo0[[:space:]]+example2.com ]]
[[ "${lines[10]}" == "Added:" ]]
[[ "${lines[11]}" =~ \:\:1[[:space:]]+example2.com ]]
}
# help ########################################################################
@test "\`help block\` exits with status 0." {
run "${_HOSTS}" help block
[[ ${status} -eq 0 ]]
}
@test "\`help block\` prints help information." {
run "${_HOSTS}" help block
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts block <hostname>..." ]]
}

158
test/disable.bats Normal file
View File

@ -0,0 +1,158 @@
#!/usr/bin/env bats
load test_helper
# `hosts disable` #############################################################
@test "\`disable\` with no arguments exits with status 1." {
run "${_HOSTS}" disable
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`disable\` with no argument does not change the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" disable
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "$(cat "${HOSTS_PATH}")" == "${_original}" ]]
}
@test "\`disable\` with no arguments prints help information." {
run "${_HOSTS}" disable
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts disable (<ip> | <hostname> | <search string>)" ]]
}
# `hosts disable <ip>` ########################################################
@test "\`disable <ip>\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
run "${_HOSTS}" disable 0.0.0.0
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`disable <ip>\` updates the hosts file." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" disable 0.0.0.0
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ \#disabled\:\ 0.0.0.0[[:space:]]+example.com ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" =~ 127.0.0.1[[:space:]]+example.net ]]
}
@test "\`disable <ip>\` disables all matches." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" disable 0.0.0.0
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ \#disabled\:\ 0.0.0.0[[:space:]]+example.com ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" =~ \#disabled\:\ 0.0.0.0[[:space:]]+example.net ]]
}
@test "\`disable <ip>\` prints feedback." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
run "${_HOSTS}" disable 0.0.0.0
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Disabling:" ]]
[[ "${lines[1]}" =~ 0.0.0.0[[:space:]]+example.com ]]
}
# `hosts disable <hostname>` ##################################################
@test "\`disable <hostname>\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
run "${_HOSTS}" disable example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`disable <hostname>\` updates the hosts file." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" disable example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ \#disabled\:\ 0.0.0.0[[:space:]]+example.com ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" =~ 127.0.0.1[[:space:]]+example.net ]]
}
@test "\`disable <hostname>\` disables all matches." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 127.0.0.1 example.com
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" disable example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ \#disabled\:\ 0.0.0.0[[:space:]]+example.com ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" =~ 127.0.0.1[[:space:]]+example.com ]]
}
@test "\`disable <hostname>\` prints feedback." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
run "${_HOSTS}" disable example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Disabling:" ]]
[[ "${lines[1]}" =~ 0.0.0.0[[:space:]]+example.com ]]
}
# help ########################################################################
@test "\`help disable\` exits with status 0." {
run "${_HOSTS}" help disable
[[ ${status} -eq 0 ]]
}
@test "\`help disable\` prints help information." {
run "${_HOSTS}" help disable
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts disable (<ip> | <hostname> | <search string>)" ]]
}

57
test/disabled.bats Normal file
View File

@ -0,0 +1,57 @@
#!/usr/bin/env bats
load test_helper
# `hosts disabled` ############################################################
@test "\`disabled\` with no arguments exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
run "${_HOSTS}" disable example.com
}
run "${_HOSTS}" disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`disabled\` with no arguments prints list of disabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
run "${_HOSTS}" disable example.com
}
run "${_HOSTS}" disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 0\.0\.0\.0[[:space:]]+example\.com ]]
[[ "${lines[1]}" =~ 127\.0\.0\.1[[:space:]]+example\.com ]]
[[ "${lines[2]}" == "" ]]
}
@test "\`disabled\` exits with status 1 when no matching entries found." {
run "${_HOSTS}" disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# help ########################################################################
@test "\`help disabled\` exits with status 0." {
run "${_HOSTS}" help disabled
[[ ${status} -eq 0 ]]
}
@test "\`help disabled\` prints help information." {
run "${_HOSTS}" help disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts disabled" ]]
}

205
test/enable.bats Normal file
View File

@ -0,0 +1,205 @@
#!/usr/bin/env bats
load test_helper
# `hosts enable` ##############################################################
@test "\`enable\` with no arguments exits with status 1." {
run "${_HOSTS}" enable
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`enable\` with no argument does not change the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" enable
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "$(cat "${HOSTS_PATH}")" == "${_original}" ]]
}
@test "\`enable\` with no arguments prints help information." {
run "${_HOSTS}" enable
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts enable (<ip> | <hostname> | <search string>)" ]]
}
# `hosts enable <ip>` #########################################################
@test "\`enable <ip>\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 127.0.0.2
}
run "${_HOSTS}" enable 127.0.0.2
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`enable <ip>\` updates the hosts file." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
run "${_HOSTS}" disable 127.0.0.2
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" enable 127.0.0.2
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ \#disabled:\ 0.0.0.0[[:space:]]+example.com ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" =~ \#disabled:\ 0.0.0.0[[:space:]]+example.net ]]
[[ "$(sed -n '13p' "${HOSTS_PATH}")" =~ 127.0.0.2[[:space:]]+example.com ]]
}
@test "\`enable <ip>\` enables all matches." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
run "${_HOSTS}" disable 127.0.0.2
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" enable 0.0.0.0
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare \
"${_original}" \
"$(cat "${HOSTS_PATH}")"
_compare \
"'0.0.0.0 example.com'" \
"'$(sed -n '11p' "${HOSTS_PATH}")'"
_compare \
"'0.0.0.0 example.net'" \
"'$(sed -n '12p' "${HOSTS_PATH}")'"
_compare \
"'#disabled: 127.0.0.2 example.com'" \
"'$(sed -n '13p' "${HOSTS_PATH}")'"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ 0.0.0.0[[:space:]]+example.com ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" =~ 0.0.0.0[[:space:]]+example.net ]]
[[ "$(sed -n '13p' "${HOSTS_PATH}")" =~ \#disabled:\ 127.0.0.2[[:space:]]+example.com ]]
}
@test "\`enable <ip>\` prints feedback." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 127.0.0.2
}
run "${_HOSTS}" enable 127.0.0.2
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Enabling:" ]]
[[ "${lines[1]}" =~ 127.0.0.2[[:space:]]+example.com ]]
}
# `hosts enable <hostname>` ###################################################
@test "\`enable <hostname>\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" enable example.net
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`enable <hostname>\` updates the hosts file." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" enable example.net
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ \#disabled:\ 0.0.0.0[[:space:]]+example.com ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" =~ 0.0.0.0[[:space:]]+example.net ]]
[[ "$(sed -n '13p' "${HOSTS_PATH}")" =~ 127.0.0.2[[:space:]]+example.com ]]
}
@test "\`enable <hostname>\` enables all matches." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
run "${_HOSTS}" disable 127.0.0.2
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" enable example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare \
"${_original}" \
"$(cat "${HOSTS_PATH}")"
_compare \
"'0.0.0.0 example.com'" \
"'$(sed -n '11p' "${HOSTS_PATH}")'"
_compare \
"'#disabled: 0.0.0.0 example.net'" \
"'$(sed -n '12p' "${HOSTS_PATH}")'"
_compare \
"'127.0.0.2 example.com'" \
"'$(sed -n '13p' "${HOSTS_PATH}")'"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ 0.0.0.0[[:space:]]+example.com ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" =~ \#disabled:\ 0.0.0.0[[:space:]]+example.net ]]
[[ "$(sed -n '13p' "${HOSTS_PATH}")" =~ 127.0.0.2[[:space:]]+example.com ]]
}
@test "\`enable <hostname>\` prints feedback." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" enable example.net
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Enabling:" ]]
[[ "${lines[1]}" =~ 0.0.0.0[[:space:]]+example.net ]]
}
# help ########################################################################
@test "\`help enable\` exits with status 0." {
run "${_HOSTS}" help enable
[[ ${status} -eq 0 ]]
}
@test "\`help enable\` prints help information." {
run "${_HOSTS}" help enable
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts enable (<ip> | <hostname> | <search string>)" ]]
}

64
test/enabled.bats Normal file
View File

@ -0,0 +1,64 @@
#!/usr/bin/env bats
load test_helper
# `hosts enabled` #############################################################
@test "\`enabled\` with no arguments exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`enabled\` with no arguments prints list of enabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 127.0.0.1[[:space:]]+localhost ]]
[[ "${lines[1]}" =~ 255.255.255.255[[:space:]]+broadcasthost ]]
[[ "${lines[2]}" =~ \:\:1[[:space:]]+localhost ]]
[[ "${lines[3]}" =~ fe80\:\:1\%lo0[[:space:]]+localhost ]]
[[ "${lines[4]}" =~ 127.0.0.2[[:space:]]+example.com ]]
}
@test "\`enabled\` exits with status 1 when no matching entries found." {
{
run "${_HOSTS}" disable localhost
run "${_HOSTS}" disable broadcasthost
}
run "${_HOSTS}" enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# help ########################################################################
@test "\`help enabled\` exits with status 0." {
run "${_HOSTS}" help enabled
[[ ${status} -eq 0 ]]
}
@test "\`help enabled\` prints help information." {
run "${_HOSTS}" help enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts enabled" ]]
}

28
test/file.bats Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env bats
load test_helper
@test "\`file\` exits with status 0." {
run "${_HOSTS}" file
[ "${status}" -eq 0 ]
}
@test "\`file\` prints \$HOSTS_PATH contents." {
run "${_HOSTS}" file
[[ "${output}" == "$(cat ${HOSTS_PATH})" ]]
}
# help ########################################################################
@test "\`help file\` exits with status 0." {
run "${_HOSTS}" help file
[[ ${status} -eq 0 ]]
}
@test "\`help file\` prints help information." {
run "${_HOSTS}" help file
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts file" ]]
}

1
test/fixtures/bin/hosts vendored Executable file
View File

@ -0,0 +1 @@
#!/usr/bin/env bash

10
test/fixtures/hosts vendored Normal file
View File

@ -0,0 +1,10 @@
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost

48
test/help.bats Normal file
View File

@ -0,0 +1,48 @@
#!/usr/bin/env bats
load test_helper
_HELP_HEADER="$(
cat <<HEREDOC
__ __
/ /_ ____ _____/ /______
/ __ \/ __ \/ ___/ __/ ___/
/ / / / /_/ (__ ) /_(__ )
/_/ /_/\____/____/\__/____/
HEREDOC
)"
export _HELP_HEADER
@test "\`help\` with no arguments exits with status 0." {
run "${_HOSTS}" help
[ "${status}" -eq 0 ]
}
@test "\`help\` with no arguments prints default help." {
run "${_HOSTS}" help
[[ $(IFS=$'\n'; echo "${lines[*]:0:5}") == "${_HELP_HEADER}" ]]
}
@test "\`hosts -h\` prints default help." {
run "${_HOSTS}" -h
[[ $(IFS=$'\n'; echo "${lines[*]:0:5}") == "${_HELP_HEADER}" ]]
}
@test "\`hosts --help\` prints default help." {
run "${_HOSTS}" --help
[[ $(IFS=$'\n'; echo "${lines[*]:0:5}") == "${_HELP_HEADER}" ]]
}
@test "\`hosts help help\` prints \`help\` subcommand usage." {
run "${_HOSTS}" help help
_expected="$(
cat <<HEREDOC
Usage:
hosts help [<command>]
Description:
Display help information for hosts or a specified command.
HEREDOC
)"
[[ "${output}" == "${_expected}" ]]
}

18
test/hosts.bats Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bats
load test_helper
@test "\`hosts\` with no arguments exits with status 0." {
run "${_HOSTS}"
[ "${status}" -eq 0 ]
}
@test "\`hosts\` with no arguments prints enabled rules." {
run "${_HOSTS}"
[[ "${#lines[@]}" -eq 4 ]]
[[ "${lines[0]}" =~ 127.0.0.1[[:space:]]+localhost ]]
[[ "${lines[1]}" =~ 255.255.255.255[[:space:]]+broadcasthost ]]
[[ "${lines[2]}" =~ \:\:1[[:space:]]+localhost ]]
[[ "${lines[3]}" =~ fe80\:\:1\%lo0[[:space:]]+localhost ]]
[[ "${lines[4]}" == "" ]]
}

214
test/list.bats Normal file
View File

@ -0,0 +1,214 @@
#!/usr/bin/env bats
load test_helper
# `hosts list` ################################################################
@test "\`list\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" list
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`list\` prints lists of enabled and disabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" list
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_expected="\
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
127.0.0.2 example.com
Disabled:
---------
0.0.0.0 example.com
0.0.0.0 example.net"
_compare "'${_expected}'" "'${output}'"
[[ "${output}" == "${_expected}" ]]
}
# `hosts list enabled` ########################################################
@test "\`list enabled\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" list enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`list enabled\` prints list of enabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" list enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 127\.0\.0\.1[[:space:]]+localhost ]]
[[ "${lines[1]}" =~ 255\.255\.255\.255[[:space:]]+broadcasthost ]]
[[ "${lines[2]}" =~ \:\:1[[:space:]]+localhost ]]
[[ "${lines[3]}" =~ fe80\:\:1\%lo0[[:space:]]+localhost ]]
[[ "${lines[4]}" =~ 127\.0\.0\.2[[:space:]]+example.com ]]
}
@test "\`list enabled\` exits with status 1 when no matching entries found." {
{
run "${_HOSTS}" disable localhost
run "${_HOSTS}" disable broadcasthost
}
run "${_HOSTS}" list enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# `hosts list disabled` #######################################################
@test "\`list disabled\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
run "${_HOSTS}" disable example.com
}
run "${_HOSTS}" list disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`list disabled\` prints list of disabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
run "${_HOSTS}" disable example.com
}
run "${_HOSTS}" list disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 0\.0\.0\.0[[:space:]]+example\.com ]]
[[ "${lines[1]}" =~ 127\.0\.0\.1[[:space:]]+example\.com ]]
[[ "${lines[2]}" == "" ]]
}
@test "\`list disabled\` exits with status 1 when no matching entries found." {
run "${_HOSTS}" list disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# `hosts list <search string>` ################################################
@test "\`list <search string>\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
}
run "${_HOSTS}" list example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`list <search string>\` prints list of matching entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
}
run "${_HOSTS}" list example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 0\.0\.0\.0[[:space:]]+example\.com ]]
[[ "${lines[1]}" =~ 127\.0\.0\.1[[:space:]]+example\.com ]]
[[ "${lines[2]}" == "" ]]
}
@test "\`list <search string>\` prints entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
run "${_HOSTS}" add 127.0.0.1 example.com
}
run "${_HOSTS}" list "Comment"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 0\.0\.0\.0[[:space:]]+example\.net[[:space:]]+\#\ Example\ Comment ]]
[[ "${lines[2]}" == "" ]]
}
@test "\`list <search string>\` prints disabled entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
run "${_HOSTS}" add 127.0.0.1 example.com
run "${_HOSTS}" add 127.0.0.1 example.biz "Example Comment"
run "${_HOSTS}" disable example.biz
}
run "${_HOSTS}" list "Comment"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 0\.0\.0\.0[[:space:]]+example\.net[[:space:]]+\#\ Example\ Comment ]]
[[ "${lines[3]}" =~ 127\.0\.0\.1[[:space:]]+example\.biz[[:space:]]+\#\ Example\ Comment ]]
[[ "${lines[4]}" == "" ]]
}
@test "\`list <search string>\` exits with status 1 when no matching entries found." {
run "${_HOSTS}" list query-that-matches-no-entries
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# help ########################################################################
@test "\`help list\` exits with status 0." {
run "${_HOSTS}" help list
[[ ${status} -eq 0 ]]
}
@test "\`help list\` prints help information." {
run "${_HOSTS}" help list
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts list [enabled | disabled | <search string>]" ]]
}

227
test/remove.bats Normal file
View File

@ -0,0 +1,227 @@
#!/usr/bin/env bats
load test_helper
# `hosts remove` ##############################################################
@test "\`remove\` with no arguments exits with status 1." {
run "${_HOSTS}" remove
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`remove\` with no argument does not change the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" remove
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "$(cat "${HOSTS_PATH}")" == "${_original}" ]]
}
@test "\`remove\` with no arguments prints help information." {
run "${_HOSTS}" remove
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts remove (<ip> | <hostname> | <search string>) [--force]" ]]
}
# `hosts remove <invalid> --force` ############################################
@test "\`remove <invalid> --force\` exits with status 1." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
}
run "${_HOSTS}" remove 127.0.0.3 --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`remove <invalid> --force\` prints error message." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
}
run "${_HOSTS}" remove 127.0.0.3 --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${output} == "${_ERROR_PREFIX}No matching entries found." ]]
}
# `hosts remove <ip> --force` #################################################
@test "\`remove <ip> --force\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
}
run "${_HOSTS}" remove 127.0.0.2 --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`remove <ip> --force\` updates the hosts file." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" remove 127.0.0.2 --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ 0.0.0.0[[:space:]]+example.com ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" =~ 0.0.0.0[[:space:]]+example.net ]]
[[ "$(sed -n '13p' "${HOSTS_PATH}")" == "" ]]
}
@test "\`remove <ip>\` removes all matches." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 0.0.0.0 example.dev
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable example.dev
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" remove 0.0.0.0 --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_expected="\
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
127.0.0.2 example.com"
_compare "'${_expected}'" "'$(cat "${HOSTS_PATH}")'"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(cat "${HOSTS_PATH}")" == "${_expected}" ]]
}
@test "\`remove <ip>\` prints feedback." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
}
run "${_HOSTS}" remove 127.0.0.2 --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Removed:" ]]
[[ "${lines[1]}" =~ 127.0.0.2[[:space:]]+example.com ]]
}
# `hosts remove <hostname> --force` ###########################################
@test "\`remove <hostname> --force\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
}
run "${_HOSTS}" remove example.com --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`remove <hostname> --force\` updates the hosts file." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" remove example.com --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" =~ 0.0.0.0[[:space:]]+example.net ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" == "" ]]
}
@test "\`remove <hostname>\` removes all matches." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 0.0.0.0 example.dev
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable example.dev
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" remove example.com --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_expected="\
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
0.0.0.0 example.net
#disabled: 0.0.0.0 example.dev"
_compare "'${_expected}'" "'$(cat "${HOSTS_PATH}")'"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(cat "${HOSTS_PATH}")" == "${_expected}" ]]
}
@test "\`remove <hostname>\` prints feedback." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
}
run "${_HOSTS}" remove example.com --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_expected="\
Removed:
0.0.0.0 example.com
127.0.0.2 example.com"
[[ "${output}" == "${_expected}" ]]
}
# help ########################################################################
@test "\`help remove\` exits with status 0." {
run "${_HOSTS}" help remove
[[ ${status} -eq 0 ]]
}
@test "\`help remove\` prints help information." {
run "${_HOSTS}" help remove
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts remove (<ip> | <hostname> | <search string>) [--force]" ]]
}

202
test/search.bats Normal file
View File

@ -0,0 +1,202 @@
#!/usr/bin/env bats
load test_helper
# `hosts search` ##############################################################
@test "\`search\` with no arguments exits with status 1." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" search
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`search\` with no arguments prints help information." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" search
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts search <search string>" ]]
}
# `hosts search enabled` ######################################################
@test "\`search enabled\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" search enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`search enabled\` prints list of enabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" search enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 127.0.0.1[[:space:]]+localhost ]]
[[ "${lines[1]}" =~ 255.255.255.255[[:space:]]+broadcasthost ]]
[[ "${lines[2]}" =~ \:\:1[[:space:]]+localhost ]]
[[ "${lines[3]}" =~ fe80\:\:1\%lo0[[:space:]]+localhost ]]
[[ "${lines[4]}" =~ 127.0.0.2[[:space:]]+example.com ]]
}
@test "\`search enabled\` exits with status 1 when no matching entries found." {
{
run "${_HOSTS}" disable localhost
run "${_HOSTS}" disable broadcasthost
}
run "${_HOSTS}" search enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# `hosts search disabled` #####################################################
@test "\`search disabled\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
run "${_HOSTS}" disable example.com
}
run "${_HOSTS}" search disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`search disabled\` prints list of disabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
run "${_HOSTS}" disable example.com
}
run "${_HOSTS}" search disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 0.0.0.0[[:space:]]+example.com ]]
[[ "${lines[1]}" =~ 127.0.0.1[[:space:]]+example.com ]]
[[ "${lines[2]}" == "" ]]
}
@test "\`search disabled\` exits with status 1 when no matching entries found." {
run "${_HOSTS}" search disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# `hosts search <search string>` ################################################
@test "\`search <search string>\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
}
run "${_HOSTS}" search example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`search <search string>\` prints list of matching entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
}
run "${_HOSTS}" search example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 0.0.0.0[[:space:]]+example.com ]]
[[ "${lines[1]}" =~ 127.0.0.1[[:space:]]+example.com ]]
[[ "${lines[2]}" == "" ]]
}
@test "\`search <search string>\` prints entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
run "${_HOSTS}" add 127.0.0.1 example.com
}
run "${_HOSTS}" search "Comment"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 0.0.0.0[[:space:]]+example.net[[:space:]]+\#\ Example\ Comment ]]
[[ "${lines[2]}" == "" ]]
}
@test "\`search <search string>\` prints disabled entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
run "${_HOSTS}" add 127.0.0.1 example.com
run "${_HOSTS}" add 127.0.0.1 example.biz "Example Comment"
run "${_HOSTS}" disable example.biz
}
run "${_HOSTS}" search "Comment"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 0.0.0.0[[:space:]]+example.net[[:space:]]+\#\ Example\ Comment ]]
[[ "${lines[3]}" =~ 127.0.0.1[[:space:]]+example.biz[[:space:]]+\#\ Example\ Comment ]]
[[ "${lines[4]}" == "" ]]
}
@test "\`search <search string>\` exits with status 1 when no matching entries found." {
run "${_HOSTS}" search query-that-matches-no-entries
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# help ########################################################################
@test "\`help search\` exits with status 0." {
run "${_HOSTS}" help search
[[ ${status} -eq 0 ]]
}
@test "\`help search\` prints help information." {
run "${_HOSTS}" help search
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts search <search string>" ]]
}

142
test/show.bats Normal file
View File

@ -0,0 +1,142 @@
#!/usr/bin/env bats
load test_helper
# `hosts show` ################################################################
@test "\`show\` with no arguments exits with status 1." {
run "${_HOSTS}" show
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`show\` with no arguments prints help information." {
run "${_HOSTS}" show
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts show (<ip> | <hostname> | <search string>)" ]]
}
# `hosts show <no matching>` ##################################################
@test "\`show <query>\` with no matching entries with status 1." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable example.com
}
run "${_HOSTS}" show bad-query
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
[[ "${lines[0]}" =~ No\ matching\ entries ]]
}
# `hosts show <ip>` ###########################################################
@test "\`show <ip>\` exits with status 0 and shows all matches." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable example.com
}
run "${_HOSTS}" show 0.0.0.0
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
[[ "${lines[0]}" =~ 0\.0\.0\.0[[:space:]]+example.net ]]
[[ "${lines[3]}" =~ 0\.0\.0\.0[[:space:]]+example.com ]]
}
# `hosts show <hostname>` #####################################################
@test "\`show <hostname>\` exits with status 0 and shows all matches." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.2 example.com
run "${_HOSTS}" disable 0.0.0.0
}
run "${_HOSTS}" show example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
[[ "${lines[0]}" =~ 127\.0\.0\.2[[:space:]]+example.com ]]
[[ "${lines[3]}" =~ 0\.0\.0\.0[[:space:]]+example.com ]]
}
# `hosts show <search string>` ################################################
@test "\`show <search string>\` exits with status 0 and shows matching entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
run "${_HOSTS}" add 127.0.0.1 example.com
}
run "${_HOSTS}" show example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
[[ "${lines[0]}" =~ 0\.0\.0\.0[[:space:]]+example.com ]]
[[ "${lines[1]}" =~ 127\.0\.0\.1[[:space:]]+example.com ]]
[[ "${lines[2]}" == "" ]]
}
@test "\`show <search string>\` prints entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
run "${_HOSTS}" add 127.0.0.1 example.com
}
run "${_HOSTS}" show "Comment"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
printf "\${lines[0]}: '%s'\\n" "${lines[0]}"
[[ "${lines[0]}" =~ 0\.0\.0\.0[[:space:]]+example\.net[[:space:]]+\#\ Example\ Comment ]]
[[ "${lines[2]}" == "" ]]
}
@test "\`show <search string>\` prints disabled entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
run "${_HOSTS}" add 127.0.0.1 example.com
run "${_HOSTS}" add 127.0.0.1 example.biz "Example Comment"
run "${_HOSTS}" disable example.biz
}
run "${_HOSTS}" show "Comment"
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" =~ 0\.0\.0\.0[[:space:]]+example\.net[[:space:]]+\#\ Example\ Comment ]]
[[ "${lines[3]}" =~ 127\.0\.0\.1[[:space:]]+example\.biz[[:space:]]+\#\ Example\ Comment ]]
[[ "${lines[4]}" == "" ]]
}
# help ########################################################################
@test "\`help show\` exits with status 0." {
run "${_HOSTS}" help show
[[ ${status} -eq 0 ]]
}
@test "\`help show\` prints help information." {
run "${_HOSTS}" help show
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts show (<ip> | <hostname> | <search string>)" ]]
}

59
test/test_helper.bash Normal file
View File

@ -0,0 +1,59 @@
###############################################################################
# test_helper.bash
#
# Test helper for Bats: Bash Automated Testing System.
#
# https://github.com/sstephenson/bats
###############################################################################
setup() {
# `$_HOSTS`
#
# The location of the `hosts` script being tested.
export _HOSTS="${BATS_TEST_DIRNAME}/../hosts"
export _HOSTS_TEMP_DIR
_HOSTS_TEMP_DIR="$(mktemp -d)"
export _HOSTS_TEMP_PATH
_HOSTS_TEMP_PATH="${_HOSTS_TEMP_DIR}/hosts"
export _ERROR_PREFIX
_ERROR_PREFIX="$(tput setaf 1)!$(tput sgr0) "
cat "${BATS_TEST_DIRNAME}/fixtures/hosts" > "${_HOSTS_TEMP_PATH}"
export HOSTS_PATH="${_HOSTS_TEMP_PATH}"
# Use empty `hosts` script in environment to avoid depending on `hosts`
# being available in `$PATH`.
export PATH="${BATS_TEST_DIRNAME}/fixtures/bin:${PATH}"
}
teardown() {
if [[ -n "${_HOSTS_TEMP_PATH}" ]] &&
[[ -e "${_HOSTS_TEMP_PATH}" ]] &&
[[ "${_HOSTS_TEMP_PATH}" =~ ^/tmp/hosts_test ]]
then
rm -f "${_HOSTS_TEMP_DIR}"/hosts_test.*
fi
}
###############################################################################
# Helpers
###############################################################################
# _compare()
#
# Usage:
# _compare <expected> <actual>
#
# Description:
# Compare the content of a variable against an expected value. When used
# within a `@test` block the output is only displayed when the test fails.
_compare() {
local _expected="${1:-}"
local _actual="${2:-}"
printf "expected:\\n%s\\n" "${_expected}"
printf "actual:\\n%s\\n" "${_actual}"
}

242
test/unblock.bats Normal file
View File

@ -0,0 +1,242 @@
#!/usr/bin/env bats
load test_helper
# `hosts unblock` #############################################################
@test "\`unblock\` with no arguments exits with status 1." {
run "${_HOSTS}" unblock
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`unblock\` with no argument does not change the hosts file." {
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" unblock
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "$(cat "${HOSTS_PATH}")" == "${_original}" ]]
}
@test "\`unblock\` with no arguments prints help information." {
run "${_HOSTS}" unblock
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts unblock <hostname>..." ]]
}
# `hosts unblock <invalid>` ###################################################
@test "\`unblock <invalid> \` exits with status 1." {
{
run "${_HOSTS}" block example.com
}
run "${_HOSTS}" unblock example.net
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
@test "\`unblock <invalid>\` prints error message." {
{
run "${_HOSTS}" block example.com
}
run "${_HOSTS}" unblock example.net
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${output} == "${_ERROR_PREFIX}No matching entries found." ]]
}
# `hosts unblock <hostname>` ##################################################
@test "\`unblock <hostname>\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" block example.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
run "${_HOSTS}" unblock example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`unblock <hostname>\` updates the hosts file." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" block example.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" unblock example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" == "0.0.0.0 example.com" ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" == "127.0.0.1 example.net" ]]
[[ "$(sed -n '13p' "${HOSTS_PATH}")" == "" ]]
}
@test "\`unblock <hostname>\` removes all matches." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" block example.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" unblock example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_expected="\
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
0.0.0.0 example.com
127.0.0.1 example.net"
_compare "'${_expected}'" "'$(cat "${HOSTS_PATH}")'"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(cat "${HOSTS_PATH}")" == "${_expected}" ]]
}
@test "\`unblock <hostname>\` prints feedback." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" block example.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
run "${_HOSTS}" unblock example.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_expected="\
Removed:
127.0.0.1 example.com
Removed:
fe80::1%lo0 example.com
Removed:
::1 example.com"
[[ "${output}" == "${_expected}" ]]
}
# `hosts unblock <hostname> <hostname2>` ######################################
@test "\`unblock <hostname> <hostname2>\` exits with status 0." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" block example.com
run "${_HOSTS}" block example2.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
run "${_HOSTS}" unblock example.com example2.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 0 ]]
}
@test "\`unblock <hostname> <hostname2>\` updates the hosts file." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" block example.com
run "${_HOSTS}" block example2.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" unblock example.com example2.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_compare "${_original}" "$(cat "${HOSTS_PATH}")"
[[ "$(sed -n '11p' "${HOSTS_PATH}")" == "0.0.0.0 example.com" ]]
[[ "$(sed -n '12p' "${HOSTS_PATH}")" == "127.0.0.1 example.net" ]]
[[ "$(sed -n '13p' "${HOSTS_PATH}")" == "" ]]
}
@test "\`unblock <hostname> <hostname2>\` removes all matches." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" block example.com
run "${_HOSTS}" block example2.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
_original="$(cat "${HOSTS_PATH}")"
run "${_HOSTS}" unblock example.com example2.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_expected="\
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
0.0.0.0 example.com
127.0.0.1 example.net"
_compare "'${_expected}'" "'$(cat "${HOSTS_PATH}")'"
[[ "$(cat "${HOSTS_PATH}")" != "${_original}" ]]
[[ "$(cat "${HOSTS_PATH}")" == "${_expected}" ]]
}
@test "\`unblock <hostname> <hostname2>\` prints feedback." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" block example.com
run "${_HOSTS}" block example2.com
run "${_HOSTS}" add 127.0.0.1 example.net
}
run "${_HOSTS}" unblock example.com example2.com
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_expected="\
Removed:
127.0.0.1 example.com
Removed:
fe80::1%lo0 example.com
Removed:
::1 example.com
Removed:
127.0.0.1 example2.com
Removed:
fe80::1%lo0 example2.com
Removed:
::1 example2.com"
_compare "'${output}'" "'${_expected}'"
diff <(echo "${output}" ) <(echo "${_expected}")
[[ "${output}" == "${_expected}" ]]
}
# help ########################################################################
@test "\`help unblock\` exits with status 0." {
run "${_HOSTS}" help unblock
[[ ${status} -eq 0 ]]
}
@test "\`help unblock\` prints help information." {
run "${_HOSTS}" help unblock
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts unblock <hostname>..." ]]
}

40
test/version.bats Normal file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env bats
load test_helper
@test "\`hosts version\` returns with 0 status." {
run "${_HOSTS}" version
[[ "${status}" -eq 0 ]]
}
@test "\`hosts version\` prints a version number." {
run "${_HOSTS}" version
printf "'%s'" "${output}"
echo "${output}" | grep -q '[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+'
}
@test "\`hosts --version\` returns with 0 status." {
run "${_HOSTS}" --version
[[ "${status}" -eq 0 ]]
}
@test "\`hosts --version\` prints a version number." {
run "${_HOSTS}" --version
printf "'%s'" "${output}"
echo "${output}" | grep -q '[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+'
}
# help ########################################################################
@test "\`help version\` exits with status 0." {
run "${_HOSTS}" help version
[[ ${status} -eq 0 ]]
}
@test "\`help version\` prints help information." {
run "${_HOSTS}" help version
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts (version | --version)" ]]
}