├── .circleci └── config.yml ├── .github ├── .github │ └── FUNDING.yml └── FUNDING.yml ├── .gitignore ├── Bakefile ├── LICENSE ├── MANIFEST.in ├── Pipfile ├── Pipfile.lock ├── README.md ├── bake ├── __init__.py ├── bakefile.py ├── bash.py ├── cache.py ├── cli.py ├── clint.py ├── constants.py ├── exceptions.py ├── scripts │ ├── __init__.py │ ├── indent.py │ ├── notred.py │ ├── red.py │ └── step.py └── utils.py ├── contrib └── bake-vscode │ ├── .vscodeignore │ ├── Bakefile │ ├── CHANGELOG.md │ ├── README.md │ ├── language-configuration.json │ ├── package.json │ ├── syntaxes │ └── Bakefile.syntax.json │ ├── t.sh │ ├── vsc-extension-quickstart.md │ └── yarn.lock ├── docker-compose.yml ├── docker ├── bake.Dockerfile ├── ci.Dockerfile ├── core.Dockerfile ├── red.Dockerfile └── scripts │ ├── tap2xml │ └── use-mirrors.sh ├── docs ├── .gitignore ├── .readthedocs.yml ├── .vscode │ └── settings.json ├── README.md ├── docs_site │ ├── Makefile │ ├── _build │ │ ├── doctrees │ │ │ ├── environment.pickle │ │ │ ├── files │ │ │ │ ├── basic_usage.doctree │ │ │ │ ├── faqs.doctree │ │ │ │ ├── installation.doctree │ │ │ │ ├── practical_examples.doctree │ │ │ │ ├── quickstart.doctree │ │ │ │ ├── some.doctree │ │ │ │ └── terminal_tricks.doctree │ │ │ └── index.doctree │ │ └── html │ │ │ ├── .buildinfo │ │ │ ├── _sources │ │ │ ├── files │ │ │ │ ├── basic_usage.md.txt │ │ │ │ ├── faqs.md.txt │ │ │ │ ├── installation.md.txt │ │ │ │ ├── practical_examples.md.txt │ │ │ │ ├── quickstart.md.txt │ │ │ │ ├── some.md.txt │ │ │ │ └── terminal_tricks.md.txt │ │ │ └── index.md.txt │ │ │ ├── _static │ │ │ ├── ajax-loader.gif │ │ │ ├── alabaster.css │ │ │ ├── basic.css │ │ │ ├── comment-bright.png │ │ │ ├── comment-close.png │ │ │ ├── comment.png │ │ │ ├── custom.css │ │ │ ├── doctools.js │ │ │ ├── documentation_options.js │ │ │ ├── down-pressed.png │ │ │ ├── down.png │ │ │ ├── file.png │ │ │ ├── jquery-3.2.1.js │ │ │ ├── jquery-3.4.1.js │ │ │ ├── jquery.js │ │ │ ├── language_data.js │ │ │ ├── minus.png │ │ │ ├── plus.png │ │ │ ├── pygments.css │ │ │ ├── searchtools.js │ │ │ ├── underscore-1.3.1.js │ │ │ ├── underscore.js │ │ │ ├── up-pressed.png │ │ │ ├── up.png │ │ │ └── websupport.js │ │ │ ├── files │ │ │ ├── basic_usage.html │ │ │ ├── faqs.html │ │ │ ├── installation.html │ │ │ ├── practical_examples.html │ │ │ ├── quickstart.html │ │ │ ├── some.html │ │ │ └── terminal_tricks.html │ │ │ ├── genindex.html │ │ │ ├── index.html │ │ │ ├── objects.inv │ │ │ ├── search.html │ │ │ └── searchindex.js │ ├── conf.py │ ├── files │ │ ├── Bakefile │ │ ├── basic_usage.md │ │ ├── faqs.md │ │ ├── installation.md │ │ ├── practical_examples.md │ │ └── terminal_tricks.md │ ├── index.md │ └── make.bat └── requirements.txt ├── examples ├── hidden-tasks │ └── Bakefile ├── reuse │ └── Bakefile └── stdlib │ └── Bakefile ├── ext ├── bake.jpg ├── bake.png ├── img.jpg ├── screencast.gif ├── screenshot.png ├── ss.png └── tattoo-design.jpg ├── setup.py └── tests ├── _common.sh ├── args.Bakefile ├── args.bats ├── basics.Bakefile ├── basics.bats ├── cache.Bakefile ├── cache.bats ├── confirm.Bakefile ├── confirm.bats ├── env.Bakefile ├── env.bats ├── include.Bakefile ├── include.bats ├── included1.Bakefile ├── included2.Bakefile ├── included3.Bakefile ├── ordering.Bakefile ├── ordering.bats ├── python.Bakefile ├── python.bats ├── self.Bakefile ├── self.bats └── utils.bats /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Python CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-python/ for more details 4 | # 5 | version: 2 6 | jobs: 7 | test: 8 | docker: 9 | - image: kennethreitz/bake:ci 10 | working_directory: /app 11 | steps: 12 | - checkout 13 | - run: 14 | name: $ pipenv install… 15 | command: | 16 | export PIPENV_MAX_SUBPROCESS=128 17 | pipenv install --dev --system --deploy 18 | - run: 19 | name: BATS tests 20 | command: | 21 | cd tests 22 | mkdir -p /app/reports/bats 23 | bats *.bats --tap | tap2xml > "/app/reports/bats/report.xml" 24 | - store_test_results: 25 | path: reports 26 | docker-push: 27 | docker: 28 | - image: kennethreitz/bake:ci 29 | 30 | working_directory: /app 31 | 32 | steps: 33 | - checkout 34 | - setup_remote_docker: 35 | docker_layer_caching: true 36 | - run: &docker-login 37 | name: $ docker login 38 | command: | 39 | set -u 40 | # docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD 41 | # echo "$DOCKERHUB_PASSWORD" | docker login --username $DOCKERHUB_USERNAME --password-stdin 42 | # echo "$GITHUB_TOKEN" | docker login docker.pkg.github.com --username $GITHUB_USERNAME --password-stdin 43 | 44 | - run: 45 | name: $ bake docker/push 46 | command: bake docker/push 47 | 48 | docker-push-ci: 49 | docker: 50 | - image: kennethreitz/bake:ci 51 | 52 | working_directory: /app 53 | 54 | steps: 55 | - checkout 56 | - setup_remote_docker: 57 | docker_layer_caching: true 58 | - run: *docker-login 59 | - run: 60 | name: $ docker-compose build ci 61 | command: | 62 | docker-compose build ci 63 | - run: 64 | name: $ docker push 65 | command: | 66 | docker push kennethreitz/bake:ci 67 | 68 | workflows: 69 | version: 2 70 | test: 71 | jobs: 72 | - test: 73 | filters: 74 | branches: 75 | ignore: 76 | - master 77 | test-and-docker-push: 78 | jobs: 79 | - test 80 | - docker-push: 81 | requires: 82 | - test 83 | filters: 84 | branches: 85 | only: 86 | - master 87 | tags: 88 | only: /^v.*/ 89 | docker-push-ci: 90 | triggers: 91 | - schedule: 92 | cron: "0 * * * *" 93 | filters: 94 | branches: 95 | only: 96 | - master 97 | jobs: 98 | - docker-push-ci 99 | -------------------------------------------------------------------------------- /.github/.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ['https://cash.app/$KR424'] 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: kennethreitz 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/settings.json 2 | bake.egg-info/* 3 | **/__pycache__/** 4 | .DS_Store 5 | .eggs 6 | build 7 | bake_cli.egg-info/* 8 | dist 9 | -------------------------------------------------------------------------------- /Bakefile: -------------------------------------------------------------------------------- 1 | 2 | REGISTRY=${REGISTRY:-docker.pkg.github.com} 3 | USERNAME=${USERNAME:-kennethreitz} 4 | 5 | //: //system //python 6 | red "System is setup for local development." 7 | //system: //warn @confirm 8 | lazy_brew_pretty pipenv bats 9 | //python: @skip:key=Pipfile.lock //system 10 | pipenv install --dev 11 | test: docker/build 12 | unset BAKEFILE 13 | docker-compose run --entrypoint bash ci -c 'set -ex && pip3 uninstall -y bake-cli && pip3 install -e . --upgrade && hash -r && cd tests && bats *.bats --pretty' 14 | release: test //warn @confirm:secure release//pypi docker/push 15 | 16 | //warn: 17 | echo 18 | echo "$(red 'Warning'): You are about to make modifications to your system." 19 | echo 20 | 21 | docker/build: 22 | # Build the images. 23 | set -ex && docker-compose build 24 | 25 | docker/bash: @interactive docker/build 26 | docker-compose run --entrypoint bash bake 27 | 28 | release//pypi: @interactive //python 29 | pipenv run python setup.py upload 30 | 31 | docker/push: docker/build //docker/github //docker/dockerhub 32 | docker/push/ci: docker/build 33 | docker-compose push ci 34 | 35 | //docker/github: docker/build 36 | set -ux 37 | 38 | declare -a IMAGES=('red', 'bake:core' 'bake:latest' 'bake:ci') 39 | 40 | for IMAGE in "${IMAGES[@]}"; do 41 | bake_step "Pushing $IMAGE..." 42 | 43 | REMOTE_IMAGE="$REGISTRY/$USERNAME/bake/$IMAGE" 44 | 45 | # Tag the images for GitHub Registry. 46 | docker tag "$USERNAME/$IMAGE" "$REMOTE_IMAGE" 47 | 48 | # Push the images to GitHub. 49 | docker push "$REMOTE_IMAGE" 50 | done 51 | 52 | //docker/dockerhub: docker/build 53 | docker-compose push 54 | 55 | random/python/ip: 56 | #!/usr/bin/env python 57 | import requests 58 | r = requests.get('https://httpbin.org/ip') 59 | print(r.json()['origin'].split(',')[0]) 60 | 61 | /kr: 62 | sparkescakesparkles="✨ 🍰 ✨" | pbcopy 63 | echo "$sparkescakesparkles" | pbcopy 64 | echo 'KR Copied!' | red --fg cyan 65 | 66 | lazy_brew_pretty() { 67 | # Install jq if it's not available. 68 | 69 | if ! which -s jq; then 70 | bake_step "Installing jq" 71 | brew install jq 2>&1 | bake_indent --char $(red '|') 72 | fi 73 | set +e 74 | 75 | # Install requested packages, if they aren't installed. 76 | for PACKAGE in "${@}"; do 77 | if ! which -s ${PACKAGE}; then 78 | bake_step "Installing ${PACKAGE}" --color green 79 | brew install "${PACKAGE}" 2>&1 | bake_indent --char $(red '|') 80 | fi 81 | done 82 | } 83 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Kenneth Reitz. 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 6 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE README.md bake/scripts/*.sh 2 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | name = "pypi" 3 | url = "https://pypi.org/simple" 4 | verify_ssl = true 5 | 6 | [dev-packages] 7 | black = "*" 8 | pytest = "*" 9 | twine = "*" 10 | 11 | [packages] 12 | bashf = {editable = true,path = "."} 13 | 14 | [requires] 15 | python_version = "3.7" 16 | 17 | [pipenv] 18 | allow_prereleases = true 19 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "8c3094f2b375bb551d144c3c956634d180195c5dc799e32f3f6bd77810f10bb0" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.7" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "bashf": { 20 | "editable": true, 21 | "path": "." 22 | }, 23 | "click": { 24 | "hashes": [ 25 | "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", 26 | "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" 27 | ], 28 | "version": "==7.0" 29 | }, 30 | "colorama": { 31 | "hashes": [ 32 | "sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", 33 | "sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48" 34 | ], 35 | "version": "==0.4.1" 36 | }, 37 | "decorator": { 38 | "hashes": [ 39 | "sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de", 40 | "sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6" 41 | ], 42 | "version": "==4.4.0" 43 | }, 44 | "delegator.py": { 45 | "hashes": [ 46 | "sha256:814657d96b98a244c479e3d5f6e9e850ac333e85f807d6bc846e72bbb2537806", 47 | "sha256:e6cc9cedab9ae59b169ee0422e17231adedadb144e63c0b5a60e6ff8adf8521b" 48 | ], 49 | "version": "==0.1.1" 50 | }, 51 | "networkx": { 52 | "hashes": [ 53 | "sha256:8311ddef63cf5c5c5e7c1d0212dd141d9a1fe3f474915281b73597ed5f1d4e3d" 54 | ], 55 | "version": "==2.3" 56 | }, 57 | "pexpect": { 58 | "hashes": [ 59 | "sha256:2094eefdfcf37a1fdbfb9aa090862c1a4878e5c7e0e7e7088bdb511c558e5cd1", 60 | "sha256:9e2c1fd0e6ee3a49b28f95d4b33bc389c89b20af6a1255906e90ff1262ce62eb" 61 | ], 62 | "version": "==4.7.0" 63 | }, 64 | "ptyprocess": { 65 | "hashes": [ 66 | "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0", 67 | "sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f" 68 | ], 69 | "version": "==0.6.0" 70 | }, 71 | "pygments": { 72 | "hashes": [ 73 | "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", 74 | "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297" 75 | ], 76 | "version": "==2.4.2" 77 | } 78 | }, 79 | "develop": { 80 | "appdirs": { 81 | "hashes": [ 82 | "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", 83 | "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" 84 | ], 85 | "version": "==1.4.3" 86 | }, 87 | "atomicwrites": { 88 | "hashes": [ 89 | "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", 90 | "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" 91 | ], 92 | "version": "==1.3.0" 93 | }, 94 | "attrs": { 95 | "hashes": [ 96 | "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", 97 | "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" 98 | ], 99 | "version": "==19.1.0" 100 | }, 101 | "black": { 102 | "hashes": [ 103 | "sha256:09a9dcb7c46ed496a9850b76e4e825d6049ecd38b611f1224857a79bd985a8cf", 104 | "sha256:68950ffd4d9169716bcb8719a56c07a2f4485354fec061cdd5910aa07369731c" 105 | ], 106 | "index": "pypi", 107 | "version": "==19.3b0" 108 | }, 109 | "bleach": { 110 | "hashes": [ 111 | "sha256:213336e49e102af26d9cde77dd2d0397afabc5a6bf2fed985dc35b5d1e285a16", 112 | "sha256:3fdf7f77adcf649c9911387df51254b813185e32b2c6619f690b593a617e19fa" 113 | ], 114 | "version": "==3.1.0" 115 | }, 116 | "certifi": { 117 | "hashes": [ 118 | "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", 119 | "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" 120 | ], 121 | "version": "==2019.9.11" 122 | }, 123 | "chardet": { 124 | "hashes": [ 125 | "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", 126 | "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" 127 | ], 128 | "version": "==3.0.4" 129 | }, 130 | "click": { 131 | "hashes": [ 132 | "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", 133 | "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" 134 | ], 135 | "version": "==7.0" 136 | }, 137 | "docutils": { 138 | "hashes": [ 139 | "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0", 140 | "sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827", 141 | "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99" 142 | ], 143 | "version": "==0.15.2" 144 | }, 145 | "idna": { 146 | "hashes": [ 147 | "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", 148 | "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" 149 | ], 150 | "version": "==2.8" 151 | }, 152 | "importlib-metadata": { 153 | "hashes": [ 154 | "sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26", 155 | "sha256:d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af" 156 | ], 157 | "markers": "python_version < '3.8'", 158 | "version": "==0.23" 159 | }, 160 | "more-itertools": { 161 | "hashes": [ 162 | "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", 163 | "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" 164 | ], 165 | "version": "==7.2.0" 166 | }, 167 | "packaging": { 168 | "hashes": [ 169 | "sha256:28b924174df7a2fa32c1953825ff29c61e2f5e082343165438812f00d3a7fc47", 170 | "sha256:d9551545c6d761f3def1677baf08ab2a3ca17c56879e70fecba2fc4dde4ed108" 171 | ], 172 | "version": "==19.2" 173 | }, 174 | "pkginfo": { 175 | "hashes": [ 176 | "sha256:7424f2c8511c186cd5424bbf31045b77435b37a8d604990b79d4e70d741148bb", 177 | "sha256:a6d9e40ca61ad3ebd0b72fbadd4fba16e4c0e4df0428c041e01e06eb6ee71f32" 178 | ], 179 | "version": "==1.5.0.1" 180 | }, 181 | "pluggy": { 182 | "hashes": [ 183 | "sha256:0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6", 184 | "sha256:fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34" 185 | ], 186 | "version": "==0.13.0" 187 | }, 188 | "py": { 189 | "hashes": [ 190 | "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", 191 | "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" 192 | ], 193 | "version": "==1.8.0" 194 | }, 195 | "pygments": { 196 | "hashes": [ 197 | "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", 198 | "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297" 199 | ], 200 | "version": "==2.4.2" 201 | }, 202 | "pyparsing": { 203 | "hashes": [ 204 | "sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80", 205 | "sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4" 206 | ], 207 | "version": "==2.4.2" 208 | }, 209 | "pytest": { 210 | "hashes": [ 211 | "sha256:813b99704b22c7d377bbd756ebe56c35252bb710937b46f207100e843440b3c2", 212 | "sha256:cc6620b96bc667a0c8d4fa592a8c9c94178a1bd6cc799dbb057dfd9286d31a31" 213 | ], 214 | "index": "pypi", 215 | "version": "==5.1.3" 216 | }, 217 | "readme-renderer": { 218 | "hashes": [ 219 | "sha256:bb16f55b259f27f75f640acf5e00cf897845a8b3e4731b5c1a436e4b8529202f", 220 | "sha256:c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d" 221 | ], 222 | "version": "==24.0" 223 | }, 224 | "requests": { 225 | "hashes": [ 226 | "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", 227 | "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" 228 | ], 229 | "version": "==2.22.0" 230 | }, 231 | "requests-toolbelt": { 232 | "hashes": [ 233 | "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f", 234 | "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0" 235 | ], 236 | "version": "==0.9.1" 237 | }, 238 | "six": { 239 | "hashes": [ 240 | "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", 241 | "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" 242 | ], 243 | "version": "==1.12.0" 244 | }, 245 | "toml": { 246 | "hashes": [ 247 | "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", 248 | "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" 249 | ], 250 | "version": "==0.10.0" 251 | }, 252 | "tqdm": { 253 | "hashes": [ 254 | "sha256:abc25d0ce2397d070ef07d8c7e706aede7920da163c64997585d42d3537ece3d", 255 | "sha256:dd3fcca8488bb1d416aa7469d2f277902f26260c45aa86b667b074cd44b3b115" 256 | ], 257 | "version": "==4.36.1" 258 | }, 259 | "twine": { 260 | "hashes": [ 261 | "sha256:630fadd6e342e725930be6c696537e3f9ccc54331742b16245dab292a17d0460", 262 | "sha256:a3d22aab467b4682a22de4a422632e79d07eebd07ff2a7079effb13f8a693787" 263 | ], 264 | "index": "pypi", 265 | "version": "==1.15.0" 266 | }, 267 | "urllib3": { 268 | "hashes": [ 269 | "sha256:2f3eadfea5d92bc7899e75b5968410b749a054b492d5a6379c1344a1481bc2cb", 270 | "sha256:9c6c593cb28f52075016307fc26b0a0f8e82bc7d1ff19aaaa959b91710a56c47" 271 | ], 272 | "version": "==1.25.5" 273 | }, 274 | "wcwidth": { 275 | "hashes": [ 276 | "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", 277 | "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" 278 | ], 279 | "version": "==0.1.7" 280 | }, 281 | "webencodings": { 282 | "hashes": [ 283 | "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", 284 | "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" 285 | ], 286 | "version": "==0.5.1" 287 | }, 288 | "zipp": { 289 | "hashes": [ 290 | "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", 291 | "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" 292 | ], 293 | "version": "==0.6.0" 294 | } 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |

