├── .gitignore ├── .travis.yml ├── package.json ├── LICENSE.md ├── README.md ├── yarnrc.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: '0.10' 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yarnrc", 3 | "version": "1.1.4", 4 | "description": "Switch between different .yarnrc files with ease and grace", 5 | "preferGlobal": true, 6 | "bin": { 7 | "yarnrc": "./yarnrc.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/vitorcamachoo/yarnrc.git" 12 | }, 13 | "keywords": [ 14 | "yarn", 15 | "yarnrc", 16 | "utility", 17 | "shell", 18 | "npm", 19 | "npmrc" 20 | ], 21 | "author": "Vitor Camacho", 22 | "license": "BSD", 23 | "devDependencies": { 24 | "rimraf": "*", 25 | "mkdirp": "*", 26 | "tape": "*", 27 | "xtend": "*" 28 | }, 29 | "scripts": { 30 | "test": "tape test.js" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, Deoxxa Development 2 | ====================================== 3 | All rights reserved. 4 | -------------------- 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of Deoxxa Development nor the names of its contributors 14 | may be used to endorse or promote products derived from this software 15 | without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY DEOXXA DEVELOPMENT ''AS IS'' AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL DEOXXA DEVELOPMENT BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | yarnrc 2 | ===== 3 | 4 | Switch between different .yarnrc files with ease and grace. 5 | 6 | Overview 7 | -------- 8 | This is an adapted version of npmrc([npmrc](https://github.com/deoxxa/npmrc)) to work 9 | with the new package manager released by Facebook known as Yarn. 10 | If you use a private npm registry, you know the pain of switching between a 11 | bunch of different .yarnrc files and manually managing symlinks. Let that be a 12 | problem no more! `yarnrc` is here to save the day, by making it dead simple to 13 | switch out your .yarnrc with a specific named version. It also tries to protect 14 | you from your own stupid self by making sure you don't accidentally overwrite an 15 | .yarnrc that you actually want to keep. 16 | 17 | 18 | Installation 19 | ------------ 20 | 21 | ``` sh 22 | npm install -g yarnrc 23 | ``` 24 | 25 | Usage 26 | ----- 27 | 28 | ``` 29 | ➜ ~ yarnrc --help 30 | 31 | yarnrc 32 | 33 | Switch between different .yarnrc files with ease and grace. 34 | 35 | Usage: 36 | yarnrc list all profiles 37 | yarnrc [name] change yarnrc profile (uses fuzzy matching) 38 | yarnrc -c [name] create a new yarnrc profile called name 39 | yarnrc -r [registry] use an npm mirror 40 | 41 | Available mirrors for yarnrc -r: 42 | au - Australian registry mirror 43 | eu - European registry mirror 44 | cn - Chinese registry mirror 45 | default - Default registry 46 | ``` 47 | 48 | #### Initialisation 49 | 50 | Calling `yarnrc` without arguments creates an `~/.yarnrcs/` directory if it doesn't exist, 51 | and copies your current `~/.yarnrc` as the 'default' .yarnrc profile. 52 | 53 | ``` 54 | ➜ ~ yarnrc 55 | Creating /Users/conrad/.yarnrcs 56 | Making /Users/conrad/.yarnrc the default yarnrc file 57 | Activating .yarnrc 'default' 58 | ``` 59 | 60 | #### Create a new .yarnrc profile 61 | 62 | ``` 63 | ➜ ~ yarnrc -c newprofile 64 | Removing old .yarnrc (/home/rvagg/.yarnrcs/default) 65 | Activating .yarnrc 'newprofile' 66 | ``` 67 | 68 | A blank profile will be created. To point your profile to a non-default registry: 69 | 70 | ``` 71 | ➜ ~ npm config set registry http://npm.nodejs.org.au:5984/registry/_design/app/_rewrite 72 | ``` 73 | 74 | Then use `npm adduser` or `npm login` to authenticate with the new profile. 75 | 76 | 77 | #### List available .yarnrc profiles 78 | 79 | ``` 80 | ➜ ~ yarnrc 81 | Available yarnrcs: 82 | 83 | * default 84 | work 85 | ``` 86 | 87 | #### Switch to a specific .yarnrc 88 | 89 | ``` 90 | ➜ ~ yarnrc work 91 | Removing old .yarnrc (/Users/conrad/.yarnrcs/default) 92 | Activating .yarnrc 'work' 93 | ``` 94 | 95 | You can also pass only the first few characters of a profile and `yarnrc` will 96 | autocomplete the profile's name. 97 | 98 | ``` 99 | ➜ ~ yarnrc def 100 | Removing old .yarnrc (/Users/conrad/.yarnrcs/work) 101 | Activating .yarnrc 'default' 102 | ``` 103 | 104 | `yarnrc ` will also go to some lengths to make sure you don't overwrite 105 | anything you might care about: 106 | 107 | ``` 108 | ➜ ~ yarnrc default 109 | Removing old .yarnrc (/Users/conrad/.yarnrcs/work) 110 | Activating .yarnrc 'default' 111 | ➜ ~ yarnrc default 112 | Current .yarnrc (/Users/conrad/.yarnrc) is already 'default' (/Users/conrad/.yarnrcs/default) 113 | ➜ ~ rm ~/.yarnrc 114 | ➜ ~ touch ~/.yarnrc 115 | ➜ ~ yarnrc default 116 | Current .yarnrc (/Users/conrad/.yarnrc) is not a regular file, not removing it 117 | ➜ ~ rm ~/.yarnrc 118 | ➜ ~ yarnrc default 119 | Activating .yarnrc 'default' 120 | ``` 121 | 122 | Note For Windows Users 123 | ---------------------- 124 | 125 | You may have to run yarnrc in a shell (cmd, PowerShell, Git Bash, etc) with 126 | elevated (Administrative) privileges to get it to run. 127 | 128 | Environment Variables 129 | --------------------- 130 | 131 | * `YARNRC_STORE` - Path to directory of profiles. Default: `~/.yarnrcs/` 132 | * `YARNRC` - Path to the yarnrc file used by npm. Default: `~/.yarnrc` 133 | 134 | Known npm registry Mirrors 135 | --------------------- 136 | 137 | For your convenience, you can change registries easily using the `-r` 138 | flag. Currently we provide aliases for: 139 | 140 | * [Australia](http://registry.npmjs.org.au/): `yarnrc -r au` 141 | * [Europe](http://registry.npmjs.eu/): `yarnrc -r eu` 142 | * [China](http://r.cnpmjs.org): `yarnrc -r cn` 143 | 144 | #### Switching registry example 145 | 146 | ``` 147 | ➜ ~ npm -r eu 148 | Using eu registry 149 | ➜ ~ npm info yarnrc 150 | npm http GET http://registry.npmjs.eu/yarnrc 151 | ^C 152 | ➜ ~ npm -r default 153 | Using default registry 154 | ➜ ~ npm info yarnrc 155 | npm http GET https://registry.npmjs.org/yarnrc 156 | ^C 157 | ``` 158 | 159 | License 160 | ------- 161 | 162 | 3-clause BSD. A copy is included with the source. 163 | 164 | Contact 165 | ------- 166 | 167 | * GitHub ([Vitorcamacho](https://github.com/Vitorcamacho/yarnrc)) 168 | * Twitter ([@vitorcamachooo](https://twitter.com/vitorcamachooo)) 169 | * Email ([vcamacho.91@gmail.com](vcamacho.91@gmail.com)) 170 | 171 | Awesome People 172 | -------------- 173 | 174 | * deoxxa "the creator" of npmrc([github](https://github.com/deoxxa)) 175 | * Jaime "the binary wizard" Pillora ([github](https://github.com/jpillora)) 176 | * Tim "two hands" Oxley ([github](https://github.com/timoxley)) 177 | * Jakob "fastest blur in the west" Krigovsky ([github](https://github.com/SonicHedgehog)) 178 | * Rod "the destroyer" Vagg ([github](https://github.com/rvagg)) 179 | * Eugene "ludicrous gibs" Asiedu ([github](https://github.com/ngenerio)) 180 | -------------------------------------------------------------------------------- /yarnrc.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const path = require('path') 4 | , fs = require('fs') 5 | , os = require('os'); 6 | 7 | const YARNRC_STORE = process.env.YARNRC_STORE || path.join(process.env.HOME || process.env.USERPROFILE, '.yarnrcs') 8 | , YARNRC = process.env.YARNRC || path.join(process.env.HOME || process.env.USERPROFILE, '.yarnrc') 9 | , registries = { 10 | au: 'http://registry.npmjs.org.au/' 11 | , eu: 'http://registry.npmjs.eu/' 12 | , cn: 'http://r.cnpmjs.org/' 13 | , defaultReg: 'https://registry.npmjs.org/' 14 | } 15 | , USAGE = 'Usage:\n' 16 | + ' yarnrc list all profiles\n' 17 | + ' yarnrc [name] change yarnrc profile (uses fuzzy matching)\n' 18 | + ' yarnrc -c [name] create a new yarnrc profile called name\n' 19 | + ' yarnrc -r [registry] use an npm mirror\n\n' 20 | + 'Available mirrors for yarnrc -r:\n' 21 | + ' au - Australian registry mirror\n' 22 | + ' eu - European registry mirror\n' 23 | + ' cn - Chinese registry mirror\n' 24 | + ' default - Default registry\n' 25 | 26 | var opts 27 | , name 28 | 29 | function printUsage () { 30 | console.error(USAGE) 31 | process.exit(1) 32 | } 33 | 34 | 35 | function printHelp () { 36 | process.stdout.write( 37 | 'yarnrc\n' 38 | + '\n' 39 | + ' Switch between different .yarnrc files with ease and grace.\n\n' 40 | + USAGE 41 | + '\n' 42 | + 'Example:\n\n' 43 | + ' # Creating and activating a new .yarnrc called "work":\n' 44 | + ' $ yarnrc -c work\n\n' 45 | + ' # Switch betwen "work" and "default"\n' 46 | + ' $ yarnrc work\n' 47 | + ' $ yarnrc default\n' 48 | + ' # Use the European npm mirror' 49 | + ' $ yarnrc -r eu\n' 50 | ) 51 | process.exit(1) 52 | } 53 | 54 | 55 | function printYarnrcs () { 56 | console.log('Available yarnrcs:\n') 57 | fs.readlink(YARNRC, function (err, link) { 58 | link = link && path.basename(link) 59 | fs.readdirSync(YARNRC_STORE).forEach(function (yarnrc) { 60 | if (yarnrc[0] !== '.') { 61 | console.log(' %s %s', link == yarnrc ? '*' : ' ', yarnrc) 62 | } 63 | }) 64 | }) 65 | } 66 | 67 | 68 | // safety check so we don't go overwriting accidentally 69 | function checkSymlink (stat) { 70 | if (!stat.isSymbolicLink()) { 71 | console.log('Current .yarnrc (%s) is not a symlink. You may want to copy it into %s.', YARNRC, YARNRC_STORE) 72 | process.exit(1) 73 | } 74 | } 75 | 76 | // make the symlink 77 | function link (name) { 78 | var ln = path.join(YARNRC_STORE, name || '') 79 | , stat 80 | 81 | if (ln == YARNRC_STORE || !fs.existsSync(ln)) { 82 | console.error('Couldn\'t find yarnrc file "%s".', name) 83 | return process.exit(1) 84 | } 85 | 86 | try { 87 | stat = fs.lstatSync(YARNRC) 88 | checkSymlink(stat) 89 | } catch (e) {} 90 | 91 | if (stat) { 92 | console.log('Removing old .yarnrc (%s)', path.basename(fs.readlinkSync(YARNRC))) 93 | fs.unlinkSync(YARNRC) 94 | } 95 | 96 | console.log('Activating .yarnrc "%s"', path.basename(ln)) 97 | fs.symlinkSync(ln, YARNRC, 'file') 98 | } 99 | 100 | // partial match yarnrc names 101 | function partialMatch(match, files) { 102 | files.sort() // own the sort order 103 | 104 | // try exact match 105 | var exactMatch = files.filter(function(file) { 106 | return file === match 107 | }).shift() 108 | if (exactMatch) return exactMatch 109 | 110 | // try starts with match 111 | var matchesStart = files.filter(function(file) { 112 | return file.indexOf(match) === 0 113 | }).shift() 114 | if (matchesStart) return matchesStart 115 | 116 | // try whatever match 117 | var matchesAnything = files.filter(function(file) { 118 | return file.match(new RegExp(match)) 119 | }).shift() 120 | if (matchesAnything) return matchesAnything 121 | } 122 | 123 | // simplistic cmdline parser, sets "name" as the first non-'-' arg 124 | // and sets "opts" as '-'-stripped characters (first char only) 125 | ;(function processCmdline () { 126 | opts = process.argv.slice(2).map(function (a) { 127 | return a[0] == '-' && a.replace(/^-+/, '')[0] 128 | }).filter(Boolean) 129 | 130 | name = process.argv.slice(2).filter(function (a) { 131 | return a[0] != '-' 132 | })[0] // first non '-' arg 133 | 134 | opts.filter(function (o) { 135 | if (o == 'c' || o == 'h' || o == 'r' || o === 'registry') // other known opts go here 136 | return false 137 | 138 | console.error('Unknown option: -' + o) 139 | return true 140 | }).length && printUsage() 141 | 142 | if (opts.indexOf('h') > -1) 143 | printHelp() 144 | }()) 145 | 146 | 147 | // set up .yarnrc if it doesn't exist 148 | ;(function makeStore () { 149 | function make () { 150 | var def = path.join(YARNRC_STORE, 'default') 151 | 152 | console.log('Initialising yarnrc...') 153 | console.log('Creating %s', YARNRC_STORE) 154 | 155 | fs.mkdirSync(YARNRC_STORE) 156 | 157 | if (fs.existsSync(YARNRC)) { 158 | console.log('Making %s the default yarnrc file', YARNRC) 159 | fs.renameSync(YARNRC, def) 160 | } else { 161 | fs.writeFileSync(def, '') 162 | } 163 | 164 | link('default') 165 | process.exit(0) 166 | } 167 | 168 | try { 169 | var stat = fs.statSync(YARNRC_STORE) 170 | if (!stat.isDirectory()) { 171 | console.error('Error: %s is not a directory', YARNRC_STORE) 172 | process.exit(1) 173 | } 174 | } catch (e) { 175 | make() 176 | } 177 | }()) 178 | 179 | 180 | // no name and no args 181 | if (!name && !opts.length) 182 | return printYarnrcs() 183 | 184 | 185 | ;(function handleOPtions() { 186 | if (~opts.indexOf('c')) 187 | createNew() 188 | else if (~opts.indexOf('r') || ~opts.indexOf('registry')) 189 | replaceRegistry() 190 | }()) 191 | 192 | // handle -r 193 | function replaceRegistry() { 194 | if (!name) { 195 | console.error('Specify the registry you want to use') 196 | return printUsage() 197 | } 198 | 199 | var registry = registries[(name === 'slow' || name === 'default') ? 'defaultReg' : name] 200 | , fileContents 201 | 202 | try { 203 | fs.existsSync(YARNRC) 204 | } catch (e) { 205 | console.warn('Make sure a .yarnrc file exits at %s.', YARNRC) 206 | process.exit(1) 207 | } 208 | 209 | if (!registry) { 210 | console.error('%s value is not a valid registry name', name) 211 | printUsage() 212 | } 213 | 214 | fileContents = fs.readFileSync(YARNRC, 'utf8').split(os.EOL) 215 | 216 | for (var i = 0, l = fileContents.length; i < l; i++) { 217 | if (~fileContents[i].indexOf('registry')) { 218 | fileContents[i] = 'registry = ' + registry 219 | break; 220 | } 221 | } 222 | 223 | if (i === l) 224 | fileContents.unshift('registry = ' + registry) 225 | fs.writeFileSync(YARNRC, fileContents.join(os.EOL)) 226 | 227 | console.log('Using %s registry.', registry) 228 | process.exit(0) 229 | } 230 | 231 | // handle -c 232 | function createNew () { 233 | if (!name) { 234 | console.error('What do you want to call your new npm configuration?') 235 | return printUsage() 236 | } 237 | 238 | var c = path.join(YARNRC_STORE, name) 239 | if (fs.existsSync(c)) { 240 | console.log('yarnrc file "%s", already exists (%s/%s)', name, YARNRC_STORE, name) 241 | return process.exit(1) 242 | } 243 | 244 | fs.writeFileSync(c, '') 245 | } 246 | 247 | 248 | if (name) name = partialMatch(name, fs.readdirSync(YARNRC_STORE)) || name 249 | 250 | // sanity/safety check, also check if they want to switch 251 | // to the already active one 252 | ;(function checkExisting () { 253 | var stat 254 | try { 255 | stat = fs.lstatSync(YARNRC) 256 | checkSymlink(stat) 257 | } catch (e) { 258 | // ignore 259 | } 260 | 261 | if (name && stat && fs.readlinkSync(YARNRC) == path.join(YARNRC_STORE, name)) { 262 | console.log('Current .yarnrc (%s) is already "%s" (%s/%s)', YARNRC, name, YARNRC_STORE, name) 263 | return process.exit(0) 264 | } 265 | }()) 266 | 267 | // if we got here, then we're ready to switch 268 | link(name) 269 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | , path = require('path') 3 | , os = require('os') 4 | , fs = require('fs') 5 | , rimraf = require('rimraf') 6 | , mkdirp = require('mkdirp') 7 | , tmpdir = require('os').tmpDir() 8 | , exec = require('child_process').exec 9 | , xtend = require('xtend') 10 | 11 | , cmd = '"' + process.execPath + '" ' 12 | + path.join(__dirname, 'yarnrc.js') 13 | , homedir = path.join(tmpdir, '.yarnrcs_test.' + process.pid) 14 | , options = { env: xtend(process.env, { HOME: homedir }) } 15 | , yarnrc = path.join(homedir, '.yarnrc') 16 | , yarnrcs = path.join(homedir, '.yarnrcs') 17 | , def = path.join(homedir, '.yarnrcs/default') 18 | , dotfile = path.join(homedir, '.yarnrcs/.dotfile') 19 | 20 | 21 | function cleanup (t) { 22 | rimraf(homedir, t.end.bind(t)) 23 | } 24 | 25 | 26 | test('blank slate', function (t) { 27 | mkdirp.sync(homedir) 28 | 29 | exec(cmd, options, function (err, stdout, stderr) { 30 | t.notOk(err, 'no error') 31 | t.equal(stderr, '', 'no stderr') 32 | t.ok(/Initialising/.test(stdout), 'got "initialising" msg') 33 | t.ok(/Creating .*\.yarnrcs/.test(stdout), 'got "creating" msg') 34 | t.ok(/Activating .yarnrc "default"/, 'got "activating" msg') 35 | t.end() 36 | }) 37 | }) 38 | 39 | test('change the registry url', function (t) { 40 | exec(cmd + ' -r au', options, function (err, stdout, stderr) { 41 | t.notOk(err, 'no error') 42 | t.ok(fs.existsSync(yarnrc), '.yarnrc file exists') 43 | t.ok(fs.existsSync(def), '.yarnrc default file exists') 44 | t.equal(fs.readFileSync(def, 'utf-8').split(os.EOL)[0], 'registry = http://registry.npmjs.org.au/', 'got the right registry url') 45 | t.end() 46 | }) 47 | }) 48 | 49 | test('error occurs when the wrong argument is supplied to -r', function (t) { 50 | exec(cmd + ' -r foo', options, function (err, stdout, stderr) { 51 | t.ok(err, 'error occured') 52 | t.equal(err.code, 1, 'process exited with the right code') 53 | t.end() 54 | }) 55 | }) 56 | 57 | test('cleanup', cleanup) 58 | 59 | 60 | test('standard .yarnrcs', function (t) { 61 | mkdirp.sync(homedir) 62 | fs.writeFileSync(yarnrc, 'foobar', 'utf8') 63 | 64 | exec(cmd, options, function (err, stdout, stderr) { 65 | t.notOk(err, 'no error') 66 | t.equal(stderr, '', 'no stderr') 67 | t.ok(/Initialising/.test(stdout), 'got "initialising" msg') 68 | t.ok(/Creating .*\.yarnrcs/.test(stdout), 'got "creating" msg') 69 | t.ok(/Activating .yarnrc "default"/, 'got "activating" msg') 70 | t.ok(/Making .*\.yarnrc the default/, 'got "making default" msg') 71 | t.equal(fs.readFileSync(yarnrc, 'utf8'), 'foobar', 'got expected contents of .yarnrc') 72 | t.equal(fs.readFileSync(def, 'utf8'), 'foobar', 'got expected contents of .yarnrcs/default') 73 | t.ok(fs.lstatSync(yarnrc).isSymbolicLink(), '.yarnrc is symlink') 74 | t.equal(fs.readlinkSync(yarnrc), def, '.yarnrc points to "default"') 75 | t.deepEqual(fs.readdirSync(yarnrcs), [ 'default' ], 'only "default" in .yarnrcs') 76 | t.end() 77 | }) 78 | }) 79 | 80 | 81 | test('create noarg', function (t) { 82 | exec(cmd + ' -c', options, function (err, stdout, stderr) { 83 | t.ok(err, 'got error') 84 | t.equal(err.code, 1, 'got correct exit code') 85 | t.equal(stdout, '', 'no stdout') 86 | t.ok(/Usage/.test(stderr), 'got Usage') 87 | t.equal(fs.readFileSync(yarnrc, 'utf8'), 'foobar', 'got expected contents of .yarnrc') 88 | t.deepEqual(fs.readdirSync(yarnrcs), [ 'default' ], 'only "default" in .yarnrcs') 89 | t.end() 90 | }) 91 | }) 92 | 93 | 94 | test('create new config', function (t) { 95 | var foobar = path.join(yarnrcs, 'foobar') 96 | exec(cmd + ' -c foobar', options, function (err, stdout, stderr) { 97 | t.notOk(err, 'no error') 98 | t.equal(stderr, '', 'no stderr') 99 | t.ok(/Removing old .+\Wdefault\W/.test(stdout), 'got "removing" msg') 100 | t.ok(/Activating .yarnrc "foobar"/.test(stdout), 'got "activating" msg') 101 | t.equal(fs.readFileSync(yarnrc, 'utf8'), '', 'got expected contents of .yarnrc') 102 | t.equal(fs.readFileSync(def, 'utf8'), 'foobar', 'got expected contents of .yarnrcs/default') 103 | t.equal(fs.readFileSync(foobar, 'utf8'), '', 'got expected contents of .yarnrcs/foobar') 104 | t.ok(fs.lstatSync(yarnrc).isSymbolicLink(), '.yarnrc is symlink') 105 | t.equal(fs.readlinkSync(yarnrc), foobar, '.yarnrc points to "foobar"') 106 | t.deepEqual(fs.readdirSync(yarnrcs), [ 'default', 'foobar' ], '"default" and "foobar" in .yarnrcs') 107 | t.end() 108 | }) 109 | }) 110 | 111 | 112 | test('switch config', function (t) { 113 | var foobar = path.join(yarnrcs, 'foobar') 114 | exec(cmd + ' default', options, function (err, stdout, stderr) { 115 | t.notOk(err, 'no error') 116 | t.equal(stderr, '', 'no stderr') 117 | t.ok(/Removing old .+\Wfoobar\W/.test(stdout), 'got "removing" msg') 118 | t.ok(/Activating .yarnrc "default"/.test(stdout), 'got "activating" msg') 119 | t.equal(fs.readFileSync(yarnrc, 'utf8'), 'foobar', 'got expected contents of .yarnrc') 120 | t.equal(fs.readFileSync(def, 'utf8'), 'foobar', 'got expected contents of .yarnrcs/default') 121 | t.equal(fs.readFileSync(foobar, 'utf8'), '', 'got expected contents of .yarnrcs/foobar') 122 | t.ok(fs.lstatSync(yarnrc).isSymbolicLink(), '.yarnrc is symlink') 123 | t.equal(fs.readlinkSync(yarnrc), def, '.yarnrc points to "foobar"') 124 | t.deepEqual(fs.readdirSync(yarnrcs), [ 'default', 'foobar' ], '"default" and "foobar" in .yarnrcs') 125 | t.end() 126 | }) 127 | }) 128 | 129 | 130 | test('list config', function (t) { 131 | fs.writeFileSync(dotfile, '.dotfile', 'utf8'); 132 | exec(cmd, options, function (err, stdout, stderr) { 133 | t.notOk(err, 'no error') 134 | t.equal(stderr, '', 'no stderr') 135 | t.ok(/Available yarnrcs/.test(stdout), 'got "Available" msg') 136 | t.ok((/\* default$/m).test(stdout), 'listed "default"') 137 | t.ok((/ foobar$/m).test(stdout), 'listed "foobar"') 138 | t.notOk((/\.dotfile$/m).test(stdout), 'listed "dotfile"') 139 | t.end() 140 | }) 141 | }) 142 | 143 | 144 | test('switch to non-existent config', function (t) { 145 | exec(cmd + ' doobar', options, function (err, stdout, stderr) { 146 | t.ok(err, 'got error') 147 | t.equal(err.code, 1, 'got correct exit code') 148 | t.equal(stdout, '', 'no stdout') 149 | t.ok(/Couldn't find yarnrc file "doobar"/.test(stderr), 'got expected error message') 150 | t.end() 151 | }) 152 | }) 153 | 154 | 155 | test('partial matching start of yarnrc', function (t) { 156 | exec(cmd + ' foo', options, function (err, stdout, stderr) { 157 | t.notOk(err, 'no error') 158 | t.equal(stderr, '', 'no stderr') 159 | t.ok(/Activating .yarnrc "foobar"/.test(stdout), 'got "activating" msg') 160 | t.end() 161 | }) 162 | }) 163 | 164 | 165 | test('partial matching prefers full match over partial', function (t) { 166 | exec(cmd + ' -c foo', options, function (err, stdout, stderr) { 167 | // create foo 168 | t.notOk(err, 'no error') 169 | // match against foobar should pick foobar not foo 170 | exec(cmd + ' foobar', options, function (err, stdout, stderr) { 171 | t.notOk(err, 'no error') 172 | t.equal(stderr, '', 'no stderr') 173 | t.ok(/Activating .yarnrc "foobar"/.test(stdout), 'got "activating" msg') 174 | t.end() 175 | }) 176 | }) 177 | }) 178 | 179 | 180 | test('partial matching prefers start of word match over partial match', function (t) { 181 | exec(cmd + ' -c bar', options, function (err, stdout, stderr) { // create bar 182 | t.notOk(err, 'no error') 183 | exec(cmd + ' default', options, function (err, stdout, stderr) { // switch to default 184 | t.notOk(err, 'no error') 185 | exec(cmd + ' ba', options, function (err, stdout, stderr) { 186 | // ensure 'ba' switches to bar not foobar. 187 | t.notOk(err, 'no error') 188 | t.equal(stderr, '', 'no stderr') 189 | t.ok(/Activating .yarnrc "bar"/.test(stdout), 'got "activating" msg') 190 | t.end() 191 | }) 192 | }) 193 | }) 194 | }) 195 | 196 | 197 | test('partial matching can match any part of yarnrc', function (t) { 198 | exec(cmd + ' ooba', options, function (err, stdout, stderr) { 199 | t.notOk(err, 'no error') 200 | t.equal(stderr, '', 'no stderr') 201 | t.ok(/Activating .yarnrc "foobar"/.test(stdout), 'got "activating" msg') 202 | t.end() 203 | }) 204 | }) 205 | 206 | 207 | test('partial matching matches alphabetically', function (t) { 208 | exec(cmd + ' -c car', options, function (err, stdout, stderr) { // create car 209 | t.notOk(err, 'no error') 210 | exec(cmd + ' default', options, function (err, stdout, stderr) { // switch to default 211 | t.notOk(err, 'no error') 212 | var foobar = path.join(yarnrcs, 'foobar') 213 | // try match ar from bar, car, foobar 214 | // should pick bar 215 | exec(cmd + ' ar', options, function (err, stdout, stderr) { 216 | t.notOk(err, 'no error') 217 | t.equal(stderr, '', 'no stderr') 218 | t.ok(/Activating .yarnrc "bar"/.test(stdout), 'got "activating" msg') 219 | t.end() 220 | }) 221 | }) 222 | }) 223 | }) 224 | 225 | test('cleanup', cleanup) 226 | --------------------------------------------------------------------------------