Skip to content
This repository has been archived by the owner on Jan 6, 2021. It is now read-only.

Commit

Permalink
feat: Convert list delimiters for PATH-style env variables (#93)
Browse files Browse the repository at this point in the history
* feat: Convert list delimiters for PATH-style env variables

In Windows, env variables that represent a list (such as PATH or NODE_PATH) separate their elements
using a semicolon(;), but in UNIX they're separated using a colon (:).

This commit adds a conversion layer, so regardless of how the delimiter is written when calling
cross-env, it will be converted to the correct platform delimiter at runtime. To interpret a colon/semicolon
literally instead, preced it with a backslash, like this: "cross-env VAR=semi\\;colon\\:"

BREAKING CHANGE: If an env variable has : or ; in its value, it will be converted to : on UNIX
systems or ; on Windows systems. To keep the old functionality, you will need to escape those
characters with a backslash.

#80

* chore: Add myself (DanReyLop) to the contributors list

* Simplified logic. Now only : (UNIX-style) are converted to ; (Windows-style), not the other way around

BREAKING CHANGE: You now must escape `:` to use it in a value of you don't want it to be swapped with `;` on Windows
  • Loading branch information
DanReyLop authored and Kent C. Dodds committed Mar 31, 2017
1 parent ea80021 commit ea0ac4b
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 3 deletions.
10 changes: 10 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@
"code",
"test"
]
},
{
"login": "DanReyLop",
"name": "Daniel Rey López",
"avatar_url": "https://avatars1.githubusercontent.com/u/1715800?v=3",
"profile": "https://daniel.blog",
"contributions": [
"code",
"test"
]
}
]
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Run scripts that set and use environment variables across platforms
[![downloads][downloads-badge]][npm-stat]