$ bake — a s☿rangely familiar workflow utility.            

6 |
  7 | 
  8 | 

~ under development ~  

9 | 10 |
11 | $ cat Bakefile $ bake install 12 | install: install/node install/python + Executing install/node: 13 | echo 'All ready!' | yarn install v1.17.3 14 | install/full: install/system install | info No lockfile found. 15 | install/python: @skip:key=Pipfile.lock | [1/4] Resolving packages... 16 | pipenv install | [2/4] Fetching packages... 17 | install/node: @skip:key=yarn.lock | [3/4] Linking dependencies... 18 | yarn install | [4/4] Building fresh packages... 19 | install/system: @confirm | success Saved lockfile. 20 | brew install pipenv yarn | Done in 0.05s. 21 | + Executing install/python: 22 | python/format: | Installing dependencies from … 23 | black . + Executing install: 24 | | All ready! 25 | utils/argv: + Done. 26 | set -u && echo "$HELLO: $@" 27 | Rinse and repeat… 28 | utils/deploy: @confirm:secure 29 | exit 0 30 |
31 |
32 |

~ see bake's own Bakefile ~            

33 | 34 | ## What's in the oven? 35 | 36 | 44 | 45 | 46 | ------------------ 47 | 48 | ### Automate Workflows — Bootstrap Development Environments — Commit The Tasks 49 | 50 | 51 | I love using `Makefile` for one-off **tasks** in projects. 52 | 53 | The problem with doing this is that you can't use familiar bash–isms when doing so, as **GNU Make** doesn't use the familiar **Bash** syntax, nor does it allow for simple ad–hoc use of arbitrary scripting languages (e.g. **Python**). 54 | 55 | 56 | project seeks to bridge all of these worlds into a single entrypoint — ideal for cross–language repositories 57 | 58 | ------------------- 59 | 60 | ## Bootstraping `bake` —                                          (for local development workflows) 61 | 62 | 63 | #### **Various `*`nix Distributions** (Python 3.6+): 64 | 65 | The primary installation method of `bake`, today, is via `pip`: 66 | 67 | ```console 68 | $ pip3 install bake-cli 69 | Collecting bake-cli 70 | … 71 | Successfully installed bake-cli-0.2.0 delegator.py-0.1.1 pexpect-4.7.0 ptyprocess-0.6.0 72 | ``` 73 | 74 | 75 | This will always work, but it will not be the default recommendation. 76 | 77 | #### MacOS (Previously known as OS X) 78 | 79 | Installation of `bake` will (soon) be very easy, with Homebrew. The formula needs a subtle adjustment — if you want to help, [here's the repo](http://github.com/kennethreitz/homebrew--)! 80 | 81 | ```console 82 | $ brew install kennethreitz/-/bake 83 | ==> Installing bake from kennethreitz/- 84 | … 85 | 🍺 /usr/local/Cellar/bake/19-09-16: 1,563 files, 16.7MB, built in 11 seconds 86 | ``` 87 | 88 | Homebrew will be the primary installation target of `bake`. 89 | 90 | ✨🍰✨ 91 | 92 | ## Bootstraping `bake` —                                             (for production workflows) 93 | 94 | #### Containers! *e.g.* Docker. 95 | 96 | You an also run `bake` via Docker! An official image has been made available [on DockerHub](https://cloud.docker.com/u/kennethreitz/repository/docker/kennethreitz/bake): 97 | 98 | ```console 99 | $ docker run kennethreitz/bake Wed Sep 18 10:11:01 2019 100 | No Bakefile found! 101 | Usage: [OPTIONS] [TASK] [ARGUMENTS]... 102 | 103 | $ bake — the strangely familiar task–runner. 104 | 105 | Options: 106 | -b, --bakefile PATH The Bakefile to use. 107 | -l, --list Lists available tasks (and their dependencies). 108 | -h, --help Show this message and exit. 109 | --allow TEXT Whitelist an environment variable for use. 110 | --no-deps Do not run dependent tasks. 111 | --yes Set medium–security prompts to yes. 112 | --continue Continue, if a task fails. 113 | -i, --interactive Run in interactive mode. 114 | --insecure Inherit parent shell's environment variables. 115 | -s, --silent Reduce output. 116 | -e, --environ-json TEXT Provide environment variables via JSON. 117 | -j, --json Output in JSON format (stdout). 118 | ``` 119 | 120 | - **`Bakefile`** is expected to live at **`/app/Bakefile`**. 121 | - If you inherit from this image, **`ONBUILD`** directives will automatically copy your application code (build context) into the container, into **`/app`**. 122 | 123 | **Bonus Points**: this image is also [available on the GitHub Package Registry](https://github.com/kennethreitz/bake/packages/24444) (beta). 124 | 125 | --------------- 126 | 127 | 128 | ### Team & Workflow Management 129 | 130 | You can use `bake` to bootstrap your team's development environments, ensuring a smooth and optimal workflow & local development experience. 131 | 132 | Here's an example, using the `Bakefile` provided above: 133 | 134 | ```console 135 | $ bake install 136 | + Executing install/node: 137 | | yarn install v1.17.3 138 | | info No lockfile found. 139 | | [1/4] Resolving packages... 140 | | [2/4] Fetching packages... 141 | | [3/4] Linking dependencies... 142 | | [4/4] Building fresh packages... 143 | | success Saved lockfile. 144 | | Done in 0.05s. 145 | + Executing install/python: 146 | | Installing dependencies from Pipfile.lock (f10bb0)… 147 | + Executing install: 148 | + Done. 149 | ``` 150 | 151 | ### Skip Steps, Automatically 152 | 153 | Because we configured `yarn.lock` and `Pipfile.lock` as cache keys, 154 | bake will automatically skip the configured steps— only running them 155 | when the files are changed! 156 | 157 | So, let's run that command again :) 158 | 159 | ```console 160 | $ bake install 161 | + Skipping install/node: 162 | + Skipping install/python. 163 | + Executing install: 164 | + Done. 165 | ``` 166 | 167 | Neat, eh? 168 | 169 | ### Arguments & Parameters: Passing Values In 170 | 171 | ```console 172 | $ bake utils/argv KEY=VALUES 1 2 3 173 | + Executing utils/argv: 174 | | VALUES: 1 2 3 175 | + Done. 176 | ``` 177 | 178 | ### (Optional) Non-Deterministic Confirmation Dialouges 179 | 180 | ```console 181 | $ bake utils/deploy 182 | What is 10 times 2?: 7 183 | Aborted. 184 | ``` 185 | 186 | --------------------- 187 | 188 | 189 | ### Community / Contrib 190 | 191 | - [Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=kennethreitz.bake) — highlights `Bakefile`— adequately. 192 | 193 | ---------------------- 194 | 195 |

 

196 | 197 |

198 | This open source software has been designed, for you, with much joy, by the hands of: 199 |

200 | 201 |

 

202 | 203 |

204 | 205 |

206 | 207 |

 

208 | 209 |

210 | 211 |

212 | -------------------------------------------------------------------------------- /bake/__init__.py: -------------------------------------------------------------------------------- 1 | from .bakefile import Bakefile 2 | -------------------------------------------------------------------------------- /bake/bash.py: -------------------------------------------------------------------------------- 1 | """ 2 | bash.py module 3 | """ 4 | import json as json_lib 5 | import re 6 | import sys 7 | import time 8 | from shlex import quote as shlex_quote 9 | import subprocess 10 | import os 11 | import delegator 12 | import click 13 | 14 | DELEGATOR_MINIMUM_TIMEOUT = 60 * 60 * 60 * 8 15 | WHICH_BASH = "bash" 16 | 17 | # Monkey-patch delegator (hack): 18 | if delegator.TIMEOUT < DELEGATOR_MINIMUM_TIMEOUT: 19 | delegator.TIMEOUT = DELEGATOR_MINIMUM_TIMEOUT 20 | 21 | __all__ = ["run", "Bash"] 22 | 23 | 24 | def system_which(command, mult=False): 25 | """Emulates the system's which. Returns None if not found.""" 26 | _which = "which -a" if not os.name == "nt" else "where" 27 | # os.environ = { 28 | # vistir.compat.fs_str(k): vistir.compat.fs_str(val) 29 | # for k, val in os.environ.items() 30 | # } 31 | result = None 32 | try: 33 | c = delegator.run("{0} {1}".format(_which, command)) 34 | try: 35 | # Which Not found… 36 | if c.return_code == 127: 37 | click.echo( 38 | "{}: the {} system utility is required for bake to find bash properly." 39 | "\n Please install it.".format( 40 | click.style("Warning", bold=True), click.style(_which, fg="red") 41 | ), 42 | err=True, 43 | ) 44 | assert c.return_code == 0 45 | except AssertionError: 46 | result = None 47 | except TypeError: 48 | if not result: 49 | result = None 50 | else: 51 | if not result: 52 | result = next(iter([c.out, c.err]), "").split("\n") 53 | result = next(iter(result)) if not mult else result 54 | return result 55 | if not result: 56 | result = None 57 | result = [result] if mult else result 58 | return result 59 | 60 | 61 | class BashProcess: 62 | """bash process object""" 63 | 64 | def __init__( 65 | self, 66 | args, 67 | parent: "bash", 68 | interactive: bool = False, 69 | blocking: bool = True, 70 | **kwargs, 71 | ) -> None: 72 | # Environ inherents from parent. 73 | 74 | # Remember passed-in arguments. 75 | self.parent = parent 76 | self.args = args 77 | self._return_code = None 78 | self.start_time = time.time() 79 | self.elapsed_time = None 80 | self.sub = None 81 | 82 | cmd = [system_which("bash"), *args] 83 | 84 | std_out = sys.stdout if interactive else subprocess.PIPE 85 | # std_out = subprocess.PIPE 86 | std_in = sys.stdin if interactive else subprocess.PIPE 87 | 88 | self.sub = subprocess.Popen( 89 | cmd, stdout=std_out, stdin=std_in, universal_newlines=True, **kwargs 90 | ) 91 | if blocking: 92 | self._return_code = self.sub.wait() 93 | 94 | self.elapsed_time = time.time() - self.start_time 95 | 96 | @property 97 | def output(self) -> str: 98 | """stdout of the running process""" 99 | return str(self.sub.stdout) 100 | 101 | @property 102 | def err(self) -> str: 103 | """stderr of the running process""" 104 | return str(self.sub.stderr) 105 | 106 | @property 107 | def json(self) -> dict: 108 | """stdout of the running process, converted to a dict if it's json""" 109 | return json_lib.loads(str(self.sub.out)) 110 | 111 | @property 112 | def ok(self) -> bool: 113 | """if the process exited with a 0 exit code""" 114 | return self.return_code == 0 115 | 116 | @property 117 | def return_code(self) -> int: 118 | """the exit code of the process""" 119 | return self._return_code or self.sub.returncode 120 | 121 | @property 122 | def pid(self) -> int: 123 | """the process id""" 124 | return self.sub.pid 125 | 126 | def __repr__(self) -> str: 127 | """string representation of the bash process""" 128 | return f"" 129 | 130 | 131 | class Bash: 132 | """an instance of bash""" 133 | 134 | def __init__(self, *, path=WHICH_BASH, environ=None, **kwargs): 135 | """constructor""" 136 | self.path = path 137 | self.environ = environ or {} 138 | self.kwargs = kwargs 139 | 140 | @property 141 | def version(self) -> str: 142 | """Returns the version number of the Bash-interpreter.""" 143 | matches = re.search(r"\bversion\s+(.+)\b", self.about) 144 | # ...GNU Bash, version 4.4.19(1)-release ... --> 4.4.19(1)-release 145 | return matches.group(1) if matches else "version_unknown" 146 | 147 | @property 148 | def about(self): 149 | return self("--version").output 150 | 151 | def __call__(self, *args) -> BashProcess: 152 | """execute the bash process as a child of this process""" 153 | return BashProcess(parent=self, args=args, **self.kwargs) 154 | 155 | def command(self, script: str, quote=True) -> BashProcess: 156 | """form up the command with shlex and execute""" 157 | maybe_quote = shlex_quote if quote else str 158 | return self(f"-c", maybe_quote(script)) 159 | -------------------------------------------------------------------------------- /bake/cache.py: -------------------------------------------------------------------------------- 1 | import click 2 | import delegator 3 | 4 | PREFIX = "bake" 5 | SEPERATOR = "." 6 | 7 | __all__ = ["Cache"] 8 | 9 | 10 | class Cache: 11 | prefix = PREFIX 12 | seperator = SEPERATOR 13 | 14 | def __init__(self, *, bf, namespace="hashes", debug=False, enabled=True): 15 | 16 | self.bf = bf 17 | self.enabled = enabled 18 | self.debug = debug 19 | self.namespace = namespace 20 | 21 | try: 22 | # Assert git exists, and appears functioning. 23 | c = delegator.run("git --version") 24 | assert c.ok 25 | if self.debug: 26 | click.echo(" + cache.git.ok: true", err=True) 27 | 28 | # Record the top-level directory of the git repository. 29 | c = delegator.run("git rev-parse --show-toplevel") 30 | self.git_root = c.out.strip() 31 | if self.debug: 32 | click.echo(f" + cache.git.root: {self.git_root!r}", err=True) 33 | 34 | # Assert Bakefile exists within it. 35 | assert self.bf.path.startswith(self.git_root) 36 | if self.debug: 37 | click.echo(f" + cache.git.contains_bakefile: true", err=True) 38 | 39 | except AssertionError: 40 | # Cache is disabled. 41 | self.enabled = False 42 | 43 | if debug: 44 | click.echo(f" + cache.enabled: true", err=True) 45 | 46 | def __repr__(self): 47 | return f"" 48 | 49 | def _key_for_hashes(self, key): 50 | return self.seperator.join((self.prefix, self.namespace, key)) 51 | 52 | def clear(self): 53 | for key in self: 54 | del self[key] 55 | 56 | if self.debug: 57 | click.echo(" + cache.git.cleared: true", err=True) 58 | 59 | def __iter__(self): 60 | # TODO: Print these. 61 | cmd = "git config --local --list" 62 | 63 | if self.debug: 64 | click.echo(f" {click.style('$', fg='green')} {cmd}", err=True) 65 | 66 | c = delegator.run(cmd) 67 | for result in c.out.split("\n"): 68 | if result.startswith(self.prefix): 69 | yield result.split("=", -1)[0][ 70 | len(self.prefix + "." + self.namespace + ".") : 71 | ] 72 | 73 | def __getitem__(self, k): 74 | key = self._key_for_hashes(k) 75 | cmd = f"git config --local --get {key}" 76 | 77 | if self.debug: 78 | click.echo(f" {click.style('$', fg='green')} {cmd}", err=True) 79 | 80 | c = delegator.run(cmd) 81 | if c.ok: 82 | return c.out.strip() 83 | else: 84 | return None 85 | 86 | def __setitem__(self, k, v): 87 | key = self._key_for_hashes(k) 88 | cmd = f"git config --local {key} {v}" 89 | 90 | if self.debug: 91 | click.echo(f" {click.style('$', fg='green')} {cmd}", err=True) 92 | 93 | c = delegator.run(cmd) 94 | return c.ok 95 | 96 | def __delitem__(self, k): 97 | key = self._key_for_hashes(k) 98 | cmd = f"git config --local --unset {key}" 99 | 100 | if self.debug: 101 | click.echo(f" {click.style('$', fg='green')} {cmd}", err=True) 102 | 103 | c = delegator.run(cmd) 104 | return c.ok 105 | -------------------------------------------------------------------------------- /bake/clint.py: -------------------------------------------------------------------------------- 1 | COMMA = "," 2 | CONJUNCTION = "and" 3 | SPACE = " " 4 | 5 | NEWLINES = ("\n", "\r", "\r\n") 6 | MAX_WIDTHS = [] 7 | 8 | 9 | def tsplit(string, delimiters): 10 | """Behaves str.split but supports tuples of delimiters.""" 11 | delimiters = tuple(delimiters) 12 | if len(delimiters) < 1: 13 | return [string] 14 | final_delimiter = delimiters[0] 15 | for i in delimiters[1:]: 16 | string = string.replace(i, final_delimiter) 17 | return string.split(final_delimiter) 18 | 19 | 20 | def eng_join(l, conj=CONJUNCTION, separator=COMMA): 21 | """Joins lists of words. Oxford comma and all.""" 22 | 23 | collector = [] 24 | left = len(l) 25 | separator = separator + SPACE 26 | conj = conj + SPACE 27 | 28 | for _l in l[:]: 29 | 30 | left += -1 31 | 32 | collector.append(_l) 33 | if left == 1: 34 | if len(l) == 2: 35 | collector.append(SPACE) 36 | else: 37 | collector.append(separator) 38 | 39 | collector.append(conj) 40 | 41 | elif left is not 0: 42 | collector.append(separator) 43 | 44 | return str().join(collector) 45 | -------------------------------------------------------------------------------- /bake/constants.py: -------------------------------------------------------------------------------- 1 | INDENT_STYLES = ("\t", " " * 4) 2 | SKIP_NEXT = False 3 | SAFE_ENVIRONS = [ 4 | "HOME", 5 | "PATH", 6 | "LANG", 7 | "LOCALE", 8 | "LANGUAGE", 9 | "USER", 10 | "TERM", 11 | "VIRTUAL_ENV", 12 | "BAKEFILE", 13 | "PYTHONUNBUFFERED", 14 | "PYTHONDONTWRITEBYTECODE", 15 | "BAKE_SILENT", 16 | ] 17 | DEFAULT_BAKEFILE_NAME = "Bakefile" 18 | -------------------------------------------------------------------------------- /bake/exceptions.py: -------------------------------------------------------------------------------- 1 | class NoBakefileFound(RuntimeError): 2 | pass 3 | 4 | 5 | class TaskNotInBashfile(ValueError): 6 | pass 7 | 8 | 9 | class FilterNotAvailable(ValueError): 10 | pass 11 | -------------------------------------------------------------------------------- /bake/scripts/__init__.py: -------------------------------------------------------------------------------- 1 | from . import red 2 | from . import indent 3 | from . import step 4 | from . import notred 5 | -------------------------------------------------------------------------------- /bake/scripts/indent.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import click 4 | 5 | 6 | @click.command(context_settings=dict(help_option_names=["-h", "--help"])) 7 | @click.option( 8 | "--read-stderr", is_flag=True, type=click.BOOL, default=True, help="Read stderr." 9 | ) 10 | @click.option("--char", nargs=1, type=click.STRING, default="|", help="Prefix char.") 11 | def entrypoint(*, char, read_stderr): 12 | """Indents and echoes string with a specific pipe.""" 13 | 14 | pipe = sys.stdin if not read_stderr else sys.stderr 15 | 16 | for line in pipe: 17 | if line: 18 | print(f" {char} ", end="") 19 | print(line.rstrip()) 20 | else: 21 | print(f" {char} ", end="") 22 | -------------------------------------------------------------------------------- /bake/scripts/notred.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import click 4 | from click.utils import strip_ansi 5 | 6 | 7 | @click.command(context_settings=dict(help_option_names=["-h", "--help"])) 8 | @click.argument("s", type=click.STRING, default=False, required=False) 9 | @click.option("--err", is_flag=True, type=click.BOOL, default=False, help="Use stderr.") 10 | def entrypoint(s, *, err): 11 | """Removes ANSI chraracters and trailing spaces from string input.""" 12 | 13 | if s is False: 14 | s = sys.stdin.read() 15 | 16 | s = s.rstrip() 17 | 18 | click.echo(strip_ansi(s)) 19 | -------------------------------------------------------------------------------- /bake/scripts/red.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import click 4 | import colorama 5 | 6 | 7 | @click.command(context_settings=dict(help_option_names=["-h", "--help"])) 8 | @click.argument("s", type=click.STRING, default=False, required=False) 9 | @click.option("--err", is_flag=True, type=click.BOOL, default=False, help="Use stderr.") 10 | @click.option( 11 | "--always", 12 | is_flag=True, 13 | type=click.BOOL, 14 | default=False, 15 | help="Always speak technicolor.", 16 | ) 17 | @click.option( 18 | "--fg", nargs=1, type=click.STRING, default="red", help="Foreground color to use." 19 | ) 20 | @click.option( 21 | "--bg", 22 | nargs=1, 23 | type=click.STRING, 24 | default="", 25 | help="Background color to use (rare).", 26 | ) 27 | @click.option("--bold", is_flag=True, type=click.BOOL, default=False, help="Be bold.") 28 | def entrypoint(s, *, fg, bg, bold, err, always): 29 | """Echoes string with specific foreground and background color.""" 30 | 31 | if always: 32 | # Don't strip colors. 33 | colorama.init(strip=False) 34 | 35 | if s is False: 36 | s = sys.stdin.read() 37 | 38 | s = s.rstrip() 39 | 40 | try: 41 | s = click.style(s, fg=fg, bg=bg) 42 | except TypeError: 43 | pass 44 | 45 | print(s) 46 | -------------------------------------------------------------------------------- /bake/scripts/step.py: -------------------------------------------------------------------------------- 1 | # + Executing random/entrypoints: 2 | 3 | import sys 4 | 5 | import colorama 6 | import click 7 | 8 | # Don't strip colors. 9 | colorama.init(strip=False) 10 | 11 | 12 | @click.command(context_settings=dict(help_option_names=["-h", "--help"])) 13 | @click.argument("s", type=click.STRING, default=False, required=False) 14 | @click.option( 15 | "--read-stderr", is_flag=True, type=click.BOOL, default=False, help="Read stderr." 16 | ) 17 | @click.option( 18 | "--no-color", is_flag=True, type=click.BOOL, default=False, help="Read stderr." 19 | ) 20 | @click.option("--char", nargs=1, type=click.STRING, default="+", help="Prefix char.") 21 | @click.option( 22 | "--color", nargs=1, type=click.STRING, default="yellow", help="Color to use." 23 | ) 24 | def entrypoint(s, *, char, read_stderr, no_color, color): 25 | """Echoes step titles in < + steptitle > format.""" 26 | 27 | pipe = sys.stdin if not read_stderr else sys.stderr 28 | if s is False: 29 | s = pipe.read() 30 | 31 | if no_color: 32 | color = "NOTACOLOR" 33 | 34 | for line in s.strip().split("\n"): 35 | try: 36 | title = str(click.style(line, fg=color)) 37 | except TypeError: 38 | title = line 39 | 40 | print(f" + {title}: ") 41 | -------------------------------------------------------------------------------- /bake/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def scrub_hidden_tasks(names): 5 | 6 | hidden_char = "//" 7 | _names = [] 8 | for name in names: 9 | if hidden_char not in str(name): 10 | _names.append(name) 11 | 12 | return _names 13 | 14 | 15 | def walk_up(bottom): 16 | """mimic os.walk, but walk 'up' instead of down the directory tree. 17 | From: https://gist.github.com/zdavkeos/1098474 18 | """ 19 | 20 | bottom = os.path.realpath(bottom) 21 | 22 | # get files in current dir 23 | try: 24 | names = os.listdir(bottom) 25 | except Exception: 26 | return 27 | 28 | dirs, nondirs = [], [] 29 | for name in names: 30 | if os.path.isdir(os.path.join(bottom, name)): 31 | dirs.append(name) 32 | else: 33 | nondirs.append(name) 34 | 35 | yield bottom, dirs, nondirs 36 | 37 | new_path = os.path.realpath(os.path.join(bottom, "..")) 38 | 39 | # see if we are at the top 40 | if new_path == bottom: 41 | return 42 | 43 | for x in walk_up(new_path): 44 | yield x 45 | -------------------------------------------------------------------------------- /contrib/bake-vscode/.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | .gitignore 4 | vsc-extension-quickstart.md 5 | -------------------------------------------------------------------------------- /contrib/bake-vscode/Bakefile: -------------------------------------------------------------------------------- 1 | ms/publish: ms/package ms/login 2 | vsce publish 3 | rm -fr bake-*.vsix 4 | 5 | ms/login: install/system 6 | set +e 7 | vsce login kennethreitz 8 | 9 | ms/package: install/system 10 | cp ../../README.md README.md 11 | vsce package 12 | 13 | install/system: 14 | npm install -g yo generator-code vsce 15 | -------------------------------------------------------------------------------- /contrib/bake-vscode/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to the "bake" extension will be documented in this file. 4 | 5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 6 | 7 | ## [Unreleased] 8 | 9 | - Initial release -------------------------------------------------------------------------------- /contrib/bake-vscode/README.md: -------------------------------------------------------------------------------- 1 | ![vanity image](https://github.com/kennethreitz/bake/blob/master/ext/img.jpg?raw=true) 2 | 3 | 4 | 5 |
  6 |     $ bake, n:
  7 |     the s☿rangely familiar task runner.
  8 | 
