Full Code of bower/bower for AI

master 4e0c3c1181c2 cached
248 files
1.1 MB
255.2k tokens
218 symbols
1 requests
Download .txt
Showing preview only (1,244K chars total). Download the full file or copy to clipboard to get everything.
Repository: bower/bower
Branch: master
Commit: 4e0c3c1181c2
Files: 248
Total size: 1.1 MB

Directory structure:
gitextract_0ya96a9h/

├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE.md
│   └── workflows/
│       └── nodejs.yml
├── .gitignore
├── .prettierignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── bin/
│   └── bower
├── lib/
│   ├── bin/
│   │   └── bower.js
│   ├── commands/
│   │   ├── cache/
│   │   │   ├── clean.js
│   │   │   └── list.js
│   │   ├── help.js
│   │   ├── home.js
│   │   ├── index.js
│   │   ├── info.js
│   │   ├── init.js
│   │   ├── install.js
│   │   ├── link.js
│   │   ├── list.js
│   │   ├── login.js
│   │   ├── lookup.js
│   │   ├── prune.js
│   │   ├── register.js
│   │   ├── search.js
│   │   ├── uninstall.js
│   │   ├── unregister.js
│   │   ├── update.js
│   │   └── version.js
│   ├── config.js
│   ├── core/
│   │   ├── Manager.js
│   │   ├── PackageRepository.js
│   │   ├── Project.js
│   │   ├── ResolveCache.js
│   │   ├── resolverFactory.js
│   │   ├── resolvers/
│   │   │   ├── FsResolver.js
│   │   │   ├── GitFsResolver.js
│   │   │   ├── GitHubResolver.js
│   │   │   ├── GitRemoteResolver.js
│   │   │   ├── GitResolver.js
│   │   │   ├── Resolver.js
│   │   │   ├── SvnResolver.js
│   │   │   ├── UrlResolver.js
│   │   │   ├── index.js
│   │   │   └── pluginResolverFactory.js
│   │   └── scripts.js
│   ├── index.js
│   ├── renderers/
│   │   ├── JsonRenderer.js
│   │   ├── StandardRenderer.js
│   │   └── index.js
│   ├── templates/
│   │   ├── helpers/
│   │   │   ├── colors.js
│   │   │   ├── condense.js
│   │   │   ├── indent.js
│   │   │   ├── index.js
│   │   │   ├── rpad.js
│   │   │   └── sum.js
│   │   ├── json/
│   │   │   ├── help-cache/
│   │   │   │   ├── clean.json
│   │   │   │   └── list.json
│   │   │   ├── help-cache.json
│   │   │   ├── help-home.json
│   │   │   ├── help-info.json
│   │   │   ├── help-init.json
│   │   │   ├── help-install.json
│   │   │   ├── help-link.json
│   │   │   ├── help-list.json
│   │   │   ├── help-login.json
│   │   │   ├── help-lookup.json
│   │   │   ├── help-prune.json
│   │   │   ├── help-register.json
│   │   │   ├── help-search.json
│   │   │   ├── help-uninstall.json
│   │   │   ├── help-unregister.json
│   │   │   ├── help-update.json
│   │   │   ├── help-version.json
│   │   │   └── help.json
│   │   └── std/
│   │       ├── conflict-resolved.std
│   │       ├── conflict.std
│   │       ├── help-cache.std
│   │       ├── help-generic.std
│   │       ├── help.std
│   │       ├── info.std
│   │       ├── lookup.std
│   │       ├── register.std
│   │       └── search-results.std
│   ├── util/
│   │   ├── abbreviations.js
│   │   ├── childProcess.js
│   │   ├── cli.js
│   │   ├── cmd.js
│   │   ├── copy.js
│   │   ├── createError.js
│   │   ├── createLink.js
│   │   ├── download.js
│   │   ├── extract.js
│   │   ├── fs.js
│   │   ├── isPathAbsolute.js
│   │   ├── readJson.js
│   │   ├── relativeToBaseDir.js
│   │   ├── removeIgnores.js
│   │   ├── resolve.js
│   │   ├── rimraf.js
│   │   ├── rootCheck.js
│   │   ├── semver.js
│   │   ├── template.js
│   │   ├── userAgent.js
│   │   ├── validLink.js
│   │   └── which.js
│   └── version.js
├── package.json
├── packages/
│   ├── bower-config/
│   │   ├── .editorconfig
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── lib/
│   │   │   ├── Config.js
│   │   │   ├── util/
│   │   │   │   ├── defaults.js
│   │   │   │   ├── expand.js
│   │   │   │   ├── paths.js
│   │   │   │   ├── proxy.js
│   │   │   │   └── rc.js
│   │   │   └── vendor/
│   │   │       └── optimist.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── assets/
│   │       │   ├── custom-ca/
│   │       │   │   ├── .bowerrc
│   │       │   │   └── ca-bundle.crt
│   │       │   ├── custom-ca-embed/
│   │       │   │   └── .bowerrc
│   │       │   ├── env-variables/
│   │       │   │   └── .bowerrc
│   │       │   └── env-variables-values/
│   │       │       └── .bowerrc
│   │       ├── cli.js
│   │       ├── helpers.js
│   │       ├── test.js
│   │       └── util/
│   │           ├── index.js
│   │           └── rc.js
│   ├── bower-endpoint-parser/
│   │   ├── .editorconfig
│   │   ├── .gitignore
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       └── test.js
│   ├── bower-json/
│   │   ├── .editorconfig
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── lib/
│   │   │   ├── json.js
│   │   │   ├── util/
│   │   │   │   ├── createError.js
│   │   │   │   ├── isAsset.js
│   │   │   │   └── isComponent.js
│   │   │   └── vendor/
│   │   │       └── ext-name.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── pkg-bower-json/
│   │       │   └── bower.json
│   │       ├── pkg-bower-json-invalid/
│   │       │   └── bower.json
│   │       ├── pkg-bower-json-malformed/
│   │       │   └── bower.json
│   │       ├── pkg-component(1)-json/
│   │       │   └── component.json
│   │       ├── pkg-component-json/
│   │       │   └── component.json
│   │       ├── pkg-dot-bower-json/
│   │       │   └── .bower.json
│   │       └── test.js
│   ├── bower-logger/
│   │   ├── .editorconfig
│   │   ├── .gitignore
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── lib/
│   │   │   └── Logger.js
│   │   ├── package.json
│   │   └── test/
│   │       └── test.js
│   └── bower-registry-client/
│       ├── .editorconfig
│       ├── .gitignore
│       ├── Client.js
│       ├── LICENSE
│       ├── README.md
│       ├── lib/
│       │   ├── index.js
│       │   ├── list.js
│       │   ├── lookup.js
│       │   ├── register.js
│       │   ├── search.js
│       │   ├── unregister.js
│       │   └── util/
│       │       ├── Cache.js
│       │       ├── createError.js
│       │       └── md5.js
│       ├── package.json
│       └── test/
│           ├── Client.js
│           ├── core/
│           │   ├── index.js
│           │   ├── list.js
│           │   ├── lookup.js
│           │   ├── register.js
│           │   ├── search.js
│           │   └── util/
│           │       ├── Cache.js
│           │       └── createError.js
│           ├── fixtures/
│           │   └── search.json
│           └── runner.js
├── publish.js
└── test/
    ├── assets/
    │   ├── resolve-cache/
    │   │   └── list-json-1.json
    │   ├── test-gz.txt
    │   └── test-temp-dir/
    │       ├── test-exception.js
    │       └── test.js
    ├── commands/
    │   ├── bower.js
    │   ├── cache/
    │   │   ├── clean.js
    │   │   └── list.js
    │   ├── help.js
    │   ├── home.js
    │   ├── index.js
    │   ├── info.js
    │   ├── init.js
    │   ├── install.js
    │   ├── link.js
    │   ├── list.js
    │   ├── login.js
    │   ├── lookup.js
    │   ├── prune.js
    │   ├── register.js
    │   ├── search.js
    │   ├── uninstall.js
    │   ├── unregister.js
    │   ├── update.js
    │   └── version.js
    ├── core/
    │   ├── Manager.js
    │   ├── packageRepository.js
    │   ├── resolveCache.js
    │   ├── resolverFactory.js
    │   ├── resolvers/
    │   │   ├── fsResolver.js
    │   │   ├── gitFsResolver.js
    │   │   ├── gitHubResolver.js
    │   │   ├── gitRemoteResolver.js
    │   │   ├── gitResolver.js
    │   │   ├── pluginResolverFactory.js
    │   │   ├── resolver.js
    │   │   ├── svnResolver.js
    │   │   └── urlResolver.js
    │   └── scripts.js
    ├── helpers.js
    ├── packages-svn.js
    ├── packages-svn.json
    ├── packages.js
    ├── packages.json
    ├── renderers/
    │   ├── JsonRenderer.js
    │   └── StandardRenderer.js
    ├── test.js
    └── util/
        ├── createLink.js
        ├── download.js
        ├── index.js
        ├── isPathAbsolute.js
        ├── nock.js
        ├── relativeToBaseDir.js
        ├── removeIgnores.js
        └── template.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[**.std]
insert_final_newline = false

[{package,bower}.json]
indent_size = 2


================================================
FILE: .eslintignore
================================================
node_modules
test/assets
test/reports
test/sample
test/tmp
packages/bower-logger/test


================================================
FILE: .eslintrc
================================================
{
  "env": {
    "node": true,
    "mocha": true
  },
  "rules": {
    "no-bitwise": 0,
    "curly": 0,
    "eqeqeq": 0,
    "guard-for-in": 0,
    "no-use-before-define": 0,
    "no-caller": 2,
    "no-new": 2,
    "no-plusplus": 0,
    "no-undef": 2,
    "no-unused-vars": 0,
    "strict": 0,
    "semi": 0,
    "comma-spacing": 2,
    "quote-props": [2, "as-needed"],
    "quotes": [2, "single", "avoid-escape"],
    "no-cond-assign": [ 2, "except-parens" ],
    "no-debugger": 2,
    "no-dupe-args": 2,
    "no-dupe-keys": 2,
    "no-duplicate-case": 2,
    "no-unreachable": 2,
    "valid-typeof": 2,
    "no-fallthrough": 2,
    "no-ex-assign": 2,
    "no-eq-null": 0,
    "no-eval": 0,
    "no-unused-expressions": 0,
    "block-scoped-var": 0,
    "no-iterator": 0,
    "no-loop-func": 2,
    "no-script-url": 0,
    "no-shadow": 0,
    "no-new-func": 2,
    "no-new-wrappers": 2,
    "no-invalid-this": 0,
    "space-before-blocks": [2, "always"],
    "space-before-function-paren": [2, "never"],
    "space-infix-ops": 2,
    "keyword-spacing": 2,
    "new-parens": 2,
    "no-multiple-empty-lines": [2, { max: 2}],
    "eol-last": 2,
    "no-trailing-spaces": 2
  }
}


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

open_collective: bower


================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
<!--

If you are reporting a new issue, make sure that we do not have any duplicates.
You can ensure this by searching the issue list for this repository.

You are welcome to open issues to discuss important general topics concerning Bower.
However for support questions, please consider using http://stackoverflow.com or
asking for help in our Discord channel: https://discordapp.com/invite/0fFM7QF0KpZaDeN9

# BUG REPORT

Use the commands below to provide key information to reproduce:
You do NOT have to include this information if this is a FEATURE REQUEST OR DISCUSSION

For more information about reporting bugs, see:
https://github.com/bower/bower/wiki/Report-a-Bug

-->

**Output of `bower -v && npm -v && node -v`:**

```
(paste your output here)
```

**Additional environment details (proxy, private registry, etc.):**



**Steps to reproduce the issue:**

1.
2.
3.

**Describe the results you received:**



**Describe the results you expected:**



**Additional information:**


================================================
FILE: .github/workflows/nodejs.yml
================================================
name: build

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - '**'

jobs:
  test:
    name: Node v${{ matrix.node-version }} on ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        # https://github.com/actions/setup-node/issues/27
        node-version: [6.x, 8.x, 10.x, 12.x, 14.x, 16.x, 18.x, 20.x, 22.x]
        os: [ubuntu-latest, macOS-latest, windows-latest]
        include:
        # Pin deprecated Node.js versions on Mac to specific MacOS,
        # as later OS architecture wont support them anymore.
        - node-version: 6.x
          os: macOS-13
        - node-version: 8.x
          os: macOS-13
        - node-version: 10.x
          os: macOS-13
        - node-version: 12.x
          os: macOS-13
        - node-version: 14.x
          os: macOS-13
        exclude:
        # Exclude older Node.js versions from macOS-latest
        - node-version: 6.x
          os: macOS-latest
        - node-version: 8.x
          os: macOS-latest
        - node-version: 10.x
          os: macOS-latest
        - node-version: 12.x
          os: macOS-latest
        - node-version: 14.x
          os: macOS-latest
    runs-on: ${{ matrix.os }}

    steps:
      - name: Set git config
        shell: bash
        run: |
          git config --global core.autocrlf false
          git config --global core.symlinks true
        if: runner.os == 'Windows'

      - uses: actions/checkout@v4
      - name: install
        run: yarn && (cd packages/bower-json && yarn link) && yarn link bower-json
      - name: lint
        run: npm run lint
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: bower tests
        run: npm test
        env:
          CI: true
        continue-on-error: ${{ matrix.os == 'windows-latest' }}  # Allow failure on Windows
      - name: bower-logger tests
        run: (cd packages/bower-logger && npm install && npm test)
        env:
          CI: true
      - name: bower-config tests
        run: (cd packages/bower-config && npm install && npm test)
        env:
          CI: true
      - name: bower-endpoint-parser tests
        run: (cd packages/bower-endpoint-parser && npm install && npm test)
        env:
          CI: true
      - name: bower-json tests
        run: (cd packages/bower-json && npm install && npm test)
        env:
          CI: true
      - name: bower-registry-client tests
        run: (cd packages/bower-registry-client && npm install && npm test)
        env:
          CI: true


================================================
FILE: .gitignore
================================================
!lib/bin
/node_modules
/npm-debug.log

/test/assets/package-*/
/test/assets/temp-*/
/test/reports
/test/tmp/

/bower.json
/component.json
/bower_components
/test/sample
!/test/sample/bower.json
/npm-shrinkwrap.json
package-lock.json


