[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ninsert_final_newline = true\ncharset = utf-8\ntrim_trailing_whitespace = true\nend_of_line = lf\n\n[*.{js,json}]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"extends\": \"standard\",\n  \"rules\": {\n    \"brace-style\": 0,\n    \"comma-dangle\": 0,\n    \"indent\": 0,\n    \"operator-linebreak\": 0,\n    \"padded-blocks\": 0,\n    \"quotes\": 0,\n    \"semi\": 0\n  }\n}\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\"on\":\n  push:\n    branches:\n      - master\njobs:\n  release:\n    name: release\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n        with:\n          cache: npm\n          node-version: lts/*\n      - run: npm clean-install\n      - run: npx semantic-release\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules/\n.tmp/\ncoverage/\nartifacts/\n/dist\nnpm-debug.log\n.nyc_output\ntest/tools/trigger-appveyor-tests.sh\nlogo/*.png"
  },
  {
    "path": ".npmignore",
    "content": "/meta\n/src\n/test\ntest/tools/trigger-appveyor-tests.sh\n/coverage\n/.travis.yml\n/appveyor.yml\njsconfig.json\ntravis_after_all.py\n/.nyc_output\n"
  },
  {
    "path": ".npmrc",
    "content": "save-exact = true\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contribution guide\n\n## Developing commitizen\n\nYou consider contributing changes to commitizen – thank you!\nPlease consider these guidelines when filing a pull request:\n\n*  Commits follow the [Angular commit convention](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines)\n*  JavaScript is written using ES2015 features\n*  2 spaces indentation\n*  Features and bug fixes should be covered by test cases\n\n## Creating releases\n\ncommitizen uses [semantic-release](https://github.com/semantic-release/semantic-release)\nto release new versions automatically.\n\n*  Commits of type `fix` will trigger bugfix releases, think `0.0.1`\n*  Commits of type `feat` will trigger feature releases, think `0.1.0`\n*  Commits with `BREAKING CHANGE` in body or footer will trigger breaking releases, think `1.0.0`\n\nAll other commit types will trigger no new release.\n\n## Gotchas\n\n### Atom removes lines with just spaces, breaking tests\n\nWhen using Atom, if you edit some of our tests, atom will remove the whitespace on some lines. Unfortunately we wanted this whitespace to\nable to test multiline commits and their difference across operating\nsystems. Atom has decided to keep the stripping of whitespace as a\ndefault. Although we understand this decision, it has the unfortunate\nside effect of editing parts of the file that you might not have\nintended. We think this should be left up to more configurable tools\nlike eslint.\n\nFor now, in order to work around this, you can take the steps outlined\n[here](https://github.com/atom/whitespace/issues/10#issuecomment-85183781) to temporarily disable automatic whitespace removal in Atom.\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "## Commitizen for contributors\n\nWhen you commit with Commitizen, you'll be prompted to fill out any required commit fields at commit time. No more waiting until later for a git commit hook to run and reject your commit (though [that](https://github.com/kentcdodds/validate-commit-msg) can still be helpful). No more digging through [CONTRIBUTING.md](CONTRIBUTING.md) to find what the preferred format is. Get instant feedback on your commit message formatting and be prompted for required fields.\n\n[![Backers on Open Collective](https://opencollective.com/commitizen/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/commitizen/sponsors/badge.svg)](#sponsors) [![travis.ci](https://img.shields.io/travis/commitizen/cz-cli.svg?branch=master)](https://travis-ci.org/commitizen/cz-cli) [![Azure Build Status](https://dev.azure.com/commitizen/cz-cli/_apis/build/status/commitizen.cz-cli?branchName=master)](https://dev.azure.com/commitizen/cz-cli/_build/latest?definitionId=2)\n[![codecov.io](https://img.shields.io/codecov/c/github/commitizen/cz-cli.svg)](https://codecov.io/github/commitizen/cz-cli?branch=master) [![npm monthly downloads](https://img.shields.io/npm/dm/commitizen.svg)](https://www.npmjs.com/package/commitizen) [![current version](https://img.shields.io/npm/v/commitizen.svg)](https://www.npmjs.com/package/commitizen) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![commitizen on stackoverflow](https://img.shields.io/badge/stackoverflow-community-orange.svg?longCache=true&logo=stackoverflow)](https://stackoverflow.com/tags/commitizen)\n\n## Installing the command line tool\n\nCommitizen is currently tested against Node.js 12, 14, & 16, although it may work in\nolder versions of Node.js. You should also have npm 6 or greater.\n\nInstallation is as simple as running the following command (if you see `EACCES` error, reading [fixing npm permissions](https://docs.npmjs.com/getting-started/fixing-npm-permissions) may help):\n\n```sh\nnpm install -g commitizen\n```\n\n## Using the command line tool\n\n### If your repo is [Commitizen friendly](#making-your-repo-commitizen-friendly):\n\nSimply use `git cz` or just `cz` instead of `git commit` when committing. You can also use `git-cz`, which is an alias for `cz`.\n\n_Alternatively_, if you are using **npm 5.2+** you can [use `npx`](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) instead of installing globally:\n\n```sh\nnpx cz\n```\n\nor as an npm script:\n\n```json\n  ...\n  \"scripts\": {\n    \"commit\": \"cz\"\n  }\n```\n\nWhen you're working in a Commitizen-friendly repository, you'll be prompted to fill in any required fields, and your commit messages will be formatted according to the standards defined by project maintainers.\n\n[![Add and commit with Commitizen](https://github.com/commitizen/cz-cli/raw/master/meta/screenshots/add-commit.png)](https://github.com/commitizen/cz-cli/raw/master/meta/screenshots/add-commit.png)\n\n### If your repo is NOT Commitizen friendly:\n\nIf you're **not** working in a Commitizen-friendly repository, then `git cz` will work just the same as `git commit`, but `npx cz` will use the [streamich/git-cz](https://github.com/streamich/git-cz) adapter. To fix this, you need to first [make your repo Commitizen friendly](#making-your-repo-commitizen-friendly)\n\n## Making your repo Commitizen friendly\n\nFor this example, we'll be setting up our repo to use [AngularJS's commit message convention](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines), also known as [conventional-changelog](https://github.com/ajoslin/conventional-changelog).\n\nFirst, install the Commitizen CLI tools:\n\n```sh\nnpm install commitizen -g\n```\n\nNext, initialize your project to use the cz-conventional-changelog adapter by typing:\n\n```sh\n# npm\ncommitizen init cz-conventional-changelog --save-dev --save-exact\n\n# yarn\ncommitizen init cz-conventional-changelog --yarn --dev --exact\n\n# pnpm\ncommitizen init cz-conventional-changelog --pnpm --save-dev --save-exact\n```\n\nNote that if you want to force install over the top of an old adapter, you can apply the `--force` argument. For more information on this, just run `commitizen help`.\n\nThe above command does three things for you:\n\n1. Installs the cz-conventional-changelog adapter npm module\n2. Saves it to `package.json`'s `dependencies` or `devDependencies`\n3. Adds the `config.commitizen` key to the root of your `package.json` file as shown here:\n\n```json\n...\n  \"config\": {\n    \"commitizen\": {\n      \"path\": \"cz-conventional-changelog\"\n    }\n  }\n```\n\nAlternatively, Commitizen configs may be added to a `.czrc` file:\n\n```json\n{\n  \"path\": \"cz-conventional-changelog\"\n}\n```\n\nThis just tells Commitizen which adapter we actually want our contributors to use when they try to commit to this repo.\n\n`commitizen.path` is resolved via [require.resolve](https://nodejs.org/api/globals.html#globals_require_resolve) and supports:\n\n- npm modules\n- directories relative to `process.cwd()` containing an `index.js` file\n- file base names relative to `process.cwd()` with `.js` extension\n- full relative file names\n- absolute paths\n\nPlease note that in the previous version of Commitizen we used czConfig. **czConfig has been deprecated**, and you should migrate to the new format before Commitizen 3.0.0.\n\n### Optional: Install and run Commitizen locally\n\nInstalling and running Commitizen locally allows you to make sure that developers are running the exact same version of Commitizen on every machine.\n\nInstall Commitizen with `npm install --save-dev commitizen`.\n\nOn **npm 5.2+** you can [use `npx`](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) to initialize the conventional changelog adapter:\n\n```\nnpx commitizen init cz-conventional-changelog --save-dev --save-exact\n```\n\nFor **previous versions of npm (< 5.2)** you can execute `./node_modules/.bin/commitizen` or `./node_modules/.bin/cz` in order to actually use the commands.\n\nYou can then initialize the conventional changelog adapter using: `./node_modules/.bin/commitizen init cz-conventional-changelog --save-dev --save-exact`\n\nAnd you can then add some nice npm scripts in your `package.json` file pointing to the local version of Commitizen:\n\n```json\n  ...\n  \"scripts\": {\n    \"commit\": \"cz\"\n  }\n```\n\nThis will be more convenient for your users because then if they want to do a commit, all they need to do is run `npm run commit` and they will get the prompts needed to start a commit!\n\n> **NOTE:** If you are using `precommit` hooks thanks to something like [`husky`](https://www.npmjs.com/package/husky), you will need to name your script something other than `\"commit\"`\n> (e.g. `\"cm\": \"cz\"`). The reason is because npm scripts has a \"feature\" where it automatically runs scripts with the name _prexxx_ where _xxx_ is the name of another script. In essence,\n> npm and husky will run `\"precommit\"` scripts twice if you name the script `\"commit\"`, and the workaround is to prevent the npm-triggered _precommit_ script.\n\n#### Optional: Running Commitizen on `git commit`\n\nThis example shows how to incorporate Commitizen into the existing `git commit` workflow by using git hooks and the `--hook` command-line option. This is useful for project maintainers\nwho wish to ensure the proper commit format is enforced on contributions from those unfamiliar with Commitizen.\n\nOnce either of these methods is implemented, users running `git commit` will be presented with an interactive Commitizen session that helps them write useful commit messages.\n\n> **NOTE:** This example assumes that the project has been set up to [use Commitizen locally](https://github.com/commitizen/cz-cli#optional-install-and-run-commitizen-locally).\n\n##### Traditional git hooks\n\nUpdate `.git/hooks/prepare-commit-msg` with the following code:\n\n```sh\n#!/bin/bash\nexec < /dev/tty && node_modules/.bin/cz --hook || true\n```\n\n##### Husky\n\nFor `husky` users, add the following configuration to the project's `package.json` file:\n\n```json\n\"husky\": {\n  \"hooks\": {\n    \"prepare-commit-msg\": \"exec < /dev/tty && npx cz --hook || true\"\n  }\n}\n```\n\n> **Why `exec < /dev/tty`?** By default, git hooks are not interactive. This command allows the user to use their terminal to interact with Commitizen during the hook.\n\n#### Congratulations! Your repo is Commitizen friendly. Time to flaunt it!\n\nAdd the \"Commitizen friendly\" badge to your README using the following markdown:\n\n```\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)\n```\n\nYour badge will look like this:\n\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)\n\nIt may also make sense to change your `README.md` or `CONTRIBUTING.md` files to include or link to the Commitizen project so that your new contributors may learn more about installing and using Commitizen.\n\n## Conventional commit messages as a global utility\n\nInstall `commitizen` globally, if you have not already.\n\n```sh\nnpm install -g commitizen\n```\n\nInstall your preferred `commitizen` adapter globally (for example [`cz-conventional-changelog`](https://www.npmjs.com/package/cz-conventional-changelog)).\n\n```sh\nnpm install -g cz-conventional-changelog\n```\n\nCreate a `.czrc` file in your `home` directory, with `path` referring to the preferred, globally-installed, `commitizen` adapter\n\n```sh\necho '{ \"path\": \"cz-conventional-changelog\" }' > ~/.czrc\n```\n\nYou are all set! Now `cd` into any `git` repository and use `git cz` instead of `git commit`, and you will find the `commitizen` prompt.\n\nPro tip: You can use all the `git commit` `options` with `git cz`. For example: `git cz -a`.\n\n> If your repository is a [Node.js](https://nodejs.org/en/) project, making it [Commitizen friendly](#making-your-repo-commitizen-friendly) is super easy.\n\nIf your repository is already [Commitizen friendly](#making-your-repo-commitizen-friendly), the local `commitizen` adapter will be used, instead of globally installed one.\n\n## Commitizen for multi-repo projects\n\nAs a project maintainer of many projects, you may want to standardize on a single commit message format for all of them. You can create your own node module which acts as a front-end for Commitizen.\n\n### 1. Create your own entry point script\n\n```js\n// my-cli.js\n\n#!/usr/bin/env node\n\"use strict\";\n\nconst path = require('path');\nconst bootstrap = require('commitizen/dist/cli/git-cz').bootstrap;\n\nbootstrap({\n  cliPath: path.join(__dirname, '../../node_modules/commitizen'),\n  // this is new\n  config: {\n    \"path\": \"cz-conventional-changelog\"\n  }\n});\n```\n\n### 2. Add the script to your `package.json` file\n\n```json\n// package.json\n\n{\n  \"name\": \"company-commit\",\n  \"bin\": \"./my-cli.js\",\n  \"dependencies\": {\n    \"commitizen\": \"^2.7.6\",\n    \"cz-conventional-changelog\": \"^1.1.5\"\n  }\n}\n```\n\n### 3. Publish it to npm and use it!\n\n```sh\nnpm install --save-dev company-commit\n\n./node_modules/.bin/company-commit\n```\n\n## Adapters\n\nWe know that every project and build process has different requirements, so we've tried to keep Commitizen open for extension. You can do this by choosing from any of the pre-built adapters or even by building your own. Here are some of the great adapters available to you:\n\n- [cz-conventional-changelog](https://www.npmjs.com/package/cz-conventional-changelog)\n- [cz-conventional-changelog-for-jira](https://www.npmjs.com/package/@digitalroute/cz-conventional-changelog-for-jira)\n- [cz-conventional-changelog-with-jiraid-detection](https://www.npmjs.com/package/cz-conventional-changelog-with-jiraid-detection)\n- [cz-jira-smart-commit](https://www.npmjs.com/package/cz-jira-smart-commit)\n- [@endemolshinegroup/cz-jira-smart-commit](https://github.com/EndemolShineGroup/cz-jira-smart-commit)\n- [@endemolshinegroup/cz-github](https://github.com/EndemolShineGroup/cz-github)\n- [rb-conventional-changelog](https://www.npmjs.com/package/rb-conventional-changelog)\n- [@mapbox/cz-mapbox-changelog](https://www.npmjs.com/package/@mapbox/cz-mapbox-changelog)\n- [cz-customizable](https://github.com/leonardoanalista/cz-customizable)\n- [cz-commitlint](https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/cz-commitlint)\n- [commitlint](https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/prompt)\n- [vscode-commitizen](https://github.com/KnisterPeter/vscode-commitizen)\n- [cz-emoji](https://github.com/ngryman/cz-emoji)\n- [cz-adapter-eslint](https://www.npmjs.com/package/cz-adapter-eslint)\n- [commitiquette](https://github.com/martinmcwhorter/commitiquette)\n- [cz-format-extension](https://github.com/tyankatsu0105/cz-format-extension)\n- [cz-emoji-conventional](https://www.npmjs.com/package/cz-emoji-conventional)\n- [cz-git](https://github.com/Zhengqbbb/cz-git)\n- [cz-vinyl](https://github.com/Exlint/cz-vinyl)\n\nTo create an adapter, just fork one of these great adapters and modify it to suit your needs. We pass you an instance of [Inquirer.js](https://github.com/SBoudrias/Inquirer.js/), but you can capture input using whatever means necessary. Just call the `commit` callback with a string and we'll be happy. Publish it to npm, and you'll be all set!\n\n## Retrying failed commits\n\nAs of version 2.7.1, you may attempt to retry the last commit using the `git cz --retry` command. This can be helpful when you have tests set up to run via a git precommit hook. In this scenario, you may have attempted a Commitizen commit, painstakingly filled out all of the commitizen fields, but your tests fail. In previous Commitizen versions, after fixing your tests, you would be forced to fill out all of the fields again. Enter the retry command. Commitizen will retry the last commit that you attempted in this repo without you needing to fill out the fields again.\n\nPlease note that the retry cache may be cleared when upgrading Commitizen versions, upgrading adapters, or if you delete the `commitizen.json` file in your home or temp directory. Additionally, the commit cache uses the filesystem path of the repo, so if you move a repo or change its path, you will not be able to retry a commit. This is an edge case but might be confusing if you have scenarios where you are moving folders that contain repos.\n\nIt is important to note that if you are running `cz` from an npm script (let's say it is called `commit`) you will need to do one of the following:\n\n- Pass `-- --retry` as an argument for your script. i.e: `npm run commit -- --retry`\n- Use [npx](https://www.npmjs.com/package/npx) to find and call the `cz` executable directly. i.e: `npx cz --retry`\n\nNote that the last two options **do not** require you to pass `--` before the args but the first **does**.\n\n## Commitizen for project maintainers\n\nAs a project maintainer, making your repo Commitizen friendly allows you to select pre-existing commit message conventions or to create your own custom commit message convention. When a contributor to your repo uses Commitizen, they will be prompted for the correct fields at commit time.\n\n## Go further\n\nCommitizen is great on its own, but it shines when you use it with some other amazing open source tools. Kent C. Dodds shows you how to accomplish this in his Egghead.io series, [How to Write an Open Source JavaScript Library](https://app.egghead.io/playlists/how-to-write-an-open-source-javascript-library). Many of the concepts can be applied to non-JavaScript projects as well.\n\n## Philosophy\n\n### About Commitizen\n\nCommitizen is an open source project that helps contributors be good open source citizens. It accomplishes this by prompting them to follow commit message conventions at commit time. It also empowers project maintainers to create or use predefined commit message conventions in their repos to better communicate their expectations to potential contributors.\n\n### Commitizen or Commit Hooks\n\nBoth! Commitizen is not meant to be a replacement for git commit hooks. Rather, it is meant to work side-by-side with them to ensure a consistent and positive experience for your contributors. Commitizen treats the commit command as a declarative action. The contributor is declaring that they wish to contribute to your project. It is up to you as the maintainer to define what rules they should be following.\n\nWe accomplish this by letting you define which adapter you'd like to use in your project. Adapters just allow multiple projects to share the same commit message conventions. A good example of an adapter is the cz-conventional-changelog adapter.\n\n## Related projects\n\n- [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog) – Generate a changelog from conventional commit history\n- [commitlint](https://github.com/conventional-changelog/commitlint) - Lint commit messages\n\n## Authors and Contributors\n\n@JimTheDev (Jim Cummins, author)\n@kentcdodds\n@accraze\n@kytwb\n@Den-dp\n\nSpecial thanks to @stevelacy, whose [gulp-git](https://www.npmjs.com/package/gulp-git) project makes commitizen possible.\n\n## Contributors\n\nThis project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].\n<a href=\"https://opencollective.com/commitizen#section-contributors\"><img src=\"https://opencollective.com/commitizen/contributors.svg?width=890&button=false\" /></a>\n\n## Backers\n\nThank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/commitizen#backer)]\n\n<a href=\"https://opencollective.com/commitizen#category-BUDGET\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/backers.svg?width=890\"></a>\n\n## Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/commitizen#sponsor)]\n\n<a href=\"https://opencollective.com/commitizen/sponsor/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/sponsor/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/commitizen/sponsor/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/sponsor/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/commitizen/sponsor/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/sponsor/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/commitizen/sponsor/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/sponsor/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/commitizen/sponsor/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/sponsor/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/commitizen/sponsor/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/sponsor/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/commitizen/sponsor/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/sponsor/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/commitizen/sponsor/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/sponsor/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/commitizen/sponsor/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/sponsor/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/commitizen/sponsor/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/commitizen/sponsor/9/avatar.svg\"></a>\n\n[commitizen-friendly]: #making-your-repo-commitizen-friendly\n"
  },
  {
    "path": "azure-pipelines.yml",
    "content": "# Node.js\n# Build a general Node.js project with npm.\n# Add steps that analyze code, save build artifacts, deploy, and more:\n# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript\n\njobs:\n- template: jobs/build.yml  # Template reference\n  parameters:\n    name: macOS\n    pool:\n      vmImage: 'macOS-latest'\n\n- template: jobs/build.yml  # Template reference\n  parameters:\n    name: Linux\n    pool:\n      vmImage: 'ubuntu-latest'\n\n- template: jobs/build.yml  # Template reference\n  parameters:\n    name: Windows\n    pool:\n      vmImage: 'windows-latest'\n    sign: true  # Extra step on Windows only\n"
  },
  {
    "path": "babel.config.js",
    "content": "module.exports = {\n  presets: [\n    [\n      \"@babel/preset-env\",\n      {\n        targets: {\n          node: \"10\",\n        },\n      },\n    ],\n  ],\n  plugins: [\"@babel/plugin-proposal-object-rest-spread\", \"istanbul\"],\n};\n"
  },
  {
    "path": "bin/commitizen",
    "content": "#!/usr/bin/env node\n\nrequire('./commitizen.js');\n"
  },
  {
    "path": "bin/commitizen.cmd",
    "content": "@node \"%~dpn0\" %*"
  },
  {
    "path": "bin/commitizen.js",
    "content": "\nrequire('../dist/cli/commitizen.js').bootstrap();\n"
  },
  {
    "path": "bin/git-cz",
    "content": "#!/usr/bin/env node\n\nrequire('./git-cz.js');\n"
  },
  {
    "path": "bin/git-cz.cmd",
    "content": "@node \"%~dpn0\" %*"
  },
  {
    "path": "bin/git-cz.js",
    "content": "var path = require('path');\n\nprocess.on('uncaughtException', function (err) {\n  console.error(err.message || err);\n  process.exit(1);\n});\n\n// catch SIGINT signal\nprocess.stdin.on('data', function (key) {\n  if (key == '\\u0003') {\n    process.exit(130); // 128 + SIGINT\n  }\n});\n\nrequire('../dist/cli/git-cz.js').bootstrap({\n  cliPath: path.join(__dirname, '../')\n});\n"
  },
  {
    "path": "jobs/build.yml",
    "content": "  # File: jobs/build.yml\n\nparameters:\n  name: ''\n  pool: ''\n  sign: false\n\njobs:\n- job: ${{ parameters.name }}\n  pool: ${{ parameters.pool }}\n  strategy:\n    maxParallel: 3\n    matrix:\n      node-16:\n        node_version: ^16.13.0\n      node-14:\n        node_version: ^14.18.0\n      node-12:\n        node_version: ^12.6.0\n  steps:\n  - task: NodeTool@0\n    displayName: \" Install Node.js\"\n    inputs:\n      versionSpec: $(node_version)\n  - script: git config --global user.email \"example@example.com\"\n  - script: git config --global user.name \"Example Git User\"\n  - script: |\n      curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@6\n      pnpm config set store-dir $(pnpm_config_cache)\n    displayName: \"Setup pnpm\"\n  - script: npm install\n  - script: npm run build\n  - script: npm test && npm run write-coverage\n  - script: bash logo/generate.sh\n  - task: PublishTestResults@2\n    displayName: 'Publish Test Results'\n    inputs:\n      testResultsFiles: '**/junit-*.xml'\n      testRunTitle: TestRun ${{ parameters.name }} $(node_version)\n  - task: PublishCodeCoverageResults@1\n    displayName: 'Publish code coverage results'\n    inputs:\n      codeCoverageTool: 'cobertura'\n      summaryFileLocation: '**/coverage/cobertura-coverage.xml'\n  - task: PublishBuildArtifacts@1\n    displayName: Publish packages\n    condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))\n    inputs:\n      pathtoPublish: '$(Build.ArtifactStagingDirectory)'\n"
  },
  {
    "path": "jsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"target\": \"ES6\",\n        \"module\": \"commonjs\",\n        \"experimentalDecorators\" : true\n    }\n}"
  },
  {
    "path": "logo/generate.sh",
    "content": "#!/bin/bash\nset -o nounset\nset -o errexit\n\n#####################################################\n# Script to create PNG files from SVG source files. #\n# Dependencies: cairosvg (https://cairosvg.org/)    #\n#                                                   #\n# Rationale: Generating from SVG instead of storing #\n#   image files decreases size of repo and avoids   #\n#   security vulnerabilites associated with binary  #\n#   image files.                                    #\n#####################################################\n\nconvert () {\n  COLOR=$1\n  # echo \"converting file $COLOR...\"\n  FILE=logo/commitizen-logo-${COLOR}.svg\n  if [ ! -f ${FILE} ]; then\n    # echo \"file $FILE missing!\"\n    exit 1\n  fi\n  # echo \"conversion in progress...\"\n  for SIZE in 16 48 96 256 512 1024; do\n    cairosvg ${FILE} -f png -W ${SIZE} -H ${SIZE} -d 300 -o logo/commitizen_logo_${COLOR}_${SIZE}x${SIZE}.png\n  done\n  # echo \"done\"\n  return 0\n}\n\nif [[ $(which cairosvg) == \"\" ]]; then\n  # We're not going to mess with installation on OSX or Windows in our build pipelines.\n  if [[ \"$OSTYPE\" == \"darwin\"* ]]; then\n    echo \"cairosvg not found in PATH.  Please see https://cairosvg.org/documentation/#installation\"\n    exit 0\n  elif [[ \"$OSTYPE\" == \"msys\"* ]]; then\n    echo \"cairosvg not found in PATH.  Please see https://cairosvg.org/documentation/#installation\"\n    exit 0\n  fi\n  pip3 install cairosvg\nfi\n\nfor COLOR in black blue white color; do\n  FILE=logo/commitizen-logo-${COLOR}.svg\n  if [ ! -f ${FILE} ]; then\n    # echo \"generating file $FILE...\"\n    sed 's|fill=\\\".*\\\"|fill=\\\"'${COLOR}'\\\"|g' <logo/commitizen-logo-mono.svg >${FILE}\n    convert ${COLOR}\n    # echo \"removing generated file $FILE...\"\n    rm $FILE\n    # echo \"success!\"\n  else\n    # echo \"file found: $FILE\"\n    convert ${COLOR}\n  fi\ndone\n\nexit 0"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"commitizen\",\n  \"version\": \"0.0.0\",\n  \"description\": \"Git commit, but play nice with conventions.\",\n  \"main\": \"dist/index.js\",\n  \"scripts\": {\n    \"check-coverage\": \"nyc check-coverage --statements 80 --branches 80 --functions 80 --lines 80 \",\n    \"commit\": \"node bin/git-cz\",\n    \"build\": \"babel src --out-dir dist\",\n    \"build:watch\": \"babel --watch src --out-dir dist\",\n    \"prepare\": \"not-in-install && npm run build || true\",\n    \"report-coverage\": \"nyc report --reporter=lcov | codecov\",\n    \"write-coverage\": \"nyc report --reporter=lcov --reporter=cobertura --reporter=html\",\n    \"semantic-release\": \"npx semantic-release\",\n    \"start\": \"npm run test:watch\",\n    \"test-actual\": \"mocha --reporter=mocha-multi-reporters --reporter-options configFile=./test/mochareporters.json test/tests/index.js\",\n    \"test\": \"nyc --require @babel/register npm run test-actual\",\n    \"test:watch\": \"nodemon -q --ignore test/.tmp/ --ignore test/artifacts/ --ignore coverage/ --exec \\\"npm run test\\\" --\"\n  },\n  \"config\": {\n    \"commitizen\": {\n      \"path\": \"./node_modules/cz-conventional-changelog\"\n    },\n    \"ghooks\": {\n      \"pre-commit\": \"npm run test && npm run check-coverage\"\n    }\n  },\n  \"homepage\": \"https://github.com/commitizen/cz-cli\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/commitizen/cz-cli.git\"\n  },\n  \"keywords\": [\n    \"commit\",\n    \"pretty\",\n    \"format\",\n    \"conventional changelog\",\n    \"commitizen\"\n  ],\n  \"bugs\": {\n    \"url\": \"https://github.com/commitizen/cz-cli/issues\"\n  },\n  \"bin\": {\n    \"cz\": \"./bin/git-cz\",\n    \"git-cz\": \"./bin/git-cz\",\n    \"commitizen\": \"./bin/commitizen\"\n  },\n  \"author\": \"Jim Cummins <jimthedev@gmail.com> (https://github.com/jimthedev)\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@babel/cli\": \"7.19.3\",\n    \"@babel/core\": \"7.20.5\",\n    \"@babel/plugin-proposal-object-rest-spread\": \"7.20.2\",\n    \"@babel/preset-env\": \"7.20.2\",\n    \"@babel/register\": \"7.18.9\",\n    \"@istanbuljs/nyc-config-babel\": \"3.0.0\",\n    \"babel-plugin-istanbul\": \"6.1.1\",\n    \"chai\": \"4.3.7\",\n    \"codecov\": \"3.8.3\",\n    \"conventional-changelog-conventionalcommits\": \"4.6.3\",\n    \"cz-conventional-changelog-default-export\": \"0.0.0-semantically-released.1\",\n    \"ghooks\": \"2.0.4\",\n    \"in-publish\": \"2.0.1\",\n    \"mocha\": \"9.2.2\",\n    \"mocha-junit-reporter\": \"1.23.3\",\n    \"mocha-multi-reporters\": \"1.5.1\",\n    \"nodemon\": \"2.0.20\",\n    \"nyc\": \"15.1.0\",\n    \"proxyquire\": \"2.1.3\",\n    \"semantic-release\": \"19.0.5\",\n    \"semver\": \"7.3.8\",\n    \"sinon\": \"12.0.1\",\n    \"uuid\": \"8.3.2\"\n  },\n  \"dependencies\": {\n    \"cachedir\": \"2.3.0\",\n    \"cz-conventional-changelog\": \"3.3.0\",\n    \"dedent\": \"0.7.0\",\n    \"detect-indent\": \"6.1.0\",\n    \"find-node-modules\": \"^2.1.2\",\n    \"find-root\": \"1.1.0\",\n    \"fs-extra\": \"9.1.0\",\n    \"glob\": \"7.2.3\",\n    \"inquirer\": \"8.2.5\",\n    \"is-utf8\": \"^0.2.1\",\n    \"lodash\": \"4.17.21\",\n    \"minimist\": \"1.2.7\",\n    \"strip-bom\": \"4.0.0\",\n    \"strip-json-comments\": \"3.1.1\"\n  },\n  \"nyc\": {\n    \"extends\": \"@istanbuljs/nyc-config-babel\",\n    \"exclude\": [\n      \"src/cli\",\n      \"test\"\n    ]\n  },\n  \"engineStrict\": true,\n  \"engines\": {\n    \"node\": \">= 12\"\n  },\n  \"collective\": {\n    \"type\": \"opencollective\",\n    \"url\": \"https://opencollective.com/commitizen\"\n  },\n  \"release\": {\n    \"preset\": \"conventionalcommits\"\n  }\n}\n"
  },
  {
    "path": "renovate.json",
    "content": "{\n  \"extends\": [\n    \"github>commitizen/commitizen-renovate-config\"\n  ]\n}\n"
  },
  {
    "path": "src/cli/commitizen.js",
    "content": "import { init } from '../commitizen';\nimport { commitizen as commitizenParser } from './parsers';\n\nlet { parse } = commitizenParser;\n\nexport {\n  bootstrap\n};\n\n/**\n * This is the main cli entry point.\n * environment may be used for debugging.\n */\nfunction bootstrap (environment = {}, argv = process.argv) {\n\n  // Get cli args\n  let rawGitArgs = argv.slice(2, argv.length);\n\n  // Parse the args\n  let parsedArgs = parse(rawGitArgs);\n  let command = parsedArgs._[0];\n\n  // Do actions based on commands\n  if (command === \"init\") {\n    let adapterNpmName = parsedArgs._[1];\n    if (adapterNpmName) {\n      console.log(`Attempting to initialize using the npm package ${adapterNpmName}`);\n      try {\n        init(process.cwd(), adapterNpmName, parsedArgs);\n      } catch (e) {\n        console.error(`Error: ${e}`);\n      }\n    } else {\n      console.error('Error: You must provide an adapter name as the second argument.');\n    }\n  } else {\n    console.log(`\n\n    Commitizen has two command line tools:\n\n      1) cz         -- used for making commits according to convention\n                       note: you can run 'git cz' if installed with -g\n      2) git-cz     -- alias for 'cz'\n      3) commitizen -- used for installing adapters into your project\n\n    Generally if you're using someone else's repo and they've already set up an\n    adapter, you're going to just be running:\n\n         cz\n\n    However, if you create a new repo and you want to make it easier for future\n    contributors to follow your commit message conventions using commitizen then\n    you'll need to run a command like this one to add this adapter to your config:\n\n         commitizen init cz-conventional-changelog --save\n\n    You should swap out cz-conventional-changelog for the NPM package name of the\n    adapter you wish you install in your project's package.json.\n\n    Detailed usage:\n\n      1) commitizen <sub-command>\n\n         init <adapter-npm-name> [args]\n\n           description: Install a commitizen adapter from npm and adds it to your\n                        config.commitizen in your package.json file.\n\n           args:\n             --save         Install the adapter to package.json dependencies\n             --save-dev     Install the adapter to devDependencies\n             --save-exact   Install an exact version instead of a range\n             --force        Force install the adapter, even if a previous one exists.\n\n      2) cz <any regular git commit arguments>\n\n          description: Runs the commitizen prompter, asking you questions so that you\n                       follow the commit conventions of the repository of the current\n                       directory.\n\n                       note: cz may even be run as 'git cz' if installed with -g.\n\n    `);\n  }\n\n}\n"
  },
  {
    "path": "src/cli/git-cz.js",
    "content": "import { configLoader } from '../commitizen';\nimport { git as useGitStrategy, gitCz as useGitCzStrategy } from './strategies';\n\nexport {\n  bootstrap\n};\n\n/**\n * This is the main cli entry point.\n * environment may be used for debugging.\n */\nfunction bootstrap (environment = {}, argv = process.argv) {\n\n  // Get cli args\n  let rawGitArgs = argv.slice(2, argv.length);\n\n  let adapterConfig = environment.config || configLoader.load();\n\n  // Choose a strategy based on the existance the adapter config\n  if (typeof adapterConfig !== 'undefined') {\n    // This tells commitizen we're in business\n    useGitCzStrategy(rawGitArgs, environment, adapterConfig);\n  } else {\n    // This tells commitizen that it is not needed, just use git\n    useGitStrategy(rawGitArgs, environment);\n  }\n}\n"
  },
  {
    "path": "src/cli/parsers/commitizen.js",
    "content": "import minimist from 'minimist';\n\nexport {\n  parse\n};\n\n/**\n * Takes args, parses with minimist and some ugly vudoo, returns output\n *\n * TODO: Aww shit this is ugly. Rewrite with mega leet tests plz, kthnx.\n */\nfunction parse (rawGitArgs) {\n\n   var args = minimist(rawGitArgs, {\n     boolean: true\n   });\n\n   return args;\n}\n"
  },
  {
    "path": "src/cli/parsers/git-cz.js",
    "content": "export {\n  parse\n};\n\nconst reShortMessage = /^-([a-zA-Z]*)m(.*)$/;\nconst reLongMessage = /^--message(=.*)?$/;\n\n/**\n * Strip message declaration from git arguments\n */\nfunction parse (rawGitArgs) {\n  let result = [];\n  let skipNext = false;\n\n  for (const arg of rawGitArgs) {\n    let match;\n\n    if (skipNext) {\n      skipNext = false;\n      continue;\n    }\n\n    match = reShortMessage.exec(arg);\n\n    if (match) {\n      if (match[1]) {\n        result.push(`-${match[1]}`);\n      }\n\n      if (!match[2]) {\n        skipNext = true;\n      }\n\n      continue;\n    }\n\n    match = reLongMessage.exec(arg);\n\n    if (match) {\n      if (!match[1]) {\n        skipNext = true;\n      }\n\n      continue;\n    }\n\n    result.push(arg);\n  }\n\n  return result;\n}\n"
  },
  {
    "path": "src/cli/parsers.js",
    "content": "import * as commitizen from './parsers/commitizen';\nimport * as gitCz from './parsers/git-cz';\n\nexport {\n  commitizen,\n  gitCz\n};\n"
  },
  {
    "path": "src/cli/strategies/git-cz.js",
    "content": "import inquirer from 'inquirer';\nimport findRoot from 'find-root';\nimport { getParsedPackageJsonFromPath } from '../../common/util';\nimport { gitCz as gitCzParser, commitizen as commitizenParser } from '../parsers';\nimport { commit, staging, adapter } from '../../commitizen';\nimport * as gitStrategy from './git';\n\n// destructure for shorter apis\nlet { parse } = gitCzParser;\n\nlet { getPrompter, resolveAdapterPath, getGitRootPath } = adapter;\nlet { isClean } = staging;\n\nexport default gitCz;\n\nfunction gitCz (rawGitArgs, environment, adapterConfig) {\n\n  // See if any override conditions exist.\n\n  // In these very specific scenarios we may want to use a different\n  // commit strategy than git-cz. For example, in the case of --amend\n  let parsedCommitizenArgs = commitizenParser.parse(rawGitArgs);\n\n  if (parsedCommitizenArgs.amend) {\n    // console.log('override --amend in place');\n    gitStrategy.default(rawGitArgs, environment);\n    return;\n  }\n\n  // Now, if we've made it past overrides, proceed with the git-cz strategy\n  let parsedGitCzArgs = parse(rawGitArgs);\n\n  // Determine if we need to process this commit as a retry instead of a\n  // normal commit.\n  let retryLastCommit = rawGitArgs && rawGitArgs[0] === '--retry';\n\n  // Determine if we need to process this commit using interactive hook mode\n  // for husky prepare-commit-message\n  let hookMode = !(typeof parsedCommitizenArgs.hook === 'undefined');\n\n  let resolvedAdapterConfigPath = resolveAdapterPath(adapterConfig.path);\n  let resolvedAdapterRootPath = findRoot(resolvedAdapterConfigPath);\n  let prompter = getPrompter(adapterConfig.path);\n  let shouldStageAllFiles = rawGitArgs.includes('-a') || rawGitArgs.includes('--all');\n\n  isClean(process.cwd(), function (error, stagingIsClean) {\n    if (error) {\n      throw error;\n    }\n\n    if (stagingIsClean && !parsedGitCzArgs.includes('--allow-empty')) {\n      throw new Error('No files added to staging! Did you forget to run git add?');\n    }\n\n    // OH GOD IM SORRY FOR THIS SECTION\n    let adapterPackageJson = getParsedPackageJsonFromPath(resolvedAdapterRootPath);\n    let cliPackageJson = getParsedPackageJsonFromPath(environment.cliPath);\n    console.log(`cz-cli@${cliPackageJson.version}, ${adapterPackageJson.name}@${adapterPackageJson.version}\\n`);\n    commit(inquirer, getGitRootPath(), prompter, {\n      args: parsedGitCzArgs,\n      disableAppendPaths: true,\n      emitData: true,\n      quiet: false,\n      retryLastCommit,\n      hookMode\n    }, function (error) {\n      if (error) {\n        throw error;\n      }\n      process.exit(0);\n    });\n  }, shouldStageAllFiles);\n\n}\n"
  },
  {
    "path": "src/cli/strategies/git.js",
    "content": "import childProcess from 'child_process';\n\nexport default git;\n\n// We don't have a config, so either we use raw args to try to commit\n// or if debug is enabled then we do a strict check for a config file.\nfunction git (rawGitArgs, environment) {\n  if (environment.debug === true) {\n    console.error('COMMITIZEN DEBUG: No cz friendly config was detected. I looked for .czrc, .cz.json, or czConfig in package.json.');\n  } else {\n    var vanillaGitArgs = [\"commit\"].concat(rawGitArgs);\n\n    var child = childProcess.spawn('git', vanillaGitArgs, {\n      stdio: 'inherit'\n    });\n\n    child.on('error', function (e, code) {\n      console.error(e);\n      throw e;\n    });\n  }\n}\n"
  },
  {
    "path": "src/cli/strategies.js",
    "content": "import git from './strategies/git';\nimport gitCz from './strategies/git-cz';\n\nexport {\n  git,\n  gitCz\n};\n"
  },
  {
    "path": "src/commitizen/adapter.js",
    "content": "import childProcess from 'child_process';\nimport path from 'path';\nimport fs from 'fs';\nimport findNodeModules from 'find-node-modules';\nimport _ from 'lodash';\nimport detectIndent from 'detect-indent';\n\nimport { isFunction } from '../common/util';\n\nexport {\n  addPathToAdapterConfig,\n  getNearestNodeModulesDirectory,\n  getNearestProjectRootDirectory,\n  getInstallStringMappings,\n  getPrompter,\n  generateInstallAdapterCommand,\n  resolveAdapterPath,\n  getGitRootPath,\n};\n\n/**\n * ADAPTER\n *\n * Adapter is generally responsible for actually installing adapters to an\n * end user's project. It does not perform checks to determine if there is\n * a previous commitizen adapter installed or if the proper fields were\n * provided. It defers that responsibility to init.\n */\n\n/**\n * Modifies the package.json, sets config.commitizen.path to the path of the adapter\n * Must be passed an absolute path to the cli's root\n */\nfunction addPathToAdapterConfig (cliPath, repoPath, adapterNpmName) {\n\n  let commitizenAdapterConfig = {\n    config: {\n      commitizen: {\n        path: `./node_modules/${adapterNpmName}`\n      }\n    }\n  };\n\n  let packageJsonPath = path.join(getNearestProjectRootDirectory(repoPath), 'package.json');\n  let packageJsonString = fs.readFileSync(packageJsonPath, 'utf-8');\n  // tries to detect the indentation and falls back to a default if it can't\n  let indent = detectIndent(packageJsonString).indent || '  ';\n  let packageJsonContent = JSON.parse(packageJsonString);\n  let newPackageJsonContent = '';\n  if (_.get(packageJsonContent, 'config.commitizen.path') !== adapterNpmName) {\n    newPackageJsonContent = _.merge(packageJsonContent, commitizenAdapterConfig);\n  }\n  fs.writeFileSync(packageJsonPath, JSON.stringify(newPackageJsonContent, null, indent) + '\\n');\n}\n\n/*\n * Get additional options for install command\n */\nfunction getInstallOptions(stringMappings) {\n  return Array.from(stringMappings.values()).filter(Boolean).join(\" \")\n}\n\n/*\n * Get specific install command for passed package manager\n */\nfunction getInstallCommand(packageManager) {\n  const fallbackCommand = 'install';\n  const commandByPackageManager = {\n    npm: 'install',\n    yarn: 'add',\n    pnpm: 'add',\n  };\n\n  return commandByPackageManager[packageManager] || fallbackCommand;\n}\n\n/**\n * Generates an npm install command given a map of strings and a package name\n */\nfunction generateInstallAdapterCommand(stringMappings, adapterNpmName, packageManager = \"npm\") {\n  return `${packageManager} ${getInstallCommand(packageManager)} ${adapterNpmName} ${getInstallOptions(stringMappings)}`;\n}\n\n/**\n * Gets the nearest npm_modules directory\n */\nfunction getNearestNodeModulesDirectory (options) {\n\n  // Get the nearest node_modules directories to the current working directory\n  let nodeModulesDirectories = findNodeModules(options);\n\n  // Make sure we find a node_modules folder\n\n  /* istanbul ignore else */\n  if (nodeModulesDirectories && nodeModulesDirectories.length > 0) {\n    return nodeModulesDirectories[0];\n  } else {\n    console.error(`Error: Could not locate node_modules in your project's root directory. Did you forget to npm init or npm install?`)\n  }\n}\n\n/**\n * Gets the nearest project root directory\n */\nfunction getNearestProjectRootDirectory (repoPath, options) {\n  return path.join(repoPath, getNearestNodeModulesDirectory(options), '/../');\n}\n\n/**\n * Gets a map of arguments where the value is the corresponding (to passed package manager) string\n */\nfunction getInstallStringMappings({ save, dev, saveDev, exact, saveExact, force }, packageManager) {\n  const npm = new Map()\n    .set('save', save && !saveDev ? '--save' : undefined)\n    .set('saveDev', saveDev ? '--save-dev' : undefined)\n    .set('saveExact', saveExact ? '--save-exact' : undefined)\n    .set('force', force ? '--force' : undefined);\n\n  const yarn = new Map()\n    .set('dev', dev ? '--dev' : undefined)\n    .set('exact', exact ? '--exact' : undefined)\n    .set('force', force ? '--force' : undefined);\n\n  const pnpm = new Map()\n    .set('save', save && !saveDev ? '--save-prod' : undefined)\n    .set('dev', saveDev ? '--save-dev' : undefined)\n    .set('exact', saveExact ? '--save-exact' : undefined);\n\n  const map = { npm, yarn, pnpm };\n\n  return map[packageManager] || npm;\n}\n\n/**\n * Gets the prompter from an adapter given an adapter path\n */\nfunction getPrompter (adapterPath) {\n  // Resolve the adapter path\n  let resolvedAdapterPath = resolveAdapterPath(adapterPath);\n\n  // Load the adapter\n  let adapter = require(resolvedAdapterPath);\n\n  /* istanbul ignore next */\n  if (adapter && adapter.prompter && isFunction(adapter.prompter)) {\n     return adapter.prompter;\n  } else if (adapter && adapter.default && adapter.default.prompter && isFunction(adapter.default.prompter)) {\n     return adapter.default.prompter;\n  } else {\n    throw new Error(`Could not find prompter method in the provided adapter module: ${adapterPath}`);\n  }\n}\n\n/**\n * Given a resolvable module name or path, which can be a directory or file, will\n * return a located adapter path or will throw.\n */\nfunction resolveAdapterPath (inboundAdapterPath) {\n  // Check if inboundAdapterPath is a path or node module name\n  let parsed = path.parse(inboundAdapterPath);\n  let isPath = parsed.dir.length > 0 && parsed.dir.charAt(0) !== \"@\";\n\n  // Resolve from the root of the git repo if inboundAdapterPath is a path\n  let absoluteAdapterPath = isPath ?\n    path.resolve(getGitRootPath(), inboundAdapterPath) :\n    inboundAdapterPath;\n\n  try {\n    // try to resolve the given path\n    return require.resolve(absoluteAdapterPath);\n  } catch (error) {\n    error.message = \"Could not resolve \" + absoluteAdapterPath + \". \" + error.message;\n    throw error;\n  }\n}\n\nfunction getGitRootPath () {\n  return childProcess.spawnSync('git', ['rev-parse', '--show-toplevel'], { encoding: 'utf8' }).stdout.trim();\n}\n"
  },
  {
    "path": "src/commitizen/cache.js",
    "content": "import fs from 'fs';\nimport _ from 'lodash';\n\nexport {\n  getCacheValueSync,\n  readCacheSync,\n  setCacheValueSync,\n};\n\n/**\n * Reads the entire cache\n */\nfunction readCacheSync (cachePath) {\n  return JSON.parse(fs.readFileSync(cachePath, 'utf8'));\n}\n\n/**\n * Sets a cache value and writes the file to disk\n */\nfunction setCacheValueSync (cachePath, key, value) {\n  var originalCache;\n  try {\n    originalCache = readCacheSync(cachePath);\n  } catch (e) {\n    originalCache = {};\n  }\n  var newCache = _.assign(originalCache, {\n    [key]: value\n  });\n  fs.writeFileSync(cachePath, JSON.stringify(newCache, null, '  '));\n  return newCache;\n}\n\n/**\n * Gets a single value from the cache given a key\n */\nfunction getCacheValueSync (cachePath, repoPath) {\n  try {\n    let cache = readCacheSync(cachePath);\n    return cache[repoPath];\n  } catch (e) {\n\n  }\n}\n"
  },
  {
    "path": "src/commitizen/commit.js",
    "content": "import path from 'path';\n\nimport cacheDir from 'cachedir';\nimport { ensureDir } from 'fs-extra';\nimport { commit as gitCommit } from '../git';\nimport * as cache from './cache';\n\nexport default commit;\n\n/**\n * Takes all of the final inputs needed in order to make dispatch a git commit\n */\nfunction dispatchGitCommit (repoPath, template, options, overrideOptions, done) {\n    // Commit the user input -- side effect that we'll test\n    gitCommit(repoPath, template, { ...options, ...overrideOptions }, function (error) {\n      done(error, template);\n    });\n}\n\n /**\n  * Asynchronously commits files using commitizen\n  */\nfunction commit (inquirer, repoPath, prompter, options, done) {\n  var cacheDirectory = cacheDir('commitizen');\n  var cachePath = path.join(cacheDirectory, 'commitizen.json');\n\n  ensureDir(cacheDirectory, function (error) {\n    if (error) {\n      console.error(\"Couldn't create commitizen cache directory: \", error);\n      // TODO: properly handle error?\n    } else {\n      if (options.retryLastCommit) {\n\n        console.log('Retrying last commit attempt.');\n\n        // We want to use the last commit instead of the current commit,\n        // so lets override some options using the values from cache.\n        let {\n          options: retryOptions,\n          overrideOptions: retryOverrideOptions,\n          template: retryTemplate\n        } = cache.getCacheValueSync(cachePath, repoPath);\n        dispatchGitCommit(repoPath, retryTemplate, retryOptions, retryOverrideOptions, done);\n\n      } else {\n        // Get user input -- side effect that is hard to test\n        prompter(inquirer, function (error, template, overrideOptions) {\n          // Allow adapters to error out\n          // (error: Error?, template: String, overrideOptions: Object)\n          if (!(error instanceof Error)) {\n            overrideOptions = template;\n            template = error;\n            error = null;\n          }\n\n          if (error) {\n            return done(error);\n          }\n\n          // We don't want to add retries to the cache, only actual commands\n          cache.setCacheValueSync(cachePath, repoPath, { template, options, overrideOptions });\n          dispatchGitCommit(repoPath, template, options, overrideOptions, done);\n        });\n      }\n    }\n  });\n\n}\n"
  },
  {
    "path": "src/commitizen/configLoader.js",
    "content": "import { loader } from '../configLoader';\n\nexport { load };\n\n// Configuration sources in priority order.\nvar configs = ['.czrc', '.cz.json', 'package.json'];\n\nfunction load (config, cwd) {\n  return loader(configs, config, cwd);\n}\n"
  },
  {
    "path": "src/commitizen/init.js",
    "content": "import childProcess from 'child_process';\nimport path from 'path';\nimport * as configLoader from './configLoader';\nimport * as adapter from './adapter';\n\nlet {\n  addPathToAdapterConfig,\n  generateInstallAdapterCommand,\n  getInstallStringMappings,\n} = adapter;\n\nexport default init;\n\nconst CLI_PATH = path.normalize(path.join(__dirname, '../../'));\n\n/**\n * CZ INIT\n *\n * Init is generally responsible for initializing an adapter in\n * a user's project. The goal is to be able to run\n * `commitizen init` and be prompted for certain fields which\n * will help you install the proper adapter for your project.\n *\n * Init does not actually create the adapter (it defers to adapter\n * for this). Instead, it is specifically designed to help gather\n * and validate the information needed to install the adapter\n * properly without interfering with a previous adapter config.\n */\n\n/**\n * The defaults for init\n */\nconst defaultInitOptions = {\n  save: false,\n  saveDev: true,\n  saveExact: false,\n  force: false,\n\n  // for --yarn use\n  // @see https://github.com/commitizen/cz-cli/issues/527#issuecomment-392653897\n  yarn: false,\n  dev: true,\n  exact: false, // should add trailing comma, thus next developer doesn't got blamed for this line\n\n  pnpm: false, // reuses `save`, `saveDev`, `saveExact`\n};\n\n/**\n * Runs npm install for the adapter then modifies the config.commitizen as needed\n */\nfunction init (repoPath, adapterNpmName, {\n  save = false,\n  saveDev = true,\n  saveExact = false,\n  force = false,\n  yarn = false,\n  dev = false,\n  exact = false,\n  pnpm = false,\n  includeCommitizen = false\n} = defaultInitOptions) {\n\n  // Don't let things move forward if required args are missing\n  checkRequiredArguments(repoPath, adapterNpmName);\n\n  // Load the current adapter config\n  let adapterConfig = loadAdapterConfig(repoPath);\n\n  const packageManager = yarn ? 'yarn' : pnpm ? 'pnpm' : 'npm';\n\n  // Get the npm string mappings based on the arguments provided\n  const stringMappings = getInstallStringMappings({ save, dev, saveDev, saveExact, force }, packageManager);\n\n  // Generate a string that represents the npm install command\n  const installAdapterCommand = generateInstallAdapterCommand(stringMappings, adapterNpmName, packageManager);\n\n  const installCommitizenCommand = generateInstallAdapterCommand(stringMappings, 'commitizen', packageManager);\n\n  // Check for previously installed adapters\n  if (adapterConfig && adapterConfig.path && adapterConfig.path.length > 0 && !force) {\n    throw new Error(`A previous adapter is already configured. Use --force to override\n    adapterConfig.path: ${adapterConfig.path}\n    repoPath: ${repoPath}\n    CLI_PATH: ${CLI_PATH}\n    installAdapterCommand: ${installAdapterCommand}\n    adapterNpmName: ${adapterNpmName}\n    `);\n  }\n\n  try {\n    childProcess.execSync(installAdapterCommand, { cwd: repoPath });\n    if(includeCommitizen) {\n      childProcess.execSync(installCommitizenCommand, { cwd: repoPath });\n    }\n    addPathToAdapterConfig(CLI_PATH, repoPath, adapterNpmName);\n  } catch (e) {\n    console.error(e);\n  }\n}\n\n/**\n * Checks to make sure that the required arguments are passed\n * Throws an exception if any are not.\n */\nfunction checkRequiredArguments (path, adapterNpmName) {\n  if (!path) {\n    throw new Error(\"Path is required when running init.\");\n  }\n  if (!adapterNpmName) {\n    throw new Error(\"The adapter's npm name is required when running init.\");\n  }\n}\n\n/**\n * CONFIG\n * Loads and returns the adapter config at key config.commitizen, if it exists\n */\nfunction loadAdapterConfig (cwd) {\n  let config = configLoader.load(null, cwd);\n  if (config) {\n    return config;\n  } else {\n\n  }\n}\n"
  },
  {
    "path": "src/commitizen/staging.js",
    "content": "import { exec } from 'child_process';\n\nexport { isClean };\n\n/**\n * Asynchrounously determines if the staging area is clean\n */\nfunction isClean (repoPath, done, stageAllFiles) {\n  exec(`git diff --cached --no-ext-diff --name-only ${!!stageAllFiles ? '&& git diff --no-ext-diff --name-only' : ''}`, {\n    maxBuffer: Infinity,\n    cwd: repoPath\n  }, function (error, stdout) {\n    if (error) {\n      return done(error);\n    }\n    let output = stdout || '';\n    done(null, output.trim().length === 0);\n  });\n}\n"
  },
  {
    "path": "src/commitizen.js",
    "content": "/* istanbul ignore file */\nimport * as adapter from './commitizen/adapter';\nimport * as cache from './commitizen/cache';\nimport commit from './commitizen/commit';\nimport * as configLoader from './commitizen/configLoader';\nimport init from './commitizen/init';\nimport * as staging from './commitizen/staging';\n\nexport {\n  adapter,\n  cache,\n  commit,\n  configLoader,\n  init,\n  staging\n};\n"
  },
  {
    "path": "src/common/util.js",
    "content": "import fs from 'fs';\nimport path from 'path';\n\nexport {\n  getParsedJsonFromFile,\n  getParsedPackageJsonFromPath,\n  isFunction,\n  isInTest\n}\n\n/**\n * Gets the parsed contents of a json file\n */\nfunction getParsedJsonFromFile (filePath, fileName, encoding = 'utf8') {\n  try {\n    var packageJsonContents = fs.readFileSync(path.join(filePath, fileName), encoding);\n    return JSON.parse(packageJsonContents);\n  } catch (e) {\n    console.error(e);\n  }\n}\n\n/**\n * A helper method for getting the contents of package.json at a given path\n */\nfunction getParsedPackageJsonFromPath (path) {\n  return getParsedJsonFromFile(path, 'package.json');\n}\n\n/**\n * Test if the passed argument is a function\n */\nfunction isFunction (functionToCheck) {\n  if (typeof functionToCheck === \"undefined\")\n  {\n    return false;\n  } else if (functionToCheck === null) {\n    return false;\n  } else {\n    var getType = {};\n    var functionType = getType.toString.call(functionToCheck);\n    return functionToCheck && (functionType === '[object Function]' || functionType === '[object AsyncFunction]');\n  }\n}\n\nfunction isInTest () {\n  return typeof global.it === 'function';\n}\n"
  },
  {
    "path": "src/configLoader/findup.js",
    "content": "import path from 'path';\nimport glob from 'glob';\n\nexport default findup;\n\n// Before, \"findup-sync\" package was used,\n// but it does not provide filter callback\nfunction findup (patterns, options, fn) {\n    /* jshint -W083 */\n\n    var lastpath;\n    var file;\n\n    options = Object.create(options);\n    options.maxDepth = 1;\n    options.cwd = path.resolve(options.cwd);\n\n    do {\n        file = patterns.filter(function (pattern) {\n            var configPath = glob.sync(pattern, options)[0];\n\n            if (configPath) {\n                return fn(path.join(options.cwd, configPath));\n            }\n        })[0];\n\n        if (file) {\n            return path.join(options.cwd, file);\n        }\n\n        lastpath = options.cwd;\n        options.cwd = path.resolve(options.cwd, '..');\n    } while (options.cwd !== lastpath);\n}\n"
  },
  {
    "path": "src/configLoader/getContent.js",
    "content": "import fs from 'fs';\nimport path from 'path';\n\nimport stripJSONComments from 'strip-json-comments';\nimport isUTF8 from 'is-utf8';\nimport stripBom from 'strip-bom';\n\nimport { getNormalizedConfig } from '../configLoader';\n\nexport default getConfigContent;\n\n/**\n * Read the content of a configuration file\n * - if not js or json: strip any comments\n * - if js or json: require it\n * @param {String} configPath - full path to configuration file\n * @return {Object}\n */\nfunction readConfigContent (configPath) {\n    const parsedPath = path.parse(configPath)\n    const isRcFile = parsedPath.ext !== '.js' && parsedPath.ext !== '.json';\n    const jsonString = readConfigFileContent(configPath);\n    const parse = isRcFile ?\n      (contents) => JSON.parse(stripJSONComments(contents)) :\n      (contents) => JSON.parse(contents);\n\n    try {\n        const parsed = parse(jsonString);\n\n        Object.defineProperty(parsed, 'configPath', {\n          value: configPath\n        });\n\n        return parsed;\n    } catch (error) {\n        error.message = [\n          `Parsing JSON at ${configPath} for commitizen config failed:`,\n          error.mesasge\n        ].join('\\n');\n\n        throw error;\n    }\n}\n\n/**\n * Get content of the configuration file\n * @param {String} configPath - partial path to configuration file\n * @param {String} directory - directory path which will be joined with config argument\n * @return {Object}\n */\nfunction getConfigContent (configPath, baseDirectory) {\n    if (!configPath) {\n      return;\n    }\n\n    const resolvedPath = path.resolve(baseDirectory, configPath);\n    const configBasename = path.basename(resolvedPath);\n\n    if (!fs.existsSync(resolvedPath)) {\n      return getNormalizedConfig(resolvedPath);\n    }\n\n    const content = readConfigContent(resolvedPath);\n    return getNormalizedConfig(configBasename, content);\n};\n\n/**\n * Read proper content from config file.\n * If the chartset of the config file is not utf-8, one error will be thrown.\n * @param {String} configPath\n * @return {String}\n */\nfunction readConfigFileContent (configPath) {\n\n  let rawBufContent = fs.readFileSync(configPath);\n\n  if (!isUTF8(rawBufContent)) {\n    throw new Error(`The config file at \"${configPath}\" contains invalid charset, expect utf8`);\n  }\n\n  return stripBom(rawBufContent.toString(\"utf8\"));\n}\n"
  },
  {
    "path": "src/configLoader/getNormalizedConfig.js",
    "content": "export default getNormalizedConfig;\n\n// Given a config and content, plucks the actual\n// settings that we're interested in\nfunction getNormalizedConfig (config, content) {\n\n  if (content && (config === 'package.json')) {\n\n  // PACKAGE.JSON\n\n    // Use the npm config key, be good citizens\n    if (content.config && content.config.commitizen) {\n      return content.config.commitizen;\n    } else if (content.czConfig) { // Old method, will be deprecated in 3.0.0\n\n      // Suppress during test\n      if (typeof global.it !== 'function')\n      {\n        console.error(\"\\n********\\nWARNING: This repository's package.json is using czConfig. czConfig will be deprecated in Commitizen 3. \\nPlease use this instead:\\n{\\n  \\\"config\\\": {\\n    \\\"commitizen\\\": {\\n      \\\"path\\\": \\\"./path/to/adapter\\\"\\n    }\\n  }\\n}\\nFor more information, see: http://commitizen.github.io/cz-cli/\\n********\\n\");\n      }\n      return content.czConfig;\n    }\n  } else {\n    // .cz.json or .czrc\n    return content;\n  }\n\n}\n"
  },
  {
    "path": "src/configLoader/loader.js",
    "content": "import path from 'path';\n\nimport { findup, getContent } from '../configLoader';\nimport { isInTest } from '../common/util.js';\n\nexport default loader;\n\n/**\n * Command line config helpers\n * Shamelessly ripped from with slight modifications:\n * https://github.com/jscs-dev/node-jscs/blob/master/lib/cli-config.js\n */\n\n/**\n * Get content of the configuration file\n * @param {String} config - partial path to configuration file\n * @param {String} [cwd = process.cwd()] - directory path which will be joined with config argument\n * @return {Object|undefined}\n */\nfunction loader (configs, config, cwd) {\n    var content;\n    var directory = cwd || process.cwd();\n\n    // If config option is given, attempt to load it\n    if (config) {\n        return getContent(config, directory);\n    }\n\n    content = getContent(\n        findup(configs, { nocase: true, cwd: directory }, function (configPath) {\n            if (path.basename(configPath) === 'package.json') {\n                // return !!this.getContent(configPath);\n            }\n\n            return true;\n        })\n    );\n\n    if (content) {\n        return content;\n    }\n    /* istanbul ignore if */\n    if (!isInTest()) {\n      // Try to load standard configs from home dir\n      var directoryArr = [process.env.USERPROFILE, process.env.HOMEPATH, process.env.HOME];\n      for (var i = 0, dirLen = directoryArr.length; i < dirLen; i++) {\n          if (!directoryArr[i]) {\n              continue;\n          }\n\n          for (var j = 0, len = configs.length; j < len; j++) {\n              content = getContent(configs[j], directoryArr[i]);\n\n              if (content) {\n                  return content;\n              }\n          }\n      }\n    }\n}\n"
  },
  {
    "path": "src/configLoader.js",
    "content": "/* istanbul ignore file */\nimport findup from './configLoader/findup';\nimport getContent from './configLoader/getContent';\nimport getNormalizedConfig from './configLoader/getNormalizedConfig';\nimport loader from './configLoader/loader';\n\nexport {\n  findup,\n  getContent,\n  getNormalizedConfig,\n  loader\n};\n"
  },
  {
    "path": "src/git/add.js",
    "content": "import childProcess from 'child_process';\n\nexport {\n  addPath,\n  addFile\n}\n\n/**\n * Synchronously adds a path to git staging\n */\nfunction addPath (repoPath) {\n  childProcess.spawnSync('git', ['add', '.'], { cwd: repoPath });\n}\n\n/**\n * Synchronously adds a file to git staging\n */\nfunction addFile (repoPath, filename) {\n  childProcess.spawnSync('git', ['add', filename], { cwd: repoPath });\n}\n"
  },
  {
    "path": "src/git/commit.js",
    "content": "import { execSync, spawn } from 'child_process';\n\nimport path from 'path';\n\nimport { writeFileSync, openSync, closeSync } from 'fs';\n\nimport dedent from 'dedent';\n\nexport { commit };\n\n/**\n * Asynchronously git commit at a given path with a message\n */\nfunction commit (repoPath, message, options, done) {\n  let called = false;\n\n  // commit the file by spawning a git process, unless the --hook\n  // option was provided. in that case, write the commit message into\n  // the .git/COMMIT_EDITMSG file\n  if (!options.hookMode) {\n    let args = ['commit', '-m', dedent(message), ...(options.args || [])];\n    let child = spawn('git', args, {\n      cwd: repoPath,\n      stdio: options.quiet ? 'ignore' : 'inherit'\n    });\n\n    child.on('error', function (err) {\n      if (called) return;\n      called = true;\n\n      done(err);\n    });\n\n    child.on('exit', function (code, signal) {\n      if (called) return;\n      called = true;\n\n      if (code) {\n        if (code === 128) {\n          console.warn(`\n            Git exited with code 128. Did you forget to run:\n\n              git config --global user.email \"you@example.com\"\n              git config --global user.name \"Your Name\"\n            `)\n        }\n        done(Object.assign(new Error(`git exited with error code ${code}`), { code, signal }));\n      } else {\n        done(null);\n      }\n    });\n  } else {\n    const gitDirPath = execSync(\n      'git rev-parse --absolute-git-dir',\n      { cwd: repoPath, encoding: 'utf8' },\n    ).trim();\n    const commitFilePath = path.join(gitDirPath, 'COMMIT_EDITMSG');\n    try {\n      const fd = openSync(commitFilePath, 'w');\n      try {\n        writeFileSync(fd, dedent(message));\n        done(null);\n      } catch (e) {\n        done(e);\n      } finally {\n        closeSync(fd);\n      }\n    } catch (e) {\n      // windows doesn't allow opening existing hidden files\n      // in 'w' mode... but it does let you do 'r+'!\n      try {\n        const fd = openSync(commitFilePath, 'r+');\n        try {\n          writeFileSync(fd, dedent(message));\n          done(null);\n        } catch (e) {\n          done(e);\n        } finally {\n          closeSync(fd);\n        }\n      } catch (e) {\n        done(e);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/git/init.js",
    "content": "import childProcess from 'child_process';\n\nexport { init };\n\n/**\n * Synchronously creates a new git repo at a path\n */\nfunction init (repoPath) {\n  childProcess.spawnSync('git', ['init'], { cwd: repoPath });\n}\n"
  },
  {
    "path": "src/git/log.js",
    "content": "import { exec } from 'child_process';\n\nexport { log };\n\n/**\n * Asynchronously gets the git log output\n */\nfunction log (repoPath, done) {\n  exec('git log', {\n    maxBuffer: Infinity,\n    cwd: repoPath\n  }, function (error, stdout, stderr) {\n    if (error) {\n      throw error;\n    }\n    done(stdout);\n  });\n}\n"
  },
  {
    "path": "src/git/whatChanged.js",
    "content": "import { exec } from 'child_process';\n\nexport { whatChanged };\n\n/**\n * Asynchronously gets the git whatchanged output\n */\nfunction whatChanged (repoPath, done) {\n  exec('git whatchanged', {\n    maxBuffer: Infinity,\n    cwd: repoPath\n  }, function (error, stdout, stderr) {\n    if (error) {\n      throw error;\n    }\n    done(stdout);\n  });\n}\n"
  },
  {
    "path": "src/git.js",
    "content": "/* istanbul ignore file */\nimport { addPath, addFile } from './git/add';\nimport { commit } from './git/commit';\nimport { init } from './git/init';\nimport { log } from './git/log';\nimport { whatChanged } from './git/whatChanged';\n\nexport {\n  addPath,\n  addFile,\n  commit,\n  init,\n  log,\n  whatChanged\n};\n"
  },
  {
    "path": "src/index.js",
    "content": "var commitizen = require('./commitizen');\nmodule.exports = commitizen;\n"
  },
  {
    "path": "src/npm.js",
    "content": "// this file left blank until npm init is implemented\n"
  },
  {
    "path": "test/config.js",
    "content": "import path from 'path';\n\n/**\n * Modify the testConfig to your liking\n */\nlet config = {\n  paths: {\n    /**\n     * Where to place the artifacts for the last test run.\n     * These are cleared at the beginning of the next test\n     * run.\n     */\n    tmp: path.join(__dirname, '/.tmp'),\n\n    /**\n     * Where to temporarily store the artifacts for the end\n     * user repo.\n     */\n    endUserRepo: path.join(__dirname, '/.tmp/enduser-app')\n  },\n\n  /**\n   * This should be set to a large enough timeout that it is\n   * longer than the longest test.\n   *\n   * Usage (in a given test):\n   *   this.timeout = config.maxTimeout;\n   *\n   * Note that only certain long tests should use this\n   * max timeout value (such as installing packages).\n   *\n   * Most tests should use the default timeout.\n   */\n  maxTimeout: 240000,\n\n  /**\n   * Whether or not to keep the artifacts of the tests after\n   * they've run.\n   *\n   * Possible options:\n   *    Positive integer    Keeps latests (n) run artifacts\n   *    false (default)     Keeps no artifacts\n   *    true | 'all'        Keeps all artifacts, Warning. See below.\n   *\n   * Artifacts are stored in test/artifacts.\n   *\n   * Each run of the test suite is given a unique id and each\n   * test is given a unique id.\n   *\n   * WARNING:\n   * 'all' or true may be useful for debugging but you should have\n   * the value set to false or a positive integer by default as the\n   * artifacts folder will continue to grow unless you manually clear\n   * it. Use at your own risk.\n   */\n  preserve: 1\n};\n\nexport { config };\n"
  },
  {
    "path": "test/fixtures/invalid-json-rc",
    "content": "{\n  \"some\": \"json\"\n  \"that\": \"is invalid\"\n}\n"
  },
  {
    "path": "test/fixtures/invalid-json.json",
    "content": "{\n  \"some\": \"json\"\n  \"that\": \"is invalid\"\n}\n"
  },
  {
    "path": "test/fixtures/valid-json-rc",
    "content": "{\n  \"some\": \"json\"\n  // with comments\n}\n"
  },
  {
    "path": "test/mochareporters.json",
    "content": "{\n    \"reporterEnabled\": \"spec, mocha-junit-reporter\",\n    \"mochaJunitReporterReporterOptions\": {\n        \"mochaFile\": \"../../junit-testresults.xml\",\n        \"includePending\": true,\n        \"outputs\": true\n    }\n}"
  },
  {
    "path": "test/tester.js",
    "content": "import * as repo from './tools/repo';\nimport * as clean from './tools/clean';\nimport * as files from './tools/files';\nimport * as util from '../src/common/util';\nimport { config as userConfig } from './config';\nimport _ from 'lodash';\n\n// Clone the user's config so we don't get caught w/our pants down\nlet patchedConfig = _.cloneDeep(userConfig);\n\nfunction bootstrap () {\n\n  // Return the patched config\n  return {\n    config: patchedConfig,\n    repo,\n    clean,\n    util,\n    files\n  }\n}\n\nexport {\n  bootstrap\n};\n"
  },
  {
    "path": "test/tests/adapter.js",
    "content": "import { expect } from 'chai';\nimport path from 'path';\n\n// TODO: augment these tests with tests using the actual cli call\n// For now we're just using the library, which is probably fine\n// in the short term\nimport { adapter, init as commitizenInit } from '../../src/commitizen';\n\nimport { isFunction } from '../../src/common/util';\n\n// Bootstrap our tester\nimport { bootstrap } from '../tester';\n\n// Destructure some things based on the bootstrap process\nlet { config, repo, clean } = bootstrap();\n\nbefore(function () {\n  // Creates the temp path\n  clean.before(config.paths.tmp);\n});\n\nbeforeEach(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  repo.createEndUser(config.paths.endUserRepo);\n});\n\ndescribe('adapter', function () {\n\n  it('resolves adapter paths', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n            contents: `duck-duck-goose`,\n            filename: `mydummyfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/cz-conventional-changelog'),\n      npmName: 'cz-conventional-changelog'\n    };\n\n    // Install an adapter\n    commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog');\n\n    // TEST\n    expect(function () { adapter.resolveAdapterPath('IAMANIMPOSSIBLEPATH'); }).to.throw(Error);\n    expect(function () { adapter.resolveAdapterPath(adapterConfig.path); }).not.to.throw(Error);\n    expect(function () { adapter.resolveAdapterPath(path.join(adapterConfig.path, 'index.js')); }).not.to.throw(Error);\n\n    // This line is only here to make sure that cz-conventional-changelog\n    // was installed for the purposes of running tests, it is not needed\n    // for testing any other adapters.\n    expect(function () { adapter.resolveAdapterPath('cz-conventional-changelog'); }).not.to.throw(Error);\n  });\n\n  it('resolves scoped adapter paths', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n            contents: `duck-duck-goose`,\n            filename: `mydummyfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/@commitizen/cz-conventional-changelog'),\n      npmName: '@commitizen/cz-conventional-changelog'\n    };\n\n    // Install an adapter\n    commitizenInit(config.paths.endUserRepo, '@commitizen/cz-conventional-changelog');\n\n    // TEST\n    expect(function () { adapter.resolveAdapterPath('IAMANIMPOSSIBLEPATH'); }).to.throw(Error);\n    expect(function () { adapter.resolveAdapterPath(adapterConfig.path); }).not.to.throw(Error);\n    expect(function () { adapter.resolveAdapterPath(path.join(adapterConfig.path, 'index.js')); }).not.to.throw(Error);\n  });\n\n  it.skip('gets adapter prompter functions', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n            contents: `duck-duck-goose`,\n            filename: `mydummyfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/cz-conventional-changelog'),\n      npmName: 'cz-conventional-changelog'\n    };\n\n    // Install an adapter\n    commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', {includeCommitizen: true});\n\n    // TEST\n    expect(function () { adapter.getPrompter('IAMANIMPOSSIBLEPATH'); }).to.throw(Error);\n    expect(function () { adapter.getPrompter(adapterConfig.path); }).not.to.throw(Error);\n    expect(isFunction(adapter.getPrompter(adapterConfig.path))).to.be.true;\n  });\n\n  it('gets adapter prompter functions for default export adapters', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n            contents: `duck-duck-goose`,\n            filename: `mydummyfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/cz-conventional-changelog-default-export'),\n      npmName: 'cz-conventional-changelog-default-export'\n    };\n\n    // Install an adapter\n    commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog-default-export');\n\n    // TEST\n    expect(function () { adapter.getPrompter('IAMANIMPOSSIBLEPATH'); }).to.throw(Error);\n    expect(function () { adapter.getPrompter(adapterConfig.path); }).not.to.throw(Error);\n    expect(isFunction(adapter.getPrompter(adapterConfig.path))).to.be.true;\n  });\n\n});\n\nafterEach(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  // All this should do is archive the tmp path to the artifacts\n  clean.afterEach(config.paths.tmp, config.preserve);\n});\n\nafter(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  // Once everything is done, the artifacts should be cleaned up based on\n  // the preserve setting in the config\n  clean.after(config.paths.tmp, config.preserve);\n});\n"
  },
  {
    "path": "test/tests/cli.js",
    "content": "import { expect } from 'chai';\nimport proxyquire from 'proxyquire';\nimport sinon from 'sinon';\n\ndescribe('git-cz', () => {\n  let bootstrap;\n  let fakeStrategies, fakeCommitizen;\n\n  beforeEach(() => {\n    fakeStrategies = {\n      git: sinon.spy(),\n      gitCz: sinon.spy()\n    }\n\n    fakeCommitizen = {\n      configLoader: {\n        load: sinon.stub()\n      }\n    }\n\n    bootstrap = proxyquire('../../src/cli/git-cz', {\n      './strategies': fakeStrategies,\n      '../commitizen': fakeCommitizen\n    }).bootstrap;\n  });\n\n  describe('bootstrap', () => {\n    describe('when config is provided', () => {\n      it('passes config to useGitCzStrategy', () => {\n        const config = sinon.spy();\n\n        bootstrap({ config });\n\n        expect(fakeStrategies.gitCz.args[0][2]).to.equal(config);\n      });\n    });\n\n    describe('when config is not provided', () => {\n\n      describe('and the config is returned from configLoader.load', () => {\n        it('uses config from configLoader.load()', () => {\n          const config = sinon.stub();\n          fakeCommitizen.configLoader.load.returns(config);\n\n          bootstrap({});\n\n          expect(fakeStrategies.gitCz.args[0][2]).to.equal(config);\n        });\n      });\n\n      describe('and the config is not returned from configLoader.load', () => {\n        it('tells commitizen to use the git strategy', () => {\n          bootstrap({});\n          expect(fakeStrategies.git.called).to.equal(true);\n        });\n      });\n    });\n\n    describe('when argv is overridden', () => {\n      it('uses the overridden argv', () => {\n        bootstrap({}, ['node', 'git-cz', 'index.js']);\n        expect(fakeStrategies.git.args[0][0][0]).to.equal('index.js');\n      });\n    })\n  });\n});\n"
  },
  {
    "path": "test/tests/commit.js",
    "content": "import { expect } from 'chai';\nimport os from 'os';\nimport fs from 'fs';\nimport path from 'path';\n\nimport inquirer from 'inquirer';\n\n// Bootstrap our tester\nimport { bootstrap } from '../tester';\n\n// Get our source files\nimport { addFile as gitAddFile, init as gitInit, log, whatChanged } from '../../src/git';\nimport { commit as commitizenCommit, init as commitizenInit } from '../../src/commitizen';\n\n// Destructure some things for cleaner tests\nlet { config, repo, clean, files } = bootstrap();\nlet { writeFilesToPath } = files;\n\nbefore(function () {\n  // Creates the temp path\n  clean.before(config.paths.tmp);\n});\n\nbeforeEach(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  /* istanbul ignore next */\n  repo.createEndUser(config.paths.endUserRepo);\n});\n\ndescribe('commit', function () {\n\n  it('should commit simple messages', function (done) {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    let dummyCommitMessage = `sip sip sippin on some sizzurp`;\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n            contents: `duck-duck-goose`,\n            filename: `mydummyfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/cz-jira-smart-commit'),\n      npmName: 'cz-jira-smart-commit'\n    };\n\n    // Quick setup the repos, adapter, and grab a simple prompter\n    let prompter = quickPrompterSetup(repoConfig, adapterConfig, dummyCommitMessage);\n    // TEST\n\n    // Pass in inquirer but it never gets used since we've mocked out a different\n    // version of prompter.\n    commitizenCommit(inquirer, repoConfig.path, prompter, { disableAppendPaths: true, quiet: true, emitData: true }, function () {\n      log(repoConfig.path, function (logOutput) {\n        expect(logOutput).to.have.string(dummyCommitMessage);\n        done();\n      });\n    });\n\n  });\n\n  it('should commit message with quotes', function (done) {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    let dummyCommitMessage = `sip \\`sip\\` sippin' on some \"sizzurp\"`;\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n            contents: `duck-duck-goose`,\n            filename: `mydummyfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/cz-jira-smart-commit'),\n      npmName: 'cz-jira-smart-commit'\n    };\n\n    // Quick setup the repos, adapter, and grab a simple prompter\n    let prompter = quickPrompterSetup(repoConfig, adapterConfig, dummyCommitMessage);\n    // TEST\n\n    // Pass in inquirer but it never gets used since we've mocked out a different\n    // version of prompter.\n    commitizenCommit(inquirer, repoConfig.path, prompter, { disableAppendPaths: true, quiet: true, emitData: true }, function () {\n      log(repoConfig.path, function (logOutput) {\n        expect(logOutput).to.have.string(dummyCommitMessage);\n        done();\n      });\n    });\n\n  });\n\n  it('should commit multiline messages', function (done) {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Git on *nix retains spaces on lines with only spaces\n    // Git on win32 removes spaces from lines with only spaces\n    let dummyCommitMessage =\n    `sip sip sippin on jnkjnkjn\n${(os.platform === 'win32') ? '' : '    '}\n    some sizzurp`;\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n            contents: `duck-duck-goose`,\n            filename: `mydummyfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/cz-conventional-changelog'),\n      npmName: 'cz-conventional-changelog'\n    };\n\n    // Quick setup the repos, adapter, and grab a simple prompter\n    let prompter = quickPrompterSetup(repoConfig, adapterConfig, dummyCommitMessage);\n    // TEST\n\n    // Pass in inquirer but it never gets used since we've mocked out a different\n    // version of prompter.\n    commitizenCommit(inquirer, repoConfig.path, prompter, { disableAppendPaths: true, quiet: true }, function () {\n      log(repoConfig.path, function (logOutput) {\n        expect(logOutput).to.have.string(dummyCommitMessage);\n        done();\n      });\n    });\n\n  });\n\n  it('should allow to override git commit options', function (done) {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    let dummyCommitMessage = `sip sip sippin on some sizzurp`;\n    let author = `A U Thor <author@example.com>`;\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n            contents: `duck-duck-goose`,\n            filename: `mydummyfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/cz-jira-smart-commit'),\n      npmName: 'cz-jira-smart-commit'\n    };\n\n    let options = {\n      args: [`--author=\"${author}\"`, '--no-edit']\n    };\n\n    // Quick setup the repos, adapter, and grab a simple prompter\n    let prompter = quickPrompterSetup(repoConfig, adapterConfig, dummyCommitMessage, options);\n    // TEST\n\n    // Pass in inquirer but it never gets used since we've mocked out a different\n    // version of prompter.\n    commitizenCommit(inquirer, repoConfig.path, prompter, { disableAppendPaths: true, quiet: true, emitData: true }, function () {\n      log(repoConfig.path, function (logOutput) {\n        expect(logOutput).to.have.string(author);\n        expect(logOutput).to.have.string(dummyCommitMessage);\n        done();\n      });\n    });\n\n  });\n\n  it('should respect original behavior of -a option', function (done) {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    let dummyCommitMessage = `sip sip sippin on some sizzurp`;\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n            contents: `duck-duck-goose`,\n            filename: `mydummyfile.txt`,\n        },\n        dummyfilecopy: {\n          contents: `duck-duck-goose`,\n          filename: `mydummyfilecopy.txt`,\n          add: false,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/cz-jira-smart-commit'),\n      npmName: 'cz-jira-smart-commit'\n    };\n\n    let options = {\n      args: ['-a']\n    };\n\n    // Quick setup the repos, adapter, and grab a simple prompter\n    let prompter = quickPrompterSetup(repoConfig, adapterConfig, dummyCommitMessage, options);\n    // TEST\n\n    // Pass in inquirer but it never gets used since we've mocked out a different\n    // version of prompter.\n    commitizenCommit(inquirer, repoConfig.path, prompter, { disableAppendPaths: true, quiet: true, emitData: true }, function () {\n      log(repoConfig.path, function (logOutput) {\n        expect(logOutput).to.have.string(dummyCommitMessage);\n      });\n      whatChanged(repoConfig.path, function (whatChangedOutput) {\n        expect(whatChangedOutput).to.have.string('A\\t' + repoConfig.files.dummyfile.filename);\n        expect(whatChangedOutput).to.not.have.string('A\\t' + repoConfig.files.dummyfilecopy.filename);\n        done();\n      });\n    });\n\n  });\n\n  it('should save directly to .git/COMMIT_EDITMSG with --hook option', function (done) {\n\n    this.timeout(config.maxTimeout);\n\n    // SETUP\n    let dummyCommitMessage = `doggies!`;\n\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n          contents: 'arf arf!',\n          filename: 'woof.txt'\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/cz-jira-smart-commit'),\n      npmName: 'cz-jira-smart-commit'\n    }\n\n    // Quick setup the repos, adapter, and grab a simple prompter\n    let prompter = quickPrompterSetup(repoConfig, adapterConfig, dummyCommitMessage);\n    // TEST\n\n    // This is a successful commit directly to .git/COMMIT_EDITMSG\n    commitizenCommit(inquirer, repoConfig.path, prompter, { disableAppendPaths: true, quiet: true, emitData: true, hookMode: true }, function (err) {\n      const commitFilePath = path.join(repoConfig.path, '.git/COMMIT_EDITMSG')\n      const commitFile = fs.openSync(commitFilePath, 'r+')\n      let commitContents = fs.readFileSync(commitFile, { flags: 'r+' }).toString();\n      fs.closeSync(commitFile);\n      expect(commitContents).to.have.string(dummyCommitMessage);\n      expect(err).to.be.a('null');\n      done();\n    });\n  });\n\n  it('should throw error if staging area is empty', function (done) {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    let dummyCommitMessage = `one does not simply ignore the tests`;\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n          contents: `duck-duck-gray-duck`,\n          filename: `mydummiestfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`,\n        }\n      }\n    };\n\n    // Describe an adapter\n    let adapterConfig = {\n      path: path.join(repoConfig.path, '/node_modules/cz-jira-smart-commit'),\n      npmName: 'cz-jira-smart-commit'\n    };\n\n    // Quick setup the repos, adapter, and grab a simple prompter\n    let prompter = quickPrompterSetup(repoConfig, adapterConfig, dummyCommitMessage);\n    // TEST\n\n    // Make an initial commit\n    commitizenCommit(inquirer, repoConfig.path, prompter, { disableAppendPaths: true, quiet: true, emitData: true }, function (error) {\n      //  Should pass, as the files are added to the staging area\n      expect(error).to.be.null;\n\n      log(repoConfig.path, function (logOutput) {\n        expect(logOutput).to.have.string(dummyCommitMessage);\n      });\n      whatChanged(repoConfig.path, function (whatChangedOutput) {\n        expect(whatChangedOutput).to.have.string('A\\t' + repoConfig.files.dummyfile.filename);\n\n        //  Make changes and don't add them to the staging area\n        writeFilesToPath({\n          dummymodified: {\n            contents: repoConfig.files.dummyfile.contents + '-modified',\n            filename: repoConfig.files.dummyfile.filename,\n            add: false,\n          }\n        }, repoConfig.path);\n        //  Define a dummy prompter\n        let prompter = function (cz, commit) {\n          commit(`${dummyCommitMessage} #2`, {});\n        };\n\n        commitizenCommit(inquirer, repoConfig.path, prompter, { disableAppendPaths: true, quiet: true, emitData: true }, function (error) {\n          //  Should fail, as staging are is empty\n          expect(error).to.be.instanceOf(Error);\n          done();\n        });\n      });\n    });\n\n  });\n});\n\nafterEach(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  // All this should do is archive the tmp path to the artifacts\n  clean.afterEach(config.paths.tmp, config.preserve);\n});\n\nafter(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  // Once everything is done, the artifacts should be cleaned up based on\n  // the preserve setting in the config\n  clean.after(config.paths.tmp, config.preserve);\n});\n\n/**\n  * This is just a helper for testing. NOTE that prompter\n  * prompter is overriden for testing purposes.\n  */\nfunction quickPrompterSetup (repoConfig, adapterConfig, commitMessage, options = {}) {\n\n  commitizenInit(repoConfig.path, adapterConfig.npmName);\n\n  // NOTE:\n  // In our real code we'd use this here but since we're testing,\n  // we'll provide prompter. We'd normally use:\n  //   let prompter = getPrompter(adapterConfig.path);\n  let prompter = function (cz, commit) {\n    commit(commitMessage, options);\n  }\n\n  gitInit(repoConfig.path);\n\n  writeFilesToPath(repoConfig.files, repoConfig.path);\n\n  for (let key in repoConfig.files) {\n    let file = repoConfig.files[key];\n    if (file.add !== false) {\n      gitAddFile(repoConfig.path, file.filename);\n    }\n  }\n\n  // NOTE: In the real world we would not be returning\n  // this we would instead be just making the commented\n  // out getPrompter() call to get user input (above).\n  return prompter;\n}\n"
  },
  {
    "path": "test/tests/configLoader.js",
    "content": "import path from 'path';\nimport { expect } from 'chai';\nimport { getContent, getNormalizedConfig } from '../../src/configLoader';\n\nconst fixturesPath = path.resolve(__dirname, '..', 'fixtures');\n\ndescribe('configLoader', function () {\n\n  it('errors appropriately for invalid json', function () {\n    expect(() => getContent('invalid-json.json', fixturesPath))\n      .to.throw(/parsing json at/i);\n    expect(() => getContent('invalid-json-rc', fixturesPath))\n      .to.throw(/parsing json at/i);\n    expect(() => getContent('invalid-charset.json', fixturesPath))\n      .to.throw(/contains invalid charset/i);\n  });\n\n  it('parses json files with comments', function () {\n    expect(getContent('valid-json-rc', fixturesPath))\n      .to.deep.equal({ 'some': 'json' });\n  });\n\n  it('normalizes package.json configs', function () {\n\n    let config = 'package.json';\n\n    let npmStyleConfig = {\n      config: {\n        commitizen: 'myNpmConfig'\n      }\n    };\n\n    let oldStyleConfig = {\n      czConfig: 'myOldConfig'\n    };\n\n    expect(getNormalizedConfig(config, npmStyleConfig)).to.equal('myNpmConfig');\n    expect(getNormalizedConfig(config, oldStyleConfig)).to.equal('myOldConfig');\n\n  });\n\n  it('normalizes .cz.json configs', function () {\n\n    let config = '.cz.json';\n\n    let czJsonStyleConfig = {\n      path: './path/to/adapter'\n    };\n\n    expect(getNormalizedConfig(config, czJsonStyleConfig)).to.deep.equal({ path: './path/to/adapter' });\n\n  });\n\n  it('normalizes .czrc configs', function () {\n\n    let config = '.czrc';\n\n    let czrcStyleConfig = {\n      path: './path/to/adapter'\n    };\n\n    expect(getNormalizedConfig(config, czrcStyleConfig)).to.deep.equal({ path: './path/to/adapter' });\n\n  });\n\n});\n"
  },
  {
    "path": "test/tests/index.js",
    "content": "import './adapter';\nimport './cli';\nimport './commit';\nimport './configLoader';\nimport './init';\nimport './parsers';\nimport './staging';\nimport './util';\n"
  },
  {
    "path": "test/tests/init.js",
    "content": "import { expect } from 'chai';\nimport semver from 'semver';\n\n// TODO: augment these tests with tests using the actual cli call\n// For now we're just using the library, which is probably fine\n// in the short term\nimport { init as commitizenInit } from '../../src/commitizen';\n\n// Bootstrap our tester\nimport { bootstrap } from '../tester';\n\n// Destructure some things based on the bootstrap process\nlet { config, repo, clean, util } = bootstrap();\n\nbefore(function () {\n  // Creates the temp path\n  clean.before(config.paths.tmp);\n});\n\nbeforeEach(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  repo.createEndUser(config.paths.endUserRepo);\n});\n\ndescribe('init', function () {\n\n  it('installs an adapter with --save-dev', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Install an adapter\n    commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog');\n\n    // TEST\n\n    // Check resulting json\n    let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n    expect(packageJson).to.have.nested.property('devDependencies.cz-conventional-changelog');\n\n  });\n\n  it('installs an adapter with --save', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Install an adapter\n    commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { save: true, saveDev: false });\n\n    // TEST\n\n    // Check resulting json\n    let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n    expect(packageJson).to.have.nested.property('dependencies.cz-conventional-changelog');\n\n  });\n\n  it('errors on previously installed adapter', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Add a first adapter\n    commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { saveDev: true });\n\n    // TEST\n    // Adding a second adapter\n    expect(function () {\n      commitizenInit(config.paths.endUserRepo, 'cz-jira-smart-commit', { saveDev: true });\n    }).to.throw(/already configured/);\n\n    // Check resulting json\n    let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n    expect(packageJson).not.to.have.nested.property('devDependencies', 'cz-jira-smart-commit');\n    expect(packageJson).to.have.nested.property('config.commitizen.path', './node_modules/cz-conventional-changelog');\n    // TODO: Eventually may need to offer both path and package keys. package = npm package name\n    // Path for local development\n  });\n\n  it('succeeds if force is true', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Add a first adapter\n    commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { saveDev: true });\n\n    // TEST\n\n    // Adding a second adapter\n    expect(function () {\n      commitizenInit(config.paths.endUserRepo, 'cz-jira-smart-commit', { saveDev: true, force: true });\n    }).to.not.throw();\n\n    let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n    expect(packageJson.devDependencies).to.have.property('cz-jira-smart-commit');\n    expect(packageJson).to.have.nested.property('config.commitizen.path', './node_modules/cz-jira-smart-commit');\n\n  });\n\n  it('installs an adapter without --save-exact', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Add a first adapter\n    commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog');\n    let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n\n    // TEST\n    expect(packageJson.devDependencies).to.have.property('cz-conventional-changelog');\n    let range = packageJson.devDependencies['cz-conventional-changelog'];\n\n    // It should satisfy the requirements of a range\n    expect(semver.validRange(range)).to.not.equal(null);\n\n    // // But you CAN NOT increment a range\n    // expect(semver.inc(range, 'major')).to.equal(null);\n    // TODO: We need to figure out how to check if the repo has save exact set\n    // in the config before we can re-enable this. The --save-exact setting\n    // in our package.json breaks this test\n\n  });\n\n  it('installs an adapter with --save-exact', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Add a first adapter\n    commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { saveExact: true });\n    let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n\n    // TEST\n    expect(packageJson.devDependencies).to.have.property('cz-conventional-changelog');\n    let range = packageJson.devDependencies['cz-conventional-changelog'];\n\n    // It should satisfy the requirements of a range\n    expect(semver.validRange(range)).to.not.equal(null);\n\n    // But you CAN increment a single version\n    expect(semver.inc(range, 'major')).not.to.equal(null);\n\n  });\n\n  it('installs an commitizen with includeCommitizen', function () {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Add a first adapter\n    commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { includeCommitizen: true });\n    let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n\n    // TEST\n    expect(packageJson.devDependencies).to.have.property('cz-conventional-changelog');\n    expect(packageJson.devDependencies).to.have.property('commitizen');\n    let range = packageJson.devDependencies['cz-conventional-changelog'];\n\n    // It should satisfy the requirements of a range\n    expect(semver.validRange(range)).to.not.equal(null);\n\n    // But you CAN increment a single version\n    expect(semver.inc(range, 'major')).not.to.equal(null);\n\n  });\n\n  const supportedPackageManagers = ['yarn', 'pnpm'];\n\n  supportedPackageManagers.forEach((packageManger) => {\n    describe(`alternative package managers: ${packageManger}`, () => {\n      it(`installs an adapter with ${packageManger}`, function () {\n        this.timeout(config.maxTimeout); // this could take a while\n\n        // SETUP\n\n        // Install an adapter\n        commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { [packageManger]: true });\n\n        // TEST\n\n        // Check resulting json\n        let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n        if (packageManger === 'yarn') {\n          expect(packageJson).to.have.nested.property('dependencies.cz-conventional-changelog');\n        } else {\n          expect(packageJson).to.have.nested.property('devDependencies.cz-conventional-changelog');\n        }\n      });\n\n      it(`installs an adapter with ${packageManger} --dev`, function () {\n        this.timeout(config.maxTimeout); // this could take a while\n\n        // SETUP\n\n        // Install an adapter\n        commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { [packageManger]: true, dev: true });\n\n        // TEST\n\n        // Check resulting json\n        let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n        expect(packageJson).to.have.nested.property('devDependencies.cz-conventional-changelog');\n      });\n\n      it(`errors (with ${packageManger}) on previously installed adapter`, function () {\n        this.timeout(config.maxTimeout); // this could take a while\n\n        // SETUP\n\n        // Add a first adapter\n        commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { [packageManger]: true, dev: true });\n\n        // TEST\n        // Adding a second adapter\n        expect(function () {\n          commitizenInit(config.paths.endUserRepo, 'cz-jira-smart-commit', { [packageManger]: true, dev: true });\n        }).to.throw(/already configured/);\n\n        // Check resulting json\n        let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n        expect(packageJson).not.to.have.nested.property('devDependencies', 'cz-jira-smart-commit');\n        expect(packageJson).to.have.nested.property(\n          'config.commitizen.path',\n          './node_modules/cz-conventional-changelog'\n        );\n        // TODO: Eventually may need to offer both path and package keys. package = npm package name\n        // Path for local development\n      });\n\n      it(`succeeds (with ${packageManger}) if force is true`, function () {\n        this.timeout(config.maxTimeout); // this could take a while\n\n        // SETUP\n\n        // Add a first adapter\n        commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { [packageManger]: true, dev: true });\n\n        // TEST\n\n        // Adding a second adapter\n        expect(function () {\n          commitizenInit(config.paths.endUserRepo, 'cz-jira-smart-commit', {\n            [packageManger]: true,\n            dev: true,\n            force: true,\n          });\n        }).to.not.throw();\n\n        let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n        expect(packageJson.devDependencies).to.have.property('cz-jira-smart-commit');\n        expect(packageJson).to.have.nested.property('config.commitizen.path', './node_modules/cz-jira-smart-commit');\n      });\n\n      it(`installs (with ${packageManger}) an adapter without --save-exact`, function () {\n        this.timeout(config.maxTimeout); // this could take a while\n\n        // SETUP\n\n        // Add a first adapter\n        commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { [packageManger]: true, dev: true });\n        let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n\n        // TEST\n        expect(packageJson.devDependencies).to.have.property('cz-conventional-changelog');\n        let range = packageJson.devDependencies['cz-conventional-changelog'];\n\n        // It should satisfy the requirements of a range\n        expect(semver.validRange(range)).to.not.equal(null);\n\n        // // But you CAN NOT increment a range\n        // expect(semver.inc(range, 'major')).to.equal(null);\n        // TODO: We need to figure out how to check if the repo has save exact set\n        // in the config before we can re-enable this. The --save-exact setting\n        // in our package.json breaks this test\n      });\n\n      it(`installs an adapter with ${packageManger} --exact`, function () {\n        this.timeout(config.maxTimeout); // this could take a while\n\n        // SETUP\n\n        // Add a first adapter\n        commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', {\n          [packageManger]: true,\n          dev: true,\n          exact: true,\n        });\n        let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo);\n\n        // TEST\n        expect(packageJson.devDependencies).to.have.property('cz-conventional-changelog');\n        let range = packageJson.devDependencies['cz-conventional-changelog'];\n\n        // It should satisfy the requirements of a range\n        expect(semver.validRange(range)).to.not.equal(null);\n\n        // But you CAN increment a single version\n        expect(semver.inc(range, 'major')).not.to.equal(null);\n      });\n    });\n  });\n\n});\n\nafterEach(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  // All this should do is archive the tmp path to the artifacts\n  clean.afterEach(config.paths.tmp, config.preserve);\n});\n\nafter(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  // Once everything is done, the artifacts should be cleaned up based on\n  // the preserve setting in the config\n  clean.after(config.paths.tmp, config.preserve);\n});\n"
  },
  {
    "path": "test/tests/parsers.js",
    "content": "import { expect } from 'chai';\nimport { gitCz as gitCzParser, commitizen as commitizenParser } from '../../src/cli/parsers';\n\ndescribe('parsers', () => {\n  describe('git-cz', () => {\n    it('should parse --message \"Hello, World!\"', () => {\n      expect(gitCzParser.parse(['--amend', '--message', 'Hello, World!'])).to.deep.equal(['--amend']);\n    });\n\n    it('should parse --message=\"Hello, World!\"', () => {\n      expect(gitCzParser.parse(['--amend', '--message=Hello, World!'])).to.deep.equal(['--amend']);\n    });\n\n    it('should parse -amwip', () => {\n      expect(gitCzParser.parse(['-amwip'])).to.deep.equal(['-a']);\n    });\n\n    it('should parse -am=wip', () => {\n      expect(gitCzParser.parse(['-am=wip'])).to.deep.equal(['-a']);\n    });\n\n    it('should parse -am wip', () => {\n      expect(gitCzParser.parse(['-am', 'wip'])).to.deep.equal(['-a']);\n    });\n\n    it('should parse -a -m wip -n', () => {\n      expect(gitCzParser.parse(['-a', '-m', 'wip', '-n'])).to.deep.equal(['-a', '-n']);\n    });\n\n    it('should parse -a -m=wip -n', () => {\n      expect(gitCzParser.parse(['-a', '-m=wip', '-n'])).to.deep.equal(['-a', '-n']);\n    });\n  });\n\n  describe('commitizen', () => {\n    it('should parse out the --amend option', () => {\n      expect(commitizenParser.parse(['--amend'])).to.deep.equal({ _: [], amend: true })\n    });\n    it('should parse out the --hook option', () => {\n      expect(commitizenParser.parse(['--hook'])).to.deep.equal({ _: [], hook: true })\n    });\n  });\n});\n"
  },
  {
    "path": "test/tests/staging.js",
    "content": "import { expect } from 'chai';\n\n// Bootstrap our tester\nimport { bootstrap } from '../tester';\n\n// Get our source files\nimport { init as gitInit, addPath as gitAdd } from '../../src/git';\nimport { staging } from '../../src/commitizen';\n\n// Destructure some things for cleaner tests\nlet { config, repo, clean, files } = bootstrap();\nlet { writeFilesToPath } = files;\n\nbefore(function () {\n  // Creates the temp path\n  clean.before(config.paths.tmp);\n});\n\nbeforeEach(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  repo.createEndUser(config.paths.endUserRepo);\n});\n\ndescribe('staging', function () {\n\n  it('should determine if a repo is clean', function (done) {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n            contents: `duck-duck-goose`,\n            filename: `mydummyfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    gitInit(repoConfig.path);\n\n    staging.isClean('./@this-actually-does-not-exist', function (stagingError) {\n      expect(stagingError).to.be.an.instanceof(Error);\n\n      staging.isClean(repoConfig.path, function (stagingIsCleanError, stagingIsClean) {\n        expect(stagingIsCleanError).to.be.null;\n        expect(stagingIsClean).to.be.true;\n\n        writeFilesToPath(repoConfig.files, repoConfig.path);\n\n        gitAdd(repoConfig.path);\n\n        staging.isClean(repoConfig.path, function (afterWriteStagingIsCleanError, afterWriteStagingIsClean) {\n          expect(afterWriteStagingIsCleanError).to.be.null;\n          expect(afterWriteStagingIsClean).to.be.false;\n\n          writeFilesToPath({\n            dummymodified: {\n              contents: repoConfig.files.dummyfile.contents + '-modified',\n              filename: repoConfig.files.dummyfile.filename,\n            }\n          }, repoConfig.path);\n\n          staging.isClean(repoConfig.path, function (afterWriteStagingIsCleanError, afterWriteStagingIsClean) {\n            expect(afterWriteStagingIsCleanError).to.be.null;\n            expect(afterWriteStagingIsClean).to.be.false;\n            done();\n          });\n        });\n      });\n    });\n  });\n\n  it('should determine if --all flag adds files to staging area', function (done) {\n\n    this.timeout(config.maxTimeout); // this could take a while\n\n    // SETUP\n\n    // Describe a repo and some files to add and commit\n    let repoConfig = {\n      path: config.paths.endUserRepo,\n      files: {\n        dummyfile: {\n          contents: `duck-duck-gray-duck`,\n          filename: `mydummiestfile.txt`,\n        },\n        gitignore: {\n          contents: `node_modules/`,\n          filename: `.gitignore`\n        }\n      }\n    };\n\n    gitInit(repoConfig.path);\n\n    staging.isClean(repoConfig.path, function (stagingIsCleanError, stagingIsClean) {\n      expect(stagingIsCleanError).to.be.null;\n      expect(stagingIsClean).to.be.true;\n\n      writeFilesToPath(repoConfig.files, repoConfig.path);\n\n      staging.isClean(repoConfig.path, function (afterWriteStagingIsCleanError, afterWriteStagingIsClean) {\n        expect(afterWriteStagingIsCleanError).to.be.null;\n        expect(afterWriteStagingIsClean).to.be.true;\n\n        done();\n      });\n    }, true);\n  });\n});\n\nafterEach(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  // All this should do is archive the tmp path to the artifacts\n  clean.afterEach(config.paths.tmp, config.preserve);\n});\n\nafter(function () {\n  this.timeout(config.maxTimeout); // this could take a while\n  // Once everything is done, the artifacts should be cleaned up based on\n  // the preserve setting in the config\n  clean.after(config.paths.tmp, config.preserve);\n});\n"
  },
  {
    "path": "test/tests/util.js",
    "content": "import { expect } from 'chai';\nimport { isFunction } from '../../src/common/util';\n\ndescribe('common util', function () {\n\n  it('isFunction determines if a function is passed', function () {\n\n    // Truthies\n    expect(isFunction(function () {})).to.be.true;\n    expect(isFunction(new Function())).to.be.true;\n\n    // Falsies\n    expect(isFunction(undefined)).to.be.false;\n    expect(isFunction(null)).to.be.false;\n    expect(isFunction(49)).to.be.false;\n    expect(isFunction([])).to.be.false;\n    expect(isFunction({})).to.be.false;\n    expect(isFunction(\"asdf\")).to.be.false;\n    expect(isFunction(true)).to.be.false;\n    expect(isFunction(false)).to.be.false;\n    expect(isFunction(Symbol('test'))).to.be.false;\n\n  });\n\n});\n"
  },
  {
    "path": "test/tools/clean.js",
    "content": "import * as path from 'path';\nimport fs from 'fs-extra';\nimport { v4 as uuidv4} from 'uuid';\n\nexport {\n  before,\n  after,\n  afterEach\n};\n\n// Unique id for each 'run' of the entire test suite\nlet testSuiteRunId = uuidv4();\n\n// At the beginning of a run purge .tmp\nfunction before (tmpPath) {\n  cleanPath(tmpPath);\n  // clean(tmpPath, 'all');\n}\n\nfunction afterEach (tmpPath, preserve) {\n  if (preserve !== false) {\n    archive(tmpPath, testSuiteRunId);\n  }\n  cleanPath(tmpPath);\n}\n\n// After should listen to the user via the config\n// Before should always purge .tmp irregardless of config\nfunction after (tmpPath, preserve) {\n  clean(tmpPath, preserve);\n}\n\n/**\n * Copies the .tmp folder to the artifacts folder,\n * then clears the .tmp folder\n *\n * Generally should be run in afterEach()\n */\nfunction archive (tmpPath, testSuiteRunId) {\n  let destinationPath = path.resolve(tmpPath + '/../artifacts/' + testSuiteRunId + '/' + uuidv4());\n  fs.mkdirSync(destinationPath, { recursive: true });\n  fs.copySync(tmpPath, destinationPath);\n}\n\n/**\n * Cleans up the artifacts folder\n *\n * Generally called in after()\n */\nfunction clean (tmpPath, preserve) {\n\n  /**\n   * If preserve is a normal integer over 0 thats how many results to keep.\n   * If string 'all' then keep all\n   * Else: don't preserve anything\n   */\n  if (preserve === 'all') {\n\n    /**\n     * Preserve all artifacts\n     * Don't purge any artifacts\n     *\n     * BEWARE: this can fill the disk up over time\n     */\n    return;\n\n  } else if (isNormalNonZeroInteger(preserve)) {\n\n    /**\n     * Preserve a specific number of artifacts\n     *\n     * 1 = keep only th last run\n     * 2 = keep the last run and the one before it, purging any that happened beforehand\n     */\n\n    // Set the path\n    let artifactsBasePath = path.resolve(tmpPath + '/../artifacts');\n\n    // The the files in this path\n    let artifactFolders = fs.readdirSync(artifactsBasePath);\n\n    // Reverse chronologially sort the files\n    artifactFolders.sort(function (a, b) {\n      return fs.statSync(path.resolve(artifactsBasePath, b)).mtime.getTime() - fs.statSync(path.resolve(artifactsBasePath, a)).mtime.getTime();\n    });\n\n    // Keep only the number of files defined in the config setting 'preserve'.\n    keep(artifactsBasePath, artifactFolders, preserve);\n  }\n\n  // Always purge tmp, it needs to be empty for next run\n  cleanPath(tmpPath);\n}\n\nfunction isNormalNonZeroInteger (str) {\n\n  if (Number.isInteger(str) && str > 0) { // Check for integers above 0\n    return str;\n  } else { // Check for strings that cast to ints that are above 0\n    var n = ~~Number(str);\n    return String(n) === str && n > 0;\n  }\n}\n\n/**\n * Given a reverse chronological array of paths\n * This deletes all files except for n of them\n *\n * n is the (1 indexed) count of files to keep.\n */\nfunction keep (basePath, paths, n) {\n\n  for (let i = paths.length; i > n; i--) {\n    fs.removeSync(path.resolve(basePath, paths[i - 1]));\n  }\n}\n\nfunction cleanPath (tmpPath) {\n  fs.removeSync(tmpPath);\n  fs.mkdirSync(tmpPath);\n}\n"
  },
  {
    "path": "test/tools/files.js",
    "content": "import fs from 'fs';\nimport path from 'path';\nimport _ from 'lodash';\n\nexport {\n  writeFilesToPath\n};\n\n/**\n * Opinionated writing of files to a path.\n *\n * Expects files to be an object where each sub\n * object has properties filename and contents.\n */\nfunction writeFilesToPath (files, directoryPath) {\n  _.forOwn(files, function (key, value) {\n    fs.writeFileSync(path.resolve(directoryPath, files[value].filename), files[value].contents);\n  });\n}\n"
  },
  {
    "path": "test/tools/repo.js",
    "content": "import childProcess from 'child_process';\nimport fs from 'fs';\n\nexport {\n  createEmpty,\n  createEndUser\n};\n\n/**\n * Create an empty repo\n */\nfunction createEmpty (path) {\n  fs.mkdirSync(path, { recursive: true });\n  childProcess.spawnSync('npm', ['init', '--force', '--yes'], { cwd: path, shell: true });\n}\n\n/**\n * Create a new repo to hold an end user app\n */\nfunction createEndUser (path) {\n  createEmpty(path);\n}\n"
  }
]