[![MIT License][license-badge]][LICENSE]
[![All Contributors](https://img.shields.io/badge/all_contributors-8-orange.svg?style=flat-square)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square)](#contributors)
[![PRs Welcome][prs-badge]][prs]
[![Donate][donate-badge]][donate]
[![Code of Conduct][coc-badge]][coc]
Expand Down Expand Up @@ -114,7 +114,7 @@ Thanks goes to these people ([emoji key][emojis]):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
| [<img src="https://avatars.githubusercontent.com/u/1500684?v=3" width="100px;"/><br /><sub>Kent C. Dodds</sub>](https://kentcdodds.com)<br />[💻](https://github.com/kentcdodds/cross-env/commits?author=kentcdodds) [📖](https://github.com/kentcdodds/cross-env/commits?author=kentcdodds) 🚇 [⚠️](https://github.com/kentcdodds/cross-env/commits?author=kentcdodds) | [<img src="https://avatars1.githubusercontent.com/u/499038?v=3" width="100px;"/><br /><sub>Ya Zhuang </sub>](https://zhuangya.me)<br />🔌 [📖](https://github.com/kentcdodds/cross-env/commits?author=zhuangya) | [<img src="https://avatars3.githubusercontent.com/u/3440094?v=3" width="100px;"/><br /><sub>James Harris</sub>](https://wopian.me)<br />[📖](https://github.com/kentcdodds/cross-env/commits?author=wopian) | [<img src="https://avatars1.githubusercontent.com/u/8941730?v=3" width="100px;"/><br /><sub>compumike08</sub>](https://github.com/compumike08)<br />[🐛](https://github.com/kentcdodds/cross-env/issues?q=author%3Acompumike08) [📖](https://github.com/kentcdodds/cross-env/commits?author=compumike08) [⚠️](https://github.com/kentcdodds/cross-env/commits?author=compumike08) | [<img src="https://avatars1.githubusercontent.com/u/2270425?v=3" width="100px;"/><br /><sub>Daniel Rodríguez Rivero</sub>](https://github.com/danielo515)<br />[🐛](https://github.com/kentcdodds/cross-env/issues?q=author%3Adanielo515) [💻](https://github.com/kentcdodds/cross-env/commits?author=danielo515) [📖](https://github.com/kentcdodds/cross-env/commits?author=danielo515) | [<img src="https://avatars2.githubusercontent.com/u/1508477?v=3" width="100px;"/><br /><sub>Jonas Keinholz</sub>](https://github.com/inyono)<br />[🐛](https://github.com/kentcdodds/cross-env/issues?q=author%3Ainyono) [💻](https://github.com/kentcdodds/cross-env/commits?author=inyono) [⚠️](https://github.com/kentcdodds/cross-env/commits?author=inyono) | [<img src="https://avatars3.githubusercontent.com/u/1656170?v=3" width="100px;"/><br /><sub>Hugo Wood</sub>](https://github.com/hgwood)<br />[🐛](https://github.com/kentcdodds/cross-env/issues?q=author%3Ahgwood) [💻](https://github.com/kentcdodds/cross-env/commits?author=hgwood) [⚠️](https://github.com/kentcdodds/cross-env/commits?author=hgwood) |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars0.githubusercontent.com/u/3715715?v=3" width="100px;"/><br /><sub>Thiebaud Thomas</sub>](https://github.com/thomasthiebaud)<br /> |
| [<img src="https://avatars0.githubusercontent.com/u/3715715?v=3" width="100px;"/><br /><sub>Thiebaud Thomas</sub>](https://github.com/thomasthiebaud)<br />[🐛](https://github.com/kentcdodds/cross-env/issues?q=author%3Athomasthiebaud) [💻](https://github.com/kentcdodds/cross-env/commits?author=thomasthiebaud) [⚠️](https://github.com/kentcdodds/cross-env/commits?author=thomasthiebaud) | [<img src="https://avatars1.githubusercontent.com/u/1715800?v=3" width="100px;"/><br /><sub>Daniel Rey López</sub>](https://daniel.blog)<br />[💻](https://github.com/kentcdodds/cross-env/commits?author=DanReyLop) [⚠️](https://github.com/kentcdodds/cross-env/commits?author=DanReyLop) |
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors][all-contributors] specification. Contributions of any kind welcome!
Expand Down
3 changes: 2 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {spawn} from 'cross-spawn'
import commandConvert from './command'
import varValueConvert from './variable'

module.exports = crossEnv

Expand Down Expand Up @@ -35,7 +36,7 @@ function getCommand(commandArgs, envVars) {
const shifted = commandArgs.shift()
const match = envSetterRegex.exec(shifted)
if (match) {
envVars[match[1]] = match[3] || match[4] || match[5]
envVars[match[1]] = varValueConvert(match[3] || match[4] || match[5])
} else {
return shifted
}
Expand Down
21 changes: 21 additions & 0 deletions src/variable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import isWindows from 'is-windows'

/**
* Converts an environment variable value to be appropriate for the current OS.
* It will transform UNIX-style list values to Windows-style.
* For example, the value of the $PATH variable "/usr/bin:/usr/local/bin:."
* will become "/usr/bin;/usr/local/bin;." on Windows.
* @param {String} originalValue Original value of the env variable
* @returns {String} Converted value
*/
export default function varValueConvert(originalValue) {
const targetSeparator = isWindows() ? ';' : ':'
return originalValue.replace(/(\\*):/g, (match, backslashes) => {
if (backslashes.length % 2) {
// Odd number of backslashes preceding it means it's escaped,
// remove 1 backslash and return the rest as-is
return match.substr(1)
}
return backslashes + targetSeparator
})
}
46 changes: 46 additions & 0 deletions src/variable.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import isWindowsMock from 'is-windows'
import varValueConvert from './variable'

beforeEach(() => {
isWindowsMock.__mock.reset()
})

test(`doesn't affect simple variable values`, () => {
isWindowsMock.__mock.returnValue = true
expect(varValueConvert('foo')).toBe('foo')
})

test(`doesn't convert a ; into a : on UNIX`, () => {
isWindowsMock.__mock.returnValue = false
expect(varValueConvert('foo;bar')).toBe('foo;bar')
})

test(`converts a : into a ; on Windows`, () => {
isWindowsMock.__mock.returnValue = true
expect(varValueConvert('foo:bar')).toBe('foo;bar')
})

test(`doesn't convert already valid separators`, () => {
isWindowsMock.__mock.returnValue = false
expect(varValueConvert('foo:bar')).toBe('foo:bar')
})

test(`doesn't convert escaped separators on Windows`, () => {
isWindowsMock.__mock.returnValue = true
expect(varValueConvert('foo\\:bar')).toBe('foo:bar')
})

test(`doesn't convert escaped separators on UNIX`, () => {
isWindowsMock.__mock.returnValue = false
expect(varValueConvert('foo\\:bar')).toBe('foo:bar')
})

test(`converts a separator even if preceded by an escaped backslash`, () => {
isWindowsMock.__mock.returnValue = true
expect(varValueConvert('foo\\\\:bar')).toBe('foo\\\\;bar')
})

test(`converts multiple separators`, () => {
isWindowsMock.__mock.returnValue = true
expect(varValueConvert('foo:bar:baz')).toBe('foo;bar;baz')
})

0 comments on commit ea0ac4b

Please sign in to comment.