================================================
FILE: .prettierignore
================================================
**/node_modules/**
**/test/assets/**
**/bower_components/**
test/sample


================================================
FILE: CHANGELOG.md
================================================
# Changelog

## Newer releases

Please see: https://github.com/bower/bower/releases

## 1.8.0 - 2016-11-07

- Download tar archives from GitHub when possible (#2263)
  - Change default shorthand resolver for github from `git://` to `https://`
- Fix ssl handling by not setting GIT_SSL_NO_VERIFY=false (#2361)
- Allow for removing components with url instead of name (#2368)
- Show in warning message location of malformed bower.json (#2357)
- Improve handling of non-semver versions in git resolver (#2316)
- Fix handling of cached releases pluginResolverFactory (#2356)
- Allow to type the entire version when conflict occured (#2243)
- Allow `owner/reponame` shorthand for registering components (#2248)
- Allow single-char repo names and package names (#2249)
- Make `bower version` no longer honor `version` in bower.json (#2232)
- Add `postinstall` hook (#2252)
- Allow for `@` instead of `#` for `install` and `info` commands (#2322)
- Upgrade all bundled modules

## 1.7.9 - 2016-04-05

- Show warnings for invalid bower.json fields
- Update bower-json
  - Less strict validation on package name (allow spaces, slashes, and "@")

## 1.7.8 - 2016-04-04

- Don't ask for git credentials in non-interactive session, fixes #956 #1009
- Prevent swallowing exceptions with programmatic api, fixes #2187
- Update graceful-fs to 4.x in all dependences, fixes nodejs/node#5213
- Resolve pluggable resolvers using cwd and fallback to global modules, fixes #1919
- Upgrade handlebars to 4.0.5, closes #2195
- Replace all % chatacters in defined scripts, instead of only first one, fixes #2174
- Update opn package to fix issues with "bower open" command on Windows
- Update bower-config
  - Do not interpolate environment variables in script hooks, fixes bower/config#47
- Update bower-json
  - Validate package name more strictly and allow only latin letters, dots, dashes and underscores
- Add support for "save" and "save-exact" in .bowerrc, #2161

## 1.7.7 - 2016-01-27

Revert locations of all files while still packaging `node_modules`.

It's because people are depending on internals of bower, like
`bower/lib/renderers/StandardRenderer`. We want to preserve this
implicit contract, but we discourage it. The only official way
to use bower programmatically is through `require('bower')`.

## 1.7.6 - 2016-01-27

- Revert location of "bin/bower" as developers are using it directly ([#2157](https://github.com/bower/bower/issues/2157))
  Note: Correctly, you should use an alias created in `npm bin --global`.

## 1.7.5 - 2016-01-26

- Remove analytics from Bower, fixes ([#2150](https://github.com/bower/bower/pull/2150))
- Default to ^ operator on `bower install --save` ([#2145](https://github.com/bower/bower/pull/2145))
- Support absolute path in .bowerrc directory option ([#2130](https://github.com/bower/bower/pull/2130))
- Display user's name upon `bower login` command ([#2133](https://github.com/bower/bower/pull/2133))
- Decompress gzip files ([#2092](https://github.com/bower/bower/pull/2092))
- Prevent name clashes in package extraction ([#2102](https://github.com/bower/bower/pull/2102))
- When strictSsl is false, set GIT_SSL_NO_VERIFY=true ([#2129](https://github.com/bower/bower/issues/2129))
- Distribute bower with npm@3 for better Windows support ([#2146](https://github.com/bower/bower/issues/2146))
- Update request to 2.67.0 and fs-write-stream-atomic to 1.0.8
- Documentation improvements

## 1.7.4 - 2016-01-21

Unpublished because of issue with npm distribution:
https://github.com/npm/npm/issues/11227

## 1.7.3 - 2016-01-20

Unpublished because of issue with npm distribution:
https://github.com/npm/npm/issues/11227

## 1.7.2 - 2015-12-31

- Lock "fs-write-stream-atomic" to 1.0.5

## 1.7.1 - 2015-12-11

- Rollback "Add `bower update --save` functionality", it causes issues and needs more testing
- Fix backward-compatibility of `bower search --json` ([#2066](https://github.com/bower/bower/issues/2066))
- Ignore prerelease versions from `bower info` output
- Update update-notifier to 0.6.0
- Better formatting of help messages (https://github.com/bower/bower/commit/de3e1089da80f47ea3667c5ab80d301cddfd8c3e)
- Add help menu for update `--save` and `update --save-dev` (https://github.com/bower/bower/commit/612aaa88eb4d4b268b2d8665c338ac086af3a5b0)

## 1.7.0 - 2015-12-07

- Add `bower update --save` functionality ([#2035](https://github.com/bower/bower/issues/2035))
- `bower search` shows help message when no package name is specified ([#2066](https://github.com/bower/bower/issues/2066))
- Update only those packages that are explicitly requested by the user. Related Issues
  - [#256](https://github.com/bower/bower/issues/256)
  - [#924](https://github.com/bower/bower/issues/924)
  - [#1770](https://github.com/bower/bower/issues/1770)
- Allow for @ in username for SVN on windows ([#1650](https://github.com/bower/bower/issues/1650))
- Update bower config
  - Loads the .bowerrc file from the cwd specified on the command line
  - Allow the use of environment variables in .bowerrc ([#41](https://github.com/bower/config/issues/41))
  - Allow for array notation in ENV variables ([#44](https://github.com/bower/config/issues/44))

## 1.6.9 - 2015-12-04

- Change git version of fs-write-stream-atomic back to npm version ([#2079](https://github.com/bower/bower/issues/2079))

## 1.6.8 - 2015-11-27

- Use fs-write-stream-atomic for downloads
- Improved downloader that properly cleans after itself
- Fix shallow host detection ([#2040](https://github.com/bower/bower/pull/2040))
- Upgrade to ([bower-config#1.2.3](https://github.com/bower/config/releases/tag/1.2.3))
  - Properly restore env variables if they are undefined at the beginning
  - Properly handle `default` setting for config.ca
  - Display proper error if .bowerrc is a directory instead of file

## 1.6.7 - 2015-11-26

- Bundless all the dependencies again

## 1.6.6 - 2015-11-25

- Fixes regression with the published npm version

## 1.6.5 - 2015-10-24

- Updates to tests and documentation
- Fixes passing options when requesting downloads

## 1.6.4 - 2015-10-24

- Fix ignoring dependencies on multiple install run ([#1970](https://github.com/bower/bower/pull/1970))
- Use --non-interactive when running svn client ([#1969](https://github.com/bower/bower/pull/1969))
- Fix downloading of URLs ending with slash ([#1956](https://github.com/bower/bower/pull/1956))
- Add user-agent field for downloads by Bower ([#1960](https://github.com/bower/bower/pull/1960))

## 1.6.3 - 2015-10-16

Fixes regression issues introduced with 1.6.2, specifically:

- Allow for bower_components to be a symlink
- Allow setting custom registry in .bowerrc

## 1.6.2 - 2015-10-15

Fix dependency issues of 1.6.1. First published release of 1.6.x.

## 1.6.1 - 2015-10-15

Fix dependency issues of 1.6.0. Reverted release.

## 1.6.0 - 2015-10-15

- Shrinkwrap all dependencies and add them to bundledDependencies ([#1948](https://github.com/bower/bower/pull/1948))
- Allow for ignoring of child dependencies ([#1394](https://github.com/bower/bower/pull/1394))
- Allow passing `--config.resolvers` through CLI ([#1922](https://github.com/bower/bower/pull/1922))
- Use defaults values from package.json if it exists (bower init) ([#1731](https://github.com/bower/bower/issues/1731))
- Properly use cerificates set in .bowerrc ([#1869](https://github.com/bower/bower/pull/1869))
- Include package name when version conflict occurs ([#1917](https://github.com/bower/bower/pull/1917))
- Add timeout for permission check ([yeoman/insight#35](https://github.com/yeoman/insight/pull/35))
- Close file-handles when possible. Prevents all sorts of permission issues on Windows ([0bb1536](https://github.com/bower/bower/commit/0bb1536c9972e13f3be06bea9a8619632966c664))
- Prevent ENOENT error on Windows when in VM environment ([isaacs/chmodr#8](https://github.com/isaacs/chmodr/pull/8))

Reverted release.

## 1.5.4 - 2015-11-24

- [fix] Lock lru-cache dependency to 2.7.0

## 1.5.3 - 2015-09-24

- Revert auto sorting of bower dependencies, fixes ([#1897](https://github.com/bower/bower/issues/1897))
- Fix --save-exact feature for github endpoints, fixes ([#1925](https://github.com/bower/bower/issues/1925))
- Fix `bower init` to support private flag again ([#1819](https://github.com/bower/bower/pull/1819))
- Bump insight dependency to support prompt timeout ([#1102](https://github.com/bower/bower/issues/1102))

## 1.5.2 - 2015-08-25

- Revert update semver version from 2.x to 5.x, fixes ([#1896](https://github.com/bower/bower/issues/1896))
- Make bower commands work from subdirectories, fixes ([#1893](https://github.com/bower/bower/issues/1893))
- Put auto shallow cloning for git behind a flag, fixes ([#1764](https://github.com/bower/bower/issues/1764))

## 1.5.1 - 2015-08-24

- If cwd provided explicitly, force using it, fixes #1866

## 1.5.0 - 2015-08-24

- Pluggable Resolvers! http://bower.io/docs/pluggable-resolvers/
- Update semver version from 2.x to 5.x ([#1852](https://github.com/bower/bower/issues/1852))
- Auto-sort dependencies alphabetically ([#1381](https://github.com/bower/bower/issues/1381))
- Make bower commands work from subdirectories ([#1866](https://github.com/bower/bower/issues/1866))
- No longer prefer installing bower as global module ([#1865](https://github.com/bower/bower/issues/1865))

## 1.4.2 - 2015-11-24

- [fix] Lock lru-cache dependency to 2.7.0

## 1.4.1 - 2015-04-01

- [fix] Reading .bowerrc upwards directory tree ([#1763](https://github.com/bower/bower/issues/1763))
- [fix] Update bower-registry-client so it uses the same bower-config as bower

## 1.4.0 - 2015-03-30

- Add login and unregister commands ([#1719](https://github.com/bower/bower/issues/1719))
- Automatically detecting smart Git hosts ([#1628](https://github.com/bower/bower/issues/1628))
- [bower/config#23] Allow npm config variables ([#1711](https://github.com/bower/bower/issues/1711))
- [bower/config#24] Merge .bowerrc files upwards directory tree ([#1689](https://github.com/bower/bower/issues/1689))
- Better homedir detection (514eb8f)
- Add --save-exact flag ([#1654](https://github.com/bower/bower/issues/1654))
- Ensure extracted files are readable (tar-fs) ([#1548](https://github.com/bower/bower/issues/1548))
- The version command in the programmatic API now returns the new version ([#1755](https://github.com/bower/bower/issues/1755))
- Some minor fixes: #1639, #1620, #1576, #1557, 962a565, a464f5a
- Improved Windows support (AppVeyor CI, tests actually passing on Windows)
- OSX testing enabled on TravisCI

It also includes improved test coverage (~60% -> ~85%) and many refactors.

## 1.3.12 - 2014-09-28

- [stability] Fix versions for unstable dependencies ([#1532](https://github.com/bower/bower/pull/1532))
- [fix] Update tar-fs to support old tar format ([#1537](https://github.com/bower/bower/issues/1537))
- [fix] Make analytics work again ([#1529](https://github.com/bower/bower/pull/1529))
- [fix] Always disable analytics for non-interactive mode ([#1529](https://github.com/bower/bower/pull/1529))
- [fix] Bower init can create private packages again ([#1522](https://github.com/bower/bower/issues/1522))
- [fix] Show again missing newline for bower search output ([#1538](https://github.com/bower/bower/issues/1538))

## 1.3.11 - 2014-09-17

- [fix] Restore install missing dependencies on update ([1519](https://github.com/bower/bower/pull/1519))

## 1.3.10 - 2014-09-13

- [fix] Back down concurrency from 50 to 5 ([#1483](https://github.com/bower/bower/pull/1483))
- [fix] Read .bowerrc from specified cwd ([#1301](https://github.com/bower/bower/pull/1301))
- [fix] Disable shallow clones except those from GitHub ([#1393](https://github.com/bower/bower/pull/1393))
- [fix] Expose bower version ([#1478](https://github.com/bower/bower/pull/1478))
- [fix] Bump dependencies, including "request" ([#1467](https://github.com/bower/bower/pull/1467))
- [fix] Prevent an error when piping bower output to head ([#1508](https://github.com/bower/bower/pull/1508))
- [fix] Disable removing unnecessary resolutions ([#1061](https://github.com/bower/bower/pull/1061))
- [fix] Display the output of hooks again ([#1484](https://github.com/bower/bower/issues/1484))
- [fix] analytics: true in .bowerrc prevents user prompt ([#1470](https://github.com/bower/bower/pull/1470))
- [perf] Use `tar-fs` instead of `tar` for faster TAR extraction ([#1490](https://github.com/bower/bower/pull/1490))

## 1.3.9 - 2014-08-06

- [fix] Handle `tmp` sometimes returning an array ([#1434](https://github.com/bower/bower/pull/1434))

## 1.3.8 - 2014-7-11

- [fix] Lock down `tmp` package dep ([#1403](https://github.com/bower/bower/pull/1403), [#1407](https://github.com/bower/bower/pull/1407))

## 1.3.7 - 2014-07-04

- [fix] callstack error when processing installed packages with circular dependencies ([#1349](https://github.com/bower/bower/issues/1349))
- [fix] Prevent bower list --paths` failing with TypeError ([#1383](https://github.com/bower/bower/issues/1383))
- "bower install" fails if there's no bower.json in current directory ([#922](https://github.com/bower/bower/issues/922))

## 1.3.6 - 2014-07-02

- [fix] Make --force always re-run installation ([#931](https://github.com/bower/bower/issues/931))
- [fix] Disable caching for local resources ([#1356](https://github.com/bower/bower/issues/1356))
- [fix] Emit errors instead throwing them when using bower.commands API ([#1297](https://github.com/bower/bower/issues/1297))
- [fix] Main files and bower.json are never ignored ([#547](https://github.com/bower/bower/issues/547))
- [fix] Check if pkgMeta is undefined during uninstall command ([#1329](https://github.com/bower/bower/issues/1329))
- [fix] Make custom tmp dir and ignores play well with each other ([#1299](https://github.com/bower/bower/issues/1299))
- Warn users when installing package with missing properties ([#694](https://github.com/bower/bower/issues/694))


## 1.3.5 - 2014-06-06
- Search compatible versions in fetching packages ([#1147](https://github.com/bower/bower/issues/1147))

## 1.3.4 - 2014-06-02

- Resolve a situation in which the install process gets into an infinite loop ([#1169](https://github.com/bower/bower/issues/1169))
- Improved CLI output for conflicts ([#1284](https://github.com/bower/bower/issues/1284))
- Changed `bower version` to mirror the tag format of `npm version` ([#1278](https://github.com/bower/bower/issues/1278))
- Allow short commit SHAs to be used ([#990](https://github.com/bower/bower/issues/990))

## 1.3.3 - 2014-04-24

- Do not cache moving targets like branches ([#1242](https://github.com/bower/bower/issues/1242))
- Suppress output if --quiet option is specified ([#1124](https://github.com/bower/bower/pull/1124))
- Use "svn export" for efficiency ([#1224](https://github.com/bower/bower/pull/1224))
- Prevent loading insights and analytics on CI ([#1221](https://github.com/bower/bower/issues/1221))
- Make "bower list" respect custom components directory ([#1237](https://github.com/bower/bower/issues/1237))
- Improve non-interactive loading performance 2x ([#1238](https://github.com/bower/bower/issues/1238))
- Load commands only on demand, improving performance ([#1232](https://github.com/bower/bower/pull/1232))

## 1.3.2 - 2014-04-05

- Added yui moduleType [PR #1129](https://github.com/bower/bower/pull/1129)
- Fixes for concurrency issues [PR #1211](https://github.com/bower/bower/pull/1211)
- `link` now installs package dependencies [PR #891](https://github.com/bower/bower/pull/891)
- Improved conflict installation message [Commit](https://github.com/bower/bower/commit/bea533acf87903d4b411bfbaa7df93f852ef46a3)
- Add --production switch to "prune" command [PR #1168](https://github.com/bower/bower/pull/1168)


## 1.3.1 - 2014-03-10

- No longer ask for permission to gather analytics when running on in a CI environment.


## 1.3.0 - 2014-03-10

- **Removed support for node 0.8.** It may still work but we will no longer fix bugs for older versions of node.
- Add **Bower Insight** for opt-in analytics integration to help improve tool and gain insight on community trends
  - Old overview of [Insight](https://github.com/yeoman/yeoman/wiki/Insight), [Issue #260](https://github.com/bower/bower/issues/260)
  - Reporting to GA. Public Dashboard is in progress.
  - [Turn off interactive mode](https://github.com/bower/bower/issues/1162) if you run Bower in a CI environment
- Add `moduleType` property to bower init ([#934](https://github.com/bower/bower/pull/934))
- Fix prune command to log only after cleanup is completed ([#1023](https://github.com/bower/bower/issues/1023))
- Fix git resolver to ignore pre-release versions ([#1017](https://github.com/bower/bower/issues/1017))
- Fix shorthand flag for `save` option on `uninstall` command ([#1031](https://github.com/bower/bower/pull/1031))
- Add `bower version` command ([#961](https://github.com/bower/bower/pull/961))
- Add .bowerrc option to use `--save` by default when using `bower install` command ([#1074](https://github.com/bower/bower/pull/1074))
- Fix git resolver caching ([#1083](https://github.com/bower/bower/issues/1083))
- Fix reading versions from cache directory ([#1076](https://github.com/bower/bower/pull/1076))
- Add svn support ([#1055](https://github.com/bower/bower/pull/1055))
- Allow circular dependencies to be installed ([#1104](https://github.com/bower/bower/pull/1104))
- Add scripts/hooks support ([#718](https://github.com/bower/bower/pull/718))

_NOTE_: It's advisable that users use `--config.interactive=false` on automated scripts.


## 1.2.8 - 2013-12-02
- Fix absolute paths ending with / not going through the FsResolver, ([#898](https://github.com/bower/bower/issues/898))
- Allow query string parameters in package URLs
- Swapped 'unzip' module for 'decompress-zip', and some other small unzipping fixes([#873](https://github.com/bower/bower/issues/873), [#896](https://github.com/bower/bower/issues/896))
- Allow the root-check to be overridden when calling bower programmatically.
- Fixed some bugs relating to packages with a very large dependency tree
- Fix a bug caused by a recent change to semver


## 1.2.7 - 2013-09-29

- Do not swallow sync errors when using the programmatic API ([#849](https://github.com/bower/bower/issues/849))
- Fix resolutions not being saved if `--force-latest` is specified ([#861](https://github.com/bower/bower/issues/861))
- Fix `bower register` warning about URL conversion, even if no conversion occurred
- Fix `bower update` not correctly catching up branch commits
- Add configured directory in `.bowerrc` to the ignores in `bower init` ([#854](https://github.com/bower/bower/issues/854))
- Fix some case sensitive issues with data stored in registry cache (e.g.: jquery/jQuery, [#859](https://github.com/bower/bower/issues/859))
- Fix bower not checking out a tag if it looks like a semver (e.g.: 1.0, [#872](https://github.com/bower/bower/issues/872))
- Fix install & update commands printing the wrong versions in some cases ([#879](https://github.com/bower/bower/issues/879))
- Give priority to mime type headers when deciding if a package need to be extracted, except if it is `octet-stream`

_NOTE_: It's advisable that users run `bower cache clean`.


## 1.2.6 - 2013-09-04

- Bower now reports download progress even for servers that do not respond with `content-length` header.
- Do not translate endpoints when registering a package to a private registry server ([#832](https://github.com/bower/bower/issues/832))
- Detect corrupted downloads by comparing downloaded bytes with `content-length` header if possible; this fixes Bower silently failing on unstable networks ([#824](https://github.com/bower/bower/issues/824) and [#792](https://github.com/bower/bower/issues/792))
- Fix quotes in fields causing Bower to crash in the `init` command ([#841](https://github.com/bower/bower/issues/841))


## 1.2.5 - 2013-08-28

- Fix persistent conflict resolutions not working correctly for branches ([#818](https://github.com/bower/bower/issues/818))
- Fix Bower failing to run if HOME is not set ([#826](https://github.com/bower/bower/issues/826))
- Bower now prints a warning if HOME is not set ([#827](https://github.com/bower/bower/issues/827))
- Fix progress message being fired after completion of long running `git clone` commands
- Other minor improvements


## 1.2.4 - 2013-08-23

- Fix ignored nested folders not being correctly handled in some cases ([#814](https://github.com/bower/bower/issues/814))


## 1.2.3 - 2013-08-22

- Fix read of environment variables that map to config properties with dashes and also support nested ones ([#8@bower-config](https://github.com/bower/config/issues/8))
- Fix `bower info <package> <property>` printing the available versions (it shouldn't!)
- Fix interactive shell not being correctly detected in node `0.8.x` ([#802](https://github.com/bower/bower/issues/802))
- Fix `extraneous` flag in the `list` command being incorrectly set for saved dev dependencies in some cases
- Fix linked dependencies not being read in `bower list` on Windows ([#813](https://github.com/bower/bower/issues/813))
- Fix update notice not working with `--json`


## 1.2.2 - 2013-08-20

- Standardize prompt behaviour with and without `--json`
- Improve detection of `git` servers that do not support shallow clones ([#805](https://github.com/bower/bower/issues/805))
- Ignore remote tags (tags ending with ^{})
- Fix bower not saving the correct endpoint in some edge cases ([#806](https://github.com/bower/bower/issues/806))


## 1.2.1 - 2013-08-19

- Fix bower throwing on non-semver targets ([#800](https://github.com/bower/bower/issues/800))


## 1.2.0 - 2013-08-19

- __Bower no longer installs a pre-release version by default, that is, if no version/range is specified__ ([#782](https://github.com/bower/bower/issues/782))
- __`bower info <package>` will now show the latest `<package>` information along with the available versions__ ([#759](https://github.com/bower/bower/issues/759))
- __`bower link` no longer requires an elevated user on Windows in most cases__ ([#472](https://github.com/bower/bower/issues/472))
- __Init command now prompts for the whole `bower.json` spec properties, filling in default values for `author` and `homepage` based on `git` settings__ ([#693](https://github.com/bower/bower/issues/693))
- Changes to endpoint sources in `bower.json` are now catched up by `bower install` and `bower update` ([#788](https://github.com/bower/bower/issues/788))
- Allow semver ranges in `bower cache clean`, e.g. `bower cache clean jquery#<2.0.0` ([#688](https://github.com/bower/bower/issues/688))
- Normalize `bower list --paths` on Windows ([#279](https://github.com/bower/bower/issues/279))
- Multiple mains are now correctly outputted as an array in `bower list --paths` ([#784](https://github.com/bower/bower/issues/784))
- Add `--relative` option to `bower list --json` so that Bower outputs relative paths instead of absolute ([#714](https://github.com/bower/bower/issues/714))
- `bower list --paths` now outputs relative paths by default; can be turned off with `--no-relative` ([#785](https://github.com/bower/bower/issues/785))
- Bower no longer fails if `symlinks` to files are present in the `bower_components` folder ([#783](https://github.com/bower/bower/issues/783) and [#791](https://github.com/bower/bower/issues/791))
- Disable git templates/hooks when running `git` ([#761](https://github.com/bower/bower/issues/761))
- Add instructions to setup git workaround for proxies when execution of `git` fails ([#250](https://github.com/bower/bower/issues/250))
- Ignore `component.json` if it looks like a component(1) file ([#556](https://github.com/bower/bower/issues/556))
- Fix multi-user usage on bower when it creates temporary directories to hold some files
- Fix prompting causing an invalid JSON output when running commands with `--json`
- When running Bower commands programmatically, prompting is now disabled by default (see the updated programmatic [usage](https://github.com/bower/bower#programmatic-api) for more info)
- Other minor improvements and fixes

Fix for `#788` requires installed components to be re-installed.


## 1.1.2 - 2013-08-10

- Detect and fallback if the git server does not support `--depth=1` when cloning ([#747](https://github.com/bower/bower/issues/747))


## 1.1.1 - 2013-08-08

- Fix silent fail when spawning child processes in some edge cases ([#722](https://github.com/bower/bower/issues/722))
- Fix `home` command not guessing the correct URL for `GitHub` ssh endpoints (requires `bower cache-clean`)
- Fix bower not correctly filtering packages with symlinks in some cases ([#730](https://github.com/bower/bower/issues/730))
- Fix multi-user usage on bower when it falls back to create a `/tmp/bower` folder ([#743](https://github.com/bower/bower/issues/743))
- Bower now sends a fake user agent when behind a proxy by default, so that corporate proxies do not block requests ([#698](https://github.com/bower/bower/issues/698))
- Bower now translates GitHub public `git://` URLs to `git@` when behind a proxy ([#731](https://github.com/bower/bower/issues/731))
- Minor improvements to the CLI output on small terminals
- Minor programmatic usage improvements
- Minor help usage fixes


## 1.1.0 - 2013-08-03

- __Fix `--save` and `--save-dev` not working correctly for the uninstall command in some situations__
- __Attempting to register a package that declares `"private": true` in `bower.json` will result in an error ([#162](https://github.com/bower/bower/issues/162))__
- __Fix retry strategy on download error that was causing some strange I/O errors__ ([#699](https://github.com/bower/bower/issues/699) and [#704](https://github.com/bower/bower/issues/704))
- __`bower prune` now clears pruned packages dependencies if they are also extraneous__ ([#708](https://github.com/bower/bower/issues/708))
- __`bower uninstall` now uninstalls uninstalled packages dependencies if they are not shared ([#609](https://github.com/bower/bower/issues/609))__
- Fix `bower list` display the `incompatible` label even if they are compatible ([#710](https://github.com/bower/bower/issues/710))
- Fix `bower cache clean` not working correctly when `package#non-semver` is specified
- Implement no operation `completion` command to prevent weird output when hitting tab ([#691](https://github.com/bower/bower/issues/691))
- Fix `bower info --help` ([#703](https://github.com/bower/bower/issues/703))
- Add colorized output for `bower info <package>#<version>` ([#571](https://github.com/bower/bower/issues/571))
- Added `bower ls` as an alias to `bower list`
- Fix regression: do not create a json file when saving is required, warn instead
- Ignore linked packages when reading dependencies in `bower init` ([#709](https://github.com/bower/bower/issues/709))
- `bower list` is now able to (partially) reconstruct the dependency tree, even for dependencies not declared in `bower.json` ([#622](https://github.com/bower/bower/issues/622))


## 1.0.3 - 2013-07-30

- Fix some changes not being saved to bower.json ([#685](https://github.com/bower/bower/issues/685))
- Fix `bower info <package> <property>` not showing information related to property of the latest version of that package ([#684](https://github.com/bower/bower/issues/684))


## 1.0.2 - 2013-07-30

- Fix severe bug originated from a wrong merge that caused conflict messages to not show up correctly


## 1.0.1 - 2013-07-29

- Fix `bower register` going ahead even if the answer was `no` ([#644](https://github.com/bower/bower/issues/644))
- Fix local endpoints with backslashes on Windows ([#2@endpoint-parser](https://github.com/bower/endpoint-parser/pull/2))
- Fix usage of multiple registries in the registry-client ([#3@registry-client](https://github.com/bower/registry-client/pull/3) and [#2@registry-client](https://github.com/bower/registry-client/pull/2))
- File extensions now have more priority than mime types when deciding if extraction is necessary ([#657](https://github.com/bower/bower/pull/657))
- Fix `Bower` not working when calling `.bat`/`.cmd` commands on Windows; it affected people using `Git portable` ([#626](https://github.com/bower/bower/issues/626))
- Fix `bower list --paths` not resolving all files to absolute paths when the `main` property contained multiple files ([660](https://github.com/bower/bower/issues/660))
- Fix `Bower` renaming `bower.json` and `component.json` files to `index.json` when it was the only file in the folder ([#674](https://github.com/bower/bower/issues/674))
- Ignore symlinks when copying/extracting since they are not portable, specially across different hard-drives ([#665](https://github.com/bower/bower/issues/665))
- Local file/dir endpoints are now exclusively referenced by an absolute path or relative path starting with `.` ([#666](https://github.com/bower/bower/issues/666))
- Linked packages `bower.json` files are now parsed, making `bower list` account linked packages dependencies ([#659](https://github.com/bower/bower/issues/659))
- Bower now fails to run with sudo unless `--allow-root` is passed ([#498](https://github.com/bower/bower/issues/498))
- Add additional system information such as node version, bower version, OS version when an error occurs ([#670](https://github.com/bower/bower/issues/670))
- `bower install` no longer overwrites `linked` packages unless it needs to ([#593](https://github.com/bower/bower/issues/593)).
- All endpoint parts are now trimmed so that the Manager can better detect similar endpoints ([#3@endpoint-parser](https://github.com/bower/endpoint-parser/pull/3))
- `bower register` now shows the server that will be used ([#647](https://github.com/bower/endpoint-parser/pull/647))


## 1.0.0 - 2013-07-23

Total rewrite of bower.
The list bellow highlights the most important stuff.
For a complete list of changes that this rewrite and release brings please read: https://github.com/bower/bower/wiki/Rewrite-state


- Clear architecture and separation of concerns
- Much much faster
- `--json` output for all commands
- `--offline` usage for all commands, except `register`
- Proper `install` and `update` commands, similar to `npm` in behaviour
- Named endpoints when installing, e.g. `bower install backbone-amd=backbone#~1.0.0`
- New interactive conflict resolution strategy
- Prevent human errors when using `register`
- New `home` command, similar to `npm`
- New `cache list` command
- New `prune` command
- Many many general bug fixes

Non-backwards compatible changes:

- The value of the `json` property from .bowerrc is no longer used
- `--map` and `--sources` from the list command were removed, use `--json` instead
- Programmatic usage changed, specially the commands interface

Users upgrading from `bower-canary` and `bower@~0.x.x` should do a `bower cache clean`.
Additionally you may remove the `~/.bower` folder manually since it's no longer used.
On Windows the folder is located in `AppData/bower`.


## 0.10.0 - 2013-07-02

- __Allow specific commits to be targeted__ ([#275](https://github.com/bower/bower/issues/275))
- __Change bower default folder from `components` to `bower_components`__ ([#434](https://github.com/bower/bower/issues/434))
- __Support semver pre-releases and builds__ ([#188](https://github.com/bower/bower/issues/188))
- Use `Content-Type` and `Content-Disposition` to guess file types, such as zip files ([#454](https://github.com/bower/bower/pull/454))
- Fix bower failing silently when using an invalid version value in the bower.json file ([#439](https://github.com/bower/bower/issues/439))
- Fix bower slowness when downloading after redirects ([#437](https://github.com/bower/bower/issues/437))
- Detect and error out with a friendly message when `git` is not installed ([#362](https://github.com/bower/bower/issues/362))
- Add `--quiet` and `--silent` CLI options ([#343](https://github.com/bower/bower/issues/343))
- Minor programmatic usage improvements

_NOTE_: The `components` folder will still be used if already created, making it easier for users to upgrade.

## 0.9.2 - 2013-04-28
- Better fix for [#429](https://github.com/bower/bower/issues/429)

## 0.9.1 - 2013-04-27
- Update `package.json`, docs and other stuff to point to the new `Bower` organisation on GitHub
- Fix root label of `bower list` being an absolute path; now uses the package name
- Fix `bower update <pkg>` updating all packages; now throws when updating an unknown package
- Fix `list` command when package use different names than the `guessed` one ([#429](https://github.com/bower/bower/issues/429))

## 0.9.0 - 2013-04-25
- __Change from `component.json` to `bower.json`__ ([#39](https://github.com/bower/bower/issues/39))
- __Compatibility with `node 0.10.x`, including fix hangs/errors when extracting `zip` files__
- Fix `--save` and `--save-dev` not working with URLs that get redirected ([#417](https://github.com/bower/bower/issues/417))
- Fix `init` command targeting `~commit` instead of `*`. ([#385](https://github.com/bower/bower/issues/385))
- Remove temporary directories before exiting ([#345](https://github.com/bower/bower/issues/345))
- Integrate `update-notifier` ([#202](https://github.com/bower/bower/issues/202))
- Use `json` name when a package name was inferred ([#192](https://github.com/bower/bower/issues/192))
- Fix `bin/bower` not exiting with an exit code greater than zero when an error occurs ([#187](https://github.com/bower/bower/issues/187))
- Fix `--save` and `--save-dev` saving resolved shorthands instead of the actual shorthands
- Fix bower using user defined git templates ([#324](https://github.com/bower/bower/issues/324))
- Add command abbreviations ([#262](https://github.com/bower/bower/issues/262))
- Improve help messages and fix abuse of colors in output
- Wait for every package to resolve before printing error messages ([#290](https://github.com/bower/bower/issues/290))
- Add `shorthand_resolver` to allow shorthands to be resolved to repositories other than GitHub ([#278](https://github.com/bower/bower/issues/278))

## 0.8.6 - 2013-04-03
- Emergency fix for `node 0.8.x` users to make `zip` extraction work again

## 0.8.5 - 2013-03-04
- Fix `cache-clean` command clearing the completion cache when the command was called with specific packages
- Add error message when an error is caught parsing an invalid `component.json`

## 0.8.4 - 2013-03-01
- Fix some more duplicate async callbacks being called twice
- Preserve new lines when saving `component.json` ([#285](https://github.com/bower/bower/issues/285))

## 0.8.3 - 2013-02-27
- Fix error when using the `update` command ([#282](https://github.com/bower/bower/issues/282))

## 0.8.2 - 2013-02-26
- Fix some errors in windows while removing directories, had to downgrade `rimraf` ([#274](https://github.com/bower/bower/issues/274))
- Prevent duplicate package names in error summaries ([#277](https://github.com/bower/bower/issues/277))

## 0.8.1 - 2013-02-25
- Fix some async callbacks being fired twice ([#274](https://github.com/bower/bower/issues/274))

## 0.8.0 - 2013-02-24
- __Add init command similar to `npm init`__ ([#219](https://github.com/bower/bower/issues/219))
- __Add devDependencies__ support ([#251](https://github.com/bower/bower/issues/251))
- __Add `--save-dev` flag to install/uninstall commands__ ([#258](https://github.com/bower/bower/issues/258))
- `cache-clean` command now clears links pointing to nonexistent folders ([#182](https://github.com/bower/bower/issues/182))
- Fix issue when downloading assets behind a proxy using `https` ([#230](https://github.com/bower/bower/issues/230))
- Fix --save saving unresolved components ([#240](https://github.com/bower/bower/issues/240))
- Fix issue when extracting some zip files ([#225](https://github.com/bower/bower/issues/225))
- Fix automatic conflict resolver not selecting the correct version
- Add `--sources` option to the `list` command ([#235](https://github.com/bower/bower/issues/235))
- Automatically clear cache when git commands fail with code 128 ([#216](https://github.com/bower/bower/issues/216))
- Fix `bower` not working correctly behind a proxy in some commands ([#208](https://github.com/bower/bower/issues/208))

## 0.7.1 - 2013-02-20
- Remove postinstall script from `bower` installation

## 0.7.0 - 2013-02-01
- __Ability to resolve conflicts__ ([#214](https://github.com/bower/bower/issues/214))
- __Ability to search and publish to different endpoints by specifying them in the `.bowerrc` file__
- __Experimental autocompletion__
- __Ability to exclude (ignore) files__
- Fix minor issues in the cache clean command
- Better error message for invalid semver tags ([#185](https://github.com/bower/bower/issues/185))
- Only show discover message in the list command only if there are packages
- Fix mismatch issue due to reading cached component.json files ([#214](https://github.com/bower/bower/issues/214))
- Better error messages when reading invalid .bowerrc files ([#220](https://github.com/bower/bower/issues/220))
- Fix update command when used in packages pointing to assets ([#197](https://github.com/bower/bower/issues/197))
- Bower now obeys packages's `.bowerrc` if they define a different `json` ([#205](https://github.com/bower/bower/issues/205))

## 0.6.8 - 2012-12-14
- Improve list command
  - Does not fetch versions if not necessary (for --map and --paths options)
  - Add --offline option to prevent versions from being fetched
- Fix uninstall command not firing the `end` event
- Fix error when executing an unknown command ([#179](https://github.com/bower/bower/issues/179))
- Fix help for the ls command (alias of list)

## 0.6.7 - 2012-12-10
- Fix uninstall removing all unsaved dependencies ([#178](https://github.com/bower/bower/issues/178))
- Fix uninstall --force flag in some cases
- Add --silent option to the register option, to avoid questioning
- Fix possible issues with options in some commands
- Fix error reporting when reading invalid project component.json

## 0.6.6 - 2012-12-03
- Improve error handling while reading component.json
- Fix package name not being correctly collected in the error summary

## 0.6.5 - 2012-12-01
- Fix error summary not being displayed in some edge cases
- Fix bower not fetching latest commits correctly in some cases

## 0.6.4 - 2012-11-29
- Fix permission on downloaded files ([#160](https://github.com/bower/bower/issues/160))

## 0.6.3 - 2012-11-24
- Fix version not being correctly set for local packages ([#155](https://github.com/bower/bower/issues/155))

## 0.6.2 - 2012-11-23
- Fix uninstall --save when there is no component.json

## 0.6.1 - 2012-11-22
- Fix uninstall when the project component.json has no deps saved ([#153](https://github.com/bower/bower/issues/153))
- Fix uncaught errors when using file writer (they are now caught and reported)
- Fix temporary directories not being deleted when an exception occurs ([#153](https://github.com/bower/bower/issues/140))

## 0.6.0 - 2012-11-21
- __Add link command__ (similar to npm)
- Fix error reporting for nested deps
- Abort if a repository is detected when installing.
  This is useful to prevent people from loosing their work
- Minor fixes and improvements

## 0.5.1 - 2012-11-20
- Add errors summary to the end of install/update commands
- Add windows instructions to the README

## 0.5.0 - 2012-11-19
- __Remove package.json support__
- __Support for local path repositories__ ([#132](https://github.com/bower/bower/issues/132))
- `install --save` now saves the correct tag (e.g: ~0.0.1) instead of 'latest'
- `install --save` now saves packages pointing directly to assets correctly
- Bower automatically creates a component.json when install with `--save` is used
- Fix issues with list command ([#142](https://github.com/bower/bower/issues/142))
- Fix local paths not being saved when installing with --save ([#114](https://github.com/bower/bower/issues/114))
- `uninstall` now uninstalls nested dependencies if they are not shared ([#83](https://github.com/bower/bower/issues/83))
- `uninstall` now warns when a dependency conflict occurs and aborts.
  It will only proceed if the `--force` flag is passed
- Bower now detects mismatches between the version specified in the component.json and the tag, informing the user
- `bower ls` now informs when a package has a new commit (for non-tagged repos)
- Add jshintrc and fix a lot of issues related with JSHint warnings
- `bower register` now prompts if the user really wants to proceed


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Bower

Bower is a large community project with many different developers contributing at all levels to the project. There is more information about [contributing](https://github.com/bower/bower/wiki/Contributor-Guidelines) in the Wiki.

<a name="bugs"></a>
## 🐛 [Bug reports](https://github.com/bower/bower/wiki/Report-a-Bug)

## Casual Involvement

* Improve the bower.io site ([tickets](https://github.com/bower/bower.github.io/issues))
* Comment on issues and drive to resolution

## High-impact Involvement

* Maintaining the bower client.
  * Read [Architecture doc](https://github.com/bower/bower/wiki/Rewrite-architecture)
  * Triage, close, fix and resolve [issues](https://github.com/bower/bower/issues)

## Using the issue tracker

The issue tracker is the preferred channel for [bug reports](#bugs),
[features requests](#features) and [submitting pull
requests](#pull-requests), but please respect the following restrictions:

* Please **do not** use the issue tracker for personal support requests. Use
  [Stack Overflow](http://stackoverflow.com/questions/tagged/bower), or in serious cases
  send an e-mail to team@bower.io
  
* Please **do not** derail or troll issues. Keep the discussion on topic and
  respect the opinions of others.

<a name="features"></a>
## Feature requests

Feature requests are welcome. But take a moment to find out whether your idea
fits with the scope and aims of the project. It's up to *you* to make a strong
case to convince the project's developers of the merits of this feature. Please
provide as much detail and context as possible.


<a name="pull-requests"></a>
## Pull requests

Good pull requests - patches, improvements, new features - are a fantastic
help. They should remain focused in scope and avoid containing unrelated
commits.

**Please ask first** before embarking on any significant pull request (e.g.
implementing features, refactoring code), otherwise you risk spending a lot of
time working on something that the project's developers might not want to merge
into the project.

Please adhere to the coding conventions used throughout a project (indentation,
accurate comments, etc.) and any other requirements (such as test coverage).

Adhering to the following this process is the best way to get your work
included in the project:

1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork,
   and configure the remotes:

   ```bash
   # Clone your fork of the repo into the current directory
   git clone https://github.com/<your-username>/bower
   # Navigate to the newly cloned directory
   cd bower
   # Assign the original repo to a remote called "upstream"
   git remote add upstream https://github.com/bower/bower
   ```

2. If you cloned a while ago, get the latest changes from upstream:

   ```bash
   git checkout master
   git pull upstream master
   ```

3. Create a new topic branch (off the main project development branch) to
   contain your feature, change, or fix:

   ```bash
   git checkout -b <topic-branch-name>
   ```

4. Make sure to update, or add to the tests when appropriate. Patches and
   features will not be accepted without tests. Run `npm test` to check that
   all tests pass after you've made changes.

5. Commit your changes in logical chunks. Please adhere to these [git commit
   message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
   or your code is unlikely be merged into the main project. Use Git's
   [interactive rebase](https://help.github.com/articles/interactive-rebase)
   feature to tidy up your commits before making them public.

6. Locally merge (or rebase) the upstream development branch into your topic branch:

   ```bash
   git pull [--rebase] upstream master
   ```

7. Push your topic branch up to your fork:

   ```bash
   git push origin <topic-branch-name>
   ```

8. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
    with a clear title and description.

9. If you are asked to amend your changes before they can be merged in, please
   use `git commit --amend` (or rebasing for multi-commit Pull Requests) and
   force push to your remote feature branch. You may also be asked to squash
   commits.

10. If you are asked to squash your commits, then please use `git rebase -i master`. It will ask you to pick your commits - pick the major commits and squash the rest.

**IMPORTANT**: By submitting a patch, you agree to license your work under the
same license as that used by the project.


<a name="maintainers"></a>
## Maintainers

If you have commit access, please follow this process for merging patches and cutting new releases.

### Reviewing changes

1. Check that a change is within the scope and philosophy of the project.
2. Check that a change has any necessary tests and a proper, descriptive commit message.
3. Checkout the change and test it locally.
4. If the change is good, and authored by someone who cannot commit to
   `master`, please try to avoid using GitHub's merge button. Apply the change
   to `master` locally (feel free to amend any minor problems in the author's
   original commit if necessary).
5. If the change is good, and authored by another maintainer/collaborator, give
   them a "Ship it!" comment and let them handle the merge.

### Submitting changes

1. All non-trivial changes should be put up for review using GitHub Pull
   Requests.
2. Your change should not be merged into `master` (or another feature branch),
   without at least one "Ship it!" comment from another maintainer/collaborator
   on the project. "Looks good to me" is not the same as "Ship it!".
3. Try to avoid using GitHub's merge button. Locally rebase your change onto
   `master` and then push to GitHub.
4. Once a feature branch has been merged into its target branch, please delete
   the feature branch from the remote repository.

### Releasing a new version

1. Include all new functional changes in the CHANGELOG.
2. Use a dedicated commit to increment the version. The version needs to be
   added to the `CHANGELOG.md` (inc. date) and the `package.json`.
3. The commit message must be of `v0.0.0` format.
4. Create an annotated tag for the version: `git tag -m "v0.0.0" v0.0.0`.
5. Push the changes and tags to GitHub: `git push --tags origin master`.
6. Publish the new version to npm: `npm publish`.


================================================
FILE: LICENSE
================================================
Copyright (c) 2013-present Twitter and other contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Bower - A package manager for the web

[![Build](https://github.com/bower/bower/workflows/build/badge.svg)](https://github.com/bower/bower/actions?query=branch%3Amaster)
[![Backers on Open Collective](https://opencollective.com/bower/backers/badge.svg)](#backers)
[![Sponsors on Open Collective](https://opencollective.com/bower/sponsors/badge.svg)](#sponsors)

> ..psst! While Bower is maintained, we recommend [yarn](https://yarnpkg.com/) and [webpack](https://webpack.js.org/) or [parcel](https://parceljs.org/) for new front-end projects!

<img align="right" height="300" src="http://bower.io/img/bower-logo.png">

---

Bower offers a generic, unopinionated solution to the problem of **front-end package management**, while exposing the package dependency model via an API that can be consumed by a more opinionated build stack. There are no system wide dependencies, no dependencies are shared between different apps, and the dependency tree is flat.

Bower runs over Git, and is package-agnostic. A packaged component can be made up of any type of asset, and use any type of transport (e.g., AMD, CommonJS, etc.).

**View complete docs on [bower.io](http://bower.io)**

[View all packages available through Bower's registry](http://bower.io/search/).

## Install

```sh
$ npm install -g bower
```

Bower depends on [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/). Also make sure that [git](http://git-scm.com/) is installed as some bower
packages require it to be fetched and installed.


## Usage

See complete command line reference at [bower.io/docs/api/](http://bower.io/docs/api/)

### Installing packages and dependencies

```sh
# install dependencies listed in bower.json
$ bower install

# install a package and add it to bower.json
$ bower install <package> --save

# install specific version of a package and add it to bower.json
$ bower install <package>#<version> --save
```

### Using packages

We discourage using bower components statically for performance and security reasons (if component has an `upload.php` file that is not ignored, that can be easily exploited to do malicious stuff).

The best approach is to process components installed by bower with build tool (like [Grunt](http://gruntjs.com/) or [gulp](http://gulpjs.com/)), and serve them concatenated or using a module loader (like [RequireJS](http://requirejs.org/)).

### Uninstalling packages

To uninstall a locally installed package:

```sh
$ bower uninstall <package-name>
```

### prezto and oh-my-zsh users

On `prezto` or `oh-my-zsh`, do not forget to `alias bower='noglob bower'` or `bower install jquery\#1.9.1`

### Never run Bower with sudo

Bower is a user command; there is no need to execute it with superuser permissions.

### Windows users

To use Bower on Windows, you must install
[Git for Windows](http://git-for-windows.github.io/) correctly. Be sure to check the
options shown below:

<img src="https://cloud.githubusercontent.com/assets/10702007/10532690/d2e8991a-7386-11e5-9a57-613c7f92e84e.png" width="534" height="418" alt="Git for Windows" />

<img src="https://cloud.githubusercontent.com/assets/10702007/10532694/dbe8857a-7386-11e5-9bd0-367e97644403.png" width="534" height="418" alt="Git for Windows" />

Note that if you use TortoiseGit and if Bower keeps asking for your SSH
password, you should add the following environment variable: `GIT_SSH -
C:\Program Files\TortoiseGit\bin\TortoisePlink.exe`. Adjust the `TortoisePlink`
path if needed.

### Ubuntu users

To use Bower on Ubuntu, you might need to link `nodejs` executable to `node`:

```
sudo ln -s /usr/bin/nodejs /usr/bin/node
```

## Configuration

Bower can be configured using JSON in a `.bowerrc` file. Read over available options at [bower.io/docs/config](http://bower.io/docs/config).


## Support

You can ask questions on following channels in order:

* [StackOverflow](http://stackoverflow.com/questions/tagged/bower)
* [Issue Tracker](https://github.com/bower/bower/issues)
* team@bower.io

## Contributing

We welcome [contributions](https://github.com/bower/bower/graphs/contributors) of all kinds from anyone. Please take a moment to review the [guidelines for contributing](CONTRIBUTING.md).

* [Bug reports](https://github.com/bower/bower/wiki/Report-a-Bug)
* [Feature requests](CONTRIBUTING.md#features)
* [Pull requests](CONTRIBUTING.md#pull-requests)


Note that on Windows for tests to pass you need to configure Git before cloning:

```
git config --global core.autocrlf input
```


## Backers

Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/bower#backer)]

<a href='https://opencollective.com/bower/tiers/sponsors/1/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/1/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/2/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/2/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/3/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/3/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/4/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/4/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/5/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/5/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/6/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/6/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/7/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/7/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/8/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/8/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/9/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/9/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/10/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/10/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/11/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/11/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/12/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/12/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/13/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/13/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/14/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/14/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/15/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/15/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/16/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/16/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/17/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/17/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/18/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/18/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/19/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/19/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/20/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/20/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/21/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/21/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/22/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/22/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/23/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/23/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/24/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/24/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/25/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/25/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/26/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/26/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/27/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/27/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/28/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/28/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/29/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/29/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/30/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/30/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/31/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/31/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/32/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/32/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/33/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/33/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/34/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/34/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/35/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/35/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/36/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/36/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/37/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/37/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/38/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/38/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/39/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/39/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/40/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/40/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/41/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/41/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/42/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/42/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/43/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/43/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/44/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/44/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/45/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/45/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/46/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/46/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/47/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/47/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/48/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/48/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/49/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/49/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/50/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/50/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/51/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/51/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/52/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/52/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/53/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/53/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/54/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/54/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/55/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/55/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/56/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/56/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/57/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/57/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/58/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/58/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/59/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/59/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/60/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/60/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/61/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/61/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/62/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/62/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/63/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/63/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/64/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/64/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/65/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/65/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/66/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/66/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/67/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/67/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/68/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/68/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/69/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/69/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/70/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/70/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/71/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/71/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/72/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/72/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/73/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/73/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/74/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/74/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/75/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/75/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/76/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/76/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/77/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/77/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/78/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/78/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/79/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/79/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/80/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/80/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/81/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/81/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/82/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/82/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/83/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/83/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/84/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/84/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/85/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/85/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/86/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/86/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/87/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/87/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/88/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/88/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/89/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/89/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/90/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/90/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/91/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/91/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/92/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/92/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/93/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/93/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/94/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/94/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/95/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/95/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/96/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/96/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/97/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/97/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/98/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/98/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/99/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/99/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/100/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/100/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/101/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/101/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/102/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/102/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/103/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/103/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/104/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/104/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/105/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/105/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/106/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/106/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/107/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/107/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/108/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/108/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/109/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/109/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/110/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/110/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/111/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/111/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/112/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/112/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/113/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/113/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/114/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/114/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/115/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/115/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/116/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/116/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/117/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/117/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/118/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/118/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/119/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/119/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/120/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/120/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/121/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/121/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/122/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/122/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/123/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/123/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/124/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/124/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/125/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/125/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/126/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/126/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/127/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/127/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/128/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/128/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/129/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/129/avatar.svg'></a>
<a href='https://opencollective.com/bower/tiers/sponsors/130/website' target='_blank'><img src='https://opencollective.com/bower/tiers/sponsors/130/avatar.svg'></a>


## License

Copyright (c) 2012-present Twitter and [other contributors](https://github.com/bower/bower/graphs/contributors)

Licensed under the MIT License


================================================
FILE: SECURITY.md
================================================
# Security Policy

For critical security issues, please send an e-mail to team@bower.io instead of filing issue here.


================================================
FILE: bin/bower
================================================
#!/usr/bin/env node

require('../lib/bin/bower');


================================================
FILE: lib/bin/bower.js
================================================
process.bin = process.title = 'bower';

var Q = require('q');
var mout = require('mout');
var Logger = require('bower-logger');
var userHome = require('user-home');
var bower = require('../');
var version = require('../version');
var cli = require('../util/cli');
var rootCheck = require('../util/rootCheck');

var options;
var renderer;
var loglevel;
var command;
var commandFunc;
var logger;
var levels = Logger.LEVELS;

options = cli.readOptions({
    version: { type: Boolean, shorthand: 'v' },
    help: { type: Boolean, shorthand: 'h' },
    'allow-root': { type: Boolean }
});

// Handle print of version
if (options.version) {
    process.stdout.write(version + '\n');
    process.exit();
}

// Root check
rootCheck(options, bower.config);

// Set loglevel
if (bower.config.silent) {
    loglevel = levels.error;
} else if (bower.config.verbose) {
    loglevel = -Infinity;
    Q.longStackSupport = true;
} else if (bower.config.quiet) {
    loglevel = levels.warn;
} else {
    loglevel = levels[bower.config.loglevel] || levels.info;
}

// Get the command to execute
while (options.argv.remain.length) {
    command = options.argv.remain.join(' ');

    // Alias lookup
    if (bower.abbreviations[command]) {
        command = bower.abbreviations[command].replace(/\s/g, '.');
        break;
    }

    command = command.replace(/\s/g, '.');

    // Direct lookup
    if (mout.object.has(bower.commands, command)) {
        break;
    }

    options.argv.remain.pop();
}

// Execute the command
commandFunc = command && mout.object.get(bower.commands, command);
command = command && command.replace(/\./g, ' ');

// If no command was specified, show bower help
// Do the same if the command is unknown
if (!commandFunc) {
    logger = bower.commands.help();
    command = 'help';
    // If the user requested help, show the command's help
    // Do the same if the actual command is a group of other commands (e.g.: cache)
} else if (options.help || !commandFunc.line) {
    logger = bower.commands.help(command);
    command = 'help';
    // Call the line method
} else {
    logger = commandFunc.line(process.argv);

    // If the method failed to interpret the process arguments
    // show the command help
    if (!logger) {
        logger = bower.commands.help(command);
        command = 'help';
    }
}

// Get the renderer and configure it with the executed command
renderer = cli.getRenderer(command, logger.json, bower.config);

function handleLogger(logger, renderer) {
    logger
        .on('end', function(data) {
            if (!bower.config.silent && !bower.config.quiet) {
                renderer.end(data);
            }
        })
        .on('error', function(err) {
            if (
                command !== 'help' &&
                (err.code === 'EREADOPTIONS' || err.code === 'EINVFORMAT')
            ) {
                logger = bower.commands.help(command);
                renderer = cli.getRenderer('help', logger.json, bower.config);
                handleLogger(logger, renderer);
            } else {
                if (levels.error >= loglevel) {
                    renderer.error(err);
                }

                process.exit(1);
            }
        })
        .on('log', function(log) {
            if (levels[log.level] >= loglevel) {
                renderer.log(log);
            }
        })
        .on('prompt', function(prompt, callback) {
            renderer.prompt(prompt).then(function(answer) {
                callback(answer);
            });
        });
}

handleLogger(logger, renderer);

// Warn if HOME is not SET
if (!userHome) {
    logger.warn(
        'no-home',
        'HOME environment variable not set. User config will not be loaded.'
    );
}

if (bower.config.interactive) {
    var updateNotifier = require('update-notifier');

    // Check for newer version of Bower
    var notifier = updateNotifier({ pkg: { name: 'bower', version: version } });

    if (notifier.update && levels.info >= loglevel) {
        notifier.notify();
    }
}


================================================
FILE: lib/commands/cache/clean.js
================================================
var fs = require('../../util/fs');
var path = require('path');
var mout = require('mout');
var Q = require('q');
var rimraf = require('../../util/rimraf');
var endpointParser = require('bower-endpoint-parser');
var PackageRepository = require('../../core/PackageRepository');
var semver = require('../../util/semver');
var defaultConfig = require('../../config');

function clean(logger, endpoints, options, config) {
    var decEndpoints;
    var names;

    options = options || {};
    config = defaultConfig(config);

    // If endpoints is an empty array, null them
    if (endpoints && !endpoints.length) {
        endpoints = null;
    }

    // Generate decomposed endpoints and names based on the endpoints
    if (endpoints) {
        decEndpoints = endpoints.map(function(endpoint) {
            return endpointParser.decompose(endpoint);
        });
        names = decEndpoints.map(function(decEndpoint) {
            return decEndpoint.name || decEndpoint.source;
        });
    }

    return Q.all([
        clearPackages(decEndpoints, config, logger),
        clearLinks(names, config, logger)
    ]).spread(function(entries) {
        return entries;
    });
}

function clearPackages(decEndpoints, config, logger) {
    var repository = new PackageRepository(config, logger);

    return repository.list().then(function(entries) {
        var promises;

        // Filter entries according to the specified packages
        if (decEndpoints) {
            entries = entries.filter(function(entry) {
                return !!mout.array.find(decEndpoints, function(decEndpoint) {
                    var entryPkgMeta = entry.pkgMeta;

                    // Check if name or source match the entry
                    if (
                        decEndpoint.name !== entryPkgMeta.name &&
                        decEndpoint.source !== entryPkgMeta.name &&
                        decEndpoint.source !== entryPkgMeta._source
                    ) {
                        return false;
                    }

                    // If target is a wildcard, simply return true
                    if (decEndpoint.target === '*') {
                        return true;
                    }

                    // If it's a semver target, compare using semver spec
                    if (semver.validRange(decEndpoint.target)) {
                        return semver.satisfies(
                            entryPkgMeta.version,
                            decEndpoint.target
                        );
                    }

                    // Otherwise, compare against target/release
                    return (
                        decEndpoint.target === entryPkgMeta._target ||
                        decEndpoint.target === entryPkgMeta._release
                    );
                });
            });
        }

        promises = entries.map(function(entry) {
            return repository.eliminate(entry.pkgMeta).then(function() {
                logger.info(
                    'deleted',
                    'Cached package ' +
                        entry.pkgMeta.name +
                        ': ' +
                        entry.canonicalDir,
                    {
                        file: entry.canonicalDir
                    }
                );
            });
        });

        return Q.all(promises)
            .then(function() {
                if (!decEndpoints) {
                    // Ensure that everything is cleaned,
                    // even invalid packages in the cache
                    return repository.clear();
                }
            })
            .then(function() {
                return entries;
            });
    });
}

function clearLinks(names, config, logger) {
    var promise;
    var dir = config.storage.links;

    // If no names are passed, grab all links
    if (!names) {
        promise = Q.nfcall(fs.readdir, dir).fail(function(err) {
            if (err.code === 'ENOENT') {
                return [];
            }

            throw err;
        });
        // Otherwise use passed ones
    } else {
        promise = Q.resolve(names);
    }

    return promise.then(function(names) {
        var promises;
        var linksToRemove = [];

        // Decide which links to delete
        promises = names.map(function(name) {
            var link = path.join(config.storage.links, name);

            return Q.nfcall(fs.readlink, link).then(
                function(linkTarget) {
                    // Link exists, check if it points to a folder
                    // that still exists
                    return (
                        Q.nfcall(fs.stat, linkTarget)
                            .then(function(stat) {
                                // Target is not a folder..
                                if (!stat.isDirectory()) {
                                    linksToRemove.push(link);
                                }
                            })
                            // Error occurred reading the link
                            .fail(function() {
                                linksToRemove.push(link);
                            })
                    );
                    // Ignore if link does not exist
                },
                function(err) {
                    if (err.code !== 'ENOENT') {
                        linksToRemove.push(link);
                    }
                }
            );
        });

        return Q.all(promises).then(function() {
            var promises;

            // Remove each link that was declared as invalid
            promises = linksToRemove.map(function(link) {
                return Q.nfcall(rimraf, link).then(function() {
                    logger.info('deleted', 'Invalid link: ' + link, {
                        file: link
                    });
                });
            });

            return Q.all(promises);
        });
    });
}

// -------------------

clean.readOptions = function(argv) {
    var cli = require('../../util/cli');
    var options = cli.readOptions(argv);
    var endpoints = options.argv.remain.slice(2);

    delete options.argv;

    return [endpoints, options];
};

module.exports = clean;


================================================
FILE: lib/commands/cache/list.js
================================================
var mout = require('mout');
var PackageRepository = require('../../core/PackageRepository');
var defaultConfig = require('../../config');

function list(logger, packages, options, config) {
    var repository;

    config = defaultConfig(config);
    repository = new PackageRepository(config, logger);

    // If packages is an empty array, null them
    if (packages && !packages.length) {
        packages = null;
    }

    return repository.list().then(function(entries) {
        if (packages) {
            // Filter entries according to the specified packages
            entries = entries.filter(function(entry) {
                return !!mout.array.find(packages, function(pkg) {
                    return pkg === entry.pkgMeta.name;
                });
            });
        }

        return entries;
    });
}

// -------------------

list.readOptions = function(argv) {
    var cli = require('../../util/cli');
    var options = cli.readOptions(argv);
    var packages = options.argv.remain.slice(2);

    delete options.argv;

    return [packages, options];
};

module.exports = list;


================================================
FILE: lib/commands/help.js
================================================
var Q = require('q');
var path = require('path');
var fs = require('../util/fs');
var createError = require('../util/createError');

function help(logger, name, config) {
    var json;

    if (name) {
        json = path.resolve(
            __dirname,
            '../templates/json/help-' + name.replace(/\s+/g, '/') + '.json'
        );
    } else {
        json = path.resolve(__dirname, '../templates/json/help.json');
    }

    return Q.promise(function(resolve) {
        fs.exists(json, resolve);
    }).then(function(exists) {
        if (!exists) {
            throw createError('Unknown command: ' + name, 'EUNKNOWNCMD', {
                command: name
            });
        }

        return require(json);
    });
}

// -------------------

help.readOptions = function(argv) {
    var cli = require('../util/cli');
    var options = cli.readOptions(argv);
    var name = options.argv.remain.slice(1).join(' ');

    return [name];
};

module.exports = help;


================================================
FILE: lib/commands/home.js
================================================
var Project = require('../core/Project');
var open = require('opn');
var endpointParser = require('bower-endpoint-parser');
var createError = require('../util/createError');
var defaultConfig = require('../config');

function home(logger, name, config) {
    var project;
    var promise;
    var decEndpoint;

    config = defaultConfig(config);
    project = new Project(config, logger);

    // Get the package meta
    // If no name is specified, read the project json
    // If a name is specified, fetch from the package repository
    if (!name) {
        promise = project.hasJson().then(function(json) {
            if (!json) {
                throw createError('You are not inside a package', 'ENOENT');
            }

            return project.getJson();
        });
    } else {
        decEndpoint = endpointParser.decompose(name);
        promise = project
            .getPackageRepository()
            .fetch(decEndpoint)
            .spread(function(canonicalDir, pkgMeta) {
                return pkgMeta;
            });
    }

    // Get homepage and open it
    return promise.then(function(pkgMeta) {
        var homepage = pkgMeta.homepage;

        if (!homepage) {
            throw createError('No homepage set for ' + pkgMeta.name, 'ENOHOME');
        }

        open(homepage, { wait: false });
        return homepage;
    });
}

// -------------------

home.readOptions = function(argv) {
    var cli = require('../util/cli');
    var options = cli.readOptions(argv);
    var name = options.argv.remain[1];

    return [name];
};

module.exports = home;


================================================
FILE: lib/commands/index.js
================================================
var Q = require('q');
var Logger = require('bower-logger');
var config = require('../config');

/**
 * Require commands only when called.
 *
 * Running `commandFactory(id)` is equivalent to `require(id)`. Both calls return
 * a command function. The difference is that `cmd = commandFactory()` and `cmd()`
 * return as soon as possible and load and execute the command asynchronously.
 */