9 |
10 | 11 | -------------------- 12 | 13 | I love using `Makefile` for one-off **tasks** in projects. 14 | 15 | The problem with doing this is that you can't use familiar bash–isms when doing so, as **GNU Make** doesn't use the familiar **Bash** syntax, nor does it allow for simple ad–hoc use of arbitrary scripting languages (e.g. **Python**). 16 | 17 | This project seeks to bridge all of these worlds into a single entrypoint — ideal for cross–language repositories. 18 | 19 | ----------------- 20 | 21 |

22 | 23 |

24 | 25 | ---------------- 26 | 27 | ### Features 'n Things 28 | 29 | - A `Bakefile`, which looks and feels like the good parts of a `Makefile`. 30 | - Except, you can write real bash code! 31 | - Environment variables are explicitly passed or whitelisted (allowed), not inherited from the parent shell. 32 | - Unlike `Makefile`, either tabs or 4 spaces can be used. 33 | - Tasks can be run safely and reliably. Rest assured that scripts are executed from the project root (e.g. location of the `Bakefile`). 34 | - See [advanced example](https://github.com/kennethreitz/bake#advanced-usage-sample) for further, juicy, details. 35 | 36 | 37 | ### Community / Contrib 38 | 39 | - [Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=kennethreitz.bake) — highlights `Bakefile`. 40 | 41 | ------------------ 42 | 43 | ## Installing `$ bake` 44 | 45 | **MacOS**: 46 | 47 | ```console 48 | $ brew install kennethreitz/-/bake 49 | ==> Installing bake from kennethreitz/- 50 | … 51 | 🍺 /usr/local/Cellar/bake/19-09-16: 1,563 files, 16.7MB, built in 11 seconds 52 | ``` 53 | 54 | **Various Linux Distributions** (Python 3.6+): 55 | 56 | ```console 57 | $ pip3 install bake-cli 58 | Collecting bake-cli 59 | … 60 | Successfully installed bake-cli-0.2.0 delegator.py-0.1.1 pexpect-4.7.0 ptyprocess-0.6.0 61 | ``` 62 | 63 | ✨🍰✨ 64 | 65 | --------------- 66 | 67 | ## `$ cat Bakefile` 68 | 69 | ```make 70 | full-install: system-deps install 71 | install: node-deps python-deps 72 | format: 73 | black . 74 | 75 | python-deps: @skip:key=Pipfile.lock 76 | pipenv install 77 | node-deps: @skip:key=yarn.lock 78 | yarn install 79 | system-deps: @confirm 80 | brew install pipenv 81 | 82 | python-example: 83 | #!/usr/bin/env python 84 | import os 85 | import sys 86 | 87 | print(os.environ['KEY']) 88 | print(sys.argv[1:]) 89 | 90 | dangerous-example: @confirm:secure 91 | # 92 | exit 0 93 | ``` 94 | 95 | 96 | ### `$ bake install` 97 | 98 | ```console 99 | + Executing 'node-deps': 100 | yarn install v1.17.3 101 | [1/4] 🔍 Resolving packages... 102 | success Already up-to-date. 103 | ✨ Done in 0.03s. 104 | + Executing 'python-deps': 105 | Installing dependencies from Pipfile.lock (2ee04c)… 106 | 🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 8/8 — 00:00:01 107 | + Done. 108 | ``` 109 | 110 | 111 | ### `$ bake python-example KEY=VALUE 1 2 3` 112 | 113 | ```console 114 | + Executing 'python-argv': 115 | VALUE 116 | ['1', '2', '3'] 117 | + Done. 118 | ``` 119 | 120 | ### `$ bake dangerous-example` 121 | 122 | ```console 123 | + Executing '@confirm:secure' · 124 | What is 10 times 2?: 7 125 | Aborted. 126 | ``` 127 | 128 | ## Advanced Usage Sample 129 | 130 | ![advanced screenshot](https://github.com/kennethreitz/bake/blob/master/ext/screenshot.png?raw=true) 131 | 132 | Fancy, eh? 133 | 134 | 135 | 136 | --------------------- 137 | 138 |

139 | This repository has been brought to you, with much joy, by Kenneth Reitz. 140 |