function commandFactory(id) {
    function runApi() {
        var command = require(id);
        var commandArgs = [].slice.call(arguments);

        return withLogger(function(logger) {
            commandArgs.unshift(logger);

            return command.apply(undefined, commandArgs);
        });
    }

    function runFromArgv(argv) {
        var commandArgs;
        var command = require(id);

        commandArgs = command.readOptions(argv);

        return withLogger(function(logger) {
            commandArgs.unshift(logger);

            return command.apply(undefined, commandArgs);
        });
    }

    function withLogger(func) {
        var logger = new Logger();

        Q.try(func, logger).done(
            function() {
                config.restore();
                var args = [].slice.call(arguments);
                args.unshift('end');
                logger.emit.apply(logger, args);
            },
            function(error) {
                config.restore();
                logger.emit('error', error);
            }
        );

        return logger;
    }

    runApi.line = runFromArgv;

    return runApi;
}

module.exports = {
    cache: {
        clean: commandFactory('./cache/clean'),
        list: commandFactory('./cache/list')
    },
    help: commandFactory('./help'),
    home: commandFactory('./home'),
    info: commandFactory('./info'),
    init: commandFactory('./init'),
    install: commandFactory('./install'),
    link: commandFactory('./link'),
    list: commandFactory('./list'),
    login: commandFactory('./login'),
    lookup: commandFactory('./lookup'),
    prune: commandFactory('./prune'),
    register: commandFactory('./register'),
    search: commandFactory('./search'),
    update: commandFactory('./update'),
    uninstall: commandFactory('./uninstall'),
    unregister: commandFactory('./unregister'),
    version: commandFactory('./version')
};


================================================
FILE: lib/commands/info.js
================================================
var mout = require('mout');
var Q = require('q');
var endpointParser = require('bower-endpoint-parser');
var PackageRepository = require('../core/PackageRepository');
var defaultConfig = require('../config');

function info(logger, endpoint, property, config) {
    if (!endpoint) {
        return;
    }

    // handle @ as version divider
    var splitParts = endpoint.split('/');
    splitParts[splitParts.length - 1] = splitParts[
        splitParts.length - 1
    ].replace('@', '#');
    endpoint = splitParts.join('/');

    var repository;
    var decEndpoint;

    config = defaultConfig(config);
    repository = new PackageRepository(config, logger);

    decEndpoint = endpointParser.decompose(endpoint);

    return Q.all([
        getPkgMeta(repository, decEndpoint, property),
        decEndpoint.target === '*' && !property
            ? repository.versions(decEndpoint.source)
            : null
    ]).spread(function(pkgMeta, versions) {
        if (versions) {
            return {
                name: decEndpoint.source,
                versions: versions,
                latest: pkgMeta
            };
        }

        return pkgMeta;
    });
}

function getPkgMeta(repository, decEndpoint, property) {
    return repository
        .fetch(decEndpoint)
        .spread(function(canonicalDir, pkgMeta) {
            pkgMeta = mout.object.filter(pkgMeta, function(value, key) {
                return key.charAt(0) !== '_';
            });

            // Retrieve specific property
            if (property) {
                pkgMeta = mout.object.get(pkgMeta, property);
            }

            return pkgMeta;
        });
}

// -------------------

info.readOptions = function(argv) {
    var cli = require('../util/cli');
    var options = cli.readOptions(argv);
    var pkg = options.argv.remain[1];
    var property = options.argv.remain[2];

    return [pkg, property];
};

module.exports = info;


================================================
FILE: lib/commands/init.js
================================================
var mout = require('mout');
var fs = require('../util/fs');
var path = require('path');
var Q = require('q');
var endpointParser = require('bower-endpoint-parser');
var Project = require('../core/Project');
var defaultConfig = require('../config');
var GitHubResolver = require('../core/resolvers/GitHubResolver');
var cmd = require('../util/cmd');
var createError = require('../util/createError');

function init(logger, config) {
    var project;

    config = config || {};

    if (!config.cwd) {
        config.cwd = process.cwd();
    }

    config = defaultConfig(config);

    // This command requires interactive to be enabled
    if (!config.interactive) {
        throw createError('Register requires an interactive shell', 'ENOINT', {
            details:
                'Note that you can manually force an interactive shell with --config.interactive'
        });
    }

    project = new Project(config, logger);

    // Start with existing JSON details
    return (
        readJson(project, logger)
            // Fill in defaults
            .then(setDefaults.bind(null, config))
            // Now prompt user to make changes
            .then(promptUser.bind(null, logger))
            // Set ignore based on the response
            .spread(setIgnore.bind(null, config))
            // Set dependencies based on the response
            .spread(setDependencies.bind(null, project))
            // All done!
            .spread(saveJson.bind(null, project, logger))
    );
}

function readJson(project, logger) {
    return project.hasJson().then(function(json) {
        if (json) {
            logger.warn(
                'existing',
                'The existing ' +
                    path.basename(json) +
                    ' file will be used and filled in'
            );
        }

        return project.getJson();
    });
}

function saveJson(project, logger, json) {
    // Cleanup empty props (null values, empty strings, objects and arrays)
    mout.object.forOwn(json, function(value, key) {
        if (!validConfigValue(value)) {
            delete json[key];
        }
    });

    logger.info('json', 'Generated json', { json: json });

    // Confirm the json with the user
    return Q.nfcall(logger.prompt.bind(logger), {
        type: 'confirm',
        message: 'Looks good?',
        default: true
    }).then(function(good) {
        if (!good) {
            return null;
        }

        // Save json (true forces file creation)
        return project.saveJson(true);
    });
}

// Test if value is of a type supported by bower.json[0] - Object, Array, String, Boolean - or a Number
// [0]: https://github.com/bower/bower.json-spec
function validConfigValue(val) {
    return (
        mout.lang.isObject(val) ||
        mout.lang.isArray(val) ||
        mout.lang.isString(val) ||
        mout.lang.isBoolean(val) ||
        mout.lang.isNumber(val)
    );
}

function setDefaults(config, json) {
    var name;
    var promise = Q.resolve();

    // Name
    if (!json.name) {
        json.name = path.basename(config.cwd);
    }

    // Main
    if (!json.main) {
        // Remove '.js' from the end of the package name if it is there
        name = path.basename(json.name, '.js');

        if (fs.existsSync(path.join(config.cwd, 'index.js'))) {
            json.main = 'index.js';
        } else if (fs.existsSync(path.join(config.cwd, name + '.js'))) {
            json.main = name + '.js';
        }
    }

    // Homepage
    if (!json.homepage) {
        // Set as GitHub homepage if it's a GitHub repository
        promise = promise.then(function() {
            return cmd('git', ['config', '--get', 'remote.origin.url'])
                .spread(function(stdout) {
                    var pair;

                    stdout = stdout.trim();
                    if (!stdout) {
                        return;
                    }

                    pair = GitHubResolver.getOrgRepoPair(stdout);
                    if (pair) {
                        json.homepage =
                            'https://github.com/' + pair.org + '/' + pair.repo;
                    }
                })
                .fail(function() {});
        });
    }

    if (!json.authors) {
        promise = promise.then(function() {
            // Get the user name configured in git
            return cmd('git', [
                'config',
                '--get',
                '--global',
                'user.name'
            ]).spread(
                function(stdout) {
                    var gitEmail;
                    var gitName = stdout.trim();

                    // Abort if no name specified
                    if (!gitName) {
                        return;
                    }

                    // Get the user email configured in git
                    return cmd('git', [
                        'config',
                        '--get',
                        '--global',
                        'user.email'
                    ])
                        .spread(
                            function(stdout) {
                                gitEmail = stdout.trim();
                            },
                            function() {}
                        )
                        .then(function() {
                            json.authors = gitName;
                            json.authors += gitEmail
                                ? ' <' + gitEmail + '>'
                                : '';
                        });
                },
                function() {}
            );
        });
    }

    return promise.then(function() {
        return json;
    });
}

function promptUser(logger, json) {
    var questions = [
        {
            name: 'name',
            message: 'name',
            default: json.name,
            type: 'input'
        },
        {
            name: 'description',
            message: 'description',
            default: json.description,
            type: 'input'
        },
        {
            name: 'main',
            message: 'main file',
            default: json.main,
            type: 'input'
        },
        {
            name: 'keywords',
            message: 'keywords',
            default: json.keywords ? json.keywords.toString() : null,
            type: 'input'
        },
        {
            name: 'authors',
            message: 'authors',
            default: json.authors ? json.authors.toString() : null,
            type: 'input'
        },
        {
            name: 'license',
            message: 'license',
            default: json.license || 'MIT',
            type: 'input'
        },
        {
            name: 'homepage',
            message: 'homepage',
            default: json.homepage,
            type: 'input'
        },
        {
            name: 'dependencies',
            message: 'set currently installed components as dependencies?',
            default:
                !mout.object.size(json.dependencies) &&
                !mout.object.size(json.devDependencies),
            type: 'confirm'
        },
        {
            name: 'ignore',
            message: 'add commonly ignored files to ignore list?',
            default: true,
            type: 'confirm'
        },
        {
            name: 'private',
            message:
                'would you like to mark this package as private which prevents it from being accidentally published to the registry?',
            default: !!json.private,
            type: 'confirm'
        }
    ];

    return Q.nfcall(logger.prompt.bind(logger), questions).then(function(
        answers
    ) {
        json.name = answers.name;
        json.description = answers.description;
        json.main = answers.main;
        json.keywords = toArray(answers.keywords);
        json.authors = toArray(answers.authors, ',');
        json.license = answers.license;
        json.homepage = answers.homepage;
        json.private = answers.private || null;

        return [json, answers];
    });
}

function toArray(value, splitter) {
    var arr = value.split(splitter || /[\s,]/);

    // Trim values
    arr = arr.map(function(item) {
        return item.trim();
    });

    // Filter empty values
    arr = arr.filter(function(item) {
        return !!item;
    });

    return arr.length ? arr : null;
}

function setIgnore(config, json, answers) {
    if (answers.ignore) {
        json.ignore = mout.array.combine(json.ignore || [], [
            '**/.*',
            'node_modules',
            'bower_components',
            config.directory,
            'test',
            'tests'
        ]);
    }

    return [json, answers];
}

function setDependencies(project, json, answers) {
    if (answers.dependencies) {
        return project.getTree().spread(function(tree, flattened, extraneous) {
            if (extraneous.length) {
                json.dependencies = {};

                // Add extraneous as dependencies
                extraneous.forEach(function(extra) {
                    var jsonEndpoint;

                    // Skip linked packages
                    if (extra.linked) {
                        return;
                    }

                    jsonEndpoint = endpointParser.decomposed2json(
                        extra.endpoint
                    );
                    mout.object.mixIn(json.dependencies, jsonEndpoint);
                });
            }

            return [json, answers];
        });
    }

    return [json, answers];
}

// -------------------

init.readOptions = function(argv) {
    return [];
};

module.exports = init;


================================================
FILE: lib/commands/install.js
================================================
var endpointParser = require('bower-endpoint-parser');
var Project = require('../core/Project');
var defaultConfig = require('../config');

function install(logger, endpoints, options, config) {
    var project;
    var decEndpoints;

    options = options || {};
    config = defaultConfig(config);
    if (options.save === undefined) {
        options.save = config.defaultSave;
    }
    project = new Project(config, logger);

    // Convert endpoints to decomposed endpoints
    endpoints = endpoints || [];
    decEndpoints = endpoints.map(function(endpoint) {
        // handle @ as version divider
        var splitParts = endpoint.split('/');
        splitParts[splitParts.length - 1] = splitParts[
            splitParts.length - 1
        ].replace('@', '#');
        endpoint = splitParts.join('/');

        return endpointParser.decompose(endpoint);
    });

    return project.install(decEndpoints, options, config);
}

// -------------------

install.readOptions = function(argv) {
    var cli = require('../util/cli');

    var options = cli.readOptions(
        {
            'force-latest': { type: Boolean, shorthand: 'F' },
            production: { type: Boolean, shorthand: 'p' },
            save: { type: Boolean, shorthand: 'S' },
            'save-dev': { type: Boolean, shorthand: 'D' },
            'save-exact': { type: Boolean, shorthand: 'E' }
        },
        argv
    );

    var packages = options.argv.remain.slice(1);

    delete options.argv;

    return [packages, options];
};

module.exports = install;


================================================
FILE: lib/commands/link.js
================================================
var path = require('path');
var rimraf = require('../util/rimraf');
var Q = require('q');
var Project = require('../core/Project');
var createLink = require('../util/createLink');
var defaultConfig = require('../config');
var relativeToBaseDir = require('../util/relativeToBaseDir');

function link(logger, name, localName, config) {
    if (name) {
        return linkTo(logger, name, localName, config);
    } else {
        return linkSelf(logger, config);
    }
}

function linkSelf(logger, config) {
    var project;

    config = defaultConfig(config);
    project = new Project(config, logger);

    return project.getJson().then(function(json) {
        var src = config.cwd;
        var dst = path.join(config.storage.links, json.name);

        // Delete previous link if any
        return (
            Q.nfcall(rimraf, dst)
                // Link globally
                .then(function() {
                    return createLink(src, dst);
                })
                .then(function() {
                    return {
                        src: src,
                        dst: dst
                    };
                })
        );
    });
}

function linkTo(logger, name, localName, config) {
    var src;
    var dst;
    var project;

    config = defaultConfig(config);
    project = new Project(config, logger);

    localName = localName || name;
    src = path.join(config.storage.links, name);
    dst = path.join(relativeToBaseDir(config.cwd)(config.directory), localName);

    // Delete destination folder if any
    return (
        Q.nfcall(rimraf, dst)
            // Link locally
            .then(function() {
                return createLink(src, dst);
            })
            // Install linked package deps
            .then(function() {
                return project.update([localName]);
            })
            .then(function(installed) {
                return {
                    src: src,
                    dst: dst,
                    installed: installed
                };
            })
    );
}

// -------------------

link.readOptions = function(argv) {
    var cli = require('../util/cli');
    var options = cli.readOptions(argv);
    var name = options.argv.remain[1];
    var localName = options.argv.remain[2];

    return [name, localName];
};

module.exports = link;


================================================
FILE: lib/commands/list.js
================================================
var path = require('path');
var mout = require('mout');
var Q = require('q');
var Project = require('../core/Project');
var semver = require('../util/semver');
var defaultConfig = require('../config');

function list(logger, options, config) {
    var project;

    options = options || {};

    // Make relative option true by default when used with paths
    if (options.paths && options.relative == null) {
        options.relative = true;
    }

    config = defaultConfig(config);
    project = new Project(config, logger);

    return project.getTree(options).spread(function(tree, flattened) {
        // Relativize paths
        // Also normalize paths on windows
        project.walkTree(
            tree,
            function(node) {
                if (node.missing) {
                    return;
                }

                if (options.relative) {
                    node.canonicalDir = path.relative(
                        config.cwd,
                        node.canonicalDir
                    );
                }
                if (options.paths) {
                    node.canonicalDir = normalize(node.canonicalDir);
                }
            },
            true
        );

        // Note that we need to to parse the flattened tree because it might
        // contain additional packages
        mout.object.forOwn(flattened, function(node) {
            if (node.missing) {
                return;
            }

            if (options.relative) {
                node.canonicalDir = path.relative(
                    config.cwd,
                    node.canonicalDir
                );
            }
            if (options.paths) {
                node.canonicalDir = normalize(node.canonicalDir);
            }
        });

        // Render paths?
        if (options.paths) {
            return paths(flattened);
        }

        // Do not check for new versions?
        if (config.offline) {
            return tree;
        }

        // Check for new versions
        return checkVersions(project, tree, logger).then(function() {
            return tree;
        });
    });
}

function checkVersions(project, tree, logger) {
    var promises;
    var nodes = [];
    var repository = project.getPackageRepository();

    // Gather all nodes, ignoring linked nodes
    project.walkTree(
        tree,
        function(node) {
            if (!node.linked) {
                nodes.push(node);
            }
        },
        true
    );

    if (nodes.length) {
        logger.info(
            'check-new',
            'Checking for new versions of the project dependencies...'
        );
    }

    // Check for new versions for each node
    promises = nodes.map(function(node) {
        var target = node.endpoint.target;

        return repository
            .versions(node.endpoint.source)
            .then(function(versions) {
                node.versions = versions;

                // Do not check if node's target is not a valid semver one
                if (versions.length && semver.validRange(target)) {
                    node.update = {
                        target: semver.maxSatisfying(versions, target),
                        latest: semver.maxSatisfying(versions, '*')
                    };
                }
            });
    });

    // Set the versions also for the root node
    tree.versions = [];

    return Q.all(promises);
}

function paths(flattened) {
    var ret = {};

    mout.object.forOwn(flattened, function(pkg, name) {
        var main;

        if (pkg.missing) {
            return;
        }

        main = pkg.pkgMeta.main;

        // If no main was specified, fallback to canonical dir
        if (!main) {
            ret[name] = pkg.canonicalDir;
            return;
        }

        // Normalize main
        if (typeof main === 'string') {
            main = [main];
        }

        // Concatenate each main entry with the canonical dir
        main = main.map(function(part) {
            return normalize(path.join(pkg.canonicalDir, part).trim());
        });

        // If only one main file, use a string
        // Otherwise use an array
        ret[name] = main.length === 1 ? main[0] : main;
    });

    return ret;
}

function normalize(src) {
    return src.replace(/\\/g, '/');
}

// -------------------

list.readOptions = function(argv) {
    var cli = require('../util/cli');

    var options = cli.readOptions(
        {
            paths: { type: Boolean, shorthand: 'p' },
            relative: { type: Boolean, shorthand: 'r' }
        },
        argv
    );

    delete options.argv;

    return [options];
};

module.exports = list;


================================================
FILE: lib/commands/login.js
================================================
var Configstore = require('configstore');
var GitHub = require('github');
var Q = require('q');

var createError = require('../util/createError');
var defaultConfig = require('../config');

function login(logger, options, config) {
    var configstore = new Configstore('bower-github');

    config = defaultConfig(config);

    var promise;

    options = options || {};

    if (options.token) {
        promise = Q.resolve({ token: options.token });
    } else {
        // This command requires interactive to be enabled
        if (!config.interactive) {
            logger.emit(
                'error',
                createError('Login requires an interactive shell', 'ENOINT', {
                    details:
                        'Note that you can manually force an interactive shell with --config.interactive'
                })
            );

            return;
        }

        var questions = [
            {
                name: 'username',
                message: 'Username',
                type: 'input',
                default: configstore.get('username')
            },
            {
                name: 'password',
                message: 'Password',
                type: 'password'
            }
        ];

        var github = new GitHub({
            version: '3.0.0'
        });

        promise = Q.nfcall(logger.prompt.bind(logger), questions).then(function(
            answers
        ) {
            configstore.set('username', answers.username);

            github.authenticate({
                type: 'basic',
                username: answers.username,
                password: answers.password
            });

            return Q.ninvoke(github.authorization, 'create', {
                scopes: ['user', 'repo'],
                note:
                    'Bower command line client (' +
                    new Date().toISOString() +
                    ')'
            });
        });
    }

    return promise.then(
        function(result) {
            configstore.set('accessToken', result.token);
            logger.info(
                'EAUTH',
                'Logged in as ' + configstore.get('username'),
                {}
            );

            return result;
        },
        function(error) {
            var message;

            try {
                message = JSON.parse(error.message).message;
            } catch (e) {
                message = 'Authorization failed';
            }

            var questions = [
                {
                    name: 'otpcode',
                    message: 'Two-Factor Auth Code',
                    type: 'input'
                }
            ];

            if (
                message === 'Must specify two-factor authentication OTP code.'
            ) {
                return Q.nfcall(logger.prompt.bind(logger), questions)
                    .then(function(answers) {
                        return Q.ninvoke(github.authorization, 'create', {
                            scopes: ['user', 'repo'],
                            note:
                                'Bower command line client (' +
                                new Date().toISOString() +
                                ')',
                            headers: {
                                'X-GitHub-OTP': answers.otpcode
                            }
                        });
                    })
                    .then(
                        function(result) {
                            configstore.set('accessToken', result.token);
                            logger.info(
                                'EAUTH',
                                'Logged in as ' + configstore.get('username'),
                                {}
                            );

                            return result;
                        },
                        function() {
                            logger.emit('error', createError(message, 'EAUTH'));
                        }
                    );
            } else {
                logger.emit('error', createError(message, 'EAUTH'));
            }
        }
    );
}

// -------------------

login.readOptions = function(argv) {
    var cli = require('../util/cli');

    var options = cli.readOptions(
        {
            token: { type: String, shorthand: 't' }
        },
        argv
    );

    delete options.argv;

    return [options];
};

module.exports = login;


================================================
FILE: lib/commands/lookup.js
================================================
var Q = require('q');
var PackageRepository = require('../core/PackageRepository');
var defaultConfig = require('../config');

function lookup(logger, name, config) {
    if (!name) {
        return new Q(null);
    }

    config = defaultConfig(config);

    var repository = new PackageRepository(config, logger);
    var registryClient = repository.getRegistryClient();

    return Q.nfcall(registryClient.lookup.bind(registryClient), name).then(
        function(entry) {
            return !entry
                ? null
                : {
                      name: name,
                      url: entry.url
                  };
        }
    );
}

// -------------------

lookup.readOptions = function(argv) {
    var cli = require('../util/cli');
    var options = cli.readOptions(argv);
    var name = options.argv.remain[1];

    return [name];
};

module.exports = lookup;


================================================
FILE: lib/commands/prune.js
================================================
var mout = require('mout');
var Project = require('../core/Project');
var defaultConfig = require('../config');

function prune(logger, options, config) {
    var project;

    options = options || {};
    config = defaultConfig(config);
    project = new Project(config, logger);

    return clean(project, options);
}

function clean(project, options, removed) {
    removed = removed || {};

    // Continually call clean until there is no more extraneous
    // dependencies to remove
    return project
        .getTree(options)
        .spread(function(tree, flattened, extraneous) {
            var names = extraneous.map(function(extra) {
                return extra.endpoint.name;
            });

            // Uninstall extraneous
            return project
                .uninstall(names, options)
                .then(function(uninstalled) {
                    // Are we done?
                    if (!mout.object.size(uninstalled)) {
                        return removed;
                    }

                    // Not yet, recurse!
                    mout.object.mixIn(removed, uninstalled);
                    return clean(project, options, removed);
                });
        });
}

// -------------------

prune.readOptions = function(argv) {
    var cli = require('../util/cli');

    var options = cli.readOptions(
        {
            production: { type: Boolean, shorthand: 'p' }
        },
        argv
    );

    delete options.argv;

    return [options];
};

module.exports = prune;


================================================
FILE: lib/commands/register.js
================================================
var Q = require('q');
var chalk = require('chalk');
var PackageRepository = require('../core/PackageRepository');
var createError = require('../util/createError');
var defaultConfig = require('../config');

function register(logger, name, source, config) {
    var repository;
    var registryClient;
    var force;
    var url;
    var githubSourceRegex = /^\w[\w-]*\/\w[\w-]*$/;
    var getGithubUrl = function(source) {
        return 'git@github.com:' + source + '.git';
    };

    config = defaultConfig(config);
    force = config.force;

    name = (name || '').trim();
    source = (source || '').trim();

    url = source.match(githubSourceRegex) ? getGithubUrl(source) : source;

    // Bypass any cache
    config.offline = false;
    config.force = true;

    return Q.try(function() {
        // Verify name and url
        if (!name || !url) {
            throw createError(
                'Usage: bower register <name> <url>',
                'EINVFORMAT'
            );
        }

        // Attempt to resolve the package referenced by the URL to ensure
        // everything is ok before registering
        repository = new PackageRepository(config, logger);
        return repository.fetch({ name: name, source: url, target: '*' });
    })
        .spread(function(canonicalDir, pkgMeta) {
            if (pkgMeta.private) {
                throw createError(
                    'The package you are trying to register is marked as private',
                    'EPRIV'
                );
            }

            // If non interactive or user forced, bypass confirmation
            if (!config.interactive || force) {
                return true;
            }

            // Confirm if the user really wants to register
            return Q.nfcall(logger.prompt.bind(logger), {
                type: 'confirm',
                message:
                    'Registering a package will make it installable via the registry (' +
                    chalk.cyan.underline(config.registry.register) +
                    '), continue?',
                default: true
            });
        })
        .then(function(result) {
            // If user response was negative, abort
            if (!result) {
                return;
            }

            // Register
            registryClient = repository.getRegistryClient();

            logger.action('register', url, {
                name: name,
                url: url
            });

            return Q.nfcall(
                registryClient.register.bind(registryClient),
                name,
                url
            );
        });
}

// -------------------

register.readOptions = function(argv) {
    var cli = require('../util/cli');

    var options = cli.readOptions(argv);
    var name = options.argv.remain[1];
    var url = options.argv.remain[2];

    return [name, url];
};

module.exports = register;


================================================
FILE: lib/commands/search.js
================================================
var Q = require('q');
var PackageRepository = require('../core/PackageRepository');
var defaultConfig = require('../config');
var cli = require('../util/cli');
var createError = require('../util/createError');

function search(logger, name, config) {
    var registryClient;

    config = defaultConfig(config);

    var repository = new PackageRepository(config, logger);
    var registryClient = repository.getRegistryClient();

    if (name) {
        return Q.nfcall(registryClient.search.bind(registryClient), name);
    } else {
        // List all packages when in interactive mode + json enabled, and
        // always when in non-interactive mode
        if (config.interactive && !config.json) {
            throw createError('no parameter to bower search', 'EREADOPTIONS');
        }

        return Q.nfcall(registryClient.list.bind(registryClient));
    }
}

// -------------------

search.readOptions = function(argv) {
    var options = cli.readOptions(argv);
    var terms = options.argv.remain.slice(1);

    var name = terms.join(' ');

    return [name];
};

module.exports = search;


================================================
FILE: lib/commands/uninstall.js
================================================
var mout = require('mout');
var Q = require('q');
var Project = require('../core/Project');
var defaultConfig = require('../config');

function uninstall(logger, names, options, config) {
    if (!names.length) {
        return new Q();
    }

    var project;

    options = options || {};
    config = defaultConfig(config);
    project = new Project(config, logger);

    return project.getTree(options).spread(function(tree, flattened) {
        // Uninstall nodes
        return (
            project
                .uninstall(names, options)
                // Clean out non-shared uninstalled dependencies
                .then(function(uninstalled) {
                    var names = Object.keys(uninstalled);
                    var children = [];

                    // Grab the dependencies of packages that were uninstalled
                    mout.object.forOwn(flattened, function(node) {
                        if (names.indexOf(node.endpoint.name) !== -1) {
                            children.push.apply(
                                children,
                                mout.object.keys(node.dependencies)
                            );
                        }
                    });

                    // Clean them!
                    return clean(project, children, uninstalled);
                })
        );
    });
}

function clean(project, names, removed) {
    removed = removed || {};

    return project.getTree().spread(function(tree, flattened) {
        var nodes = [];
        var dependantsCounter = {};

        // Grab the nodes of each specified name
        mout.object.forOwn(flattened, function(node) {
            if (names.indexOf(node.endpoint.name) !== -1) {
                nodes.push(node);
            }
        });

        // Walk the down the tree, gathering dependants of the packages
        project.walkTree(
            tree,
            function(node, nodeName) {
                if (names.indexOf(nodeName) !== -1) {
                    dependantsCounter[nodeName] =
                        dependantsCounter[nodeName] || 0;
                    dependantsCounter[nodeName] += node.nrDependants;
                }
            },
            true
        );

        // Filter out those that have no dependants
        nodes = nodes.filter(function(node) {
            return !dependantsCounter[node.endpoint.name];
        });

        // Are we done?
        if (!nodes.length) {
            return Q.resolve(removed);
        }

        // Grab the nodes after filtering
        names = nodes.map(function(node) {
            return node.endpoint.name;
        });

        // Uninstall them
        return (
            project
                .uninstall(names)
                // Clean out non-shared uninstalled dependencies
                .then(function(uninstalled) {
                    var children;

                    mout.object.mixIn(removed, uninstalled);

                    // Grab the dependencies of packages that were uninstalled
                    children = [];
                    nodes.forEach(function(node) {
                        children.push.apply(
                            children,
                            mout.object.keys(node.dependencies)
                        );
                    });

                    // Recurse!
                    return clean(project, children, removed);
                })
        );
    });
}

// -------------------

uninstall.readOptions = function(argv) {
    var cli = require('../util/cli');

    var options = cli.readOptions(
        {
            save: { type: Boolean, shorthand: 'S' },
            'save-dev': { type: Boolean, shorthand: 'D' }
        },
        argv
    );

    var names = options.argv.remain.slice(1);

    delete options.argv;

    return [names, options];
};

module.exports = uninstall;


================================================
FILE: lib/commands/unregister.js
================================================
var chalk = require('chalk');
var Q = require('q');

var defaultConfig = require('../config');
var PackageRepository = require('../core/PackageRepository');
var createError = require('../util/createError');

function unregister(logger, name, config) {
    if (!name) {
        return;
    }

    var repository;
    var registryClient;
    var force;

    config = defaultConfig(config);
    force = config.force;

    // Bypass any cache
    config.offline = false;
    config.force = true;

    // Trim name
    name = name.trim();

    repository = new PackageRepository(config, logger);

    if (!config.accessToken) {
        return logger.emit(
            'error',
            createError(
                'Use "bower login" with collaborator credentials',
                'EFORBIDDEN'
            )
        );
    }

    return Q.resolve()
        .then(function() {
            // If non interactive or user forced, bypass confirmation
            if (!config.interactive || force) {
                return true;
            }

            return Q.nfcall(logger.prompt.bind(logger), {
                type: 'confirm',
                message:
                    'You are about to remove component "' +
                    chalk.cyan.underline(name) +
                    '" from the bower registry (' +
                    chalk.cyan.underline(config.registry.register) +
                    '). It is generally considered bad behavior to remove versions of a library that others are depending on. Are you really sure?',
                default: false
            });
        })
        .then(function(result) {
            // If user response was negative, abort
            if (!result) {
                return;
            }

            registryClient = repository.getRegistryClient();

            logger.action('unregister', name, { name: name });

            return Q.nfcall(
                registryClient.unregister.bind(registryClient),
                name
            );
        })
        .then(function(result) {
            logger.info('Package unregistered', name);

            return result;
        });
}

// -------------------

unregister.readOptions = function(argv) {
    var cli = require('../util/cli');

    var options = cli.readOptions(argv);
    var name = options.argv.remain[1];

    return [name];
};

module.exports = unregister;


================================================
FILE: lib/commands/update.js
================================================
var Project = require('../core/Project');
var defaultConfig = require('../config');

function update(logger, names, options, config) {
    var project;

    options = options || {};
    config = defaultConfig(config);
    project = new Project(config, logger);

    // If names is an empty array, null them
    if (names && !names.length) {
        names = null;
    }

    return project.update(names, options);
}

// -------------------

update.readOptions = function(argv) {
    var cli = require('../util/cli');

    var options = cli.readOptions(
        {
            'force-latest': { type: Boolean, shorthand: 'F' },
            production: { type: Boolean, shorthand: 'p' }
        },
        argv
    );

    var names = options.argv.remain.slice(1);

    delete options.argv;

    return [names, options];
};

module.exports = update;


================================================
FILE: lib/commands/version.js
================================================
var semver = require('semver');
var which = require('../util/which');
var fs = require('../util/fs');
var path = require('path');
var Q = require('q');
var execFile = require('../util/childProcess').execFile;
var defaultConfig = require('../config');
var createError = require('../util/createError');

function version(logger, versionArg, options, config) {
    options = options || {};

    config = defaultConfig(config);

    return bump(logger, config, versionArg, options.message);
}

function bump(logger, config, versionArg, message) {
    var cwd = config.cwd || process.cwd();
    var newVersion;

    if (!versionArg) {
        throw createError('No <version> agrument provided', 'EREADOPTIONS');
    }

    return driver
        .check(cwd)
        .then(function() {
            return Q.all([driver.versions(cwd), driver.currentVersion(cwd)]);
        })
        .spread(function(versions, currentVersion) {
            currentVersion = currentVersion || '0.0.0';

            if (semver.valid(versionArg)) {
                newVersion = semver.valid(versionArg);
            } else {
                newVersion = semver.inc(currentVersion, versionArg);

                if (!newVersion) {
                    throw createError(
                        'Invalid <version> argument: ' + versionArg,
                        'EINVALIDVERSION',
                        { version: versionArg }
                    );
                }
            }

            newVersion =
                currentVersion[0] === 'v' ? 'v' + newVersion : newVersion;

            if (versions) {
                versions.forEach(function(version) {
                    if (semver.eq(version, newVersion)) {
                        throw createError(
                            'Version exists: ' + newVersion,
                            'EVERSIONEXISTS',
                            { versions: versions, newVersion: newVersion }
                        );
                    }
                });
            }

            return driver.bump(cwd, newVersion, message).then(function() {
                return {
                    oldVersion: currentVersion,
                    newVersion: newVersion
                };
            });
        })
        .then(function(result) {
            logger.info(
                'version',
                'Bumped package version from ' +
                    result.oldVersion +
                    ' to ' +
                    result.newVersion,
                result
            );

            return result.newVersion;
        });
}

var driver = {
    check: function(cwd) {
        function checkGit(cwd) {
            var gitDir = path.join(cwd, '.git');
            return Q.nfcall(fs.stat, gitDir).then(
                function(stat) {
                    if (stat.isDirectory()) {
                        return checkGitStatus(cwd);
                    }
                    return false;
                },
                function() {
                    //Ignore not found .git directory
                    return false;
                }
            );
        }

        function checkGitStatus(cwd) {
            return Q.nfcall(which, 'git')
                .fail(function(err) {
                    err.code = 'ENOGIT';
                    throw err;
                })
                .then(function(gitPath) {
                    return Q.nfcall(
                        execFile,
                        gitPath,
                        ['status', '--porcelain'],
                        { env: process.env, cwd: cwd }
                    );
                })
                .then(function(value) {
                    var stdout = value[0];
                    var lines = filterModifiedStatusLines(stdout);
                    if (lines.length) {
                        throw createError(
                            'Version bump requires clean working directory',
                            'EWORKINGDIRECTORYDIRTY'
                        );
                    }
                    return true;
                });
        }

        function filterModifiedStatusLines(stdout) {
            return stdout
                .trim()
                .split('\n')
                .filter(function(line) {
                    return line.trim() && !line.match(/^\?\? /);
                })
                .map(function(line) {
                    return line.trim();
                });
        }

        return checkGit(cwd).then(function(hasGit) {
            if (!hasGit) {
                throw createError(
                    'Version bump currently supports only git repositories',
                    'ENOTGITREPOSITORY'
                );
            }
        });
    },
    versions: function(cwd) {
        return Q.nfcall(execFile, 'git', ['tag'], {
            env: process.env,
            cwd: cwd
        }).then(
            function(res) {
                var versions = res[0].split(/\r?\n/).filter(semver.valid);

                return versions;
            },
            function() {
                return [];
            }
        );
    },
    currentVersion: function(cwd) {
        return Q.nfcall(execFile, 'git', ['describe', '--abbrev=0', '--tags'], {
            env: process.env,
            cwd: cwd
        }).then(
            function(res) {
                var version = res[0].split(/\r?\n/).filter(semver.valid)[0];

                return version;
            },
            function() {
                return undefined;
            }
        );
    },
    bump: function(cwd, tag, message) {
        message = message || tag;
        message = message.replace(/%s/g, tag);
        return Q.nfcall(
            execFile,
            'git',
            ['commit', '-m', message, '--allow-empty'],
            { env: process.env, cwd: cwd }
        ).then(function() {
            return Q.nfcall(execFile, 'git', ['tag', tag, '-am', message], {
                env: process.env,
                cwd: cwd
            });
        });
    }
};

version.readOptions = function(argv) {
    var cli = require('../util/cli');

    var options = cli.readOptions(
        {
            message: { type: String, shorthand: 'm' }
        },
        argv
    );

    return [options.argv.remain[1], options];
};

module.exports = version;


================================================
FILE: lib/config.js
================================================
var tty = require('tty');
var object = require('mout').object;
var bowerConfig = require('bower-config');
var Configstore = require('configstore');

var current;

function defaultConfig(config) {
    config = config || {};

    return readCachedConfig(config.cwd || process.cwd(), config);
}

function readCachedConfig(cwd, overwrites) {
    current = bowerConfig.create(cwd).load(overwrites);

    var config = current.toObject();

    var configstore = new Configstore('bower-github').all;

    object.mixIn(config, configstore);

    // If interactive is auto (null), guess its value
    if (config.interactive == null) {
        config.interactive =
            process.bin === 'bower' && tty.isatty(1) && !process.env.CI;
    }

    // Merge common CLI options into the config
    if (process.bin === 'bower') {
        var cli = require('./util/cli');

        object.mixIn(
            config,
            cli.readOptions({
                force: { type: Boolean, shorthand: 'f' },
                offline: { type: Boolean, shorthand: 'o' },
                verbose: { type: Boolean, shorthand: 'V' },
                quiet: { type: Boolean, shorthand: 'q' },
                loglevel: { type: String, shorthand: 'l' },
                json: { type: Boolean, shorthand: 'j' },
                silent: { type: Boolean, shorthand: 's' }
            })
        );
    }

    return config;
}