141 | 142 | ![kr soul icon](https://github.com/kennethreitz/bake/blob/master/ext/tattoo-design.jpg?raw=true) 143 | 144 |

145 | As above, so below. 146 |

147 | -------------------------------------------------------------------------------- /contrib/bake-vscode/language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | // symbol used for single line comment. Remove this entry if your language does not support line comments 4 | "lineComment": "#" 5 | }, 6 | // symbols used as brackets 7 | "brackets": [ 8 | [ 9 | "{", 10 | "}" 11 | ], 12 | [ 13 | "[", 14 | "]" 15 | ], 16 | [ 17 | "(", 18 | ")" 19 | ] 20 | ], 21 | // symbols that are auto closed when typing 22 | "autoClosingPairs": [ 23 | [ 24 | "{", 25 | "}" 26 | ], 27 | [ 28 | "[", 29 | "]" 30 | ], 31 | [ 32 | "(", 33 | ")" 34 | ], 35 | [ 36 | "\"", 37 | "\"" 38 | ], 39 | [ 40 | "'", 41 | "'" 42 | ] 43 | ], 44 | // symbols that that can be used to surround a selection 45 | "surroundingPairs": [ 46 | [ 47 | "{", 48 | "}" 49 | ], 50 | [ 51 | "[", 52 | "]" 53 | ], 54 | [ 55 | "(", 56 | ")" 57 | ], 58 | [ 59 | "\"", 60 | "\"" 61 | ], 62 | [ 63 | "'", 64 | "'" 65 | ] 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /contrib/bake-vscode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bake", 3 | "displayName": "bake", 4 | "description": "Hilighting for Bake: a strangely familiar task runner.", 5 | "version": "0.0.1", 6 | "publisher": "kennethreitz", 7 | "repository": "https://github.com/kennethreitz/bake.git", 8 | "engines": { 9 | "vscode": "^1.38.0" 10 | }, 11 | "categories": [ 12 | "Programming Languages" 13 | ], 14 | "contributes": { 15 | "languages": [ 16 | { 17 | "id": "bakefile", 18 | "aliases": [ 19 | "Bakefile", 20 | "bakefile" 21 | ], 22 | "extensions": [ 23 | "Bakefile" 24 | ], 25 | "configuration": "./language-configuration.json" 26 | } 27 | ], 28 | "grammars": [ 29 | { 30 | "language": "bakefile", 31 | "scopeName": "source.bakefile", 32 | "path": "./syntaxes/Bakefile.syntax.json", 33 | "embeddedLanguages": { 34 | "task": "source.shell" 35 | } 36 | } 37 | ] 38 | }, 39 | "dependencies": { 40 | "generator-code": "^1.2.6", 41 | "vsce": "^1.66.0" 42 | }, 43 | "__metadata": { 44 | "id": "9c773cc4-328c-4e24-84c9-3cc5ba85b3d0", 45 | "publisherDisplayName": "kennethreitz", 46 | "publisherId": "7bf106b0-2ddb-49af-9b16-bbd0067cf5a9" 47 | } 48 | } -------------------------------------------------------------------------------- /contrib/bake-vscode/t.sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/contrib/bake-vscode/t.sh -------------------------------------------------------------------------------- /contrib/bake-vscode/vsc-extension-quickstart.md: -------------------------------------------------------------------------------- 1 | # Welcome to your VS Code Extension 2 | 3 | ## What's in the folder 4 | 5 | * This folder contains all of the files necessary for your extension. 6 | * `package.json` - this is the manifest file in which you declare your language support and define the location of the grammar file that has been copied into your extension. 7 | * `syntaxes/makefile.tmLanguage` - this is the Text mate grammar file that is used for tokenization. 8 | * `language-configuration.json` - this is the language configuration, defining the tokens that are used for comments and brackets. 9 | 10 | ## Get up and running straight away 11 | 12 | * Make sure the language configuration settings in `language-configuration.json` are accurate. 13 | * Press `F5` to open a new window with your extension loaded. 14 | * Create a new file with a file name suffix matching your language. 15 | * Verify that syntax highlighting works and that the language configuration settings are working. 16 | 17 | ## Make changes 18 | 19 | * You can relaunch the extension from the debug toolbar after making changes to the files listed above. 20 | * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. 21 | 22 | ## Add more language features 23 | 24 | * To add features such as intellisense, hovers and validators check out the VS Code extenders documentation at https://code.visualstudio.com/docs 25 | 26 | ## Install your extension 27 | 28 | * To start using your extension with Visual Studio Code copy it into the `/.vscode/extensions` folder and restart Code. 29 | * To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension. 30 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.4" 2 | 3 | services: 4 | core: 5 | image: kennethreitz/bake:core 6 | build: 7 | context: . 8 | dockerfile: ./docker/core.Dockerfile 9 | 10 | bake: 11 | image: kennethreitz/bake:${DOCKER_RELEASE:-latest} 12 | build: 13 | context: . 14 | dockerfile: ./docker/bake.Dockerfile 15 | depends_on: 16 | - core 17 | volumes: 18 | - .:/app 19 | 20 | red: 21 | image: kennethreitz/red:${DOCKER_RELEASE:-latest} 22 | build: 23 | context: . 24 | dockerfile: ./docker/red.Dockerfile 25 | depends_on: 26 | - core 27 | 28 | ci: 29 | image: kennethreitz/bake:ci 30 | build: 31 | context: . 32 | dockerfile: ./docker/ci.Dockerfile 33 | depends_on: 34 | - core 35 | volumes: 36 | - .:/app 37 | -------------------------------------------------------------------------------- /docker/bake.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM kennethreitz/bake:core 2 | 3 | ENV BAKEFILE_PATH /app/Bakefile 4 | 5 | # -- Install latest Bake. 6 | RUN set -ex && \ 7 | pip3 install bake-cli --upgrade --quiet > /dev/null 8 | 9 | # -- Really slim down that image. 10 | RUN set -ex && \ 11 | rm -fr /var/lib/apt/lists 12 | 13 | # -- Copy Bakefile of depending Dockerfiles. 14 | ONBUILD COPY ./Bakefile /app/Bakefile 15 | 16 | # -- Copy the application over. 17 | ONBUILD COPY . /app 18 | 19 | ENTRYPOINT [ "bake" ] 20 | -------------------------------------------------------------------------------- /docker/ci.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM kennethreitz/bake:core 2 | 3 | ENV TERM xterm 4 | 5 | # -- Install CI deps. 6 | RUN set -ex && \ 7 | apt-get update -qq && \ 8 | apt-get install expect npm docker.io docker-compose zlib1g-dev libxml-libxml-perl libxml-generator-perl -y -qq >/dev/null && \ 9 | apt-get clean -y -qq && \ 10 | apt-get autoclean -y -qq && \ 11 | apt-get clean -y -qq && \ 12 | apt-get autoclean -y -qq && \ 13 | # -- Really slim down that image. 14 | rm -fr /var/lib/apt/lists/* 15 | 16 | # -- Copy in tap2junit plugin. 17 | COPY ./docker/scripts/tap2xml /usr/local/bin/tap2xml 18 | 19 | RUN cpan 20 | # -- Install latest Bake. 21 | RUN set -ex && \ 22 | pip3 install bake-cli --upgrade --quiet > /dev/null 23 | 24 | # -- Install BATS. 25 | RUN set -ex && npm install -g bats > /dev/null 26 | 27 | ENTRYPOINT [ "bash" ] 28 | -------------------------------------------------------------------------------- /docker/core.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3-slim-buster 2 | 3 | # Tell Ubuntu to not prompt during apt installs. 4 | ARG DEBIAN_FRONTEND='noninteractive' 5 | 6 | # -- Setup mirrors, for faster downloads (main sources can be *very* slow sometimes). 7 | COPY ./docker/scripts/use-mirrors.sh /opt/use-mirrors.sh 8 | RUN set -ex && \ 9 | /opt/use-mirrors.sh && \ 10 | rm -fr /opt/use-mirrors.sh 11 | 12 | # -- System dependencies + common utilities. 13 | RUN set -ex && \ 14 | apt-get update -qq && \ 15 | apt-get upgrade -y -qq && \ 16 | apt-get install curl git -y -qq --no-install-recommends >/dev/null && \ 17 | apt-get clean -y -qq && \ 18 | apt-get autoclean -y -qq 19 | 20 | # -- Install Pipenv. 21 | RUN set -ex && \ 22 | pip3 install pipenv --quiet --no-cache 2>/dev/null 23 | 24 | # -- Home directory. 25 | RUN set -ex && \ 26 | mkdir /app 27 | 28 | WORKDIR /app 29 | 30 | ENTRYPOINT [ "bash" ] 31 | -------------------------------------------------------------------------------- /docker/red.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM kennethreitz/bake:core 2 | 3 | # -- Install latest Bake. 4 | RUN set -ex && \ 5 | pip3 install bake-cli --upgrade --quiet > /dev/null 6 | 7 | # -- Really slim down that image. 8 | RUN set -ex && \ 9 | rm -fr /var/lib/apt/lists 10 | 11 | ENTRYPOINT [ "red" ] 12 | -------------------------------------------------------------------------------- /docker/scripts/use-mirrors.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SOURCES_LIST='/etc/apt/sources.list' 4 | 5 | 6 | # deb http://snapshot.debian.org/archive/debian/20190910T000000Z buster main 7 | echo 'deb https://mirror.math.princeton.edu/pub/debian buster main' > ${SOURCES_LIST} 8 | # deb http://snapshot.debian.org/archive/debian-security/20190910T000000Z buster/updates main 9 | echo 'deb http://security.debian.org/debian-security buster/updates main' >> ${SOURCES_LIST} 10 | # deb http://snapshot.debian.org/archive/debian/20190910T000000Z buster-updates main 11 | echo 'deb http://deb.debian.org/debian buster-updates main' >> ${SOURCES_LIST} 12 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /docs/.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Build documentation in the docs/ directory with Sphinx 8 | sphinx: 9 | configuration: docs/docs_site/conf.py 10 | 11 | # Build documentation with MkDocs 12 | #mkdocs: 13 | # configuration: mkdocs.yml 14 | 15 | # Optionally build your docs in additional formats such as PDF and ePub 16 | formats: all 17 | 18 | # Optionally set the version of Python and requirements required to build your docs 19 | python: 20 | version: 3.7 21 | install: 22 | - requirements: docs/requirements.txt 23 | -------------------------------------------------------------------------------- /docs/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.pythonPath": "venv/bin/python3" 3 | } -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Bake Documentation 2 | 3 | ## Status: Under development 4 | ## To Do: 5 | * ~~**Respect & maintain Kenneth Reitz's consistency and don't make the docs look ugly**~~ 6 | 7 | * ~~Make the docs site up and running with Sphinx~~ 8 | * ~~Add installation instruction~~ 9 | * Deploy v0.1.0 10 | * Turn the Sphinx site builder's `Makefile` into a `Bakefile` and add that as an example 11 | * Automate flask template via `Bakefile` 12 | * Automate hugo blog deployment with `Bakefile` 13 | * Find out more awesome examples 14 | -------------------------------------------------------------------------------- /docs/docs_site/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/docs_site/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/docs_site/_build/doctrees/files/basic_usage.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/doctrees/files/basic_usage.doctree -------------------------------------------------------------------------------- /docs/docs_site/_build/doctrees/files/faqs.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/doctrees/files/faqs.doctree -------------------------------------------------------------------------------- /docs/docs_site/_build/doctrees/files/installation.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/doctrees/files/installation.doctree -------------------------------------------------------------------------------- /docs/docs_site/_build/doctrees/files/practical_examples.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/doctrees/files/practical_examples.doctree -------------------------------------------------------------------------------- /docs/docs_site/_build/doctrees/files/quickstart.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/doctrees/files/quickstart.doctree -------------------------------------------------------------------------------- /docs/docs_site/_build/doctrees/files/some.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/doctrees/files/some.doctree -------------------------------------------------------------------------------- /docs/docs_site/_build/doctrees/files/terminal_tricks.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/doctrees/files/terminal_tricks.doctree -------------------------------------------------------------------------------- /docs/docs_site/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/docs_site/_build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: bdca5955648a0cd028e7478308f123b6 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_sources/files/basic_usage.md.txt: -------------------------------------------------------------------------------- 1 | Basic Usage 2 | ================ 3 | 4 | In a typical workflow, **Bakefile** lives in the **root** directory of your project and you should be running **bake** command from the same directory. Bakefiles contain information regarding the tasks that you want to accomplish. A task is basically an assortment of bash commands which can be anything from a simple one liner to a uber complicated hierarchical workflow with multiple subtasks. Each task has to follow a specific structure. 5 | 6 | .. code-block:: bash 7 | TASKNAME/SUBTASKNAME : [OPTIONS] [TASK] [ARGUMENTS] 8 | BASH_COMMAND_GOES_HERE 9 | 10 | **Bake is space aware. Use four spaces to indent in the appropriate positions.** 11 | 12 | Task without Subtasks 13 | ------------------------ 14 | 15 | Here is a simple example of a Bakefile containing a single task. 16 | 17 | .. code-block:: bash 18 | 19 | # Bakefile 20 | 21 | task1: 22 | 23 | # print a Rambrant quote 24 | echo "“Painting is the grandchild of Nature.” 25 | 26 | ― Rembrandt Van Rijn" 27 | 28 | To run this task, type: 29 | 30 | .. code-block:: bash 31 | 32 | $ bake task1 33 | 34 | You terminal should print something like this: 35 | 36 | .. code-block:: bash 37 | 38 | + Executing task1: 39 | | “Painting is the grandchild of Nature.” 40 | | ― Rembrandt Van Rijn 41 | + Done. 42 | 43 | 44 | Task with Subtasks 45 | ----------------------------- 46 | 47 | Subtasks can be defined via `task/subtask` format. You can also use `task//subtask` format to define subtasks. Nested subtasks can be defined as `task/subtask/subsubtask` format. Bake runs the tasks in order agnostic way. So,it doesn't matter whether the tasks or subtasks are defined before or after main task. For example: 48 | 49 | .. code-block:: bash 50 | 51 | # Bakefile 52 | 53 | # task with subtasks 54 | task2: task2/subtask1 task2//subtask2 55 | 56 | # subtasks 57 | task2/subtask1: 58 | # print a Vinci quote 59 | echo "“Nothing strengthens authority so much as silence.” 60 | 61 | - Leonardo Da Vinci" 62 | 63 | task2//subtask2: 64 | # print a Gogh quote 65 | echo "“Art is to console those who are broken by life.” 66 | 67 | - Vincent van Gogh" 68 | 69 | 70 | You can choose to run individual subtasks or all the tasks at the same time. To run a subtask, run: 71 | 72 | .. code-block:: bash 73 | 74 | $ bake task2/subtask1 75 | 76 | .. code-block:: bash 77 | 78 | + Executing task2/subtask1: 79 | | “Nothing strengthens authority so much as silence.” 80 | | - Leonardo Da Vinci 81 | + Done. 82 | 83 | Or you can run all the subtasks simultaneously by calling the primary task. To run all the subtasks under `task2`, run: 84 | 85 | .. code-block:: bash 86 | $ bake task2 87 | 88 | .. code-block:: bash 89 | 90 | + Executing task2/subtask1: 91 | | “Nothing strengthens authority so much as silence.” 92 | | - Leonardo Da Vinci 93 | + Executing task2//subtask2: 94 | | “Art is to console those who are broken by life.” 95 | | - Vincent van Gogh 96 | + Executing task2: 97 | + Done. 98 | 99 | Task with Arguments 100 | ----------------------- 101 | 102 | Arguments can be easily passed to the task in `bake taskname arg1 arg2 ...` format 103 | 104 | .. code-block:: bash 105 | 106 | # Bakefile 107 | 108 | # task with argument 109 | task3/subtask1: 110 | # take any number of integers and return their sum 111 | num1=$1 112 | num2=$2 113 | ((sum=num1 + num2)) 114 | echo "Sum of $1 & $2 is $sum" 115 | 116 | Run the task via: 117 | 118 | .. code-block:: bash 119 | 120 | $ bake task3/subtask1 1 2 121 | 122 | You should see the output in the terminal: 123 | 124 | .. code-block:: bash 125 | 126 | + Executing task3/subtask1: 127 | | Sum of 1 & 2 is 3 128 | + Done. 129 | 130 | Task with Confirmation Prompt 131 | ------------------------------- 132 | 133 | You can fire a confirmation prompt before running a task via `taskname:@confirm`. 134 | 135 | .. code-block:: bash 136 | 137 | # Bakefile 138 | 139 | # task with confirmation prompt 140 | task4/subtask1:@confirm 141 | echo "Performing ls command..." 142 | echo "" 143 | echo "Files in your current folder:" 144 | ls 145 | 146 | Run the command via: 147 | .. code-block:: bash 148 | 149 | $ bake task4/subtask1 150 | 151 | The output should be (depends where you run the command): 152 | 153 | .. code-block:: bash 154 | 155 | ? Do you want to continue? [y/N]: y 156 | + Executing task4/subtask1: 157 | | Performing ls command 158 | | 159 | | Files in your current folder: 160 | | Bakefile 161 | | faqs.md 162 | | installation.md 163 | | quickstart.md 164 | + Done. 165 | 166 | Task with Interactive Prompts 167 | -------------------------------- 168 | 169 | If you want to show interactive prompts (normally bake supresses them) of the underlying `Bash` commands, you can do so using `taskname:@interactive` format. For example: 170 | 171 | .. code-block:: bash 172 | 173 | # Bakefile 174 | 175 | # take username and password and echo them out 176 | task5:@interactive 177 | read -p 'Username: ' username 178 | read -sp 'Password: ' password 179 | echo 180 | echo "" 181 | echo "Username is $username" 182 | echo "Password is $password" 183 | 184 | Defining the task in this way will let you interact with the underlying prompts. Run the task: 185 | 186 | .. code-block:: bash 187 | 188 | $ bake task5 189 | 190 | This will let out the underlying interactive prompts. 191 | 192 | .. code-block:: bash 193 | 194 | + Executing task5: 195 | Username: rednafi 196 | Password: 197 | 198 | Username is rednafi 199 | Password is rembrandt 200 | + Done. 201 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_sources/files/faqs.md.txt: -------------------------------------------------------------------------------- 1 | # Frequently Asked Questions 2 | * RecursionError: 3 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_sources/files/installation.md.txt: -------------------------------------------------------------------------------- 1 | Installation 2 | ================ 3 | 4 | For Local Development 5 | ---------------------- 6 | 7 | ------------------------------------------- 8 | Various *nix Distributions (Python 3.6+) 9 | ------------------------------------------- 10 | 11 | 12 | The primary installation method of `bake` , today, is via `pip` : 13 | 14 | .. code-block:: bash 15 | 16 | $ pip3 install bake-cli 17 | 18 | 19 | This will always work, but it will not be the default recommendation. 20 | 21 | ------------------------------------ 22 | MacOS (Previously known as OS X) 23 | ------------------------------------ 24 | 25 | Installation of bake will (soon) be very easy, with Homebrew. The formula needs a subtle adjustment — if you want to help, `here's the repo! `_ 26 | 27 | .. code-block:: bash 28 | 29 | $ brew install kennethreitz/-/bake 30 | 31 | 32 | 33 | For Production Environment 34 | --------------------------- 35 | You an also run `bake` via Docker! An official image has been made available on `DockerHub. `_ 36 | 37 | 38 | .. code-block:: bash 39 | 40 | $ docker run kennethreitz/bake 41 | 42 | * Bakefile is expected to live at `/app/Bakefile`. 43 | If you inherit from this image, ONBUILD directives will automatically copy your application code (build context) into the container, into /app. 44 | 45 | * Bonus Points: this image is also available on the `GitHub Package Registry `_ (beta). 46 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_sources/files/practical_examples.md.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_sources/files/practical_examples.md.txt -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_sources/files/quickstart.md.txt: -------------------------------------------------------------------------------- 1 | Quickstart 2 | ================ 3 | 4 | In a typical workflow, **Bakefile** lives in the **root** directory of your project and you should be running **bake** command from the same directory. Bakefiles contain information regarding the tasks that you want to accomplish. A task is basically an assortment of bash commands which can be anything from a simple one liner to a uber complicated hierarchical workflow with multiple subtasks. Each task has to follow a specific structure. 5 | 6 | .. code-block:: bash 7 | TASKNAME/SUBTASKNAME : [OPTIONS] [TASK] [ARGUMENTS] 8 | BASH_COMMAND_GOES_HERE 9 | 10 | **Bake is space aware. Use four spaces to indent in the appropriate positions.** 11 | 12 | Task without Subtasks 13 | ------------------------ 14 | 15 | Here is a simple example of a Bakefile containing a single task. 16 | 17 | .. code-block:: bash 18 | 19 | # Bakefile 20 | 21 | task1: 22 | 23 | # print a Rambrant quote 24 | echo "“Painting is the grandchild of Nature.” 25 | 26 | ― Rembrandt Van Rijn" 27 | 28 | To run this task, type: 29 | 30 | .. code-block:: bash 31 | 32 | bake task1 33 | 34 | You terminal should print something like this: 35 | 36 | .. code-block:: bash 37 | 38 | + Executing task1: 39 | | “Painting is the grandchild of Nature.” 40 | | ― Rembrandt Van Rijn 41 | + Done. 42 | 43 | 44 | Task with Subtasks 45 | ----------------------------- 46 | Subtasks can be defined via `task/subtask` format. You can also use `task//subtask` format to define subtasks. For example: 47 | 48 | .. code-block:: bash 49 | 50 | # Bakefile 51 | 52 | # task with subtasks 53 | task2: task2/subtask1 task2//subtask2 54 | 55 | # subtasks 56 | task2/subtask1: 57 | # print a Vinci quote 58 | echo "“Nothing strengthens authority so much as silence.” 59 | 60 | - Leonardo Da Vinci" 61 | 62 | task2//subtask2: 63 | # print a Gogh quote 64 | echo "“Art is to console those who are broken by life.” 65 | 66 | - Vincent van Gogh" 67 | 68 | 69 | You can choose to run individual subtasks or all the tasks at the same time. To run a subtask, run: 70 | 71 | .. code-block:: bash 72 | 73 | bake task2/subtask1 74 | 75 | .. code-block:: bash 76 | 77 | + Executing task2/subtask1: 78 | | “Nothing strengthens authority so much as silence.” 79 | | - Leonardo Da Vinci 80 | + Done. 81 | 82 | Or you can run all the subtasks simultaneously by calling the primary task. To all subtasks under `task2`, run: 83 | 84 | .. code-block:: bash 85 | bake task2 86 | 87 | .. code-block:: bash 88 | 89 | + Executing task2/subtask1: 90 | | “Nothing strengthens authority so much as silence.” 91 | | - Leonardo Da Vinci 92 | + Executing task2//subtask2: 93 | | “Art is to console those who are broken by life.” 94 | | - Vincent van Gogh 95 | + Executing task2: 96 | + Done. 97 | 98 | Task with Arguments 99 | ----------------------- 100 | 101 | Arguments can be easily passed to the task in `bake taskname arg1 arg2 ...` format 102 | 103 | .. code-block:: bash 104 | 105 | # Bakefile 106 | 107 | # task with argument 108 | task3/subtask1: 109 | # take any number of integers and return their sum 110 | num1=$1 111 | num2=$2 112 | ((sum=num1 + num2)) 113 | echo "Sum of $1 & $2 is $sum" 114 | 115 | Run the task via: 116 | 117 | .. code-block:: bash 118 | 119 | bake task3/subtask1 1 2 120 | 121 | You should see the output in the terminal: 122 | 123 | .. code-block:: bash 124 | 125 | + Executing task3/subtask1: 126 | | Sum of 1 & 2 is 3 127 | + Done. 128 | 129 | Task with Confirmation Prompt 130 | ------------------------------- 131 | 132 | You can fire a confirmation prompt before running a task using `taskname:@confirm` format. 133 | 134 | .. code-block:: bash 135 | 136 | # Bakefile 137 | 138 | # task with confirmation prompt 139 | task4/subtask1:@confirm 140 | echo "Performing ls command..." 141 | echo "" 142 | echo "Files in your current folder:" 143 | ls 144 | 145 | The output should be (depends where you run the command): 146 | 147 | .. code-block:: bash 148 | 149 | ? Do you want to continue? [y/N]: y 150 | + Executing task4/subtask1: 151 | | Performing ls command 152 | | 153 | | Files in your current folder: 154 | | Bakefile 155 | | faqs.md 156 | | installation.md 157 | | quickstart.md 158 | + Done. 159 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_sources/files/some.md.txt: -------------------------------------------------------------------------------- 1 | Some 2 | ============ 3 | 4 | .. code-block:: bash 5 | 6 | echo "o" 7 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_sources/files/terminal_tricks.md.txt: -------------------------------------------------------------------------------- 1 | A Few Terminal Tricks 2 | ================================ 3 | 4 | Viewing the Task Names 5 | -------------------------- 6 | 7 | Running `bake` on the terminal will bring up all the tasks inside the `Bakefile`. 8 | 9 | .. code-block:: bash 10 | 11 | $ bake 12 | 13 | It could show you something like this: 14 | 15 | .. code-block:: bash 16 | 17 | - task1 18 | - task2… 19 | + task2/subtask1. 20 | - task2/subtask1 21 | - task3/subtask1 22 | - task4/subtask1 23 | - task5/subtask1 24 | - task6/subtask1 25 | - task6/subtask2 26 | - task6… 27 | + task6/subtask1 & task6/subtask2. 28 | 29 | 30 | Specifiying Task Levels 31 | ----------------------------- 32 | 33 | You can also specify the task level up to which you want to see your task list on the terminal. To do this, run: 34 | 35 | .. code-block:: bash 36 | 37 | $ bake --levels 2 38 | 39 | This should show more nested subtasks (if there are any). 40 | 41 | .. code-block:: bash 42 | - task1 43 | - task2… 44 | + task2/subtask1 & task2//subtask2. 45 | - task2/subtask1 46 | - task3/subtask1 47 | - task4/subtask1 48 | - task5/subtask1 49 | - task6/subtask1 50 | - task6/subtask2 51 | - task6… 52 | + task6/subtask1 & task6/subtask2. 53 | Note: 1 more tasks are available. Please use $ bake --levels 3 to see more. 54 | 55 | 56 | Viewing The Tasks as JSON 57 | ------------------------------ 58 | 59 | To view the tasks as JSON upto a specific level, run: 60 | 61 | .. code-block:: bash 62 | 63 | $ bake --json --levels 2 64 | 65 | The output should look something like this: 66 | 67 | .. code-block:: bash 68 | 69 | { 70 | "tasks": { 71 | "task1": { 72 | "depends_on": [] 73 | }, 74 | "task2": { 75 | "depends_on": [ 76 | "task2/subtask1", 77 | "task2//subtask2" 78 | ] 79 | }, 80 | "task2/subtask1": { 81 | "depends_on": [] 82 | 83 | .... 84 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_sources/index.md.txt: -------------------------------------------------------------------------------- 1 | .. Bake documentation master file, created by 2 | sphinx-quickstart on Fri Nov 15 16:18:46 2019. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | **Bake**: The s☿rangely familiar workflow utility 🍳 7 | ================================================= 8 | 9 | **Bake** helps you write task automation scripts like **GNU Make** but instead of fiddling with GNU Make's complicated rules and syntax, you get to do it in pure **Bash**. Just like Make's **Makefile** and **make** command, Bake has **Bakefile** and **bake** command. 10 | 11 | In a typical project workflow, the `Bakefile` most often resides in the same directory as the other source files for the project. You can have many different `Bakefiles` on your machine at any one time. In fact, if you have a large project, you may choose to manage it using separate `Bakefiles` for different parts of the project. The combination of `bake` command, `Bakefile` and the familiar bash syntax provides a very powerful tool for managing projects and automating repetitive tasks. It can not only be used to control the compilation of source code, but also to prepare manual pages and to install the application into a target directory. 12 | 13 | 14 | What's in the oven? 📦 15 | ------------------------ 16 | 17 | * A **Bakefile**, which looks and feels like the good parts of a **Makefile**. 18 | * Except, you can write real `bash` code! (Any and all syntax is accepted — no magic going on here.) 19 | * Unlike **Makefile**, you may utilize **[ 4 × U+0020 a.k.a. “spaces”]** for indentation. 20 | * Environment variables are explicitly passed or whitelisted (--allow), not inherited from the parent shell. 21 | * Tasks can be run safely and reliably. Rest assured that scripts are executed from the project root directory. 22 | * There are many other benefits to this design, that have yet to be expressed in this document. 23 | 24 | Table of Contents 📕 25 | -------------------------- 26 | .. toctree:: 27 | :maxdepth: 3 28 | :glob: 29 | 30 | files/installation 31 | files/basic_usage 32 | files/terminal_tricks 33 | 34 | 35 | Indices & Tables ⚙️ 36 | ---------------------- 37 | 38 | * :ref:`genindex` 39 | * :ref:`modindex` 40 | * :ref:`search` 41 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/ajax-loader.gif -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/comment-bright.png -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/comment-close.png -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/comment.png -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/custom.css: -------------------------------------------------------------------------------- 1 | /* This file intentionally left blank. */ 2 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | }; 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s === 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * highlight a given string on a jquery object by wrapping it in 66 | * span elements with the given class name. 67 | */ 68 | jQuery.fn.highlightText = function(text, className) { 69 | function highlight(node, addItems) { 70 | if (node.nodeType === 3) { 71 | var val = node.nodeValue; 72 | var pos = val.toLowerCase().indexOf(text); 73 | if (pos >= 0 && 74 | !jQuery(node.parentNode).hasClass(className) && 75 | !jQuery(node.parentNode).hasClass("nohighlight")) { 76 | var span; 77 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); 78 | if (isInSVG) { 79 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 80 | } else { 81 | span = document.createElement("span"); 82 | span.className = className; 83 | } 84 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 85 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 86 | document.createTextNode(val.substr(pos + text.length)), 87 | node.nextSibling)); 88 | node.nodeValue = val.substr(0, pos); 89 | if (isInSVG) { 90 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); 91 | var bbox = node.parentElement.getBBox(); 92 | rect.x.baseVal.value = bbox.x; 93 | rect.y.baseVal.value = bbox.y; 94 | rect.width.baseVal.value = bbox.width; 95 | rect.height.baseVal.value = bbox.height; 96 | rect.setAttribute('class', className); 97 | addItems.push({ 98 | "parent": node.parentNode, 99 | "target": rect}); 100 | } 101 | } 102 | } 103 | else if (!jQuery(node).is("button, select, textarea")) { 104 | jQuery.each(node.childNodes, function() { 105 | highlight(this, addItems); 106 | }); 107 | } 108 | } 109 | var addItems = []; 110 | var result = this.each(function() { 111 | highlight(this, addItems); 112 | }); 113 | for (var i = 0; i < addItems.length; ++i) { 114 | jQuery(addItems[i].parent).before(addItems[i].target); 115 | } 116 | return result; 117 | }; 118 | 119 | /* 120 | * backward compatibility for jQuery.browser 121 | * This will be supported until firefox bug is fixed. 122 | */ 123 | if (!jQuery.browser) { 124 | jQuery.uaMatch = function(ua) { 125 | ua = ua.toLowerCase(); 126 | 127 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 128 | /(webkit)[ \/]([\w.]+)/.exec(ua) || 129 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 130 | /(msie) ([\w.]+)/.exec(ua) || 131 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 132 | []; 133 | 134 | return { 135 | browser: match[ 1 ] || "", 136 | version: match[ 2 ] || "0" 137 | }; 138 | }; 139 | jQuery.browser = {}; 140 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 141 | } 142 | 143 | /** 144 | * Small JavaScript module for the documentation. 145 | */ 146 | var Documentation = { 147 | 148 | init : function() { 149 | this.fixFirefoxAnchorBug(); 150 | this.highlightSearchWords(); 151 | this.initIndexTable(); 152 | if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { 153 | this.initOnKeyListeners(); 154 | } 155 | }, 156 | 157 | /** 158 | * i18n support 159 | */ 160 | TRANSLATIONS : {}, 161 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, 162 | LOCALE : 'unknown', 163 | 164 | // gettext and ngettext don't access this so that the functions 165 | // can safely bound to a different name (_ = Documentation.gettext) 166 | gettext : function(string) { 167 | var translated = Documentation.TRANSLATIONS[string]; 168 | if (typeof translated === 'undefined') 169 | return string; 170 | return (typeof translated === 'string') ? translated : translated[0]; 171 | }, 172 | 173 | ngettext : function(singular, plural, n) { 174 | var translated = Documentation.TRANSLATIONS[singular]; 175 | if (typeof translated === 'undefined') 176 | return (n == 1) ? singular : plural; 177 | return translated[Documentation.PLURALEXPR(n)]; 178 | }, 179 | 180 | addTranslations : function(catalog) { 181 | for (var key in catalog.messages) 182 | this.TRANSLATIONS[key] = catalog.messages[key]; 183 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 184 | this.LOCALE = catalog.locale; 185 | }, 186 | 187 | /** 188 | * add context elements like header anchor links 189 | */ 190 | addContextElements : function() { 191 | $('div[id] > :header:first').each(function() { 192 | $('\u00B6'). 193 | attr('href', '#' + this.id). 194 | attr('title', _('Permalink to this headline')). 195 | appendTo(this); 196 | }); 197 | $('dt[id]').each(function() { 198 | $('\u00B6'). 199 | attr('href', '#' + this.id). 200 | attr('title', _('Permalink to this definition')). 201 | appendTo(this); 202 | }); 203 | }, 204 | 205 | /** 206 | * workaround a firefox stupidity 207 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 208 | */ 209 | fixFirefoxAnchorBug : function() { 210 | if (document.location.hash && $.browser.mozilla) 211 | window.setTimeout(function() { 212 | document.location.href += ''; 213 | }, 10); 214 | }, 215 | 216 | /** 217 | * highlight the search words provided in the url in the text 218 | */ 219 | highlightSearchWords : function() { 220 | var params = $.getQueryParameters(); 221 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 222 | if (terms.length) { 223 | var body = $('div.body'); 224 | if (!body.length) { 225 | body = $('body'); 226 | } 227 | window.setTimeout(function() { 228 | $.each(terms, function() { 229 | body.highlightText(this.toLowerCase(), 'highlighted'); 230 | }); 231 | }, 10); 232 | $('') 234 | .appendTo($('#searchbox')); 235 | } 236 | }, 237 | 238 | /** 239 | * init the domain index toggle buttons 240 | */ 241 | initIndexTable : function() { 242 | var togglers = $('img.toggler').click(function() { 243 | var src = $(this).attr('src'); 244 | var idnum = $(this).attr('id').substr(7); 245 | $('tr.cg-' + idnum).toggle(); 246 | if (src.substr(-9) === 'minus.png') 247 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 248 | else 249 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 250 | }).css('display', ''); 251 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 252 | togglers.click(); 253 | } 254 | }, 255 | 256 | /** 257 | * helper function to hide the search marks again 258 | */ 259 | hideSearchWords : function() { 260 | $('#searchbox .highlight-link').fadeOut(300); 261 | $('span.highlighted').removeClass('highlighted'); 262 | }, 263 | 264 | /** 265 | * make the url absolute 266 | */ 267 | makeURL : function(relativeURL) { 268 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 269 | }, 270 | 271 | /** 272 | * get the current relative url 273 | */ 274 | getCurrentURL : function() { 275 | var path = document.location.pathname; 276 | var parts = path.split(/\//); 277 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 278 | if (this === '..') 279 | parts.pop(); 280 | }); 281 | var url = parts.join('/'); 282 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 283 | }, 284 | 285 | initOnKeyListeners: function() { 286 | $(document).keyup(function(event) { 287 | var activeElementType = document.activeElement.tagName; 288 | // don't navigate when in search box or textarea 289 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { 290 | switch (event.keyCode) { 291 | case 37: // left 292 | var prevHref = $('link[rel="prev"]').prop('href'); 293 | if (prevHref) { 294 | window.location.href = prevHref; 295 | return false; 296 | } 297 | case 39: // right 298 | var nextHref = $('link[rel="next"]').prop('href'); 299 | if (nextHref) { 300 | window.location.href = nextHref; 301 | return false; 302 | } 303 | } 304 | } 305 | }); 306 | } 307 | }; 308 | 309 | // quick alias for translations 310 | _ = Documentation.gettext; 311 | 312 | $(document).ready(function() { 313 | Documentation.init(); 314 | }); 315 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: '', 4 | LANGUAGE: 'None', 5 | COLLAPSE_INDEX: false, 6 | FILE_SUFFIX: '.html', 7 | HAS_SOURCE: true, 8 | SOURCELINK_SUFFIX: '.txt', 9 | NAVIGATION_WITH_KEYS: false 10 | }; -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/down-pressed.png -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/down.png -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/file.png -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/language_data.js: -------------------------------------------------------------------------------- 1 | /* 2 | * language_data.js 3 | * ~~~~~~~~~~~~~~~~ 4 | * 5 | * This script contains the language-specific data used by searchtools.js, 6 | * namely the list of stopwords, stemmer, scorer and splitter. 7 | * 8 | * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. 9 | * :license: BSD, see LICENSE for details. 10 | * 11 | */ 12 | 13 | var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; 14 | 15 | 16 | /* Non-minified version JS is _stemmer.js if file is provided */ 17 | /** 18 | * Porter Stemmer 19 | */ 20 | var Stemmer = function() { 21 | 22 | var step2list = { 23 | ational: 'ate', 24 | tional: 'tion', 25 | enci: 'ence', 26 | anci: 'ance', 27 | izer: 'ize', 28 | bli: 'ble', 29 | alli: 'al', 30 | entli: 'ent', 31 | eli: 'e', 32 | ousli: 'ous', 33 | ization: 'ize', 34 | ation: 'ate', 35 | ator: 'ate', 36 | alism: 'al', 37 | iveness: 'ive', 38 | fulness: 'ful', 39 | ousness: 'ous', 40 | aliti: 'al', 41 | iviti: 'ive', 42 | biliti: 'ble', 43 | logi: 'log' 44 | }; 45 | 46 | var step3list = { 47 | icate: 'ic', 48 | ative: '', 49 | alize: 'al', 50 | iciti: 'ic', 51 | ical: 'ic', 52 | ful: '', 53 | ness: '' 54 | }; 55 | 56 | var c = "[^aeiou]"; // consonant 57 | var v = "[aeiouy]"; // vowel 58 | var C = c + "[^aeiouy]*"; // consonant sequence 59 | var V = v + "[aeiou]*"; // vowel sequence 60 | 61 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 62 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 63 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 64 | var s_v = "^(" + C + ")?" + v; // vowel in stem 65 | 66 | this.stemWord = function (w) { 67 | var stem; 68 | var suffix; 69 | var firstch; 70 | var origword = w; 71 | 72 | if (w.length < 3) 73 | return w; 74 | 75 | var re; 76 | var re2; 77 | var re3; 78 | var re4; 79 | 80 | firstch = w.substr(0,1); 81 | if (firstch == "y") 82 | w = firstch.toUpperCase() + w.substr(1); 83 | 84 | // Step 1a 85 | re = /^(.+?)(ss|i)es$/; 86 | re2 = /^(.+?)([^s])s$/; 87 | 88 | if (re.test(w)) 89 | w = w.replace(re,"$1$2"); 90 | else if (re2.test(w)) 91 | w = w.replace(re2,"$1$2"); 92 | 93 | // Step 1b 94 | re = /^(.+?)eed$/; 95 | re2 = /^(.+?)(ed|ing)$/; 96 | if (re.test(w)) { 97 | var fp = re.exec(w); 98 | re = new RegExp(mgr0); 99 | if (re.test(fp[1])) { 100 | re = /.$/; 101 | w = w.replace(re,""); 102 | } 103 | } 104 | else if (re2.test(w)) { 105 | var fp = re2.exec(w); 106 | stem = fp[1]; 107 | re2 = new RegExp(s_v); 108 | if (re2.test(stem)) { 109 | w = stem; 110 | re2 = /(at|bl|iz)$/; 111 | re3 = new RegExp("([^aeiouylsz])\\1$"); 112 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 113 | if (re2.test(w)) 114 | w = w + "e"; 115 | else if (re3.test(w)) { 116 | re = /.$/; 117 | w = w.replace(re,""); 118 | } 119 | else if (re4.test(w)) 120 | w = w + "e"; 121 | } 122 | } 123 | 124 | // Step 1c 125 | re = /^(.+?)y$/; 126 | if (re.test(w)) { 127 | var fp = re.exec(w); 128 | stem = fp[1]; 129 | re = new RegExp(s_v); 130 | if (re.test(stem)) 131 | w = stem + "i"; 132 | } 133 | 134 | // Step 2 135 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 136 | if (re.test(w)) { 137 | var fp = re.exec(w); 138 | stem = fp[1]; 139 | suffix = fp[2]; 140 | re = new RegExp(mgr0); 141 | if (re.test(stem)) 142 | w = stem + step2list[suffix]; 143 | } 144 | 145 | // Step 3 146 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 147 | if (re.test(w)) { 148 | var fp = re.exec(w); 149 | stem = fp[1]; 150 | suffix = fp[2]; 151 | re = new RegExp(mgr0); 152 | if (re.test(stem)) 153 | w = stem + step3list[suffix]; 154 | } 155 | 156 | // Step 4 157 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 158 | re2 = /^(.+?)(s|t)(ion)$/; 159 | if (re.test(w)) { 160 | var fp = re.exec(w); 161 | stem = fp[1]; 162 | re = new RegExp(mgr1); 163 | if (re.test(stem)) 164 | w = stem; 165 | } 166 | else if (re2.test(w)) { 167 | var fp = re2.exec(w); 168 | stem = fp[1] + fp[2]; 169 | re2 = new RegExp(mgr1); 170 | if (re2.test(stem)) 171 | w = stem; 172 | } 173 | 174 | // Step 5 175 | re = /^(.+?)e$/; 176 | if (re.test(w)) { 177 | var fp = re.exec(w); 178 | stem = fp[1]; 179 | re = new RegExp(mgr1); 180 | re2 = new RegExp(meq1); 181 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 182 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 183 | w = stem; 184 | } 185 | re = /ll$/; 186 | re2 = new RegExp(mgr1); 187 | if (re.test(w) && re2.test(w)) { 188 | re = /.$/; 189 | w = w.replace(re,""); 190 | } 191 | 192 | // and turn initial Y back to y 193 | if (firstch == "y") 194 | w = firstch.toLowerCase() + w.substr(1); 195 | return w; 196 | } 197 | } 198 | 199 | 200 | 201 | 202 | 203 | var splitChars = (function() { 204 | var result = {}; 205 | var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, 206 | 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, 207 | 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, 208 | 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, 209 | 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, 210 | 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, 211 | 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, 212 | 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, 213 | 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, 214 | 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; 215 | var i, j, start, end; 216 | for (i = 0; i < singles.length; i++) { 217 | result[singles[i]] = true; 218 | } 219 | var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], 220 | [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], 221 | [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], 222 | [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], 223 | [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], 224 | [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], 225 | [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], 226 | [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], 227 | [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], 228 | [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], 229 | [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], 230 | [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], 231 | [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], 232 | [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], 233 | [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], 234 | [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], 235 | [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], 236 | [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], 237 | [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], 238 | [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], 239 | [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], 240 | [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], 241 | [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], 242 | [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], 243 | [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], 244 | [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], 245 | [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], 246 | [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], 247 | [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], 248 | [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], 249 | [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], 250 | [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], 251 | [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], 252 | [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], 253 | [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], 254 | [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], 255 | [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], 256 | [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], 257 | [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], 258 | [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], 259 | [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], 260 | [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], 261 | [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], 262 | [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], 263 | [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], 264 | [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], 265 | [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], 266 | [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], 267 | [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; 268 | for (i = 0; i < ranges.length; i++) { 269 | start = ranges[i][0]; 270 | end = ranges[i][1]; 271 | for (j = start; j <= end; j++) { 272 | result[j] = true; 273 | } 274 | } 275 | return result; 276 | })(); 277 | 278 | function splitQuery(query) { 279 | var result = []; 280 | var start = -1; 281 | for (var i = 0; i < query.length; i++) { 282 | if (splitChars[query.charCodeAt(i)]) { 283 | if (start !== -1) { 284 | result.push(query.slice(start, i)); 285 | start = -1; 286 | } 287 | } else if (start === -1) { 288 | start = i; 289 | } 290 | } 291 | if (start !== -1) { 292 | result.push(query.slice(start)); 293 | } 294 | return result; 295 | } 296 | 297 | 298 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/plus.png -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #eeffcc; } 3 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ 8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 9 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ 11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic } /* Generic.Emph */ 15 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 18 | .highlight .go { color: #333333 } /* Generic.Output */ 19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 28 | .highlight .kt { color: #902000 } /* Keyword.Type */ 29 | .highlight .m { color: #208050 } /* Literal.Number */ 30 | .highlight .s { color: #4070a0 } /* Literal.String */ 31 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 32 | .highlight .nb { color: #007020 } /* Name.Builtin */ 33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 34 | .highlight .no { color: #60add5 } /* Name.Constant */ 35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 37 | .highlight .ne { color: #007020 } /* Name.Exception */ 38 | .highlight .nf { color: #06287e } /* Name.Function */ 39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */ 46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 50 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */ 51 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 52 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 53 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ 54 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 55 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 56 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 57 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 58 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 59 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 60 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 61 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 62 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 63 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 64 | .highlight .fm { color: #06287e } /* Name.Function.Magic */ 65 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 66 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 67 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 68 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ 69 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/underscore.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.3.1 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c, 10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each= 11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a== 12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= 13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e= 14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a, 17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}}; 24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments, 25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)}; 26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"}; 27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a), 28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+ 29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]= 30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain= 31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 32 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/up-pressed.png -------------------------------------------------------------------------------- /docs/docs_site/_build/html/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/_static/up.png -------------------------------------------------------------------------------- /docs/docs_site/_build/html/files/faqs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <no title> — Bake documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 | 32 | 33 |
34 | 35 |

# Frequently Asked Questions 36 | * RecursionError:

37 | 38 | 39 |
40 | 41 |
42 |
43 | 89 |
90 |
91 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/files/installation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Installation — Bake documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 | 32 | 33 |
34 | 35 |
36 |

Installation

37 |
38 |

For Local Development

39 |
40 |

Various *nix Distributions (Python 3.6+)

41 |

The primary installation method of bake , today, is via pip :

42 |
$ pip3 install bake-cli
 43 | 
44 |
45 |

This will always work, but it will not be the default recommendation.

46 |
47 |
48 |

MacOS (Previously known as OS X)

49 |

Installation of bake will (soon) be very easy, with Homebrew. The formula needs a subtle adjustment — if you want to help, here’s the repo!

50 |
$ brew install kennethreitz/-/bake
 51 | 
52 |
53 |
54 |
55 |
56 |

For Production Environment

57 |

You an also run bake via Docker! An official image has been made available on DockerHub.

58 |
$ docker run kennethreitz/bake
 59 | 
60 |
61 |
    62 |
  • Bakefile is expected to live at /app/Bakefile.

  • 63 |
64 |

If you inherit from this image, ONBUILD directives will automatically copy your application code (build context) into the container, into /app.

65 | 68 |
69 |
70 | 71 | 72 |
73 | 74 |
75 |
76 | 130 |
131 |
132 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/files/practical_examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <no title> — Bake documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 |
29 | 30 | 31 |
32 | 33 | 34 | 35 |
36 | 37 |
38 |
39 | 84 |
85 |
86 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/files/quickstart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Quickstart — Bake documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 | 31 | 32 |
33 | 34 |
35 |

Quickstart

36 |

In a typical workflow, Bakefile lives in the root directory of your project and you should be running bake command from the same directory. Bakefiles contain information regarding the tasks that you want to accomplish. A task is basically an assortment of bash commands which can be anything from a simple one liner to a uber complicated hierarchical workflow with multiple subtasks. Each task has to follow a specific structure.

37 |

Bake is space aware. Use four spaces to indent in the appropriate positions.

38 |
39 |

Task without Subtasks

40 |

Here is a simple example of a Bakefile containing a single task.

41 |
# Bakefile
 42 | 
 43 | task1:
 44 | 
 45 | # print a Rambrant quote
 46 | echo "“Painting is the grandchild of Nature.”
 47 | 
 48 | ― Rembrandt Van Rijn"
 49 | 
50 |
51 |

To run this task, type:

52 |
bake task1
 53 | 
54 |
55 |

You terminal should print something like this:

56 |
+ Executing task1:
 57 | |  “Painting is the grandchild of Nature.”
 58 | |  ― Rembrandt Van Rijn
 59 | + Done.
 60 | 
61 |
62 |
63 |
64 |

Task with Subtasks

65 |

Subtasks can be defined via task/subtask format. You can also use task//subtask format to define subtasks. For example:

66 |
# Bakefile
 67 | 
 68 | # task with subtasks
 69 | task2: task2/subtask1 task2//subtask2
 70 | 
 71 | # subtasks
 72 | task2/subtask1:
 73 |     # print a Vinci quote
 74 |     echo "“Nothing strengthens authority so much as silence.”
 75 | 
 76 |     - Leonardo Da Vinci"
 77 | 
 78 | task2//subtask2:
 79 |     # print a Gogh quote
 80 |     echo "“Art is to console those who are broken by life.”
 81 | 
 82 |     - Vincent van Gogh"
 83 | 
84 |
85 |

You can choose to run individual subtasks or all the tasks at the same time. To run a subtask, run:

86 |
bake task2/subtask1
 87 | 
88 |
89 |
+ Executing task2/subtask1:
 90 | |  “Nothing strengthens authority so much as silence.”
 91 | |  - Leonardo Da Vinci
 92 | + Done.
 93 | 
94 |
95 |

Or you can run all the subtasks simultaneously by calling the primary task. To all subtasks under task2, run:

96 |
+ Executing task2/subtask1:
 97 | |  “Nothing strengthens authority so much as silence.”
 98 | |  - Leonardo Da Vinci
 99 | + Executing task2//subtask2:
100 | |  “Art is to console those who are broken by life.”
101 | |  - Vincent van Gogh
102 | + Executing task2:
103 | + Done.
104 | 
105 |
106 |
107 |
108 |

Task with Arguments

109 |

Arguments can be easily passed to the task in bake taskname arg1 arg2 … format

110 |
# Bakefile
111 | 
112 | # task with argument
113 | task3/subtask1:
114 |     # take any number of integers and return their sum
115 |     num1=$1
116 |     num2=$2
117 |     ((sum=num1 + num2))
118 |     echo "Sum of $1 & $2 is $sum"
119 | 
120 |
121 |

Run the task via:

122 |
bake task3/subtask1 1 2
123 | 
124 |
125 |

You should see the output in the terminal:

126 |
+ Executing task3/subtask1:
127 | |  Sum of 1 & 2 is 3
128 | + Done.
129 | 
130 |
131 |
132 |
133 |

Task with Confirmation Prompt

134 |

You can fire a confirmation prompt before running a task using taskname:@confirm format.

135 |
# Bakefile
136 | 
137 | # task with confirmation prompt
138 | task4/subtask1:@confirm
139 |     echo "Performing ls command..."
140 |     echo ""
141 |     echo "Files in your current folder:"
142 |     ls
143 | 
144 |
145 |

The output should be (depends where you run the command):

146 |
? Do you want to continue? [y/N]: y
147 | + Executing task4/subtask1:
148 | |  Performing ls command
149 | |
150 | |  Files in your current folder:
151 | |  Bakefile
152 | |  faqs.md
153 | |  installation.md
154 | |  quickstart.md
155 | + Done.
156 | 
157 |
158 |
159 |
160 | 161 | 162 |
163 | 164 |
165 |
166 | 217 |
218 |
219 | 230 | 231 | 232 | 233 | 234 | 235 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/files/some.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Some — Bake documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 |
32 | 33 | 34 |
35 | 36 |
37 |

Some

38 |
echo "o"
 39 | 
40 |
41 |
42 | 43 | 44 |
45 | 46 |
47 |
48 | 95 |
96 |
97 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/files/terminal_tricks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | A Few Terminal Tricks — Bake documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 | 31 | 32 |
33 | 34 |
35 |

A Few Terminal Tricks

36 |
37 |

Viewing the Task Names

38 |

Running bake on the terminal will bring up all the tasks inside the Bakefile.

39 |
$ bake
 40 | 
41 |
42 |

It could show you something like this:

43 |
- task1
 44 | - task2…
 45 |     + task2/subtask1.
 46 | - task2/subtask1
 47 | - task3/subtask1
 48 | - task4/subtask1
 49 | - task5/subtask1
 50 | - task6/subtask1
 51 | - task6/subtask2
 52 | - task6…
 53 |     + task6/subtask1 & task6/subtask2.
 54 | 
55 |
56 |
57 |
58 |

Specifiying Task Levels

59 |

You can also specify the task level up to which you want to see your task list on the terminal. To do this, run:

60 |
$ bake --levels 2
 61 | 
62 |
63 |

This should show more nested subtasks (if there are any).

64 |

Note: 1 more tasks are available. Please use $ bake –levels 3 to see more.

65 |
66 |
67 |

Viewing The Tasks as JSON

68 |

To view the tasks as JSON upto a specific level, run:

69 |
$ bake --json --levels 2
 70 | 
71 |
72 |

The output should look something like this:

73 |
{
 74 | "tasks": {
 75 |     "task1": {
 76 |     "depends_on": []
 77 |     },
 78 |     "task2": {
 79 |     "depends_on": [
 80 |         "task2/subtask1",
 81 |         "task2//subtask2"
 82 |     ]
 83 |     },
 84 |     "task2/subtask1": {
 85 |     "depends_on": []
 86 | 
 87 |     ....
 88 | 
89 |
90 |
91 |
92 | 93 | 94 |
95 | 96 |
97 |
98 | 149 |
150 |
151 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/genindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Index — Bake documentation 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 | 31 | 32 |
33 | 34 | 35 |

Index

36 | 37 |
38 | 39 |
40 | 41 | 42 |
43 | 44 |
45 |
46 | 91 |
92 |
93 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Bake: The s☿rangely familiar workflow utility 🍳 — Bake documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 | 31 | 32 |
33 | 34 |
35 |

Bake: The s☿rangely familiar workflow utility 🍳

36 |

Bake helps you write task automation scripts like GNU Make but instead of fiddling with GNU Make’s complicated rules and syntax, you get to do it in pure Bash. Just like Make’s Makefile and make command, Bake has Bakefile and bake command.

37 |

In a typical project workflow, the Bakefile most often resides in the same directory as the other source files for the project. You can have many different Bakefiles on your machine at any one time. In fact, if you have a large project, you may choose to manage it using separate Bakefiles for different parts of the project. The combination of bake command, Bakefile and the familiar bash syntax provides a very powerful tool for managing projects and automating repetitive tasks. It can not only be used to control the compilation of source code, but also to prepare manual pages and to install the application into a target directory.

38 |
39 |

What’s in the oven? 📦

40 |
    41 |
  • A Bakefile, which looks and feels like the good parts of a Makefile.

  • 42 |
  • Except, you can write real bash code! (Any and all syntax is accepted — no magic going on here.)

  • 43 |
  • Unlike Makefile, you may utilize [ 4 × U+0020 a.k.a. “spaces”] for indentation.

  • 44 |
  • Environment variables are explicitly passed or whitelisted (–allow), not inherited from the parent shell.

  • 45 |
  • Tasks can be run safely and reliably. Rest assured that scripts are executed from the project root directory.

  • 46 |
  • There are many other benefits to this design, that have yet to be expressed in this document.

  • 47 |
48 |
49 | 79 |
80 |

Indices & Tables ⚙️

81 | 86 |
87 |
88 | 89 | 90 |
91 | 92 |
93 |
94 | 140 |
141 |
142 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/_build/html/objects.inv -------------------------------------------------------------------------------- /docs/docs_site/_build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Search — Bake documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 | 35 | 36 |
37 | 38 |

Search

39 |
40 | 41 |

42 | Please activate JavaScript to enable the search 43 | functionality. 44 |

45 |
46 |

47 | From here you can search these documents. Enter your search 48 | words into the box below and click "search". Note that the search 49 | function will automatically search for all of the words. Pages 50 | containing fewer words won't appear in the result list. 51 |

52 |
53 | 54 | 55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 |
63 | 64 |
65 |
66 | 101 |
102 |
103 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /docs/docs_site/_build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["files/basic_usage","files/faqs","files/installation","files/practical_examples","files/terminal_tricks","index"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,sphinx:56},filenames:["files/basic_usage.md","files/faqs.md","files/installation.md","files/practical_examples.md","files/terminal_tricks.md","index.md"],objects:{},objnames:{},objtypes:{},terms:{"05s":[],"default":2,"export":[],"return":0,"while":[],For:[0,5],The:[0,2],There:5,Use:0,accept:5,accomplish:0,adjust:2,after:0,agnost:0,all:[0,4,5],allow:5,also:[0,2,4,5],alwai:2,angel:[],ani:[0,4,5],anyth:0,app:2,applic:[2,5],appropri:0,arg1:0,arg2:0,argument:5,argv:[],aribitrari:[],art:0,ask:1,assort:0,assur:5,author:0,autom:5,automat:2,avail:[2,4],awar:0,bake:[0,2,4],bakefil:[0,2,4,5],bash:[0,5],basic:5,been:2,befor:0,benefit:5,beta:2,black:[],block:0,bonu:2,brew:2,bring:4,broken:0,build:2,call:0,can:[0,4,5],carv:[],cat:[],choos:[0,5],cli:2,code:[0,2,5],combin:5,command:[0,5],compil:5,complic:[0,5],confirm:5,consol:0,contain:[0,2],context:2,continu:0,control:5,copi:2,could:4,current:0,defin:0,depend:0,depends_on:4,deploi:[],design:5,develop:5,differ:5,direct:2,directori:[0,5],distribut:5,docker:2,dockerhub:2,document:5,doesn:0,done:0,each:0,easi:2,easili:0,echo:0,environ:5,etch:[],exampl:0,except:5,excess:[],execut:[0,5],exit:[],expect:2,explain:[],explicitli:5,express:5,face:[],fact:5,faq:0,feel:5,fetch:[],few:5,fiddl:5,file:[0,5],fire:0,folder:0,follow:0,format:0,formula:2,found:[],four:0,free:[],frequent:1,fresh:[],from:[0,2,5],full:[],get:5,github:2,gnu:5,gogh:0,going:5,good:5,grandchild:0,grow:[],has:[0,2,5],have:5,heart:[],hello:[],help:[2,5],here:[0,2,5],hierarch:0,him:[],homebrew:2,ignor:[],imag:2,indent:[0,5],index:5,individu:0,info:[],inform:0,inherit:[2,5],insid:4,instal:[0,5],instead:5,integ:0,interact:5,itself:[],json:5,just:5,kei:[],kennethreitz:2,kind:[],known:5,larg:5,leonardo:0,let:0,level:5,life:0,like:[0,4,5],liner:0,link:[],list:4,live:[0,2],local:5,lock:[],lockfil:[],look:[4,5],machin:5,maco:5,made:2,magic:5,mai:5,main:0,make:5,makefil:5,manag:5,mani:5,manual:5,marbl:[],matter:0,method:2,michelangelo:[],modul:5,moment:[],more:4,most:5,much:0,multipl:0,name:5,natur:0,need:2,nest:[0,4],nix:5,node:[],normal:0,note:4,noth:0,num1:0,num2:0,number:0,offici:2,often:5,older:[],onbuild:2,one:[0,5],onli:5,onto:[],order:0,other:5,our:[],out:0,output:[0,4],packag:2,page:5,paint:0,parent:5,part:5,pass:[0,5],password:0,perform:0,pip3:2,pip:2,pipenv:[],pipfil:[],pleas:4,point:2,posit:0,power:5,prepar:5,previous:5,primari:[0,2],print:0,product:5,project:[0,5],prompt:5,provid:5,pure:5,python:5,question:1,quickstart:0,quot:0,rambrant:0,ran:[],read:0,readi:[],real:5,recommend:2,recursionerror:1,rednafi:0,regard:0,registri:2,reliabl:5,rembrandt:0,repeat:[],repetit:5,repo:2,resid:5,resolv:[],rest:5,rijn:0,rins:[],root:[0,5],rule:5,run:[0,2,4,5],safe:5,same:[0,5],save:[],saw:[],script:5,search:5,secur:[],see:[0,4],seek:[],separ:5,set:[],shell:5,should:[0,4],show:[0,4],silenc:0,simpl:0,simultan:0,singl:0,skip:[],someth:[0,4],soon:2,sourc:5,space:[0,5],specif:[0,4],specifi:4,specifii:5,start:[],strengthen:0,string:[],strive:[],structur:0,subsubtask:0,subtask1:[0,4],subtask2:[0,4],subtask:[4,5],subtl:2,success:[],sum:0,supress:0,syntax:5,system:[],take:0,target:5,task1:[0,4],task2:[0,4],task3:[0,4],task4:[0,4],task5:[0,4],task6:4,task:5,tasknam:0,termin:[0,5],them:0,thi:[0,2,4,5],those:0,time:[0,5],todai:2,tool:5,trick:5,type:0,typic:[0,5],uber:0,under:0,underli:0,unlik:5,until:[],upto:4,usag:5,use:[0,4],used:5,usernam:0,using:[0,5],util:[],van:0,variabl:5,variou:5,veri:[2,5],via:[0,2],view:5,vincent:0,vinci:0,violenc:[],wai:0,want:[0,2,4],where:0,whether:0,which:[0,4,5],whitelist:5,who:0,without:5,work:2,workflow:0,write:5,yarn:[],yet:5,you:[0,2,4,5],your:[0,2,4,5]},titles:["Basic Usage","<no title>","Installation","<no title>","A Few Terminal Tricks","Bake: The s\u263frangely familiar workflow utility \ud83c\udf73"],titleterms:{"while":[],For:2,The:[4,5],argument:0,bake:5,basic:0,bootstrap:[],confirm:0,content:5,develop:2,distribut:2,environ:2,execut:[],familiar:5,few:4,ignor:[],indic:5,instal:2,interact:0,json:4,known:2,level:4,local:2,maco:2,multipl:[],name:4,nix:2,oven:5,previous:2,product:2,prompt:0,python:2,quickstart:[],rang:5,specifii:4,subtask:0,tabl:5,task:[0,4],termin:4,trick:4,usag:0,util:5,variou:2,view:4,what:5,without:0,workflow:5}}) -------------------------------------------------------------------------------- /docs/docs_site/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # import os 16 | # import sys 17 | # sys.path.insert(0, os.path.abspath('.')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = u'Bake' 23 | copyright = u'2019, Kenneth Reitz' 24 | author = u'Kenneth Reitz' 25 | 26 | # The short X.Y version 27 | version = u'' 28 | # The full version, including alpha/beta/rc tags 29 | release = u'' 30 | 31 | 32 | # -- General configuration --------------------------------------------------- 33 | 34 | # If your documentation needs a minimal Sphinx version, state it here. 35 | # 36 | # needs_sphinx = '1.0' 37 | 38 | # Add any Sphinx extension module names here, as strings. They can be 39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 40 | # ones. 41 | extensions = [ 42 | 'sphinx.ext.mathjax', 43 | ] 44 | 45 | # Add any paths that contain templates here, relative to this directory. 46 | templates_path = ['_templates'] 47 | 48 | # The suffix(es) of source filenames. 49 | # You can specify multiple suffix as a list of string: 50 | # 51 | # source_suffix = ['.rst', '.md'] 52 | source_suffix = '.md' 53 | 54 | # The master toctree document. 55 | master_doc = 'index' 56 | 57 | # The language for content autogenerated by Sphinx. Refer to documentation 58 | # for a list of supported languages. 59 | # 60 | # This is also used if you do content translation via gettext catalogs. 61 | # Usually you set "language" from the command line for these cases. 62 | language = None 63 | 64 | # List of patterns, relative to source directory, that match files and 65 | # directories to ignore when looking for source files. 66 | # This pattern also affects html_static_path and html_extra_path. 67 | exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store'] 68 | 69 | # The name of the Pygments (syntax highlighting) style to use. 70 | pygments_style = 'sphinx' 71 | 72 | 73 | # -- Options for HTML output ------------------------------------------------- 74 | 75 | # The theme to use for HTML and HTML Help pages. See the documentation for 76 | # a list of builtin themes. 77 | # 78 | html_theme = 'alabaster' 79 | 80 | # Theme options are theme-specific and customize the look and feel of a theme 81 | # further. For a list of options available for each theme, see the 82 | # documentation. 83 | # 84 | # html_theme_options = {} 85 | 86 | # Add any paths that contain custom static files (such as style sheets) here, 87 | # relative to this directory. They are copied after the builtin static files, 88 | # so a file named "default.css" will overwrite the builtin "default.css". 89 | html_static_path = ['_static'] 90 | 91 | # Custom sidebar templates, must be a dictionary that maps document names 92 | # to template names. 93 | # 94 | # The default sidebars (for documents that don't match any pattern) are 95 | # defined by theme itself. Builtin themes are using these templates by 96 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 97 | # 'searchbox.html']``. 98 | # 99 | # html_sidebars = {} 100 | 101 | 102 | # -- Options for HTMLHelp output --------------------------------------------- 103 | 104 | # Output file base name for HTML help builder. 105 | htmlhelp_basename = 'Bakedoc' 106 | 107 | 108 | # -- Options for LaTeX output ------------------------------------------------ 109 | 110 | latex_elements = { 111 | # The paper size ('letterpaper' or 'a4paper'). 112 | # 113 | # 'papersize': 'letterpaper', 114 | 115 | # The font size ('10pt', '11pt' or '12pt'). 116 | # 117 | # 'pointsize': '10pt', 118 | 119 | # Additional stuff for the LaTeX preamble. 120 | # 121 | # 'preamble': '', 122 | 123 | # Latex figure (float) alignment 124 | # 125 | # 'figure_align': 'htbp', 126 | } 127 | 128 | # Grouping the document tree into LaTeX files. List of tuples 129 | # (source start file, target name, title, 130 | # author, documentclass [howto, manual, or own class]). 131 | latex_documents = [ 132 | (master_doc, 'Bake.tex', u'Bake Documentation', 133 | u'Kenneth Reitz', 'manual'), 134 | ] 135 | 136 | 137 | # -- Options for manual page output ------------------------------------------ 138 | 139 | # One entry per manual page. List of tuples 140 | # (source start file, name, description, authors, manual section). 141 | man_pages = [ 142 | (master_doc, 'bake', u'Bake Documentation', 143 | [author], 1) 144 | ] 145 | 146 | 147 | # -- Options for Texinfo output ---------------------------------------------- 148 | 149 | # Grouping the document tree into Texinfo files. List of tuples 150 | # (source start file, target name, title, author, 151 | # dir menu entry, description, category) 152 | texinfo_documents = [ 153 | (master_doc, 'Bake', u'Bake Documentation', 154 | author, 'Bake', 'One line description of project.', 155 | 'Miscellaneous'), 156 | ] 157 | 158 | 159 | # -- Options for Epub output ------------------------------------------------- 160 | 161 | # Bibliographic Dublin Core info. 162 | epub_title = project 163 | 164 | # The unique identifier of the text. This can be a ISBN number 165 | # or the project homepage. 166 | # 167 | # epub_identifier = '' 168 | 169 | # A unique identification for the text. 170 | # 171 | # epub_uid = '' 172 | 173 | # A list of files that should not be packed into the epub file. 174 | epub_exclude_files = ['search.html'] 175 | 176 | 177 | # -- Extension configuration ------------------------------------------------- 178 | -------------------------------------------------------------------------------- /docs/docs_site/files/Bakefile: -------------------------------------------------------------------------------- 1 | # Bakefile 2 | task1: 3 | 4 | # print a Rambrant quote 5 | echo "“Painting is the grandchild of Nature.” 6 | 7 | ― Rembrandt Van Rijn" 8 | 9 | # task with subtasks 10 | task2: task2/subtask1 task2//subtask2 11 | 12 | # subtasks 13 | task2/subtask1: 14 | # print a Vinci quote 15 | echo "“Nothing strengthens authority so much as silence.” 16 | 17 | - Leonardo Da Vinci" 18 | 19 | task2//subtask2: 20 | # print a Gogh quote 21 | echo "“Art is to console those who are broken by life.” 22 | 23 | - Vincent van Gogh" 24 | 25 | # task with argument 26 | task3/subtask1: 27 | # take any number of integers and return their sum 28 | num1=$1 29 | num2=$2 30 | ((sum=num1 + num2)) 31 | echo "Sum of $1 & $2 is $sum" 32 | 33 | # confirmation prompt 34 | task4/subtask1:@confirm 35 | echo "Performing ls command..." 36 | echo "" 37 | echo "Files in your current folder:" 38 | ls 39 | 40 | 41 | # interactive task 42 | task5/subtask1:@interactive 43 | read -p 'Username: ' username 44 | read -sp 'Password: ' password 45 | echo 46 | echo "" 47 | echo "Username is $username" 48 | echo "Password is $password" 49 | 50 | # ignore tasks 51 | 52 | task6/subtask1: 53 | echo "“I saw the angel in the marble and carved until I set him free.” 54 | 55 | - Michelangelo" 56 | 57 | task6/subtask2:@skip:key=faqs.md 58 | echo "I ran out of quotes." 59 | 60 | task6: task6/subtask1 task6/subtask2 61 | -------------------------------------------------------------------------------- /docs/docs_site/files/basic_usage.md: -------------------------------------------------------------------------------- 1 | Basic Usage 2 | ================ 3 | 4 | In a typical workflow, **Bakefile** lives in the **root** directory of your project and you should be running **bake** command from the same directory. Bakefiles contain information regarding the tasks that you want to accomplish. A task is basically an assortment of bash commands which can be anything from a simple one liner to a uber complicated hierarchical workflow with multiple subtasks. Each task has to follow a specific structure. 5 | 6 | .. code-block:: bash 7 | TASKNAME/SUBTASKNAME : [OPTIONS] [TASK] [ARGUMENTS] 8 | BASH_COMMAND_GOES_HERE 9 | 10 | **Bake is space aware. Use four spaces to indent in the appropriate positions.** 11 | 12 | Task without Subtasks 13 | ------------------------ 14 | 15 | Here is a simple example of a Bakefile containing a single task. 16 | 17 | .. code-block:: bash 18 | 19 | # Bakefile 20 | 21 | task1: 22 | 23 | # print a Rambrant quote 24 | echo "“Painting is the grandchild of Nature.” 25 | 26 | ― Rembrandt Van Rijn" 27 | 28 | To run this task, type: 29 | 30 | .. code-block:: bash 31 | 32 | $ bake task1 33 | 34 | You terminal should print something like this: 35 | 36 | .. code-block:: bash 37 | 38 | + Executing task1: 39 | | “Painting is the grandchild of Nature.” 40 | | ― Rembrandt Van Rijn 41 | + Done. 42 | 43 | 44 | Task with Subtasks 45 | ----------------------------- 46 | 47 | Subtasks can be defined via `task/subtask` format. You can also use `task//subtask` format to define subtasks. Nested subtasks can be defined as `task/subtask/subsubtask` format. Bake runs the tasks in order agnostic way. So,it doesn't matter whether the tasks or subtasks are defined before or after the main task. For example: 48 | 49 | .. code-block:: bash 50 | 51 | # Bakefile 52 | 53 | # task with subtasks 54 | task2: task2/subtask1 task2//subtask2 55 | 56 | # subtasks 57 | task2/subtask1: 58 | # print a Vinci quote 59 | echo "“Nothing strengthens authority so much as silence.” 60 | 61 | - Leonardo Da Vinci" 62 | 63 | task2//subtask2: 64 | # print a Gogh quote 65 | echo "“Art is to console those who are broken by life.” 66 | 67 | - Vincent van Gogh" 68 | 69 | 70 | You can choose to run individual subtasks or all the tasks at the same time. To run a subtask, run: 71 | 72 | .. code-block:: bash 73 | 74 | $ bake task2/subtask1 75 | 76 | .. code-block:: bash 77 | 78 | + Executing task2/subtask1: 79 | | “Nothing strengthens authority so much as silence.” 80 | | - Leonardo Da Vinci 81 | + Done. 82 | 83 | Or you can run all the subtasks simultaneously by calling the primary task. To run all the subtasks under `task2`, run: 84 | 85 | .. code-block:: bash 86 | $ bake task2 87 | 88 | .. code-block:: bash 89 | 90 | + Executing task2/subtask1: 91 | | “Nothing strengthens authority so much as silence.” 92 | | - Leonardo Da Vinci 93 | + Executing task2//subtask2: 94 | | “Art is to console those who are broken by life.” 95 | | - Vincent van Gogh 96 | + Executing task2: 97 | + Done. 98 | 99 | Task with Arguments 100 | ----------------------- 101 | 102 | Arguments can be easily passed to the task in `bake taskname arg1 arg2 ...` format 103 | 104 | .. code-block:: bash 105 | 106 | # Bakefile 107 | 108 | # task with argument 109 | task3/subtask1: 110 | # take any number of integers and return their sum 111 | num1=$1 112 | num2=$2 113 | ((sum=num1 + num2)) 114 | echo "Sum of $1 & $2 is $sum" 115 | 116 | Run the task via: 117 | 118 | .. code-block:: bash 119 | 120 | $ bake task3/subtask1 1 2 121 | 122 | You should see the output in the terminal: 123 | 124 | .. code-block:: bash 125 | 126 | + Executing task3/subtask1: 127 | | Sum of 1 & 2 is 3 128 | + Done. 129 | 130 | Task with Confirmation Prompt 131 | ------------------------------- 132 | 133 | You can fire a confirmation prompt before running a task via `taskname:@confirm`. 134 | 135 | .. code-block:: bash 136 | 137 | # Bakefile 138 | 139 | # task with confirmation prompt 140 | task4/subtask1:@confirm 141 | echo "Performing ls command..." 142 | echo "" 143 | echo "Files in your current folder:" 144 | ls 145 | 146 | Run the command via: 147 | .. code-block:: bash 148 | 149 | $ bake task4/subtask1 150 | 151 | The output should be (depends where you run the command): 152 | 153 | .. code-block:: bash 154 | 155 | ? Do you want to continue? [y/N]: y 156 | + Executing task4/subtask1: 157 | | Performing ls command 158 | | 159 | | Files in your current folder: 160 | | Bakefile 161 | | faqs.md 162 | | installation.md 163 | | quickstart.md 164 | + Done. 165 | 166 | Task with Interactive Prompts 167 | -------------------------------- 168 | 169 | If you want to show interactive prompts (normally bake supresses them) of the underlying `Bash` commands, you can do so using `taskname:@interactive` format. For example: 170 | 171 | .. code-block:: bash 172 | 173 | # Bakefile 174 | 175 | # take username and password and echo them out 176 | task5:@interactive 177 | read -p 'Username: ' username 178 | read -sp 'Password: ' password 179 | echo 180 | echo "" 181 | echo "Username is $username" 182 | echo "Password is $password" 183 | 184 | Defining the task in this way will let you interact with the underlying prompts. Run the task: 185 | 186 | .. code-block:: bash 187 | 188 | $ bake task5 189 | 190 | This will let out the underlying interactive prompts. 191 | 192 | .. code-block:: bash 193 | 194 | + Executing task5: 195 | Username: rednafi 196 | Password: 197 | 198 | Username is rednafi 199 | Password is rembrandt 200 | + Done. 201 | -------------------------------------------------------------------------------- /docs/docs_site/files/faqs.md: -------------------------------------------------------------------------------- 1 | # Frequently Asked Questions 2 | * RecursionError: 3 | -------------------------------------------------------------------------------- /docs/docs_site/files/installation.md: -------------------------------------------------------------------------------- 1 | Installation 2 | ================ 3 | 4 | For Local Development 5 | ---------------------- 6 | 7 | ------------------------------------------- 8 | Various *nix Distributions (Python 3.6+) 9 | ------------------------------------------- 10 | 11 | 12 | The primary installation method of `bake` , today, is via `pip` : 13 | 14 | .. code-block:: bash 15 | 16 | $ pip3 install bake-cli 17 | 18 | 19 | This will always work, but it will not be the default recommendation. 20 | 21 | ------------------------------------ 22 | MacOS (Previously known as OS X) 23 | ------------------------------------ 24 | 25 | Installation of bake will (soon) be very easy, with Homebrew. The formula needs a subtle adjustment — if you want to help, `here's the repo! `_ 26 | 27 | .. code-block:: bash 28 | 29 | $ brew install kennethreitz/-/bake 30 | 31 | 32 | 33 | For Production Environment 34 | --------------------------- 35 | You an also run `bake` via Docker! An official image has been made available on `DockerHub. `_ 36 | 37 | 38 | .. code-block:: bash 39 | 40 | $ docker run kennethreitz/bake 41 | 42 | * Bakefile is expected to live at `/app/Bakefile`. 43 | If you inherit from this image, ONBUILD directives will automatically copy your application code (build context) into the container, into /app. 44 | 45 | * Bonus Points: this image is also available on the `GitHub Package Registry `_ (beta). 46 | -------------------------------------------------------------------------------- /docs/docs_site/files/practical_examples.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/docs/docs_site/files/practical_examples.md -------------------------------------------------------------------------------- /docs/docs_site/files/terminal_tricks.md: -------------------------------------------------------------------------------- 1 | A Few Terminal Tricks 2 | ================================ 3 | 4 | Viewing the Task Names 5 | -------------------------- 6 | 7 | Running `bake` on the terminal will bring up all the tasks inside the `Bakefile`. 8 | 9 | .. code-block:: bash 10 | 11 | $ bake 12 | 13 | It could show you something like this: 14 | 15 | .. code-block:: bash 16 | 17 | - task1 18 | - task2… 19 | + task2/subtask1. 20 | - task2/subtask1 21 | - task3/subtask1 22 | - task4/subtask1 23 | - task5/subtask1 24 | - task6/subtask1 25 | - task6/subtask2 26 | - task6… 27 | + task6/subtask1 & task6/subtask2. 28 | 29 | 30 | Specifiying Task Levels 31 | ----------------------------- 32 | 33 | You can also specify the task level up to which you want to see your task list on the terminal. To do this, run: 34 | 35 | .. code-block:: bash 36 | 37 | $ bake --levels 2 38 | 39 | This should show more nested subtasks (if there are any). 40 | 41 | .. code-block:: bash 42 | - task1 43 | - task2… 44 | + task2/subtask1 & task2//subtask2. 45 | - task2/subtask1 46 | - task3/subtask1 47 | - task4/subtask1 48 | - task5/subtask1 49 | - task6/subtask1 50 | - task6/subtask2 51 | - task6… 52 | + task6/subtask1 & task6/subtask2. 53 | Note: 1 more tasks are available. Please use $ bake --levels 3 to see more. 54 | 55 | 56 | Viewing The Tasks as JSON 57 | ------------------------------ 58 | 59 | To view the tasks as JSON upto a specific level, run: 60 | 61 | .. code-block:: bash 62 | 63 | $ bake --json --levels 2 64 | 65 | The output should look something like this: 66 | 67 | .. code-block:: bash 68 | 69 | { 70 | "tasks": { 71 | "task1": { 72 | "depends_on": [] 73 | }, 74 | "task2": { 75 | "depends_on": [ 76 | "task2/subtask1", 77 | "task2//subtask2" 78 | ] 79 | }, 80 | "task2/subtask1": { 81 | "depends_on": [] 82 | 83 | .... 84 | -------------------------------------------------------------------------------- /docs/docs_site/index.md: -------------------------------------------------------------------------------- 1 | .. Bake documentation master file, created by 2 | sphinx-quickstart on Fri Nov 15 16:18:46 2019. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | **Bake**: The s☿rangely familiar workflow utility 🍳 7 | ================================================= 8 | 9 | **Bake** helps you write task automation scripts like **GNU Make** but instead of fiddling with GNU Make's complicated rules and syntax, you get to do it in pure **Bash**. Just like Make's **Makefile** and **make** command, Bake has **Bakefile** and **bake** command. 10 | 11 | In a typical project workflow, the `Bakefile` most often resides in the same directory as the other source files for the project. You can have many different `Bakefiles` on your machine at any one time. In fact, if you have a large project, you may choose to manage it using separate `Bakefiles` for different parts of the project. The combination of `bake` command, `Bakefile` and the familiar bash syntax provides a very powerful tool for managing projects and automating repetitive tasks. It can not only be used to control the compilation of source code, but also to prepare manual pages and to install the application into a target directory. 12 | 13 | 14 | What's in the oven? 📦 15 | ------------------------ 16 | 17 | * A **Bakefile**, which looks and feels like the good parts of a **Makefile**. 18 | * Except, you can write real `bash` code! (Any and all syntax is accepted — no magic going on here.) 19 | * Unlike **Makefile**, you may utilize **[ 4 × U+0020 a.k.a. “spaces”]** for indentation. 20 | * Environment variables are explicitly passed or whitelisted (--allow), not inherited from the parent shell. 21 | * Tasks can be run safely and reliably. Rest assured that scripts are executed from the project root directory. 22 | * There are many other benefits to this design, that have yet to be expressed in this document. 23 | 24 | Table of Contents 📕 25 | -------------------------- 26 | .. toctree:: 27 | :maxdepth: 3 28 | :glob: 29 | 30 | files/installation 31 | files/basic_usage 32 | files/terminal_tricks 33 | 34 | 35 | Indices & Tables ⚙️ 36 | ---------------------- 37 | 38 | * :ref:`genindex` 39 | * :ref:`modindex` 40 | * :ref:`search` 41 | -------------------------------------------------------------------------------- /docs/docs_site/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx==2.2.1 2 | recommonmark=0.6.0 3 | -------------------------------------------------------------------------------- /examples/hidden-tasks/Bakefile: -------------------------------------------------------------------------------- 1 | shown: 2 | not//shown: 3 | # -- By default. 4 | # Show with bake --levels 3 5 | -------------------------------------------------------------------------------- /examples/reuse/Bakefile: -------------------------------------------------------------------------------- 1 | hello: hello/reuse hello/reuse/concurrent 2 | echo "You just ran $(red 'hello') directly, then indirectly (via bake+bash; 6 times, concurrently!)" 3 | hello/basic: 4 | sleep 2 5 | echo "[$(red $(uuidgen))] hello!" 6 | hello/reuse: 7 | bake hello/basic 8 | 9 | hello/reuse/concurrent: 10 | set -ex && \ 11 | bake hello/reuse & 12 | bake hello/reuse & 13 | bake hello/reuse & 14 | bake hello/reuse & 15 | bake hello/reuse & 16 | bake hello/reuse 17 | -------------------------------------------------------------------------------- /examples/stdlib/Bakefile: -------------------------------------------------------------------------------- 1 | TEXT='Hi, there!' 2 | 3 | echo: echo/normal echo/colors/red echo/colors/ansi-rainbow echo/indent 4 | 5 | echo/normal: 6 | echo "$TEXT" 7 | 8 | echo/colors/red: 9 | echo "$TEXT" | red 10 | 11 | echo/colors/ansi-rainbow: 12 | declare -a COLORS=('BLACK' 'WHITE' 'RED' 'GREEN' 'YELLOW' 'BLUE' 'PURPLE' 'CYAN') 13 | for COLOR in "${COLORS[@]}"; do 14 | echo "$TEXT" | bake_fg_color $COLOR 15 | done 16 | 17 | 18 | echo/indent: 19 | echo "$TEXT" | red | bake_indent '>' 20 | -------------------------------------------------------------------------------- /ext/bake.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/ext/bake.jpg -------------------------------------------------------------------------------- /ext/bake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/ext/bake.png -------------------------------------------------------------------------------- /ext/img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/ext/img.jpg -------------------------------------------------------------------------------- /ext/screencast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/ext/screencast.gif -------------------------------------------------------------------------------- /ext/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/ext/screenshot.png -------------------------------------------------------------------------------- /ext/ss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/ext/ss.png -------------------------------------------------------------------------------- /ext/tattoo-design.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/bake/27aa2ed38d21987fd9ec00b4664985ed767f91ec/ext/tattoo-design.jpg -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Note: To use the 'upload' functionality of this file, you must: 5 | # $ pipenv install twine --dev 6 | 7 | import io 8 | import os 9 | import sys 10 | from shutil import rmtree 11 | 12 | from setuptools import find_packages, setup, Command 13 | 14 | # Package meta-data. 15 | NAME = "bake-cli" 16 | DESCRIPTION = "The familar Make / Bash hybrid." 17 | URL = "https://github.com/kennethreitz/bake" 18 | EMAIL = "me@kennethreitz.org" 19 | AUTHOR = "Kenneth Reitz" 20 | REQUIRES_PYTHON = ">=3.6.0" 21 | VERSION = "0.12.0" 22 | 23 | # What packages are required for this module to be executed? 24 | REQUIRED = ["click", "delegator.py", "pygments", "networkx", "colorama"] 25 | 26 | # What packages are optional? 27 | EXTRAS = { 28 | # 'fancy feature': ['django'], 29 | } 30 | 31 | # The rest you shouldn't have to touch too much :) 32 | # ------------------------------------------------ 33 | # Except, perhaps the License and Trove Classifiers! 34 | # If you do change the License, remember to change the Trove Classifier for that! 35 | 36 | here = os.path.abspath(os.path.dirname(__file__)) 37 | 38 | # Import the README and use it as the long-description. 39 | # Note: this will only work if 'README.md' is present in your MANIFEST.in file! 40 | try: 41 | with io.open(os.path.join(here, "README.md"), encoding="utf-8") as f: 42 | long_description = "\n" + f.read() 43 | except FileNotFoundError: 44 | long_description = DESCRIPTION 45 | 46 | # Load the package's __version__.py module as a dictionary. 47 | about = {} 48 | if not VERSION: 49 | project_slug = NAME.lower().replace("-", "_").replace(" ", "_") 50 | with open(os.path.join(here, project_slug, "__version__.py")) as f: 51 | exec(f.read(), about) 52 | else: 53 | about["__version__"] = VERSION 54 | 55 | 56 | class UploadCommand(Command): 57 | """Support setup.py upload.""" 58 | 59 | description = "Build and publish the package." 60 | user_options = [] 61 | 62 | @staticmethod 63 | def status(s): 64 | """Prints things in bold.""" 65 | print("\033[1m{0}\033[0m".format(s)) 66 | 67 | def initialize_options(self): 68 | pass 69 | 70 | def finalize_options(self): 71 | pass 72 | 73 | def run(self): 74 | try: 75 | self.status("Removing previous builds…") 76 | rmtree(os.path.join(here, "dist")) 77 | except OSError: 78 | pass 79 | 80 | self.status("Building Source and Wheel (universal) distribution…") 81 | os.system("{0} setup.py sdist bdist_wheel --universal".format(sys.executable)) 82 | 83 | self.status("Pushing git tags…") 84 | os.system("git push --tags") 85 | 86 | self.status("Uploading the package to PyPI via Twine…") 87 | os.system("twine upload dist/*") 88 | 89 | sys.exit() 90 | 91 | 92 | # Where the magic happens: 93 | setup( 94 | name=NAME, 95 | version=about["__version__"], 96 | description=DESCRIPTION, 97 | long_description=long_description, 98 | long_description_content_type="text/markdown", 99 | author=AUTHOR, 100 | author_email=EMAIL, 101 | python_requires=REQUIRES_PYTHON, 102 | url=URL, 103 | packages=find_packages(exclude=["tests", "*.tests", "*.tests.*", "tests.*"]), 104 | # If your package is a single module, use this instead of 'packages': 105 | # py_modules=['mypackage'], 106 | entry_points={ 107 | "console_scripts": [ 108 | "bake=bake.cli:entrypoint", 109 | "red=bake.scripts.red:entrypoint", 110 | "notred=bake.scripts.notred:entrypoint", 111 | "bake_indent=bake.scripts.indent:entrypoint", 112 | "bake_step=bake.scripts.step:entrypoint", 113 | ] 114 | }, 115 | install_requires=REQUIRED, 116 | extras_require=EXTRAS, 117 | include_package_data=True, 118 | license="MIT", 119 | classifiers=[ 120 | # Trove classifiers 121 | # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers 122 | "License :: OSI Approved :: MIT License", 123 | "Programming Language :: Python", 124 | "Programming Language :: Python :: 3", 125 | "Programming Language :: Python :: 3.6", 126 | "Programming Language :: Python :: 3.7", 127 | "Programming Language :: Python :: Implementation :: CPython", 128 | "Programming Language :: Python :: Implementation :: PyPy", 129 | ], 130 | # $ setup.py publish support. 131 | cmdclass={"upload": UploadCommand}, 132 | ) 133 | -------------------------------------------------------------------------------- /tests/_common.sh: -------------------------------------------------------------------------------- 1 | timeout() { 2 | time=$1 3 | command="/bin/sh -c \"$2\"" 4 | 5 | expect -c "set echo \"-noecho\"; set timeout $time; spawn -noecho $command; expect timeout { exit 0 } eof { exit 1 }" 6 | 7 | } 8 | export timeout 9 | -------------------------------------------------------------------------------- /tests/args.Bakefile: -------------------------------------------------------------------------------- 1 | argv: 2 | set -u 3 | echo "${@}" 4 | echo "${KEY}" 5 | -------------------------------------------------------------------------------- /tests/args.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | export BAKEFILE=args.Bakefile 3 | 4 | @test "arguments don't work (set -u)" { 5 | run bake argv 6 | [ "${status}" -eq 1 ] 7 | } 8 | 9 | @test "arguments do work [argv]" { 10 | run bake --silent argv 1 2 KEY=VALUE 3 11 | [[ "${lines[0]}" == *"1 2 3"* ]] 12 | } 13 | 14 | 15 | @test "arguments do work [environ]" { 16 | run bake --silent argv 1 2 KEY=VALUE 3 17 | [[ "${lines[1]}" == *"VALUE"* ]] 18 | } 19 | -------------------------------------------------------------------------------- /tests/basics.Bakefile: -------------------------------------------------------------------------------- 1 | //two: 2 | one/two/three/four: 3 | one/two/: 4 | 5 | echo: 6 | echo ${1} 7 | 8 | echo/dep: dep 9 | bake echo ${1} | red 10 | 11 | dep: 12 | echo 'Installing dep…' 13 | exit 0 14 | 15 | fail: 16 | exit 1 17 | 18 | deps/fail: fail 19 | -------------------------------------------------------------------------------- /tests/basics.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | export BAKEFILE=basics.Bakefile 4 | 5 | @test "bake --h" { 6 | run bake --help 7 | [ "${lines[0]}" = "Usage: [OPTIONS] [TASK] [ARGUMENTS]..." ] 8 | } 9 | 10 | @test "bake --help" { 11 | run bake --help 12 | [ "${lines[0]}" = "Usage: [OPTIONS] [TASK] [ARGUMENTS]..." ] 13 | } 14 | 15 | @test "bake --json" { 16 | run bake --json 17 | [ "${#lines[@]}" -eq 23 ] 18 | } 19 | 20 | @test "bake --json --levels 0" { 21 | run bake --json --levels 0 22 | [ "${#lines[@]}" -eq 3 ] 23 | } 24 | 25 | @test "bake --levels 0" { 26 | run bake --levels 0 27 | [ "${lines[0]}" = "" ] 28 | } 29 | 30 | @test "bake --levels 1" { 31 | run bake --levels 1 32 | [ "${#lines[@]}" -eq 4 ] 33 | } 34 | 35 | @test "bake --levels 2" { 36 | run bake --levels 3 37 | [ "${#lines[@]}" -eq 10 ] 38 | } 39 | 40 | @test "bake --levels 3" { 41 | run bake --levels 3 42 | [ "${#lines[@]}" -eq 10 ] 43 | } 44 | 45 | @test "bake --levels 4" { 46 | run bake --levels 4 47 | [ "${#lines[@]}" -eq 10 ] 48 | } 49 | 50 | 51 | @test "bake fails on 'exit 1'" { 52 | run bake fail 53 | [ "${status}" -eq 1 ] 54 | } 55 | 56 | @test "bake fails on sub–task 'exit 1'" { 57 | run bake deps/fail 58 | [ "${status}" -eq 1 ] 59 | } 60 | 61 | @test "bake runs tasks" { 62 | run bake -b basics.Bakefile echo 63 | [ "${status}" -eq 0 ] 64 | } 65 | 66 | @test "bake runs sub-tasks" { 67 | run bake echo/dep 68 | [ "${status}" -eq 0 ] 69 | } 70 | 71 | @test "bake --no-deps" { 72 | run bake deps/fail --no-deps 73 | [ "${status}" -eq 0 ] 74 | } 75 | -------------------------------------------------------------------------------- /tests/cache.Bakefile: -------------------------------------------------------------------------------- 1 | task: skipme 2 | exit 0 3 | skipme: @skip:key=cache.Bakefile 4 | exit 0 5 | -------------------------------------------------------------------------------- /tests/cache.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | export BAKEFILE=cache.Bakefile 4 | 5 | @test "skips clear" { 6 | bake --clear-skips 7 | } 8 | 9 | @test "cache runs" { 10 | run bake task 11 | [[ $output != *Skipping* ]] 12 | } 13 | 14 | @test "cache skips" { 15 | run bake task 16 | [[ $output == *Skipping* ]] 17 | } 18 | 19 | @test "skip skips" { 20 | run bake --no-deps task 21 | [[ $output != *Skipping* ]] 22 | } 23 | -------------------------------------------------------------------------------- /tests/confirm.Bakefile: -------------------------------------------------------------------------------- 1 | secure: @confirm 2 | exit 0 3 | 4 | secure/real: @confirm:secure 5 | exit 1 6 | -------------------------------------------------------------------------------- /tests/confirm.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | export BAKEFILE=confirm.Bakefile 3 | source ./_common.sh 4 | 5 | @test "confirm works" { 6 | timeout 1 "bake -b confirm.Bakefile secure" 7 | } 8 | 9 | @test "confirm --yes works" { 10 | bake secure --yes 11 | } 12 | 13 | @test "confirm:secure works" { 14 | timeout 1 "bake -b confirm.Bakefile secure/real" 15 | } 16 | 17 | @test "confirm:secure --yes don't work" { 18 | timeout 1 "bake -b confirm.Bakefile secure/real --yes" 19 | } 20 | -------------------------------------------------------------------------------- /tests/env.Bakefile: -------------------------------------------------------------------------------- 1 | env: 2 | env 3 | -------------------------------------------------------------------------------- /tests/env.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | export BAKEFILE=env.Bakefile 3 | export HELLO=WORLD 4 | 5 | 6 | @test "env cache clear" { 7 | bake --clear-envs env 8 | } 9 | 10 | 11 | @test "removal of environment untrusted variables" { 12 | run bake env 13 | [[ "${output}" != *HELLO=WORLD* ]] 14 | } 15 | 16 | 17 | @test "allowance of environment untrusted variables" { 18 | run bake --allow HELLO 19 | run bake env 20 | [[ "${output}" == *"WORLD"* ]] 21 | } 22 | -------------------------------------------------------------------------------- /tests/include.Bakefile: -------------------------------------------------------------------------------- 1 | include included1.Bakefile included2.Bakefile 2 | 3 | include: included1 included2 included3 4 | -------------------------------------------------------------------------------- /tests/include.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | export BAKEFILE=include.Bakefile 3 | 4 | @test "test include first file" { 5 | run bake --silent included1 6 | [[ "${lines[0]}" == "Included1" ]] 7 | } 8 | 9 | @test "test include second file" { 10 | run bake --silent included2 11 | [[ "${lines[0]}" == "Included2" ]] 12 | } 13 | 14 | @test "test include of a included file" { 15 | run bake --silent included3 16 | [[ "${lines[0]}" == "Included3" ]] 17 | } 18 | 19 | @test "test task with dependencies as includes" { 20 | run bake --silent include 21 | [[ "${lines[0]}" == "Included1" ]] 22 | [[ "${lines[1]}" == "Included2" ]] 23 | [[ "${lines[2]}" == "Included3" ]] 24 | } 25 | -------------------------------------------------------------------------------- /tests/included1.Bakefile: -------------------------------------------------------------------------------- 1 | included1: 2 | echo Included1 3 | -------------------------------------------------------------------------------- /tests/included2.Bakefile: -------------------------------------------------------------------------------- 1 | include included3.Bakefile 2 | 3 | included2: 4 | echo Included2 5 | -------------------------------------------------------------------------------- /tests/included3.Bakefile: -------------------------------------------------------------------------------- 1 | included3: 2 | echo Included3 3 | -------------------------------------------------------------------------------- /tests/ordering.Bakefile: -------------------------------------------------------------------------------- 1 | build: build/stage 2 | 3 | build/stage: fetch 4 | echo Building stage 5 | 6 | fetch: fetch/consul fetch/s6-overlay 7 | 8 | fetch/consul: 9 | echo Fetching consul 10 | 11 | fetch/s6-overlay: 12 | echo Fetching S6 13 | -------------------------------------------------------------------------------- /tests/ordering.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | export BAKEFILE=ordering.Bakefile 3 | 4 | @test "dependencies are resolved correctly" { 5 | run bake 6 | [[ "${status}" -eq 0 ]] 7 | [[ "${lines[0]}" == *"build…"* ]] 8 | [[ "${lines[1]}" == *"fetch/consul, fetch/s6-overlay, fetch, & build/stage."* ]] 9 | } 10 | -------------------------------------------------------------------------------- /tests/python.Bakefile: -------------------------------------------------------------------------------- 1 | python: 2 | #!/usr/bin/env python 3 | print('not bash') 4 | -------------------------------------------------------------------------------- /tests/python.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | export BAKEFILE=python.Bakefile 3 | @test "python" { 4 | run bake --silent python 5 | [[ "${lines[0]}" == "not bash" ]] 6 | } 7 | -------------------------------------------------------------------------------- /tests/self.Bakefile: -------------------------------------------------------------------------------- 1 | LIFE='42.' 2 | 3 | echo: 4 | echo ${LIFE} 5 | 6 | also-echo: 7 | bake echo 8 | -------------------------------------------------------------------------------- /tests/self.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | export BAKEFILE=self.Bakefile 3 | 4 | @test "test echo" { 5 | run bake --silent echo 6 | [[ "${lines[0]}" == "42." ]] 7 | } 8 | 9 | @test "test subshell echo" { 10 | run bake --silent also-echo 11 | [[ "${lines[0]}" == "42." ]] 12 | } 13 | -------------------------------------------------------------------------------- /tests/utils.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | declare -a COLORS=('white', 'red', 'green', 'blue', 'cyan', 'purple', 'magenta') 4 | 5 | @test "$(red red) --help" { 6 | run red --help 7 | [ "${lines[0]}" = "Usage: red [OPTIONS] [S]" ] 8 | } 9 | 10 | @test "$(red red) \${s}" { 11 | run red test 12 | [[ "${lines[0]}" == *"test"* ]] 13 | } 14 | 15 | @test "echo \${s} | $(red red)" { 16 | output=$(echo test | red) 17 | [[ "$output" == *"test"* ]] 18 | } 19 | 20 | 21 | @test "$(red red) --fg \${COLOR}" { 22 | for COLOR in "${COLORS[@]}"; do 23 | output=$(echo test | red --fg ${COLOR} ) 24 | [[ "$output" == *"test"* ]] 25 | done 26 | } 27 | 28 | @test "$(red red) --fg \${COLOR} --bold" { 29 | for COLOR in "${COLORS[@]}"; do 30 | output=$(echo test | red --fg ${COLOR} --bold) 31 | [[ "$output" == *"test"* ]] 32 | done 33 | } 34 | 35 | @test "$(red red) --bg \${COLOR}" { 36 | for COLOR in "${COLORS[@]}"; do 37 | output=$(echo test | red --bg ${COLOR} ) 38 | [[ "$output" == *"test"* ]] 39 | done 40 | } 41 | 42 | @test "$(red red) --bg \${COLOR} --bold" { 43 | for COLOR in "${COLORS[@]}"; do 44 | output=$(echo test | red --bg ${COLOR} --bold) 45 | [[ "$output" == *"test"* ]] 46 | done 47 | } 48 | 49 | 50 | @test "$(red notred --fg blue) \${s}" { 51 | run notred test 52 | [[ "${lines[0]}" == "test" ]] 53 | } 54 | 55 | @test "$(red red) \${s} | $(red notred --fg blue)" { 56 | output=$(red test | notred) 57 | [[ "$output" == *"test"* ]] 58 | } 59 | 60 | @test "which $(red red)" { 61 | run which red 62 | [ "${status}" -eq 0 ] 63 | } 64 | 65 | @test "which $(red notred --fg blue)" { 66 | run which notred 67 | [ "${status}" -eq 0 ] 68 | } 69 | 70 | @test "which $(red bake_indent --fg cyan)" { 71 | run which bake_indent 72 | [ "${status}" -eq 0 ] 73 | } 74 | 75 | @test "which $(red bake_step --fg cyan)" { 76 | run which bake_step 77 | [ "${status}" -eq 0 ] 78 | } 79 | 80 | @test "$(red bake_step --fg cyan) \${s}" { 81 | run bake_step --no-color 'Step 1' 82 | [[ "${lines[0]}" == " + Step 1: " ]] 83 | } 84 | 85 | 86 | @test "$(red bake_step --fg cyan) --help" { 87 | run bake_step --help 88 | [ "${lines[0]}" = "Usage: bake_step [OPTIONS] [S]" ] 89 | } 90 | 91 | @test "$(red bake_indent --fg cyan) --help" { 92 | run bake_indent --help 93 | [ "${lines[0]}" = "Usage: bake_indent [OPTIONS]" ] 94 | } 95 | --------------------------------------------------------------------------------