function restoreConfig() {
    if (current) {
        current.restore();
    }
}

function resetCache() {
    restoreConfig();
    current = undefined;
}

module.exports = defaultConfig;
module.exports.restore = restoreConfig;
module.exports.reset = resetCache;


================================================
FILE: lib/core/Manager.js
================================================
var Q = require('q');
var mout = require('mout');
var path = require('path');
var mkdirp = require('mkdirp');
var rimraf = require('../util/rimraf');
var fs = require('../util/fs');
var endpointParser = require('bower-endpoint-parser');
var PackageRepository = require('./PackageRepository');
var semver = require('../util/semver');
var copy = require('../util/copy');
var createError = require('../util/createError');
var scripts = require('./scripts');
var relativeToBaseDir = require('../util/relativeToBaseDir');

function Manager(config, logger) {
    this._config = config;
    this._logger = logger;
    this._repository = new PackageRepository(this._config, this._logger);

    this.configure({});
}

// -----------------

Manager.prototype.configure = function(setup) {
    var targetsHash = {};
    this._conflicted = {};

    // Targets - ignore those specified in ignoredDependencies
    this._targets = mout.array.reject(
        setup.targets || [],
        function(target) {
            return mout.array.contains(
                this._config.ignoredDependencies,
                target.name
            );
        },
        this
    );

    this._targets.forEach(function(decEndpoint) {
        decEndpoint.initialName = decEndpoint.name;
        decEndpoint.dependants = mout.object.values(decEndpoint.dependants);
        targetsHash[decEndpoint.name] = true;

        // If the endpoint is marked as newly, make it unresolvable
        decEndpoint.unresolvable = !!decEndpoint.newly;
    });

    // Resolved & installed
    this._resolved = {};
    this._installed = {};
    mout.object.forOwn(
        setup.resolved,
        function(decEndpoint, name) {
            decEndpoint.dependants = mout.object.values(decEndpoint.dependants);
            this._resolved[name] = [decEndpoint];
            this._installed[name] = decEndpoint.pkgMeta;
        },
        this
    );

    // Installed
    mout.object.mixIn(this._installed, setup.installed);

    // Incompatibles
    this._incompatibles = {};
    setup.incompatibles = this._uniquify(setup.incompatibles || []);
    setup.incompatibles.forEach(function(decEndpoint) {
        var name = decEndpoint.name;

        this._incompatibles[name] = this._incompatibles[name] || [];
        this._incompatibles[name].push(decEndpoint);
        decEndpoint.dependants = mout.object.values(decEndpoint.dependants);

        // Mark as conflicted so that the resolution is not removed
        this._conflicted[name] = true;

        // If not a target/resolved, add as target
        if (!targetsHash[name] && !this._resolved[name]) {
            this._targets.push(decEndpoint);
        }
    }, this);

    // Resolutions
    this._resolutions = setup.resolutions || {};

    // Uniquify targets
    this._targets = this._uniquify(this._targets);

    // Force-latest
    this._forceLatest = !!setup.forceLatest;

    return this;
};

/**
 * It starts recursive fetching of targets. The flow is as follows:
 *
 * 1. this._fetch() that calls:
 * 2. this._onFetchError() or this._onFetchSuccess() that calls:
 * 3. this._parseDependencies() that calls for all dependencies:
 * 4. this._fetch() again.
 *
 * Fetching and parsing of dependencies continues until all dependencies are fetched.
 *
 */
Manager.prototype.resolve = function() {
    // If already resolving, error out
    if (this._working) {
        return Q.reject(createError('Already working', 'EWORKING'));
    }

    // Reset stuff
    this._fetching = {};
    this._nrFetching = 0;
    this._failed = {};
    this._hasFailed = false;
    this._deferred = Q.defer();

    // If there's nothing to resolve, simply dissect
    if (!this._targets.length) {
        process.nextTick(this._dissect.bind(this));
        // Otherwise, fetch each target from the repository
        // and let the process roll out
    } else {
        this._targets.forEach(this._fetch.bind(this));
    }

    // Unset working flag when done
    return this._deferred.promise.fin(
        function() {
            this._working = false;
        }.bind(this)
    );
};

Manager.prototype.preinstall = function(json) {
    var that = this;
    var componentsDir = relativeToBaseDir(this._config.cwd)(
        this._config.directory
    );

    // If nothing to install, skip the code bellow
    if (mout.lang.isEmpty(that._dissected)) {
        return Q.resolve({});
    }

    return Q.nfcall(mkdirp, componentsDir).then(function() {
        return scripts.preinstall(
            that._config,
            that._logger,
            that._dissected,
            that._installed,
            json
        );
    });
};

Manager.prototype.postinstall = function(json) {
    var that = this;
    var componentsDir = relativeToBaseDir(this._config.cwd)(
        this._config.directory
    );

    // If nothing to install, skip the code bellow
    if (mout.lang.isEmpty(that._dissected)) {
        return Q.resolve({});
    }

    return Q.nfcall(mkdirp, componentsDir).then(function() {
        return scripts.postinstall(
            that._config,
            that._logger,
            that._dissected,
            that._installed,
            json
        );
    });
};

Manager.prototype.install = function(json) {
    var componentsDir;
    var componentsDirContents;
    var that = this;

    // If already resolving, error out
    if (this._working) {
        return Q.reject(createError('Already working', 'EWORKING'));
    }

    // If nothing to install, skip the code bellow
    if (mout.lang.isEmpty(that._dissected)) {
        return Q.resolve({});
    }

    componentsDir = relativeToBaseDir(this._config.cwd)(this._config.directory);
    return Q.nfcall(mkdirp, componentsDir)
        .then(function() {
            var promises = [];
            componentsDirContents = fs.readdirSync(componentsDir);

            mout.object.forOwn(that._dissected, function(decEndpoint, name) {
                var promise;
                var dst;
                var release = decEndpoint.pkgMeta._release;
                var exists = mout.array.contains(componentsDirContents, name);

                that._logger.action(
                    'install',
                    name + (release ? '#' + release : ''),
                    that.toData(decEndpoint)
                );

                dst = path.join(componentsDir, name);

                if (exists && !that._installed[name] && !that._config.force) {
                    // There is a folder in the components directory that has
                    // this name, but it was not installed by bower.
                    that._logger.warn(
                        'skipped',
                        name +
                            ' was not installed because there is already a non-bower directory with that name in the components directory (' +
                            path.relative(that._config.cwd, dst) +
                            '). You can force installation with --force.'
                    );
                    return;
                }

                // Remove existent and copy canonical dir
                promise = Q.nfcall(rimraf, dst)
                    .then(
                        copy.copyDir.bind(copy, decEndpoint.canonicalDir, dst)
                    )
                    .then(function() {
                        var metaFile = path.join(dst, '.bower.json');

                        decEndpoint.canonicalDir = dst;

                        // Store additional metadata in bower.json
                        return Q.nfcall(fs.readFile, metaFile).then(function(
                            contents
                        ) {
                            var json = JSON.parse(contents.toString());

                            json._target = decEndpoint.target;
                            json._originalSource = decEndpoint.source;
                            if (decEndpoint.newly) {
                                json._direct = true;
                            }

                            json = JSON.stringify(json, null, '  ');
                            return Q.nfcall(fs.writeFile, metaFile, json);
                        });
                    });

                promises.push(promise);
            });

            return Q.all(promises);
        })
        .then(function() {
            // Sync up dissected dependencies and dependants
            // See: https://github.com/bower/bower/issues/879
            mout.object.forOwn(
                that._dissected,
                function(pkg) {
                    // Sync dependencies
                    mout.object.forOwn(
                        pkg.dependencies,
                        function(dependency, name) {
                            var dissected =
                                this._dissected[name] ||
                                (this._resolved[name]
                                    ? this._resolved[name][0]
                                    : dependency);
                            pkg.dependencies[name] = dissected;
                        },
                        this
                    );

                    // Sync dependants
                    pkg.dependants = pkg.dependants.map(function(dependant) {
                        var name = dependant.name;
                        var dissected =
                            this._dissected[name] ||
                            (this._resolved[name]
                                ? this._resolved[name][0]
                                : dependant);

                        return dissected;
                    }, this);
                },
                that
            );

            // Resolve with meaningful data
            return mout.object.map(
                that._dissected,
                function(decEndpoint) {
                    return this.toData(decEndpoint);
                },
                that
            );
        })
        .fin(
            function() {
                this._working = false;
            }.bind(this)
        );
};

Manager.prototype.toData = function(decEndpoint, extraKeys, upperDeps) {
    var names;
    var extra;

    var data = {};

    upperDeps = upperDeps || [];
    data.endpoint = mout.object.pick(decEndpoint, ['name', 'source', 'target']);

    if (decEndpoint.canonicalDir) {
        data.canonicalDir = decEndpoint.canonicalDir;
        data.pkgMeta = decEndpoint.pkgMeta;
    }

    if (extraKeys) {
        extra = mout.object.pick(decEndpoint, extraKeys);
        extra = mout.object.filter(extra, function(value) {
            return !!value;
        });
        mout.object.mixIn(data, extra);
    }

    if (decEndpoint.dependencies) {
        data.dependencies = {};

        // Call recursively for each dependency but ordered
        // by dependency names
        names = Object.keys(decEndpoint.dependencies).sort();
        names.forEach(function(name) {
            // Prevent from infinite recursion when installing cyclic
            // dependencies
            if (!mout.array.contains(upperDeps, name)) {
                data.dependencies[name] = this.toData(
                    decEndpoint.dependencies[name],
                    extraKeys,
                    upperDeps.concat(decEndpoint.name)
                );
            }
        }, this);
    }

    data.nrDependants = mout.object.size(decEndpoint.dependants);

    return data;
};

Manager.prototype.getPackageRepository = function() {
    return this._repository;
};

// -----------------

Manager.prototype._fetch = function(decEndpoint) {
    var name = decEndpoint.name;

    // Check if the whole process started to fail fast
    if (this._hasFailed) {
        return;
    }

    // Mark as being fetched
    this._fetching[name] = this._fetching[name] || [];
    this._fetching[name].push(decEndpoint);
    this._nrFetching++;

    // Fetch it from the repository
    // Note that the promise is stored in the decomposed endpoint
    // because it might be reused if a similar endpoint needs to be resolved
    return (decEndpoint.promise = this._repository
        .fetch(decEndpoint)
        // When done, call onFetchSuccess
        .spread(this._onFetchSuccess.bind(this, decEndpoint))
        // If it fails, call onFetchFailure
        .fail(this._onFetchError.bind(this, decEndpoint)));
};

Manager.prototype._onFetchSuccess = function(
    decEndpoint,
    canonicalDir,
    pkgMeta,
    isTargetable
) {
    var name;
    var resolved;
    var index;
    var incompatibles;
    var initialName =
        decEndpoint.initialName != null
            ? decEndpoint.initialName
            : decEndpoint.name;
    var fetching = this._fetching[initialName];

    // Remove from being fetched list
    mout.array.remove(fetching, decEndpoint);
    this._nrFetching--;

    // Store some needed stuff
    decEndpoint.name = name = decEndpoint.name || pkgMeta.name;
    decEndpoint.canonicalDir = canonicalDir;
    decEndpoint.pkgMeta = pkgMeta;
    delete decEndpoint.promise;

    // Add to the resolved list
    // If there's an exact equal endpoint, replace instead of adding
    // This can happen because the name might not be known from the start
    resolved = this._resolved[name] = this._resolved[name] || [];
    index = mout.array.findIndex(resolved, function(resolved) {
        return resolved.target === decEndpoint.target;
    });
    if (index !== -1) {
        // Merge dependants
        decEndpoint.dependants.push.apply(
            decEndpoint.dependants,
            resolved[index.dependants]
        );
        decEndpoint.dependants = this._uniquify(decEndpoint.dependants);
        resolved.splice(index, 1);
    }
    resolved.push(decEndpoint);

    // Parse dependencies
    this._parseDependencies(decEndpoint, pkgMeta);

    // Check if there are incompatibilities for this package name
    // If there are, we need to fetch them
    incompatibles = this._incompatibles[name];
    if (incompatibles) {
        // Filter already resolved
        incompatibles = incompatibles.filter(function(incompatible) {
            return !resolved.some(function(decEndpoint) {
                return incompatible.target === decEndpoint.target;
            });
        }, this);
        // Filter being resolved
        incompatibles = incompatibles.filter(function(incompatible) {
            return !fetching.some(function(decEndpoint) {
                return incompatible.target === decEndpoint.target;
            });
        }, this);

        incompatibles.forEach(this._fetch.bind(this));
        delete this._incompatibles[name];
    }

    // If the package is not targetable, flag it
    // It will be needed later so that untargetable endpoints
    // will not get * converted to ^version
    if (!isTargetable) {
        decEndpoint.untargetable = true;
    }

    // If there are no more packages being fetched,
    // finish the resolve process by dissecting all resolved packages
    if (this._nrFetching <= 0) {
        process.nextTick(this._dissect.bind(this));
    }
};

Manager.prototype._onFetchError = function(decEndpoint, err) {
    var name = decEndpoint.name;

    err.data = err.data || {};
    err.data.endpoint = mout.object.pick(decEndpoint, [
        'name',
        'source',
        'target'
    ]);

    // Remove from being fetched list
    mout.array.remove(this._fetching[name], decEndpoint);
    this._nrFetching--;

    // Add to the failed list
    this._failed[name] = this._failed[name] || [];
    this._failed[name].push(err);
    delete decEndpoint.promise;

    // Make the whole process to fail fast
    this._failFast();

    // If there are no more packages being fetched,
    // finish the resolve process (with an error)
    if (this._nrFetching <= 0) {
        process.nextTick(this._dissect.bind(this));
    }
};

Manager.prototype._failFast = function() {
    if (this._hasFailed) {
        return;
    }

    this._hasFailed = true;

    // If after some amount of time all pending tasks haven't finished,
    // we force the process to end
    this._failFastTimeout = setTimeout(
        function() {
            this._nrFetching = Infinity;
            this._dissect();
        }.bind(this),
        20000
    );
};

/**
 * Parses decEndpoint dependencies and fetches missing ones.
 *
 * It fetches all non-yet-fetching dependencies with _fetch.
 *
 *
 * @param {string} pkgMeta Metadata of package to resolve dependencies.
 */
Manager.prototype._parseDependencies = function(decEndpoint, pkgMeta) {
    var pending = [];

    decEndpoint.dependencies = decEndpoint.dependencies || {};

    // Parse package dependencies
    mout.object.forOwn(
        pkgMeta.dependencies,
        function(value, key) {
            var resolved;
            var fetching;
            var compatible;
            var childDecEndpoint = endpointParser.json2decomposed(key, value);

            // Check if this dependency should be skipped.
            if (
                mout.array.contains(
                    this._config.ignoredDependencies,
                    childDecEndpoint.name
                )
            ) {
                this._logger.action(
                    'skipped',
                    childDecEndpoint.name,
                    this.toData(decEndpoint)
                );
                return;
            }

            // Check if a compatible one is already resolved
            // If there's one, we don't need to resolve it twice
            resolved = this._resolved[key];
            if (resolved) {
                // Find if there's one with the exact same target
                compatible = mout.array.find(
                    resolved,
                    function(resolved) {
                        return childDecEndpoint.target === resolved.target;
                    },
                    this
                );

                // If we found one, merge stuff instead of adding as resolved
                if (compatible) {
                    decEndpoint.dependencies[key] = compatible;
                    compatible.dependants.push(decEndpoint);
                    compatible.dependants = this._uniquify(
                        compatible.dependants
                    );

                    return;
                }

                // Find one that is compatible
                compatible = mout.array.find(
                    resolved,
                    function(resolved) {
                        return this._areCompatible(childDecEndpoint, resolved);
                    },
                    this
                );

                // If we found one, add as resolved
                // and copy resolved properties from the compatible one
                if (compatible) {
                    decEndpoint.dependencies[key] = compatible;
                    childDecEndpoint.canonicalDir = compatible.canonicalDir;
                    childDecEndpoint.pkgMeta = compatible.pkgMeta;
                    childDecEndpoint.dependencies = compatible.dependencies;
                    childDecEndpoint.dependants = [decEndpoint];
                    this._resolved[key].push(childDecEndpoint);

                    return;
                }
            }

            // Check if a compatible one is being fetched
            // If there's one, we wait and reuse it to avoid resolving it twice
            fetching = this._fetching[key];
            if (fetching) {
                compatible = mout.array.find(
                    fetching,
                    function(fetching) {
                        return this._areCompatible(childDecEndpoint, fetching);
                    },
                    this
                );

                if (compatible) {
                    pending.push(compatible.promise);
                    return;
                }
            }

            // Mark endpoint as unresolvable if the parent is also unresolvable
            childDecEndpoint.unresolvable = !!decEndpoint.unresolvable;

            // Otherwise, just fetch it from the repository
            decEndpoint.dependencies[key] = childDecEndpoint;
            childDecEndpoint.dependants = [decEndpoint];
            this._fetch(childDecEndpoint);
        },
        this
    );

    if (pending.length > 0) {
        Q.all(pending).then(
            function() {
                this._parseDependencies(decEndpoint, pkgMeta);
            }.bind(this)
        );
    }
};

/**
 * After batch of packages has been fetched, the results are stored in _resolved hash.
 *
 * {
 *   packageName: [array, of, decEndpoints]
 * }
 *
 * This method takes all possible decEndpoints and selects only one of them per packageName.
 *
 * It stores selected packages in the this._dissected array.
 *
 * The _dissected array is used later on by install method to move packages to config.directory.
 */
Manager.prototype._dissect = function() {
    var err;
    var componentsDir;
    var promise = Q.resolve();
    var suitables = {};
    var that = this;

    // If something failed, reject the whole resolve promise
    // with the first error
    if (this._hasFailed) {
        clearTimeout(this._failFastTimeout); // Cancel fail fast timeout

        err = mout.object.values(this._failed)[0][0];
        this._deferred.reject(err);
        return;
    }

    // Find a suitable version for each package name
    mout.object.forOwn(
        this._resolved,
        function(decEndpoints, name) {
            var semvers;
            var nonSemvers;

            // Filter out non-semver ones
            semvers = decEndpoints.filter(function(decEndpoint) {
                return !!decEndpoint.pkgMeta.version;
            });

            // Sort semver ones DESC
            semvers.sort(function(first, second) {
                var result = semver.rcompare(
                    first.pkgMeta.version,
                    second.pkgMeta.version
                );

                // If they are equal and one of them is a wildcard target,
                // give lower priority
                if (!result) {
                    if (first.target === '*') {
                        return 1;
                    }
                    if (second.target === '*') {
                        return -1;
                    }
                }

                // If they are equal and one of them is an exact target,
                // give higher priority
                if (!result) {
                    if (first.target === first.pkgMeta.version) {
                        return -1;
                    }
                    if (second.target === second.pkgMeta.version) {
                        return 1;
                    }
                }

                return result;
            });

            // Convert wildcard targets to semver range targets if they are newly
            // Note that this can only be made if they can be targetable
            // If they are not, the resolver is incapable of handling targets
            semvers.forEach(function(decEndpoint) {
                if (
                    decEndpoint.newly &&
                    decEndpoint.target === '*' &&
                    !decEndpoint.untargetable
                ) {
                    decEndpoint.target = '^' + decEndpoint.pkgMeta.version;
                    decEndpoint.originalTarget = '*';
                }
            });

            // Filter non-semver ones
            nonSemvers = decEndpoints.filter(function(decEndpoint) {
                return !decEndpoint.pkgMeta.version;
            });

            promise = promise.then(function() {
                return that
                    ._electSuitable(name, semvers, nonSemvers)
                    .then(function(suitable) {
                        suitables[name] = suitable;
                    });
            });
        },
        this
    );

    // After a suitable version has been elected for every package
    promise
        .then(
            function() {
                // Look for extraneous resolutions
                mout.object.forOwn(
                    this._resolutions,
                    function(resolution, name) {
                        if (this._conflicted[name]) {
                            return;
                        }

                        // Packages that didn't have any conflicts in resolution yet have
                        // "resolution" entry in bower.json are deemed unnecessary
                        //
                        // Probably in future we want to use them for force given resolution, but for now...
                        // See: https://github.com/bower/bower/issues/1362
                        this._logger.warn(
                            'extra-resolution',
                            'Unnecessary resolution: ' +
                                name +
                                '#' +
                                resolution,
                            {
                                name: name,
                                resolution: resolution,
                                action: 'delete'
                            }
                        );
                    },
                    this
                );

                // Filter only packages that need to be installed
                componentsDir = relativeToBaseDir(this._config.cwd)(
                    this._config.directory
                );
                this._dissected = mout.object.filter(
                    suitables,
                    function(decEndpoint, name) {
                        var installedMeta = this._installed[name];
                        var dst;

                        // Skip linked dependencies
                        if (decEndpoint.linked) {
                            return false;
                        }

                        // Skip if source is the same as dest
                        // FIXME: Shoudn't we force installation if force flag is used here?
                        dst = path.join(componentsDir, name);
                        if (dst === decEndpoint.canonicalDir) {
                            return false;
                        }

                        // We skip installing decEndpoint, if:
                        //   1. We have installed package with the same name
                        //   2. Packages have matching meta fields (needs explanation)
                        //   3. We didn't force the installation
                        if (
                            installedMeta &&
                            installedMeta._target === decEndpoint.target &&
                            installedMeta._originalSource ===
                                decEndpoint.source &&
                            installedMeta._release ===
                                decEndpoint.pkgMeta._release
                        ) {
                            return this._config.force;
                        }

                        return true;
                    },
                    this
                );
            }.bind(this)
        )
        .then(this._deferred.resolve, this._deferred.reject);
};

Manager.prototype._electSuitable = function(name, semvers, nonSemvers) {
    var suitable;
    var resolution;
    var unresolvable;
    var dataPicks;
    var save;
    var picks = [];
    var versionRegex = /(?:[\d\w]\.){2}[\d\w](?:.)*/;
    var picksReleases;

    // If there are both semver and non-semver, there's no way
    // to figure out the suitable one
    if (semvers.length && nonSemvers.length) {
        picks.push.apply(picks, semvers);
        picks.push.apply(picks, nonSemvers);
        // If there are only non-semver ones, the suitable is elected
        // only if there's one
    } else if (nonSemvers.length) {
        if (nonSemvers.length === 1) {
            return Q.resolve(nonSemvers[0]);
        }

        picks.push.apply(picks, nonSemvers);
        // If there are only semver ones, figure out which one is
        // compatible with every requirement
    } else {
        suitable = mout.array.find(semvers, function(subject) {
            return semvers.every(function(decEndpoint) {
                return (
                    subject === decEndpoint ||
                    semver.satisfies(
                        subject.pkgMeta.version,
                        decEndpoint.target
                    )
                );
            });
        });

        if (suitable) {
            return Q.resolve(suitable);
        }

        picks.push.apply(picks, semvers);
    }

    // At this point, there's a conflict
    this._conflicted[name] = true;

    // Prepare data to be sent bellow
    // 1 - Sort picks by version/release
    picks.sort(function(pick1, pick2) {
        var version1 = pick1.pkgMeta.version;
        var version2 = pick2.pkgMeta.version;
        var comp;

        // If both have versions, compare their versions using semver
        if (version1 && version2) {
            comp = semver.compare(version1, version2);
            if (comp) {
                return comp;
            }
        } else {
            // If one of them has a version, it's considered higher
            if (version1) {
                return 1;
            }
            if (version2) {
                return -1;
            }
        }

        // Give priority to the one with most dependants
        if (pick1.dependants.length > pick2.dependants.length) {
            return -1;
        }
        if (pick1.dependants.length < pick2.dependants.length) {
            return 1;
        }

        return 0;
    });

    // 2 - Transform data
    dataPicks = picks.map(function(pick) {
        var dataPick = this.toData(pick);
        dataPick.dependants = pick.dependants.map(this.toData, this);
        dataPick.dependants.sort(function(dependant1, dependant2) {
            return dependant1.endpoint.name.localeCompare(
                dependant2.endpoint.name
            );
        });
        return dataPick;
    }, this);

    // Check if there's a resolution that resolves the conflict
    // Note that if one of them is marked as unresolvable,
    // the resolution has no effect
    resolution = this._resolutions[name];
    unresolvable = mout.object.find(picks, function(pick) {
        return pick.unresolvable;
    });

    if (resolution && !unresolvable) {
        suitable = -1;

        // Range resolution
        if (semver.validRange(resolution)) {
            suitable = mout.array.findIndex(picks, function(pick) {
                return (
                    pick.pkgMeta.version &&
                    semver.satisfies(pick.pkgMeta.version, resolution)
                );
            });
        }

        // Exact match resolution (e.g. branches/tags)
        if (suitable === -1) {
            suitable = mout.array.findIndex(picks, function(pick) {
                return (
                    pick.target === resolution ||
                    pick.pkgMeta._release === resolution
                );
            });
        }

        if (suitable === -1) {
            this._logger.warn(
                'resolution',
                'Unsuitable resolution declared for ' +
                    name +
                    ': ' +
                    resolution,
                {
                    name: name,
                    picks: dataPicks,
                    resolution: resolution
                }
            );
        } else {
            this._logger.conflict(
                'solved',
                'Unable to find suitable version for ' + name,
                {
                    name: name,
                    picks: dataPicks,
                    resolution: resolution,
                    suitable: dataPicks[suitable]
                }
            );
            return Q.resolve(picks[suitable]);
        }
    }

    // If force latest is enabled, resolve to the highest semver version
    // or whatever non-semver if none available
    if (this._forceLatest) {
        suitable = picks.length - 1;

        this._logger.conflict(
            'solved',
            'Unable to find suitable version for ' + name,
            {
                name: name,
                picks: dataPicks,
                suitable: dataPicks[suitable],
                forced: true
            }
        );

        // Save resolution
        if (this._config.argv.cooked.includes('--save')) {
            this._storeResolution(picks[suitable]);
        }

        return Q.resolve(picks[suitable]);
    }

    // If interactive is disabled, error out
    if (!this._config.interactive) {
        throw createError(
            'Unable to find suitable version for ' + name,
            'ECONFLICT',
            {
                name: name,
                picks: dataPicks
            }
        );
    }

    // At this point the user needs to make a decision
    this._logger.conflict(
        'incompatible',
        'Unable to find suitable version for ' + name,
        {
            name: name,
            picks: dataPicks
        }
    );

    picksReleases = picks.map(function(pick) {
        return pick.pkgMeta._release;
    });
    return Q.nfcall(this._logger.prompt.bind(this._logger), {
        type: 'input',
        message: 'Answer',
        validate: function(choice) {
            var invalidChoice = 'Invalid choice';

            if (choice.match(versionRegex)) {
                return picksReleases.indexOf(choice) != -1
                    ? true
                    : invalidChoice;
            }

            choice = Number(mout.string.trim(choice.trim(), '!'));

            if (!choice || choice < 1 || choice > picks.length) {
                return invalidChoice;
            }

            return true;
        }
    }).then(
        function(choice) {
            var pick;

            // Sanitize choice
            choice = choice.trim();
            save = /^!/.test(choice) || /!$/.test(choice); // Save if prefixed or suffixed with !

            if (choice.match(versionRegex)) {
                pick = picks[picksReleases.indexOf(choice)];
            } else {
                choice = Number(mout.string.trim(choice, '!'));
                pick = picks[choice - 1];
            }

            // Save resolution
            if (save) {
                this._storeResolution(pick);
            }

            return pick;
        }.bind(this)
    );
};

Manager.prototype._storeResolution = function(pick) {
    var resolution;
    var name = pick.name;

    if (pick.target === '*') {
        resolution = pick.pkgMeta._release || '*';
    } else {
        resolution = pick.target;
    }

    this._logger.info(
        'resolution',
        'Saved ' + name + '#' + resolution + ' as resolution',
        {
            name: name,
            resolution: resolution,
            action: this._resolutions[name] ? 'edit' : 'add'
        }
    );
    this._resolutions[name] = resolution;
};

/**
 * Checks if some endpoint is compatible with already resolved target.
 *
 * It is used in two situations:
 *   * checks if resolved component matches dependency constraint
 *   * checks if not resolved component matches already fetched component
 *
 * If candidate matches already resolved component, it won't be downloaded.
 *
 * @param {Endpoint} candidate endpoint
 * @param {Endpoint} resolved endpoint
 *
 * @return {Boolean}
 */
Manager.prototype._areCompatible = function(candidate, resolved) {
    var resolvedVersion;
    var highestCandidate;
    var highestResolved;
    var candidateIsRange = semver.validRange(candidate.target);
    var resolvedIsRange = semver.validRange(resolved.target);
    var candidateIsVersion = semver.valid(candidate.target);
    var resolvedIsVersion = semver.valid(resolved.target);

    // Check if targets are equal
    if (candidate.target === resolved.target) {
        return true;
    }

    resolvedVersion = resolved.pkgMeta && resolved.pkgMeta.version;
    // If there is no pkgMeta, resolvedVersion is downloading now
    // Check based on target requirements
    if (!resolvedVersion) {
        // If one of the targets is range and other is version,
        // check version against the range
        if (candidateIsVersion && resolvedIsRange) {
            return semver.satisfies(candidate.target, resolved.target);
        }

        if (resolvedIsVersion && candidateIsRange) {
            return semver.satisfies(resolved.target, candidate.target);
        }

        if (resolvedIsVersion && candidateIsVersion) {
            return semver.eq(resolved.target, candidate.target);
        }

        // If both targets are range, check that both have same
        // higher cap
        if (resolvedIsRange && candidateIsRange) {
            highestCandidate = this._getCap(
                semver.toComparators(candidate.target),
                'highest'
            );
            highestResolved = this._getCap(
                semver.toComparators(resolved.target),
                'highest'
            );

            // This never happens, but you can't be sure without tests
            if (!highestResolved.version || !highestCandidate.version) {
                return false;
            }

            return (
                semver.eq(highestCandidate.version, highestResolved.version) &&
                highestCandidate.comparator === highestResolved.comparator
            );
        }
        return false;
    }

    // If target is a version, compare against the resolved version
    if (candidateIsVersion) {
        return semver.eq(candidate.target, resolvedVersion);
    }

    // If target is a range, check if resolved version satisfies it
    if (candidateIsRange) {
        return semver.satisfies(resolvedVersion, candidate.target);
    }

    return false;
};

/**
 * Gets highest/lowest version from set of comparators.
 *
 * The only thing that matters for this function is version number.
 * Returned comparator is splitted to comparator and version parts.
 *
 * It is used to receive lowest / highest bound of toComparators result:
 * semver.toComparators('~0.1.1') // => [ [ '>=0.1.1-0', '<0.2.0-0' ] ]
 *
 * Examples:
 *
 * _getCap([['>=2.1.1-0', '<2.2.0-0'], '<3.2.0'], 'highest')
 * // => { comparator: '<', version: '3.2.0' }
 *
 * _getCap([['>=2.1.1-0', '<2.2.0-0'], '<3.2.0'], 'lowest')
 * // => { comparator: '>=', version: '2.1.1-0' }
 *
 * @param {Array.<Array|string>} comparators
 * @param {string} side, 'highest' (default) or 'lowest'
 *
 * @return {{ comparator: string, version: string }}
 */
Manager.prototype._getCap = function(comparators, side) {
    var matches;
    var candidate;
    var cap = {};
    var compare = side === 'lowest' ? semver.lt : semver.gt;

    comparators.forEach(function(comparator) {
        // Get version of this comparator
        // If it's an array, call recursively
        if (Array.isArray(comparator)) {
            candidate = this._getCap(comparator, side);

            // Compare with the current highest version
            if (!cap.version || compare(candidate.version, cap.version)) {
                cap = candidate;
            }
            // Otherwise extract the version from the comparator
            // using a simple regexp
        } else {
            matches = comparator.match(/(.*?)(\d+\.\d+\.\d+.*)$/);
            if (!matches) {
                return;
            }

            // Compare with the current highest version
            if (!cap.version || compare(matches[2], cap.version)) {
                cap.version = matches[2];
                cap.comparator = matches[1];
            }
        }
    }, this);

    return cap;
};

/**
 * Filters out unique endpoints, comparing by name and then source.
 *
 * It leaves last matching endpoint.
 *
 * Examples:
 *
 *  manager._uniquify([
 *      { name: 'foo', source: 'google.com' },
 *      { name: 'foo', source: 'facebook.com' }
 *  ]);
 *  // => { name: 'foo', source: 'facebook.com' }
 *
 * @param {Array.<Endpoint>} decEndpoints
 * @return {Array.<Endpoint>} Filtered elements of decEndpoints
 *
 */
Manager.prototype._uniquify = function(decEndpoints) {
    var length = decEndpoints.length;

    return decEndpoints.filter(function(decEndpoint, index) {
        var x;
        var current;

        for (x = index + 1; x < length; ++x) {
            current = decEndpoints[x];

            if (current === decEndpoint) {
                return false;
            }

            // Compare name if both set
            // Fallback to compare sources
            if (!current.name && !decEndpoint.name) {
                if (current.source !== decEndpoint.source) {
                    continue;
                }
            } else if (current.name !== decEndpoint.name) {
                continue;
            }

            // Compare targets if name/sources are equal
            if (current.target === decEndpoint.target) {
                return false;
            }
        }

        return true;
    });
};

module.exports = Manager;


================================================
FILE: lib/core/PackageRepository.js
================================================
var mout = require('mout');
var Q = require('q');
var ResolveCache = require('./ResolveCache');
var resolverFactory = require('./resolverFactory');
var createError = require('../util/createError');
var RegistryClient = require('bower-registry-client');

function PackageRepository(config, logger) {
    var registryOptions;

    this._config = config;
    this._logger = logger;

    // Instantiate the registry
    registryOptions = mout.object.deepMixIn({}, this._config);
    registryOptions.cache = this._config.storage.registry;

    this._registryClient = new RegistryClient(registryOptions, logger);

    // Instantiate the resolve cache
    this._resolveCache = new ResolveCache(this._config);
}

// -----------------

PackageRepository.prototype.fetch = function(decEndpoint) {
    var logger;
    var that = this;
    var isTargetable;
    var info = {
        decEndpoint: decEndpoint
    };

    // Create a new logger that pipes everything to ours that will be
    // used to fetch
    logger = this._logger.geminate();
    // Intercept all logs, adding additional information
    logger.intercept(function(log) {
        that._extendLog(log, info);
    });

    return (
        this._getResolver(decEndpoint, logger)
            // Decide if we retrieve from the cache or not
            // Also decide if we validate the cached entry or not
            .then(function(resolver) {
                info.resolver = resolver;
                isTargetable = resolver.constructor.isTargetable;

                if (!resolver.isCacheable()) {
                    return that._resolve(resolver, logger);
                }

                // If force flag is used, bypass cache, but write to cache anyway
                if (that._config.force) {
                    logger.action(
                        'resolve',
                        resolver.getSource() + '#' + resolver.getTarget()
                    );
                    return that._resolve(resolver, logger);
                }

                // Note that we use the resolver methods to query the
                // cache because transformations/normalisations can occur
                return (
                    that._resolveCache
                        .retrieve(resolver.getSource(), resolver.getTarget())
                        // Decide if we can use the one from the resolve cache
                        .spread(function(canonicalDir, pkgMeta) {
                            // If there's no package in the cache
                            if (!canonicalDir) {
                                // And the offline flag is passed, error out
                                if (that._config.offline) {
                                    throw createError(
                                        'No cached version for ' +
                                            resolver.getSource() +
                                            '#' +
                                            resolver.getTarget(),
                                        'ENOCACHE',
                                        {
                                            resolver: resolver
                                        }
                                    );
                                }

                                // Otherwise, we have to resolve it
                                logger.info(
                                    'not-cached',
                                    resolver.getSource() +
                                        (resolver.getTarget()
                                            ? '#' + resolver.getTarget()
                                            : '')
                                );
                                logger.action(
                                    'resolve',
                                    resolver.getSource() +
                                        '#' +
                                        resolver.getTarget()
                                );

                                return that._resolve(resolver, logger);
                            }

                            info.canonicalDir = canonicalDir;
                            info.pkgMeta = pkgMeta;

                            logger.info(
                                'cached',
                                resolver.getSource() +
                                    (pkgMeta._release
                                        ? '#' + pkgMeta._release
                                        : '')
                            );

                            // If offline flag is used, use directly the cached one
                            if (that._config.offline) {
                                return [canonicalDir, pkgMeta, isTargetable];
                            }

                            // Otherwise check for new contents
                            logger.action(
                                'validate',
                                (pkgMeta._release
                                    ? pkgMeta._release + ' against '
                                    : '') +
                                    resolver.getSource() +
                                    (resolver.getTarget()
                                        ? '#' + resolver.getTarget()
                                        : '')
                            );

                            return resolver
                                .hasNew(pkgMeta)
                                .then(function(hasNew) {
                                    // If there are no new contents, resolve to
                                    // the cached one
                                    if (!hasNew) {
                                        return [
                                            canonicalDir,
                                            pkgMeta,
                                            isTargetable
                                        ];
                                    }

                                    // Otherwise resolve to the newest one
                                    logger.info(
                                        'new',
                                        'version for ' +
                                            resolver.getSource() +
                                            '#' +
                                            resolver.getTarget()
                                    );
                                    logger.action(
                                        'resolve',
                                        resolver.getSource() +
                                            '#' +
                                            resolver.getTarget()
                                    );

                                    return that._resolve(resolver, logger);
                                });
                        })
                );
            })
            // If something went wrong, also extend the error
            .fail(function(err) {
                that._extendLog(err, info);
                throw err;
            })
    );
};

PackageRepository.prototype.versions = function(source) {
    // Resolve the source using the factory because the
    // source can actually be a registry name
    return this._getResolver({ source: source }).then(
        function(resolver) {
            // If offline, resolve using the cached versions
            if (this._config.offline) {
                return this._resolveCache.versions(resolver.getSource());
            }

            // Otherwise, fetch remotely
            return resolver.constructor.versions(resolver.getSource());
        }.bind(this)
    );
};

PackageRepository.prototype.eliminate = function(pkgMeta) {
    return Q.all([
        this._resolveCache.eliminate(pkgMeta),
        Q.nfcall(
            this._registryClient.clearCache.bind(this._registryClient),
            pkgMeta.name
        )
    ]);
};

PackageRepository.prototype.clear = function() {
    return Q.all([
        this._resolveCache.clear(),
        Q.nfcall(this._registryClient.clearCache.bind(this._registryClient))
    ]);
};

PackageRepository.prototype.reset = function() {
    this._resolveCache.reset();
    this._registryClient.resetCache();
};

PackageRepository.prototype.list = function() {
    return this._resolveCache.list();
};

PackageRepository.prototype.getRegistryClient = function() {
    return this._registryClient;
};

PackageRepository.prototype.getResolveCache = function() {
    return this._resolveCache;
};

PackageRepository.clearRuntimeCache = function() {
    ResolveCache.clearRuntimeCache();
    RegistryClient.clearRuntimeCache();
    resolverFactory.clearRuntimeCache();
};

// ---------------------

PackageRepository.prototype._getResolver = function(decEndpoint, logger) {
    logger = logger || this._logger;

    // Get the appropriate resolver
    return resolverFactory(
        decEndpoint,
        { config: this._config, logger: logger },
        this._registryClient
    );
};

PackageRepository.prototype._resolve = function(resolver, logger) {
    var that = this;

    // Resolve the resolver
    return (
        resolver
            .resolve()
            // Store in the cache
            .then(function(canonicalDir) {
                if (!resolver.isCacheable()) {
                    return canonicalDir;
                }

                return that._resolveCache.store(
                    canonicalDir,
                    resolver.getPkgMeta()
                );
            })
            // Resolve promise with canonical dir and package meta
            .then(function(dir) {
                var pkgMeta = resolver.getPkgMeta();

                logger.info(
                    'resolved',
                    resolver.getSource() +
                        (pkgMeta._release ? '#' + pkgMeta._release : '')
                );
                return [dir, pkgMeta, resolver.constructor.isTargetable()];
            })
    );
};

PackageRepository.prototype._extendLog = function(log, info) {
    log.data = log.data || {};

    // Store endpoint info in each log
    if (info.decEndpoint) {
        log.data.endpoint = mout.object.pick(info.decEndpoint, [
            'name',
            'source',
            'target'
        ]);
    }

    // Store the resolver info in each log
    if (info.resolver) {
        log.data.resolver = {
            name: info.resolver.getName(),
            source: info.resolver.getSource(),
            target: info.resolver.getTarget()
        };
    }

    // Store the canonical dir and its meta in each log
    if (info.canonicalDir) {
        log.data.canonicalDir = info.canonicalDir;
        log.data.pkgMeta = info.pkgMeta;
    }

    return log;
};

module.exports = PackageRepository;


================================================
FILE: lib/core/Project.js
================================================
var glob = require('glob');
var path = require('path');
var fs = require('../util/fs');
var Q = require('q');
var mout = require('mout');
var rimraf = require('../util/rimraf');
var endpointParser = require('bower-endpoint-parser');
var Logger = require('bower-logger');
var md5 = require('md5-hex');
var Manager = require('./Manager');
var semver = require('../util/semver');
var createError = require('../util/createError');
var readJson = require('../util/readJson');
var validLink = require('../util/validLink');
var scripts = require('./scripts');
var relativeToBaseDir = require('../util/relativeToBaseDir');

function Project(config, logger) {
    this._config = config;
    this._logger = logger || new Logger();
    this._manager = new Manager(this._config, this._logger);

    this._options = {};
}

// -----------------

Project.prototype.install = function(decEndpoints, options, config) {
    var that = this;
    var targets = [];
    var resolved = {};
    var incompatibles = [];

    // If already working, error out
    if (this._working) {
        return Q.reject(createError('Already working', 'EWORKING'));
    }

    this._options = options || {};
    this._config = config || {};
    this._working = true;

    // Analyse the project
    return this._analyse()
      
Download .txt
gitextract_0ya96a9h/

├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE.md
│   └── workflows/
│       └── nodejs.yml
├── .gitignore
├── .prettierignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── bin/
│   └── bower
├── lib/
│   ├── bin/
│   │   └── bower.js
│   ├── commands/
│   │   ├── cache/
│   │   │   ├── clean.js
│   │   │   └── list.js
│   │   ├── help.js
│   │   ├── home.js
│   │   ├── index.js
│   │   ├── info.js
│   │   ├── init.js
│   │   ├── install.js
│   │   ├── link.js
│   │   ├── list.js
│   │   ├── login.js
│   │   ├── lookup.js
│   │   ├── prune.js
│   │   ├── register.js
│   │   ├── search.js
│   │   ├── uninstall.js
│   │   ├── unregister.js
│   │   ├── update.js
│   │   └── version.js
│   ├── config.js
│   ├── core/
│   │   ├── Manager.js
│   │   ├── PackageRepository.js
│   │   ├── Project.js
│   │   ├── ResolveCache.js
│   │   ├── resolverFactory.js
│   │   ├── resolvers/
│   │   │   ├── FsResolver.js
│   │   │   ├── GitFsResolver.js
│   │   │   ├── GitHubResolver.js
│   │   │   ├── GitRemoteResolver.js
│   │   │   ├── GitResolver.js
│   │   │   ├── Resolver.js
│   │   │   ├── SvnResolver.js
│   │   │   ├── UrlResolver.js
│   │   │   ├── index.js
│   │   │   └── pluginResolverFactory.js
│   │   └── scripts.js
│   ├── index.js
│   ├── renderers/
│   │   ├── JsonRenderer.js
│   │   ├── StandardRenderer.js
│   │   └── index.js
│   ├── templates/
│   │   ├── helpers/
│   │   │   ├── colors.js
│   │   │   ├── condense.js
│   │   │   ├── indent.js
│   │   │   ├── index.js
│   │   │   ├── rpad.js
│   │   │   └── sum.js
│   │   ├── json/
│   │   │   ├── help-cache/
│   │   │   │   ├── clean.json
│   │   │   │   └── list.json
│   │   │   ├── help-cache.json
│   │   │   ├── help-home.json
│   │   │   ├── help-info.json
│   │   │   ├── help-init.json
│   │   │   ├── help-install.json
│   │   │   ├── help-link.json
│   │   │   ├── help-list.json
│   │   │   ├── help-login.json
│   │   │   ├── help-lookup.json
│   │   │   ├── help-prune.json
│   │   │   ├── help-register.json
│   │   │   ├── help-search.json
│   │   │   ├── help-uninstall.json
│   │   │   ├── help-unregister.json
│   │   │   ├── help-update.json
│   │   │   ├── help-version.json
│   │   │   └── help.json
│   │   └── std/
│   │       ├── conflict-resolved.std
│   │       ├── conflict.std
│   │       ├── help-cache.std
│   │       ├── help-generic.std
│   │       ├── help.std
│   │       ├── info.std
│   │       ├── lookup.std
│   │       ├── register.std
│   │       └── search-results.std
│   ├── util/
│   │   ├── abbreviations.js
│   │   ├── childProcess.js
│   │   ├── cli.js
│   │   ├── cmd.js
│   │   ├── copy.js
│   │   ├── createError.js
│   │   ├── createLink.js
│   │   ├── download.js
│   │   ├── extract.js
│   │   ├── fs.js
│   │   ├── isPathAbsolute.js
│   │   ├── readJson.js
│   │   ├── relativeToBaseDir.js
│   │   ├── removeIgnores.js
│   │   ├── resolve.js
│   │   ├── rimraf.js
│   │   ├── rootCheck.js
│   │   ├── semver.js
│   │   ├── template.js
│   │   ├── userAgent.js
│   │   ├── validLink.js
│   │   └── which.js
│   └── version.js
├── package.json
├── packages/
│   ├── bower-config/
│   │   ├── .editorconfig
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── lib/
│   │   │   ├── Config.js
│   │   │   ├── util/
│   │   │   │   ├── defaults.js
│   │   │   │   ├── expand.js
│   │   │   │   ├── paths.js
│   │   │   │   ├── proxy.js
│   │   │   │   └── rc.js
│   │   │   └── vendor/
│   │   │       └── optimist.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── assets/
│   │       │   ├── custom-ca/
│   │       │   │   ├── .bowerrc
│   │       │   │   └── ca-bundle.crt
│   │       │   ├── custom-ca-embed/
│   │       │   │   └── .bowerrc
│   │       │   ├── env-variables/
│   │       │   │   └── .bowerrc
│   │       │   └── env-variables-values/
│   │       │       └── .bowerrc
│   │       ├── cli.js
│   │       ├── helpers.js
│   │       ├── test.js
│   │       └── util/
│   │           ├── index.js
│   │           └── rc.js
│   ├── bower-endpoint-parser/
│   │   ├── .editorconfig
│   │   ├── .gitignore
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       └── test.js
│   ├── bower-json/
│   │   ├── .editorconfig
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── lib/
│   │   │   ├── json.js
│   │   │   ├── util/
│   │   │   │   ├── createError.js
│   │   │   │   ├── isAsset.js
│   │   │   │   └── isComponent.js
│   │   │   └── vendor/
│   │   │       └── ext-name.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── pkg-bower-json/
│   │       │   └── bower.json
│   │       ├── pkg-bower-json-invalid/
│   │       │   └── bower.json
│   │       ├── pkg-bower-json-malformed/
│   │       │   └── bower.json
│   │       ├── pkg-component(1)-json/
│   │       │   └── component.json
│   │       ├── pkg-component-json/
│   │       │   └── component.json
│   │       ├── pkg-dot-bower-json/
│   │       │   └── .bower.json
│   │       └── test.js
│   ├── bower-logger/
│   │   ├── .editorconfig
│   │   ├── .gitignore
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── lib/
│   │   │   └── Logger.js
│   │   ├── package.json
│   │   └── test/
│   │       └── test.js
│   └── bower-registry-client/
│       ├── .editorconfig
│       ├── .gitignore
│       ├── Client.js
│       ├── LICENSE
│       ├── README.md
│       ├── lib/
│       │   ├── index.js
│       │   ├── list.js
│       │   ├── lookup.js
│       │   ├── register.js
│       │   ├── search.js
│       │   ├── unregister.js
│       │   └── util/
│       │       ├── Cache.js
│       │       ├── createError.js
│       │       └── md5.js
│       ├── package.json
│       └── test/
│           ├── Client.js
│           ├── core/
│           │   ├── index.js
│           │   ├── list.js
│           │   ├── lookup.js
│           │   ├── register.js
│           │   ├── search.js
│           │   └── util/
│           │       ├── Cache.js
│           │       └── createError.js
│           ├── fixtures/
│           │   └── search.json
│           └── runner.js
├── publish.js
└── test/
    ├── assets/
    │   ├── resolve-cache/
    │   │   └── list-json-1.json
    │   ├── test-gz.txt
    │   └── test-temp-dir/
    │       ├── test-exception.js
    │       └── test.js
    ├── commands/
    │   ├── bower.js
    │   ├── cache/
    │   │   ├── clean.js
    │   │   └── list.js
    │   ├── help.js
    │   ├── home.js
    │   ├── index.js
    │   ├── info.js
    │   ├── init.js
    │   ├── install.js
    │   ├── link.js
    │   ├── list.js
    │   ├── login.js
    │   ├── lookup.js
    │   ├── prune.js
    │   ├── register.js
    │   ├── search.js
    │   ├── uninstall.js
    │   ├── unregister.js
    │   ├── update.js
    │   └── version.js
    ├── core/
    │   ├── Manager.js
    │   ├── packageRepository.js
    │   ├── resolveCache.js
    │   ├── resolverFactory.js
    │   ├── resolvers/
    │   │   ├── fsResolver.js
    │   │   ├── gitFsResolver.js
    │   │   ├── gitHubResolver.js
    │   │   ├── gitRemoteResolver.js
    │   │   ├── gitResolver.js
    │   │   ├── pluginResolverFactory.js
    │   │   ├── resolver.js
    │   │   ├── svnResolver.js
    │   │   └── urlResolver.js
    │   └── scripts.js
    ├── helpers.js
    ├── packages-svn.js
    ├── packages-svn.json
    ├── packages.js
    ├── packages.json
    ├── renderers/
    │   ├── JsonRenderer.js
    │   └── StandardRenderer.js
    ├── test.js
    └── util/
        ├── createLink.js
        ├── download.js
        ├── index.js
        ├── isPathAbsolute.js
        ├── nock.js
        ├── relativeToBaseDir.js
        ├── removeIgnores.js
        └── template.js
Download .txt
SYMBOL INDEX (218 symbols across 104 files)

FILE: lib/bin/bower.js
  function handleLogger (line 96) | function handleLogger(logger, renderer) {

FILE: lib/commands/cache/clean.js
  function clean (line 11) | function clean(logger, endpoints, options, config) {
  function clearPackages (line 41) | function clearPackages(decEndpoints, config, logger) {
  function clearLinks (line 113) | function clearLinks(names, config, logger) {

FILE: lib/commands/cache/list.js
  function list (line 5) | function list(logger, packages, options, config) {

FILE: lib/commands/help.js
  function help (line 6) | function help(logger, name, config) {

FILE: lib/commands/home.js
  function home (line 7) | function home(logger, name, config) {

FILE: lib/commands/index.js
  function commandFactory (line 12) | function commandFactory(id) {

FILE: lib/commands/info.js
  function info (line 7) | function info(logger, endpoint, property, config) {
  function getPkgMeta (line 45) | function getPkgMeta(repository, decEndpoint, property) {

FILE: lib/commands/init.js
  function init (line 12) | function init(logger, config) {
  function readJson (line 49) | function readJson(project, logger) {
  function saveJson (line 64) | function saveJson(project, logger, json) {
  function validConfigValue (line 91) | function validConfigValue(val) {
  function setDefaults (line 101) | function setDefaults(config, json) {
  function promptUser (line 193) | function promptUser(logger, json) {
  function toArray (line 276) | function toArray(value, splitter) {
  function setIgnore (line 292) | function setIgnore(config, json, answers) {
  function setDependencies (line 307) | function setDependencies(project, json, answers) {

FILE: lib/commands/install.js
  function install (line 5) | function install(logger, endpoints, options, config) {

FILE: lib/commands/link.js
  function link (line 9) | function link(logger, name, localName, config) {
  function linkSelf (line 17) | function linkSelf(logger, config) {
  function linkTo (line 44) | function linkTo(logger, name, localName, config) {

FILE: lib/commands/list.js
  function list (line 8) | function list(logger, options, config) {
  function checkVersions (line 79) | function checkVersions(project, tree, logger) {
  function paths (line 127) | function paths(flattened) {
  function normalize (line 163) | function normalize(src) {

FILE: lib/commands/login.js
  function login (line 8) | function login(logger, options, config) {

FILE: lib/commands/lookup.js
  function lookup (line 5) | function lookup(logger, name, config) {

FILE: lib/commands/prune.js
  function prune (line 5) | function prune(logger, options, config) {
  function clean (line 15) | function clean(project, options, removed) {

FILE: lib/commands/register.js
  function register (line 7) | function register(logger, name, source, config) {

FILE: lib/commands/search.js
  function search (line 7) | function search(logger, name, config) {

FILE: lib/commands/uninstall.js
  function uninstall (line 6) | function uninstall(logger, names, options, config) {
  function clean (line 44) | function clean(project, names, removed) {

FILE: lib/commands/unregister.js
  function unregister (line 8) | function unregister(logger, name, config) {

FILE: lib/commands/update.js
  function update (line 4) | function update(logger, names, options, config) {

FILE: lib/commands/version.js
  function version (line 10) | function version(logger, versionArg, options, config) {
  function bump (line 18) | function bump(logger, config, versionArg, message) {
  function checkGit (line 86) | function checkGit(cwd) {
  function checkGitStatus (line 102) | function checkGitStatus(cwd) {
  function filterModifiedStatusLines (line 129) | function filterModifiedStatusLines(stdout) {

FILE: lib/config.js
  function defaultConfig (line 8) | function defaultConfig(config) {
  function readCachedConfig (line 14) | function readCachedConfig(cwd, overwrites) {
  function restoreConfig (line 50) | function restoreConfig() {
  function resetCache (line 56) | function resetCache() {

FILE: lib/core/Manager.js
  function Manager (line 15) | function Manager(config, logger) {

FILE: lib/core/PackageRepository.js
  function PackageRepository (line 8) | function PackageRepository(config, logger) {

FILE: lib/core/Project.js
  function Project (line 18) | function Project(config, logger) {
  function resolveUrlNames (line 263) | function resolveUrlNames(names, flattened) {

FILE: lib/core/ResolveCache.js
  function ResolveCache (line 14) | function ResolveCache(config) {

FILE: lib/core/resolverFactory.js
  function createInstance (line 11) | function createInstance(decEndpoint, options, registryClient) {
  function getConstructor (line 28) | function getConstructor(decEndpoint, options, registryClient) {
  function clearRuntimeCache (line 271) | function clearRuntimeCache() {

FILE: lib/core/resolvers/FsResolver.js
  function FsResolver (line 12) | function FsResolver(decEndpoint, config, logger) {

FILE: lib/core/resolvers/GitFsResolver.js
  function GitFsResolver (line 9) | function GitFsResolver(decEndpoint, config, logger) {

FILE: lib/core/resolvers/GitHubResolver.js
  function GitHubResolver (line 10) | function GitHubResolver(decEndpoint, config, logger) {

FILE: lib/core/resolvers/GitRemoteResolver.js
  function GitRemoteResolver (line 9) | function GitRemoteResolver(decEndpoint, config, logger) {

FILE: lib/core/resolvers/GitResolver.js
  function GitResolver (line 23) | function GitResolver(decEndpoint, config, logger) {

FILE: lib/core/resolvers/Resolver.js
  function Resolver (line 14) | function Resolver(decEndpoint, config, logger) {

FILE: lib/core/resolvers/SvnResolver.js
  function SvnResolver (line 21) | function SvnResolver(decEndpoint, config, logger) {

FILE: lib/core/resolvers/UrlResolver.js
  function UrlResolver (line 14) | function UrlResolver(decEndpoint, config, logger) {

FILE: lib/core/resolvers/pluginResolverFactory.js
  function pluginResolverFactory (line 11) | function pluginResolverFactory(resolverFactory, bower) {

FILE: lib/index.js
  function clearRuntimeCache (line 5) | function clearRuntimeCache() {

FILE: lib/renderers/JsonRenderer.js
  function JsonRenderer (line 6) | function JsonRenderer() {

FILE: lib/renderers/StandardRenderer.js
  function StandardRenderer (line 12) | function StandardRenderer(command, config) {

FILE: lib/templates/helpers/colors.js
  function colors (line 5) | function colors(Handlebars) {

FILE: lib/templates/helpers/condense.js
  function condense (line 5) | function condense(Handlebars) {

FILE: lib/templates/helpers/indent.js
  function indent (line 3) | function indent(Handlebars) {

FILE: lib/templates/helpers/rpad.js
  function rpad (line 3) | function rpad(Handlebars) {

FILE: lib/templates/helpers/sum.js
  function sum (line 1) | function sum(Handlebars) {

FILE: lib/util/abbreviations.js
  function expandNames (line 4) | function expandNames(obj, prefix, stack) {

FILE: lib/util/childProcess.js
  function execFile (line 4) | function execFile(cmd, args, opt, cb) {
  function spawn (line 13) | function spawn(cmd, args, opt) {

FILE: lib/util/cli.js
  function readOptions (line 5) | function readOptions(options, argv) {
  function getRenderer (line 40) | function getRenderer(command, json, config) {

FILE: lib/util/cmd.js
  function getWindowsCommand (line 27) | function getWindowsCommand(command) {
  function executeCmd (line 57) | function executeCmd(command, args, options) {
  function cmd (line 125) | function cmd(command, args, options) {

FILE: lib/util/copy.js
  function copy (line 6) | function copy(reader, writer) {
  function copyMode (line 38) | function copyMode(src, dst) {
  function filterSymlinks (line 44) | function filterSymlinks(entry) {
  function parseOptions (line 48) | function parseOptions(opts) {
  function copyFile (line 65) | function copyFile(src, dst, opts) {
  function copyDir (line 93) | function copyDir(src, dst, opts) {

FILE: lib/util/createError.js
  function createError (line 3) | function createError(msg, code, props) {

FILE: lib/util/createLink.js
  function createLink (line 9) | function createLink(src, dst, type) {

FILE: lib/util/download.js
  function download (line 18) | function download(url, file, options) {
  function fetch (line 75) | function fetch(url, file, options) {

FILE: lib/util/extract.js
  function extractZip (line 37) | function extractZip(archive, dst) {
  function extractTar (line 52) | function extractTar(archive, dst) {
  function extractTarGz (line 80) | function extractTarGz(archive, dst) {
  function extractGz (line 110) | function extractGz(archive, dst) {
  function isSymlink (line 133) | function isSymlink(_, entry) {
  function filterSymlinks (line 137) | function filterSymlinks(entry) {
  function getExtractor (line 141) | function getExtractor(archive) {
  function isSingleDir (line 153) | function isSingleDir(dir) {
  function moveDirectory (line 173) | function moveDirectory(srcDir, destDir) {
  function canExtract (line 192) | function canExtract(src, mimeType) {
  function extract (line 203) | function extract(src, dst, opts) {

FILE: lib/util/isPathAbsolute.js
  function isPathAbsolute (line 1) | function isPathAbsolute(filePath) {

FILE: lib/util/readJson.js
  function readJson (line 12) | function readJson(file, options) {

FILE: lib/util/relativeToBaseDir.js
  function relativeToBaseDir (line 4) | function relativeToBaseDir(baseDir) {

FILE: lib/util/removeIgnores.js
  function removeIgnores (line 7) | function removeIgnores(dir, meta) {

FILE: lib/util/resolve.js
  function startsWith (line 4) | function startsWith(string, searchString, position) {

FILE: lib/util/rootCheck.js
  function rootCheck (line 6) | function rootCheck(options, config) {

FILE: lib/util/semver.js
  function maxSatisfying (line 4) | function maxSatisfying(versions, range, strictMatch) {
  function maxSatisfyingIndex (line 42) | function maxSatisfyingIndex(versions, range, strictMatch) {
  function clean (line 52) | function clean(version) {
  function isPreRelease (line 66) | function isPreRelease(version) {

FILE: lib/util/template.js
  function render (line 15) | function render(name, data, escape) {
  function exists (line 33) | function exists(name) {

FILE: lib/util/validLink.js
  function validLink (line 4) | function validLink(file) {

FILE: lib/util/which.js
  function which (line 8) | function which(name, opt, cb) {
  function whichSync (line 26) | function whichSync(name, opt) {

FILE: packages/bower-config/lib/Config.js
  function Config (line 9) | function Config(cwd) {
  function readCertFile (line 34) | function readCertFile(path) {
  function loadCAs (line 57) | function loadCAs(caConfig) {
  function normalise (line 88) | function normalise(config) {

FILE: packages/bower-config/lib/util/expand.js
  function camelCase (line 5) | function camelCase(config) {
  function doEnvReplaceStr (line 25) | function doEnvReplaceStr(f) {
  function envReplace (line 43) | function envReplace(config) {
  function expand (line 78) | function expand(config) {

FILE: packages/bower-config/lib/util/paths.js
  function generateFakeUser (line 6) | function generateFakeUser() {

FILE: packages/bower-config/lib/util/rc.js
  function rc (line 13) | function rc(name, cwd, argv) {
  function parse (line 53) | function parse(content, file) {
  function json (line 75) | function json(file) {
  function env (line 103) | function env(prefix) {
  function find (line 136) | function find(filename, dir) {

FILE: packages/bower-config/lib/vendor/optimist.js
  function Argv (line 20) | function Argv(processArgs, cwd) {
  function rebase (line 332) | function rebase(base, dir) {

FILE: packages/bower-config/test/helpers.js
  function TempDir (line 25) | function TempDir(defaults) {

FILE: packages/bower-config/test/test.js
  function assertCAContents (line 88) | function assertCAContents(caData, name) {

FILE: packages/bower-endpoint-parser/index.js
  function decompose (line 1) | function decompose(endpoint) {
  function compose (line 23) | function compose(decEndpoint) {
  function json2decomposed (line 42) | function json2decomposed(key, value) {
  function decomposed2json (line 73) | function decomposed2json(decEndpoint) {
  function trim (line 113) | function trim(str) {
  function isWildcard (line 117) | function isWildcard(target) {
  function isSource (line 121) | function isSource(value) {

FILE: packages/bower-json/lib/json.js
  function read (line 10) | function read(file, options, callback) {
  function readSync (line 62) | function readSync(file, options) {
  function parse (line 101) | function parse(json, options) {
  function getIssues (line 132) | function getIssues(json) {
  function validate (line 233) | function validate(json) {
  function normalize (line 241) | function normalize(json) {
  function find (line 249) | function find(folder, files, callback) {
  function findSync (line 288) | function findSync(folder, files) {

FILE: packages/bower-json/lib/util/createError.js
  function createError (line 1) | function createError(msg, code) {

FILE: packages/bower-json/lib/util/isAsset.js
  function isAsset (line 3) | function isAsset(filename) {

FILE: packages/bower-json/lib/util/isComponent.js
  function isComponent (line 5) | function isComponent(file, callback) {

FILE: packages/bower-logger/lib/Logger.js
  function Logger (line 6) | function Logger() {

FILE: packages/bower-registry-client/Client.js
  function RegistryClient (line 5) | function RegistryClient(config, logger) {

FILE: packages/bower-registry-client/lib/list.js
  function list (line 9) | function list(callback) {
  function addResult (line 78) | function addResult(accumulated, result) {
  function doRequest (line 88) | function doRequest(index, callback) {
  function getMaxAge (line 169) | function getMaxAge() {
  function initCache (line 174) | function initCache() {
  function clearCache (line 203) | function clearCache(callback) {
  function resetCache (line 218) | function resetCache() {

FILE: packages/bower-registry-client/lib/lookup.js
  function lookup (line 9) | function lookup(name, callback) {
  function doRequest (line 80) | function doRequest(name, index, callback) {
  function getMaxAge (line 176) | function getMaxAge(entry) {
  function initCache (line 186) | function initCache() {
  function clearCache (line 215) | function clearCache(name, callback) {
  function resetCache (line 243) | function resetCache() {

FILE: packages/bower-registry-client/lib/register.js
  function register (line 5) | function register(name, url, callback) {

FILE: packages/bower-registry-client/lib/search.js
  function search (line 16) | function search(name, callback) {
  function addResult (line 86) | function addResult(accumulated, result) {
  function doRequest (line 96) | function doRequest(name, index, callback) {
  function getMaxAge (line 180) | function getMaxAge() {
  function initCache (line 185) | function initCache() {
  function clearCache (line 214) | function clearCache(name, callback) {
  function resetCache (line 237) | function resetCache() {

FILE: packages/bower-registry-client/lib/unregister.js
  function unregister (line 5) | function unregister(name, callback) {

FILE: packages/bower-registry-client/lib/util/Cache.js
  function Cache (line 8) | function Cache(dir, options) {

FILE: packages/bower-registry-client/lib/util/createError.js
  function createError (line 1) | function createError(msg, code) {

FILE: packages/bower-registry-client/lib/util/md5.js
  function md5 (line 3) | function md5(contents) {

FILE: test/commands/login.js
  function FakeGitHub (line 5) | function FakeGitHub() {}
  function FakeConfigstore (line 40) | function FakeConfigstore() {}

FILE: test/commands/register.js
  function FakeRepository (line 8) | function FakeRepository() {}

FILE: test/commands/uninstall.js
  function bowerJson (line 25) | function bowerJson() {

FILE: test/commands/unregister.js
  function FakeRepository (line 5) | function FakeRepository() {}

FILE: test/core/packageRepository.js
  function resolverFactory (line 48) | function resolverFactory(decEndpoint, options, _registryClient) {

FILE: test/core/resolveCache.js
  function initialize (line 61) | function initialize(cacheDir) {

FILE: test/core/resolverFactory.js
  function callFactory (line 39) | function callFactory(decEndpoint, config, skipRegistry) {

FILE: test/core/resolvers/fsResolver.js
  function create (line 40) | function create(decEndpoint) {
  function assertMain (line 111) | function assertMain(dir, singleFile) {

FILE: test/core/resolvers/gitFsResolver.js
  function clearResolverRuntimeCache (line 32) | function clearResolverRuntimeCache() {
  function create (line 36) | function create(decEndpoint) {
  function cleanup (line 151) | function cleanup(err) {

FILE: test/core/resolvers/gitHubResolver.js
  function create (line 22) | function create(decEndpoint) {

FILE: test/core/resolvers/gitRemoteResolver.js
  function clearResolverRuntimeCache (line 24) | function clearResolverRuntimeCache() {
  function create (line 28) | function create(decEndpoint) {
  function createCmdHandlerFn (line 334) | function createCmdHandlerFn(testSource, stderr) {

FILE: test/core/resolvers/gitResolver.js
  function clearResolverRuntimeCache (line 30) | function clearResolverRuntimeCache() {
  function create (line 35) | function create(decEndpoint) {
  function DummyResolver (line 331) | function DummyResolver() {
  function CustomGitResolver (line 1527) | function CustomGitResolver() {}

FILE: test/core/resolvers/pluginResolverFactory.js
  function create (line 51) | function create(decEndpoint) {

FILE: test/core/resolvers/resolver.js
  function create (line 37) | function create(decEndpoint) {
  function DummyResolver (line 300) | function DummyResolver() {

FILE: test/core/resolvers/svnResolver.js
  function clearResolverRuntimeCache (line 34) | function clearResolverRuntimeCache() {
  function create (line 39) | function create(decEndpoint) {
  function DummyResolver (line 254) | function DummyResolver() {
  function CustomSvnResolver (line 887) | function CustomSvnResolver() {}

FILE: test/core/resolvers/urlResolver.js
  function create (line 32) | function create(decEndpoint) {
  function assertMain (line 238) | function assertMain(dir, singleFile) {
  function performTest (line 852) | function performTest(header, extraction) {

FILE: test/helpers.js
  function TempDir (line 61) | function TempDir(defaults) {

FILE: test/packages-svn.js
  function ensurePackage (line 43) | function ensurePackage(admin, dir) {
  function checkRelease (line 100) | function checkRelease(dir, release) {
  function createRelease (line 121) | function createRelease(admin, dir, release, files) {

FILE: test/packages.js
  function ensurePackage (line 34) | function ensurePackage(dir) {
  function checkRelease (line 81) | function checkRelease(dir, release) {
  function createRelease (line 100) | function createRelease(dir, release, files) {

FILE: test/util/download.js
  function downloadTest (line 15) | function downloadTest(opts) {
  function testGzip (line 187) | function testGzip(sourceFilename) {
Condensed preview — 248 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,258K chars).
[
  {
    "path": ".editorconfig",
    "chars": 267,
    "preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ni"
  },
  {
    "path": ".eslintignore",
    "chars": 86,
    "preview": "node_modules\ntest/assets\ntest/reports\ntest/sample\ntest/tmp\npackages/bower-logger/test\n"
  },
  {
    "path": ".eslintrc",
    "chars": 1179,
    "preview": "{\n  \"env\": {\n    \"node\": true,\n    \"mocha\": true\n  },\n  \"rules\": {\n    \"no-bitwise\": 0,\n    \"curly\": 0,\n    \"eqeqeq\": 0,"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 70,
    "preview": "# These are supported funding model platforms\n\nopen_collective: bower\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 989,
    "preview": "<!--\n\nIf you are reporting a new issue, make sure that we do not have any duplicates.\nYou can ensure this by searching t"
  },
  {
    "path": ".github/workflows/nodejs.yml",
    "chars": 2619,
    "preview": "name: build\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - '**'\n\njobs:\n  test:\n    name"
  },
  {
    "path": ".gitignore",
    "chars": 233,
    "preview": "!lib/bin\n/node_modules\n/npm-debug.log\n\n/test/assets/package-*/\n/test/assets/temp-*/\n/test/reports\n/test/tmp/\n\n/bower.jso"
  },
  {
    "path": ".prettierignore",
    "chars": 72,
    "preview": "**/node_modules/**\n**/test/assets/**\n**/bower_components/**\ntest/sample\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 40490,
    "preview": "# Changelog\n\n## Newer releases\n\nPlease see: https://github.com/bower/bower/releases\n\n## 1.8.0 - 2016-11-07\n\n- Download t"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 6363,
    "preview": "# Contributing to Bower\n\nBower is a large community project with many different developers contributing at all levels to"
  },
  {
    "path": "LICENSE",
    "chars": 1082,
    "preview": "Copyright (c) 2013-present Twitter and other contributors\n\nPermission is hereby granted, free of charge, to any person o"
  },
  {
    "path": "README.md",
    "chars": 26032,
    "preview": "# Bower - A package manager for the web\n\n[![Build](https://github.com/bower/bower/workflows/build/badge.svg)](https://gi"
  },
  {
    "path": "SECURITY.md",
    "chars": 118,
    "preview": "# Security Policy\n\nFor critical security issues, please send an e-mail to team@bower.io instead of filing issue here.\n"
  },
  {
    "path": "bin/bower",
    "chars": 50,
    "preview": "#!/usr/bin/env node\n\nrequire('../lib/bin/bower');\n"
  },
  {
    "path": "lib/bin/bower.js",
    "chars": 4033,
    "preview": "process.bin = process.title = 'bower';\n\nvar Q = require('q');\nvar mout = require('mout');\nvar Logger = require('bower-lo"
  },
  {
    "path": "lib/commands/cache/clean.js",
    "chars": 6238,
    "preview": "var fs = require('../../util/fs');\nvar path = require('path');\nvar mout = require('mout');\nvar Q = require('q');\nvar rim"
  },
  {
    "path": "lib/commands/cache/list.js",
    "chars": 1104,
    "preview": "var mout = require('mout');\nvar PackageRepository = require('../../core/PackageRepository');\nvar defaultConfig = require"
  },
  {
    "path": "lib/commands/help.js",
    "chars": 975,
    "preview": "var Q = require('q');\nvar path = require('path');\nvar fs = require('../util/fs');\nvar createError = require('../util/cre"
  },
  {
    "path": "lib/commands/home.js",
    "chars": 1587,
    "preview": "var Project = require('../core/Project');\nvar open = require('opn');\nvar endpointParser = require('bower-endpoint-parser"
  },
  {
    "path": "lib/commands/index.js",
    "chars": 2305,
    "preview": "var Q = require('q');\nvar Logger = require('bower-logger');\nvar config = require('../config');\n\n/**\n * Require commands "
  },
  {
    "path": "lib/commands/info.js",
    "chars": 1932,
    "preview": "var mout = require('mout');\nvar Q = require('q');\nvar endpointParser = require('bower-endpoint-parser');\nvar PackageRepo"
  },
  {
    "path": "lib/commands/init.js",
    "chars": 9640,
    "preview": "var mout = require('mout');\nvar fs = require('../util/fs');\nvar path = require('path');\nvar Q = require('q');\nvar endpoi"
  },
  {
    "path": "lib/commands/install.js",
    "chars": 1546,
    "preview": "var endpointParser = require('bower-endpoint-parser');\nvar Project = require('../core/Project');\nvar defaultConfig = req"
  },
  {
    "path": "lib/commands/link.js",
    "chars": 2342,
    "preview": "var path = require('path');\nvar rimraf = require('../util/rimraf');\nvar Q = require('q');\nvar Project = require('../core"
  },
  {
    "path": "lib/commands/list.js",
    "chars": 4674,
    "preview": "var path = require('path');\nvar mout = require('mout');\nvar Q = require('q');\nvar Project = require('../core/Project');\n"
  },
  {
    "path": "lib/commands/login.js",
    "chars": 4445,
    "preview": "var Configstore = require('configstore');\nvar GitHub = require('github');\nvar Q = require('q');\n\nvar createError = requi"
  },
  {
    "path": "lib/commands/lookup.js",
    "chars": 886,
    "preview": "var Q = require('q');\nvar PackageRepository = require('../core/PackageRepository');\nvar defaultConfig = require('../conf"
  },
  {
    "path": "lib/commands/prune.js",
    "chars": 1526,
    "preview": "var mout = require('mout');\nvar Project = require('../core/Project');\nvar defaultConfig = require('../config');\n\nfunctio"
  },
  {
    "path": "lib/commands/register.js",
    "chars": 2909,
    "preview": "var Q = require('q');\nvar chalk = require('chalk');\nvar PackageRepository = require('../core/PackageRepository');\nvar cr"
  },
  {
    "path": "lib/commands/search.js",
    "chars": 1103,
    "preview": "var Q = require('q');\nvar PackageRepository = require('../core/PackageRepository');\nvar defaultConfig = require('../conf"
  },
  {
    "path": "lib/commands/uninstall.js",
    "chars": 3870,
    "preview": "var mout = require('mout');\nvar Q = require('q');\nvar Project = require('../core/Project');\nvar defaultConfig = require("
  },
  {
    "path": "lib/commands/unregister.js",
    "chars": 2376,
    "preview": "var chalk = require('chalk');\nvar Q = require('q');\n\nvar defaultConfig = require('../config');\nvar PackageRepository = r"
  },
  {
    "path": "lib/commands/update.js",
    "chars": 846,
    "preview": "var Project = require('../core/Project');\nvar defaultConfig = require('../config');\n\nfunction update(logger, names, opti"
  },
  {
    "path": "lib/commands/version.js",
    "chars": 6338,
    "preview": "var semver = require('semver');\nvar which = require('../util/which');\nvar fs = require('../util/fs');\nvar path = require"
  },
  {
    "path": "lib/config.js",
    "chars": 1659,
    "preview": "var tty = require('tty');\nvar object = require('mout').object;\nvar bowerConfig = require('bower-config');\nvar Configstor"
  },
  {
    "path": "lib/core/Manager.js",
    "chars": 41102,
    "preview": "var Q = require('q');\nvar mout = require('mout');\nvar path = require('path');\nvar mkdirp = require('mkdirp');\nvar rimraf"
  },
  {
    "path": "lib/core/PackageRepository.js",
    "chars": 10846,
    "preview": "var mout = require('mout');\nvar Q = require('q');\nvar ResolveCache = require('./ResolveCache');\nvar resolverFactory = re"
  },
  {
    "path": "lib/core/Project.js",
    "chars": 35697,
    "preview": "var glob = require('glob');\nvar path = require('path');\nvar fs = require('../util/fs');\nvar Q = require('q');\nvar mout ="
  },
  {
    "path": "lib/core/ResolveCache.js",
    "chars": 14459,
    "preview": "var fs = require('../util/fs');\nvar path = require('path');\nvar mout = require('mout');\nvar Q = require('q');\nvar mkdirp"
  },
  {
    "path": "lib/core/resolverFactory.js",
    "chars": 8904,
    "preview": "var Q = require('q');\nvar fs = require('../util/fs');\nvar path = require('path');\nvar mout = require('mout');\nvar resolv"
  },
  {
    "path": "lib/core/resolvers/FsResolver.js",
    "chars": 4468,
    "preview": "var util = require('util');\nvar fs = require('../../util/fs');\nvar path = require('path');\nvar mout = require('mout');\nv"
  },
  {
    "path": "lib/core/resolvers/GitFsResolver.js",
    "chars": 2900,
    "preview": "var util = require('util');\nvar Q = require('q');\nvar mout = require('mout');\nvar path = require('path');\nvar GitResolve"
  },
  {
    "path": "lib/core/resolvers/GitHubResolver.js",
    "chars": 5818,
    "preview": "var util = require('util');\nvar path = require('path');\nvar mout = require('mout');\nvar Q = require('q');\nvar GitRemoteR"
  },
  {
    "path": "lib/core/resolvers/GitRemoteResolver.js",
    "chars": 11467,
    "preview": "var util = require('util');\nvar url = require('url');\nvar Q = require('q');\nvar mout = require('mout');\nvar LRU = requir"
  },
  {
    "path": "lib/core/resolvers/GitResolver.js",
    "chars": 13263,
    "preview": "var util = require('util');\nvar path = require('path');\nvar Q = require('q');\nvar rimraf = require('../../util/rimraf');"
  },
  {
    "path": "lib/core/resolvers/Resolver.js",
    "chars": 6452,
    "preview": "var fs = require('../../util/fs');\nvar path = require('path');\nvar Q = require('q');\nvar tmp = require('tmp');\nvar mkdir"
  },
  {
    "path": "lib/core/resolvers/SvnResolver.js",
    "chars": 14446,
    "preview": "var util = require('util');\nvar Q = require('q');\nvar which = require('../../util/which');\nvar LRU = require('lru-cache'"
  },
  {
    "path": "lib/core/resolvers/UrlResolver.js",
    "chars": 9753,
    "preview": "var util = require('util');\nvar path = require('path');\nvar fs = require('../../util/fs');\nvar url = require('url');\nvar"
  },
  {
    "path": "lib/core/resolvers/index.js",
    "chars": 251,
    "preview": "module.exports = {\n    GitFs: require('./GitFsResolver'),\n    GitRemote: require('./GitRemoteResolver'),\n    GitHub: req"
  },
  {
    "path": "lib/core/resolvers/pluginResolverFactory.js",
    "chars": 12369,
    "preview": "var Q = require('q');\nvar path = require('path');\nvar fs = require('../../util/fs');\nvar object = require('mout/object')"
  },
  {
    "path": "lib/core/scripts.js",
    "chars": 3714,
    "preview": "var mout = require('mout');\nvar cmd = require('../util/cmd');\nvar Q = require('q');\nvar shellquote = require('shell-quot"
  },
  {
    "path": "lib/index.js",
    "chars": 634,
    "preview": "var commands = require('./commands');\nvar version = require('./version');\nvar abbreviations = require('./util/abbreviati"
  },
  {
    "path": "lib/renderers/JsonRenderer.js",
    "chars": 3510,
    "preview": "var chalk = require('chalk');\nvar Q = require('q');\nvar promptly = require('promptly');\nvar createError = require('../ut"
  },
  {
    "path": "lib/renderers/StandardRenderer.js",
    "chars": 14179,
    "preview": "var chalk = require('chalk');\nvar path = require('path');\nvar mout = require('mout');\nvar archy = require('archy');\nvar "
  },
  {
    "path": "lib/renderers/index.js",
    "chars": 103,
    "preview": "module.exports = {\n    Json: require('./JsonRenderer'),\n    Standard: require('./StandardRenderer')\n};\n"
  },
  {
    "path": "lib/templates/helpers/colors.js",
    "chars": 344,
    "preview": "var chalk = require('chalk');\n\nvar templateColors = ['yellow', 'green', 'cyan', 'red', 'white', 'magenta'];\n\nfunction co"
  },
  {
    "path": "lib/templates/helpers/condense.js",
    "chars": 597,
    "preview": "var mout = require('mout');\nvar leadLinesRegExp = /^\\r?\\n/;\nvar multipleLinesRegExp = /\\r?\\n(\\r?\\n)+/gm;\n\nfunction conde"
  },
  {
    "path": "lib/templates/helpers/indent.js",
    "chars": 330,
    "preview": "var mout = require('mout');\n\nfunction indent(Handlebars) {\n    Handlebars.registerHelper('indent', function(context) {\n "
  },
  {
    "path": "lib/templates/helpers/index.js",
    "chars": 180,
    "preview": "module.exports = {\n    colors: require('./colors'),\n    condense: require('./condense'),\n    indent: require('./indent')"
  },
  {
    "path": "lib/templates/helpers/rpad.js",
    "chars": 332,
    "preview": "var mout = require('mout');\n\nfunction rpad(Handlebars) {\n    Handlebars.registerHelper('rpad', function(context) {\n     "
  },
  {
    "path": "lib/templates/helpers/sum.js",
    "chars": 148,
    "preview": "function sum(Handlebars) {\n    Handlebars.registerHelper('sum', function(val1, val2) {\n        return val1 + val2;\n    }"
  },
  {
    "path": "lib/templates/json/help-cache/clean.json",
    "chars": 430,
    "preview": "{\n    \"command\": \"cache clean\",\n    \"description\": \"Cleans cached packages.\",\n    \"usage\": [\n        \"cache clean [<opti"
  },
  {
    "path": "lib/templates/json/help-cache/list.json",
    "chars": 352,
    "preview": "{\n    \"command\": \"cache list\",\n    \"description\": \"Lists cached packages.\",\n    \"usage\": [\n        \"cache list [<options"
  },
  {
    "path": "lib/templates/json/help-cache.json",
    "chars": 242,
    "preview": "{\n    \"command\": \"cache\",\n    \"usage\": [\n        \"cache <command> [<args>] [<options>]\"\n    ],\n    \"commands\": {\n       "
  },
  {
    "path": "lib/templates/json/help-home.json",
    "chars": 473,
    "preview": "{\n    \"command\": \"home\",\n    \"description\": \"Opens a package homepage into your favorite browser.\\n\\nIf no <package> is "
  },
  {
    "path": "lib/templates/json/help-info.json",
    "chars": 455,
    "preview": "{\n    \"command\": \"info\",\n    \"description\": \"Displays overall information of a package or of a particular version.\",\n   "
  },
  {
    "path": "lib/templates/json/help-init.json",
    "chars": 320,
    "preview": "{\n    \"command\": \"init\",\n    \"description\": \"Creates a bower.json file based on answers to questions.\",\n    \"usage\": [\n "
  },
  {
    "path": "lib/templates/json/help-install.json",
    "chars": 1935,
    "preview": "{\n    \"command\": \"install\",\n    \"description\": \"Installs the project dependencies or a specific set of endpoints.\\nEndpo"
  },
  {
    "path": "lib/templates/json/help-link.json",
    "chars": 795,
    "preview": "{\n    \"command\": \"link\",\n    \"description\": \"The link functionality allows developers to easily test their packages.\\nLi"
  },
  {
    "path": "lib/templates/json/help-list.json",
    "chars": 680,
    "preview": "{\n    \"command\": \"list\",\n    \"description\": \"List local packages - and possible updates.\",\n    \"usage\": [\n        \"list "
  },
  {
    "path": "lib/templates/json/help-login.json",
    "chars": 535,
    "preview": "{\n    \"command\": \"login\",\n    \"description\": \"Authenticate with GitHub and store credentials to be used later.\",\n    \"us"
  },
  {
    "path": "lib/templates/json/help-lookup.json",
    "chars": 312,
    "preview": "{\n    \"command\": \"lookup\",\n    \"description\": \"Look up a single package URL by name.\",\n    \"usage\": [\n        \"lookup <n"
  },
  {
    "path": "lib/templates/json/help-prune.json",
    "chars": 303,
    "preview": "{\n    \"command\": \"prune\",\n    \"description\": \"Uninstalls local extraneous packages.\",\n    \"usage\": [\n        \"prune [<op"
  },
  {
    "path": "lib/templates/json/help-register.json",
    "chars": 478,
    "preview": "{\n    \"command\": \"register\",\n    \"description\": \"Registers a package.\",\n    \"usage\": [\n        \"register <name> <url> [<"
  },
  {
    "path": "lib/templates/json/help-search.json",
    "chars": 303,
    "preview": "{\n    \"command\": \"search\",\n    \"description\": \"Search for packages by name.\",\n    \"usage\": [\n        \"search <name> [<op"
  },
  {
    "path": "lib/templates/json/help-uninstall.json",
    "chars": 926,
    "preview": "{\n    \"command\": \"uninstall\",\n    \"description\": \"Uninstalls a package locally from your bower_components directory\",\n  "
  },
  {
    "path": "lib/templates/json/help-unregister.json",
    "chars": 478,
    "preview": "{\n    \"command\": \"unregister\",\n    \"description\": \"Unregisters a package.\",\n    \"usage\": [\n        \"unregister <name> [<"
  },
  {
    "path": "lib/templates/json/help-update.json",
    "chars": 1003,
    "preview": "{\n    \"command\": \"update\",\n    \"description\": \"Updates installed packages to their newest version according to bower.jso"
  },
  {
    "path": "lib/templates/json/help-version.json",
    "chars": 797,
    "preview": "{\n    \"command\": \"version\",\n    \"description\": \"Creates an empty version commit and tag, and fail if the repo is not cle"
  },
  {
    "path": "lib/templates/json/help.json",
    "chars": 2725,
    "preview": "{\n    \"usage\": [\n        \"<command> [<args>] [<options>]\"\n    ],\n    \"commands\": {\n        \"cache\":           \"Manage bo"
  },
  {
    "path": "lib/templates/std/conflict-resolved.std",
    "chars": 551,
    "preview": "{{#yellow}}Please note that,{{/yellow}}\n{{#condense}}\n{{#each picks}}\n    {{#if dependants}}{{#green}}{{dependants}}{{/g"
  },
  {
    "path": "lib/templates/std/conflict.std",
    "chars": 544,
    "preview": "{{#yellow}}Unable to find a suitable version for {{name}}, please choose one by typing one of the numbers below:{{/yello"
  },
  {
    "path": "lib/templates/std/help-cache.std",
    "chars": 252,
    "preview": "\nUsage:\n\n{{#condense}}\n{{#each usage}}\n    {{#cyan}}bower{{/cyan}} {{.}}\n{{/each}}\n{{/condense}}\n\nCommands:\n\n{{#condense"
  },
  {
    "path": "lib/templates/std/help-generic.std",
    "chars": 429,
    "preview": "\nUsage:\n\n{{#condense}}\n{{#each usage}}\n    {{#cyan}}bower{{/cyan}} {{.}}\n{{/each}}\n{{/condense}}\n\n\nOptions:\n\n{{#condense"
  },
  {
    "path": "lib/templates/std/help.std",
    "chars": 480,
    "preview": "\nUsage:\n\n{{#condense}}\n{{#each usage}}\n    {{#cyan}}bower{{/cyan}} {{.}}\n{{/each}}\n{{/condense}}\n\nCommands:\n\n{{#condense"
  },
  {
    "path": "lib/templates/std/info.std",
    "chars": 357,
    "preview": "{{#if versions}}{{#cyan}}Available versions:{{/cyan}}\n{{#condense}}\n{{#versions}}\n  - {{.}}\n{{/versions}}\n{{/condense}}\n"
  },
  {
    "path": "lib/templates/std/lookup.std",
    "chars": 112,
    "preview": "{{#condense}}\n{{#if url}}\n{{#cyan}}{{name}}{{/cyan}} {{url}}\n{{else}}\nPackage not found.\n{{/if}}\n{{/condense}}\n\n"
  },
  {
    "path": "lib/templates/std/register.std",
    "chars": 276,
    "preview": "Package {{#cyan}}{{name}}{{/cyan}} registered successfully!\nAll valid semver tags on {{#cyan}}{{url}}{{/cyan}} will be a"
  },
  {
    "path": "lib/templates/std/search-results.std",
    "chars": 140,
    "preview": "{{#if .}}Search results:\n\n{{#condense}}\n{{#.}}\n    {{#cyan}}{{{name}}}{{/cyan}} {{{url}}}\n{{/.}}\n{{/condense}}\n\n{{else}}"
  },
  {
    "path": "lib/util/abbreviations.js",
    "chars": 678,
    "preview": "var abbrev = require('abbrev');\nvar mout = require('mout');\n\nfunction expandNames(obj, prefix, stack) {\n    prefix = pre"
  },
  {
    "path": "lib/util/childProcess.js",
    "chars": 449,
    "preview": "var childProcess = require('child_process');\r\nvar which = require('./which');\r\n\r\nfunction execFile(cmd, args, opt, cb) {"
  },
  {
    "path": "lib/util/cli.js",
    "chars": 1239,
    "preview": "var mout = require('mout');\nvar nopt = require('nopt');\nvar renderers = require('../renderers');\n\nfunction readOptions(o"
  },
  {
    "path": "lib/util/cmd.js",
    "chars": 3862,
    "preview": "var cp = require('./childProcess');\nvar path = require('path');\nvar Q = require('q');\nvar mout = require('mout');\nvar wh"
  },
  {
    "path": "lib/util/copy.js",
    "chars": 2796,
    "preview": "var fstream = require('fstream');\nvar fstreamIgnore = require('fstream-ignore');\nvar fs = require('./fs');\nvar Q = requi"
  },
  {
    "path": "lib/util/createError.js",
    "chars": 234,
    "preview": "var mout = require('mout');\n\nfunction createError(msg, code, props) {\n    var err = new Error(msg);\n    err.code = code;"
  },
  {
    "path": "lib/util/createLink.js",
    "chars": 2357,
    "preview": "var fs = require('./fs');\nvar path = require('path');\nvar Q = require('q');\nvar mkdirp = require('mkdirp');\nvar createEr"
  },
  {
    "path": "lib/util/download.js",
    "chars": 4523,
    "preview": "var progress = require('request-progress');\nvar request = require('request');\nvar Q = require('q');\nvar mout = require('"
  },
  {
    "path": "lib/util/extract.js",
    "chars": 7653,
    "preview": "var path = require('path');\nvar fs = require('./fs');\nvar zlib = require('zlib');\nvar DecompressZip = require('decompres"
  },
  {
    "path": "lib/util/fs.js",
    "chars": 846,
    "preview": "var fs = require('graceful-fs');\n\nvar readdir = fs.readdir.bind(fs);\nvar readdirSync = fs.readdirSync.bind(fs);\n\nmodule."
  },
  {
    "path": "lib/util/isPathAbsolute.js",
    "chars": 111,
    "preview": "function isPathAbsolute(filePath) {\n    return filePath.charAt(0) === '/';\n}\n\nmodule.exports = isPathAbsolute;\n"
  },
  {
    "path": "lib/util/readJson.js",
    "chars": 1831,
    "preview": "var path = require('path');\nvar bowerJson = require('bower-json');\nvar Q = require('q');\n\n// The valid options are the s"
  },
  {
    "path": "lib/util/relativeToBaseDir.js",
    "chars": 357,
    "preview": "var path = require('path');\nvar isPathAbsolute = require('./isPathAbsolute');\n\nfunction relativeToBaseDir(baseDir) {\n   "
  },
  {
    "path": "lib/util/removeIgnores.js",
    "chars": 1734,
    "preview": "var path = require('path');\nvar rimraf = require('../util/rimraf');\nvar fstreamIgnore = require('fstream-ignore');\nvar m"
  },
  {
    "path": "lib/util/resolve.js",
    "chars": 554,
    "preview": "var requireg = require('requireg');\nvar resolve = require('resolve');\n\nfunction startsWith(string, searchString, positio"
  },
  {
    "path": "lib/util/rimraf.js",
    "chars": 1092,
    "preview": "var rimraf = require('rimraf');\nvar chmodr = require('chmodr');\nvar fs = require('./fs');\n\nmodule.exports = function(dir"
  },
  {
    "path": "lib/util/rootCheck.js",
    "chars": 1029,
    "preview": "var isRoot = require('is-root');\nvar createError = require('./createError');\n\nvar renderer;\n\nfunction rootCheck(options,"
  },
  {
    "path": "lib/util/semver.js",
    "chars": 1991,
    "preview": "var semver = require('semver');\nvar mout = require('mout');\n\nfunction maxSatisfying(versions, range, strictMatch) {\n    "
  },
  {
    "path": "lib/util/template.js",
    "chars": 979,
    "preview": "var path = require('path');\nvar fs = require('./fs');\nvar Handlebars = require('handlebars');\nvar mout = require('mout')"
  },
  {
    "path": "lib/util/userAgent.js",
    "chars": 192,
    "preview": "var version = require('../version');\n\nmodule.exports =\n    'node/' +\n    process.version +\n    ' ' +\n    process.platfor"
  },
  {
    "path": "lib/util/validLink.js",
    "chars": 538,
    "preview": "var Q = require('q');\nvar fs = require('./fs');\n\nfunction validLink(file) {\n    // Ensures that a file is a symlink that"
  },
  {
    "path": "lib/util/which.js",
    "chars": 1335,
    "preview": "var join = require('path').join;\r\nvar execFileSync = require('child_process').execFileSync;\r\nvar cache = {};\r\nvar origin"
  },
  {
    "path": "lib/version.js",
    "chars": 116,
    "preview": "var findup = require('findup-sync');\n\nmodule.exports = require(findup('package.json', { cwd: __dirname })).version;\n"
  },
  {
    "path": "package.json",
    "chars": 2722,
    "preview": "{\n  \"private\": true,\n  \"name\": \"bower\",\n  \"version\": \"1.8.14\",\n  \"description\": \"The browser package manager\",\n  \"author"
  },
  {
    "path": "packages/bower-config/.editorconfig",
    "chars": 188,
    "preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ni"
  },
  {
    "path": "packages/bower-config/.gitignore",
    "chars": 127,
    "preview": "node_modules\nnpm-debug.log\n\ntest/assets/github-test-package\ntest/assets/github-test-package-copy\ntest/assets/temp\ntest/r"
  },
  {
    "path": "packages/bower-config/CHANGELOG.md",
    "chars": 4011,
    "preview": "# Changelog\n\n## 1.4.2\n\n- Prevent errors when expanded env variable does not exist\n\n## 1.4.2\n\n- Update minimist to 0.2.1 "
  },
  {
    "path": "packages/bower-config/LICENSE",
    "chars": 1074,
    "preview": "Copyright (c) 2012 Twitter and other contributors\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "packages/bower-config/README.md",
    "chars": 1948,
    "preview": "# bower-config\n\n> The Bower config (`.bowerrc`) reader and writer.\n\n[Bower](http://bower.io/) can be configured using JS"
  },
  {
    "path": "packages/bower-config/lib/Config.js",
    "chars": 2831,
    "preview": "var lang = require('mout/lang');\nvar object = require('mout/object');\nvar rc = require('./util/rc');\nvar expand = requir"
  },
  {
    "path": "packages/bower-config/lib/util/defaults.js",
    "chars": 1497,
    "preview": "var path = require('path');\nvar paths = require('./paths');\n\n// Guess proxy defined in the env\nvar proxy = process.env.H"
  },
  {
    "path": "packages/bower-config/lib/util/expand.js",
    "chars": 3733,
    "preview": "var object = require('mout/object');\nvar lang = require('mout/lang');\nvar string = require('mout/string');\n\nfunction cam"
  },
  {
    "path": "packages/bower-config/lib/util/paths.js",
    "chars": 1547,
    "preview": "var os = require('os');\nvar path = require('path');\nvar osenv = require('osenv');\nvar crypto = require('crypto');\n\nfunct"
  },
  {
    "path": "packages/bower-config/lib/util/proxy.js",
    "chars": 2757,
    "preview": "// EnvProxy uses the proxy vaiables passed to it in set and sets the\n// process.env uppercase proxy variables to them wi"
  },
  {
    "path": "packages/bower-config/lib/util/rc.js",
    "chars": 4306,
    "preview": "var path = require('path');\nvar fs = require('graceful-fs');\nvar optimist = require('../vendor/optimist');\nvar osenv = r"
  },
  {
    "path": "packages/bower-config/lib/vendor/optimist.js",
    "chars": 9358,
    "preview": "var path = require('path');\nvar minimist = require('minimist');\nvar wordwrap = require('wordwrap');\n\n/*  Hack an instanc"
  },
  {
    "path": "packages/bower-config/package.json",
    "chars": 776,
    "preview": "{\n  \"name\": \"bower-config\",\n  \"version\": \"1.4.3\",\n  \"description\": \"The Bower config reader and writer.\",\n  \"author\": \"T"
  },
  {
    "path": "packages/bower-config/test/assets/custom-ca/.bowerrc",
    "chars": 52,
    "preview": "{\n    \"ca\": \"test/assets/custom-ca/ca-bundle.crt\"\n}\n"
  },
  {
    "path": "packages/bower-config/test/assets/custom-ca/ca-bundle.crt",
    "chars": 2474,
    "preview": "Equifax Secure CA\n=================\n-----BEGIN CERTIFICATE-----\nMIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYD"
  },
  {
    "path": "packages/bower-config/test/assets/custom-ca-embed/.bowerrc",
    "chars": 2529,
    "preview": "{\n    \"ca\": \"Equifax Secure CA\\n=================\\n-----BEGIN CERTIFICATE-----\\nMIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0B"
  },
  {
    "path": "packages/bower-config/test/assets/env-variables/.bowerrc",
    "chars": 102,
    "preview": "{\n  \"proxy\": \"http://HTTP_PROXY\",\n  \"https-proxy\": \"http://HTTPS_PROXY\",\n  \"no-proxy\": \"google.com\"\n}\n"
  },
  {
    "path": "packages/bower-config/test/assets/env-variables-values/.bowerrc",
    "chars": 324,
    "preview": "{\n   \"scripts\" : {\n      \"postinstall\" : \"${_myshellvar}\"\n   },\n   \"storage\" : {\n      \"packages\" : \"${_BOWERRC_MY_PACKA"
  },
  {
    "path": "packages/bower-config/test/cli.js",
    "chars": 204,
    "preview": "#!/usr/bin/env node\n\nvar path = require('path');\nvar bowerConfig = require('..');\n\nvar config = bowerConfig.read(path.jo"
  },
  {
    "path": "packages/bower-config/test/helpers.js",
    "chars": 3447,
    "preview": "var Q = require('q');\nvar mkdirp = require('mkdirp');\nvar rimraf = require('rimraf');\nvar uuid = require('node-uuid');\nv"
  },
  {
    "path": "packages/bower-config/test/test.js",
    "chars": 10058,
    "preview": "var assert = require('assert');\nvar path = require('path');\n\ndescribe('NPM Config on package.json', function() {\n    bef"
  },
  {
    "path": "packages/bower-config/test/util/index.js",
    "chars": 55,
    "preview": "describe('util', function() {\n    require('./rc');\n});\n"
  },
  {
    "path": "packages/bower-config/test/util/rc.js",
    "chars": 2250,
    "preview": "var expect = require('expect.js');\nvar helpers = require('../helpers');\n\ndescribe('rc', function() {\n    var tempDir = n"
  },
  {
    "path": "packages/bower-endpoint-parser/.editorconfig",
    "chars": 188,
    "preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ni"
  },
  {
    "path": "packages/bower-endpoint-parser/.gitignore",
    "chars": 26,
    "preview": "/node_modules\n/npm-debug.*"
  },
  {
    "path": "packages/bower-endpoint-parser/LICENSE",
    "chars": 1074,
    "preview": "Copyright (c) 2012 Twitter and other contributors\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "packages/bower-endpoint-parser/README.md",
    "chars": 3357,
    "preview": "# bower-endpoint-parser\n\nLittle module that helps with endpoints parsing.\n\n\n## API\n\n### .decompose(endpoint)\n\nDecomposes"
  },
  {
    "path": "packages/bower-endpoint-parser/index.js",
    "chars": 3061,
    "preview": "function decompose(endpoint) {\n    // Note that we allow spaces in targets and sources but they are trimmed\n    var regE"
  },
  {
    "path": "packages/bower-endpoint-parser/package.json",
    "chars": 586,
    "preview": "{\n  \"name\": \"bower-endpoint-parser\",\n  \"version\": \"0.2.2\",\n  \"description\": \"Little module that helps with endpoints par"
  },
  {
    "path": "packages/bower-endpoint-parser/test/test.js",
    "chars": 15789,
    "preview": "var expect = require('expect.js');\nvar lang = require('mout/lang');\nvar object = require('mout/object');\nvar endpointPar"
  },
  {
    "path": "packages/bower-json/.editorconfig",
    "chars": 188,
    "preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ni"
  },
  {
    "path": "packages/bower-json/.gitignore",
    "chars": 42,
    "preview": "/node_modules\n/npm-debug.*\n\n/test/reports\n"
  },
  {
    "path": "packages/bower-json/CHANGELOG.md",
    "chars": 456,
    "preview": "# 0.8.4\n\n- Update deep-extend (security fix)\n\n# 0.8.3\n\n- Fix requires\n\n# 0.8.2\n\n- Drop dependency on meow (vendor ext-na"
  },
  {
    "path": "packages/bower-json/LICENSE",
    "chars": 1082,
    "preview": "Copyright (c) 2012-present Twitter and other contributors\n\nPermission is hereby granted, free of charge, to any person o"
  },
  {
    "path": "packages/bower-json/README.md",
    "chars": 4042,
    "preview": "# bower-json\n\nRead `bower.json` files with semantics, normalisation, defaults and validation.\n\nInstall via [npm](https:/"
  },
  {
    "path": "packages/bower-json/lib/json.js",
    "chars": 8306,
    "preview": "var fs = require('graceful-fs');\nvar path = require('path');\nvar deepExtend = require('deep-extend');\nvar isAsset = requ"
  },
  {
    "path": "packages/bower-json/lib/util/createError.js",
    "chars": 135,
    "preview": "function createError(msg, code) {\n    var err = new Error(msg);\n    err.code = code;\n\n    return err;\n}\n\nmodule.exports "
  },
  {
    "path": "packages/bower-json/lib/util/isAsset.js",
    "chars": 395,
    "preview": "var extName = require('../vendor/ext-name');\n\nfunction isAsset(filename) {\n    var info = extName(filename);\n\n    return"
  },
  {
    "path": "packages/bower-json/lib/util/isComponent.js",
    "chars": 1192,
    "preview": "var fs = require('graceful-fs');\nvar intersect = require('intersect');\n\n// Function to check if a file is a component(1)"
  },
  {
    "path": "packages/bower-json/lib/vendor/ext-name.js",
    "chars": 399,
    "preview": "'use strict';\n\nvar endsWith = require('ends-with');\nvar extList = require('ext-list');\nvar sortKeysLength = require('sor"
  },
  {
    "path": "packages/bower-json/package.json",
    "chars": 738,
    "preview": "{\n  \"name\": \"bower-json\",\n  \"version\": \"0.8.4\",\n  \"description\": \"Read bower.json files with semantics, normalisation, d"
  },
  {
    "path": "packages/bower-json/test/pkg-bower-json/bower.json",
    "chars": 73,
    "preview": "{\n    \"name\": \"some-pkg\",\n    \"version\": \"0.0.0\",\n    \"main\": \"foo.js\"\n}\n"
  },
  {
    "path": "packages/bower-json/test/pkg-bower-json-invalid/bower.json",
    "chars": 3,
    "preview": "{}\n"
  },
  {
    "path": "packages/bower-json/test/pkg-bower-json-malformed/bower.json",
    "chars": 2,
    "preview": "{\n"
  },
  {
    "path": "packages/bower-json/test/pkg-component(1)-json/component.json",
    "chars": 291,
    "preview": "{\n  \"name\": \"route\",\n  \"repo\": \"apily/route\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Route component\",\n  \"keywords\": [\""
  },
  {
    "path": "packages/bower-json/test/pkg-component-json/component.json",
    "chars": 51,
    "preview": "{\n    \"name\": \"some-pkg\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "packages/bower-json/test/pkg-dot-bower-json/.bower.json",
    "chars": 83,
    "preview": "{\n    \"name\": \"some-installed-pkg\",\n    \"version\": \"0.0.1\",\n    \"main\": \"bar.js\"\n}\n"
  },
  {
    "path": "packages/bower-json/test/test.js",
    "chars": 17402,
    "preview": "var path = require('path');\nvar expect = require('expect.js');\nvar _s = require('underscore.string');\nvar bowerJson = re"
  },
  {
    "path": "packages/bower-logger/.editorconfig",
    "chars": 188,
    "preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ni"
  },
  {
    "path": "packages/bower-logger/.gitignore",
    "chars": 26,
    "preview": "/node_modules\n/npm-debug.*"
  },
  {
    "path": "packages/bower-logger/LICENSE",
    "chars": 1074,
    "preview": "Copyright (c) 2012 Twitter and other contributors\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "packages/bower-logger/README.md",
    "chars": 2565,
    "preview": "# bower-logger\n\nThe logger used in the various architecture components of Bower.\n\nInstall\n\n```sh\nnpm install --save bowe"
  },
  {
    "path": "packages/bower-logger/lib/Logger.js",
    "chars": 3099,
    "preview": "var EventEmitter = require('events').EventEmitter;\nvar util = require('util');\n\nvar slice = Array.prototype.slice;\n\nfunc"
  },
  {
    "path": "packages/bower-logger/package.json",
    "chars": 582,
    "preview": "{\n  \"name\": \"bower-logger\",\n  \"version\": \"0.2.1\",\n  \"description\": \"The logger used in the various architecture componen"
  },
  {
    "path": "packages/bower-logger/test/test.js",
    "chars": 12849,
    "preview": "var expect = require('expect.js');\nvar EventEmitter = require('events').EventEmitter;\nvar Logger = require('../');\n\ndesc"
  },
  {
    "path": "packages/bower-registry-client/.editorconfig",
    "chars": 188,
    "preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ni"
  },
  {
    "path": "packages/bower-registry-client/.gitignore",
    "chars": 26,
    "preview": "/node_modules\n/npm-debug.*"
  },
  {
    "path": "packages/bower-registry-client/Client.js",
    "chars": 2108,
    "preview": "var async = require('async');\nvar methods = require('./lib');\nvar Cache = require('./lib/util/Cache');\n\nfunction Registr"
  },
  {
    "path": "packages/bower-registry-client/LICENSE",
    "chars": 1074,
    "preview": "Copyright (c) 2012 Twitter and other contributors\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "packages/bower-registry-client/README.md",
    "chars": 4226,
    "preview": "# bower-registry-client\n\n> Provides easy interaction with the Bower registry\n\n\n## Install\n\n```\n$ npm install --save bowe"
  },
  {
    "path": "packages/bower-registry-client/lib/index.js",
    "chars": 194,
    "preview": "module.exports = {\n    lookup: require('./lookup'),\n    list: require('./list'),\n    register: require('./register'),\n  "
  },
  {
    "path": "packages/bower-registry-client/lib/list.js",
    "chars": 6619,
    "preview": "var path = require('path');\nvar url = require('url');\nvar async = require('async');\nvar request = require('request');\nva"
  },
  {
    "path": "packages/bower-registry-client/lib/lookup.js",
    "chars": 7450,
    "preview": "var path = require('path');\nvar url = require('url');\nvar async = require('async');\nvar request = require('request');\nva"
  },
  {
    "path": "packages/bower-registry-client/lib/register.js",
    "chars": 2129,
    "preview": "var parseUrl = require('url').parse;\nvar request = require('request');\nvar createError = require('./util/createError');\n"
  },
  {
    "path": "packages/bower-registry-client/lib/search.js",
    "chars": 7418,
    "preview": "var path = require('path');\nvar url = require('url');\nvar async = require('async');\nvar request = require('request');\nva"
  },
  {
    "path": "packages/bower-registry-client/lib/unregister.js",
    "chars": 1537,
    "preview": "var parseUrl = require('url').parse;\nvar request = require('request');\nvar createError = require('./util/createError');\n"
  },
  {
    "path": "packages/bower-registry-client/lib/util/Cache.js",
    "chars": 4735,
    "preview": "var fs = require('graceful-fs');\nvar path = require('path');\nvar async = require('async');\nvar mkdirp = require('mkdirp'"
  },
  {
    "path": "packages/bower-registry-client/lib/util/createError.js",
    "chars": 135,
    "preview": "function createError(msg, code) {\n    var err = new Error(msg);\n    err.code = code;\n\n    return err;\n}\n\nmodule.exports "
  },
  {
    "path": "packages/bower-registry-client/lib/util/md5.js",
    "chars": 178,
    "preview": "var crypto = require('crypto');\n\nfunction md5(contents) {\n    return crypto\n        .createHash('md5')\n        .update(c"
  },
  {
    "path": "packages/bower-registry-client/package.json",
    "chars": 751,
    "preview": "{\n  \"name\": \"bower-registry-client\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Provides easy interaction with the Bower re"
  },
  {
    "path": "packages/bower-registry-client/test/Client.js",
    "chars": 25449,
    "preview": "var RegistryClient = require('../Client');\nvar fs = require('fs');\nvar expect = require('expect.js');\nvar md5 = require("
  },
  {
    "path": "packages/bower-registry-client/test/core/index.js",
    "chars": 633,
    "preview": "var index = require('../../lib/index');\nvar expect = require('expect.js');\n\ndescribe('index module', function() {\n    de"
  },
  {
    "path": "packages/bower-registry-client/test/core/list.js",
    "chars": 863,
    "preview": "var list = require('../../lib/list');\nvar expect = require('expect.js');\n\ndescribe('list module', function() {\n    descr"
  },
  {
    "path": "packages/bower-registry-client/test/core/lookup.js",
    "chars": 887,
    "preview": "var lookup = require('../../lib/lookup');\nvar expect = require('expect.js');\n\ndescribe('lookup module', function() {\n   "
  },
  {
    "path": "packages/bower-registry-client/test/core/register.js",
    "chars": 326,
    "preview": "var register = require('../../lib/register');\nvar expect = require('expect.js');\n\ndescribe('register module', function()"
  },
  {
    "path": "packages/bower-registry-client/test/core/search.js",
    "chars": 887,
    "preview": "var search = require('../../lib/search');\nvar expect = require('expect.js');\n\ndescribe('search module', function() {\n   "
  },
  {
    "path": "packages/bower-registry-client/test/core/util/Cache.js",
    "chars": 1976,
    "preview": "var Cache = require('../../../lib/util/Cache');\nvar expect = require('expect.js');\n\ndescribe('Cache', function() {\n    b"
  },
  {
    "path": "packages/bower-registry-client/test/core/util/createError.js",
    "chars": 877,
    "preview": "var createError = require('../../../lib/util/createError');\nvar expect = require('expect.js');\n\ndescribe('createError', "
  },
  {
    "path": "packages/bower-registry-client/test/fixtures/search.json",
    "chars": 27794,
    "preview": "[{\"name\":\"jquery\",\"url\":\"git://github.com/components/jquery.git\"},{\"name\":\"jquery-ui\",\"url\":\"git://github.com/components"
  },
  {
    "path": "packages/bower-registry-client/test/runner.js",
    "chars": 216,
    "preview": "require('./Client');\nrequire('./core/search');\nrequire('./core/register');\nrequire('./core/lookup');\nrequire('./core/lis"
  },
  {
    "path": "publish.js",
    "chars": 3823,
    "preview": "var tmp = require('tmp');\nvar fs = require('fs');\nvar path = require('path');\nvar glob = require('glob');\n\nvar childProc"
  },
  {
    "path": "test/assets/resolve-cache/list-json-1.json",
    "chars": 1172,
    "preview": "[\n  {\n    \"canonicalDir\": \"/test/tmp/temp-resolve-cache/3668e6529b32a6d3e8931a68474e909d/0.2.0\",\n    \"pkgMeta\": {\n      "
  },
  {
    "path": "test/assets/test-temp-dir/test-exception.js",
    "chars": 593,
    "preview": "var fs = require('../../../lib/util/fs');\nvar path = require('path');\nvar Logger = require('bower-logger');\nvar Resolver"
  },
  {
    "path": "test/assets/test-temp-dir/test.js",
    "chars": 535,
    "preview": "var fs = require('../../../lib/util/fs');\nvar path = require('path');\nvar Logger = require('bower-logger');\nvar Resolver"
  },
  {
    "path": "test/commands/bower.js",
    "chars": 629,
    "preview": "var expect = require('expect.js');\nvar runBin = require('../helpers').runBin;\n\ndescribe('bower', function() {\n    proces"
  },
  {
    "path": "test/commands/cache/clean.js",
    "chars": 3095,
    "preview": "var expect = require('expect.js');\nvar md5 = require('md5-hex');\nvar helpers = require('../../helpers');\n\nvar cacheClean"
  },
  {
    "path": "test/commands/cache/list.js",
    "chars": 2233,
    "preview": "var expect = require('expect.js');\nvar helpers = require('../../helpers');\n\nvar cacheList = helpers.command('cache/list'"
  }
]

// ... and 48 more files (download for full content)

About this extraction

This page contains the full source code of the bower/bower GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 248 files (1.1 MB), approximately 255.2k tokens, and a symbol index with 218 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!