Skip to content

Commit

Permalink
Add not(), remove flip|invert|unset()
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed Jan 6, 2019
1 parent 7371dd9 commit d55fc0b
Show file tree
Hide file tree
Showing 22 changed files with 94 additions and 635 deletions.
29 changes: 12 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ It also allows you to perform operations on them including:
- [setting](#setpermission-permissions) and
[unsetting](#unsetpermission-permissions). Using bitwise operations can be
tedious and error-prone.
- [inverting](#flippermission). For example a
- [inverting](#notpermission). For example a
[`umask`](https://linux.die.net/man/2/umask) of `117` means new files will be
created with `661` permissions.
- checking the [minimal](#minpermissions) or
Expand Down Expand Up @@ -351,31 +351,26 @@ unixPermissions.unset('---------', 'a-x') // '--x--x--x'
unixPermissions.unset('a+xr', 'a+r') // 'a+x,a-r'
```

## `invert(permission)`
## `not(permission)`

Inverts `permission` and unsets the special permissions.
Inverts `permission`.

For example a [`umask`](https://linux.die.net/man/2/umask) of `117` means new
files will be created with `661` permissions.

<!-- eslint-disable line-comment-position, no-inline-comments -->

```js
unixPermissions.invert('660') // '=0117'
unixPermissions.invert('7660') // '=0117'
unixPermissions.invert('rws-ws-w-') // '---r--r-x'
```

## `flip(permission)`

Inverts `permission` including the special permissions.
Special permissions are only inverted to a positive value when `permission`
explicitly negates them.

<!-- eslint-disable line-comment-position, no-inline-comments -->

```js
unixPermissions.flip('660') // '=7117'
unixPermissions.flip('7660') // '=0117'
unixPermissions.flip('rws-ws-w-') // '---r--r-t'
unixPermissions.not('u+xs') // 'u-xs'
unixPermissions.not('u-xs') // 'u+xs'
unixPermissions.not('u=x') // 'u=rws'
unixPermissions.not('a=x') // 'a=rw'
unixPermissions.not('rws-ws-w-') // '---r--r-x'
unixPermissions.not('0660') // '0117'
unixPermissions.not('1660') // '0117'
```

## `min(permissions...)`
Expand Down
16 changes: 3 additions & 13 deletions src/cli/commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@
"describe": "Returns the result of setting `permissions` on `permission`.",
"examples": [["set a=w a+r", "Output: a=rw"]]
},
{
"command": "unset <permission> [permissions...]",
"describe": "Returns the result of unsetting `permissions` on `permission`.",
"examples": [["unset a=wr a+r", "Output: a=w"]]
},
{
"command": "contain <permission> <permissions...>",
"describe": "Tests whether `permission` includes `permissions`. Returns `true` or `false` or (on the CLI) use the exit code `0` or `1`.",
Expand Down Expand Up @@ -73,14 +68,9 @@
"examples": [["positive a=rw", "Output: a+rw"]]
},
{
"command": "invert <permission>",
"describe": "Inverts permission and unsets the special permissions",
"examples": [["invert 744", "Output: =0033"]]
},
{
"command": "flip <permission>",
"describe": "Inverts permission including the special permissions",
"examples": [["flip 744", "Output: =7033"]]
"command": "not <permission>",
"describe": "Inverts permission",
"examples": [["not 744", "Output: =0033"]]
},
{
"command": "min <permission> [permissions...]",
Expand Down
26 changes: 0 additions & 26 deletions src/functions/flip.js

This file was deleted.

34 changes: 0 additions & 34 deletions src/functions/invert.js

This file was deleted.

8 changes: 2 additions & 6 deletions src/functions/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ const { positive } = require('./positive')
const { contain } = require('./contain')
const { equal } = require('./equal')
const { set } = require('./set')
const { unset } = require('./unset')
const { flip } = require('./flip')
const { invert } = require('./invert')
const { not } = require('./not')
const { min, max } = require('./min_max')

module.exports = {
Expand All @@ -18,9 +16,7 @@ module.exports = {
contain,
equal,
set,
unset,
flip,
invert,
not,
min,
max,
}
46 changes: 38 additions & 8 deletions src/functions/not.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,50 @@
'use strict'

const { unaryMap } = require('../helpers')
const { SPECIAL_PERMISSIONS } = require('../constants')
const { NODES_MAP } = require('../nodes')
const { mapValues } = require('../utils')

// Similar to invert() except keep omitted permissions as is.
// We do not export not() because:
// - on types that do not support `add:false` like `stat` or `number`, it
// would always result in 0, which is confusing.
// - `unset()`, `invert()` and `flip()` should cover most use cases
// Invert a permission's `+` and `-`.
// Missing permissions are not inverted.
// Special flags are unset unless the permission is partial. This is because:
// - `not()` or `unset()` on `u+s` should be `u-s`, `-1555` should be `+1555`
// - but `not()` or `unset()` on `1555` should be `0222`
// I.e. setting special flags as part of `not()` or `unset()` should only be
// done when explicit.
const notMap = function(nodesMap) {
return mapValues(nodesMap, invertAdd)
const nodesMapA = mapValues(nodesMap, node => notNode({ node }))

if (isPartial({ nodesMap })) {
return nodesMapA
}

const nodesMapB = mapValues(nodesMapA, unsetSpecial)
return nodesMapB
}

const invertAdd = function({ add, ...node }) {
const notNode = function({ node, node: { add } }) {
return { ...node, add: !add }
}

const isPartial = function({ nodesMap }) {
return Object.keys(nodesMap).length !== Object.keys(NODES_MAP).length
}

const unsetSpecial = function(node) {
if (!isSpecial(node)) {
return node
}

return { ...node, add: false }
}

const isSpecial = function({ permission }) {
return SPECIAL_PERMISSIONS.includes(permission)
}

const not = unaryMap.bind(null, notMap)

module.exports = {
notMap,
not,
}
19 changes: 0 additions & 19 deletions src/functions/unset.js

This file was deleted.

13 changes: 9 additions & 4 deletions src/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const { isPlainObject, omitBy } = require('./utils')
// the first one that does not return `undefined`
const parse = function(perm) {
const { type, nodes } = parsePerm({ perm, funcName: 'parse' })
const nodesMap = getNodesMap(nodes)
const nodesMap = normalizeNodes({ nodes })
return { type, nodesMap }
}

Expand All @@ -22,9 +22,8 @@ const parseCategory = function(perm, category) {
category,
})
const nodes = catNodes.map(catNode => addCategory({ catNode, category }))
const nodesMap = getNodesMap(nodes)
const nodesMapA = omitBy(nodesMap, isInvalidNode)
return { type, nodesMap: nodesMapA }
const nodesMap = normalizeNodes({ nodes })
return { type, nodesMap }
}

const parsePerm = function({ perm, funcName, category }) {
Expand Down Expand Up @@ -66,6 +65,12 @@ const addCategory = function({
return { ...catNode, category }
}

const normalizeNodes = function({ nodes }) {
const nodesMap = getNodesMap(nodes)
const nodesMapA = omitBy(nodesMap, isInvalidNode)
return nodesMapA
}

// Exclude special flags not valid for current category
const isInvalidNode = function(node, nodeKey) {
return NODES_MAP[nodeKey] === undefined
Expand Down
9 changes: 0 additions & 9 deletions test/flip.js

This file was deleted.

2 changes: 1 addition & 1 deletion test/helpers/data/contain.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const { BASE_SET_DATA } = require('./set_unset')
const { BASE_SET_DATA } = require('./set')

const CONTAIN_DATA = [
...BASE_SET_DATA,
Expand Down
2 changes: 1 addition & 1 deletion test/helpers/data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ module.exports = {
...require('./min_max'),
...require('./contain'),
...require('./equal'),
...require('./set_unset'),
...require('./set'),
}
4 changes: 2 additions & 2 deletions test/helpers/data/set_unset.js → test/helpers/data/set.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const BASE_SET_DATA = [
['o-x', 'o+'],
]

const SET_UNSET_DATA = [
const SET_DATA = [
...BASE_SET_DATA,

// Equal operator
Expand Down Expand Up @@ -50,5 +50,5 @@ const SET_UNSET_DATA = [

module.exports = {
BASE_SET_DATA,
SET_UNSET_DATA,
SET_DATA,
}
2 changes: 1 addition & 1 deletion test/invert.js → test/not.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ const { SIMPLE_DATA, performTests } = require('./helpers')

performTests({
title: args => `should invert ${args}`,
command: 'invert',
command: 'not',
data: SIMPLE_DATA,
})
4 changes: 2 additions & 2 deletions test/set.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
'use strict'

const { SET_UNSET_DATA, performTests } = require('./helpers')
const { SET_DATA, performTests } = require('./helpers')

performTests({
title: ([arg, ...args]) => `should set ${arg} with ${args.join(' ')}`,
command: 'set',
data: SET_UNSET_DATA,
data: SET_DATA,
})
Loading

0 comments on commit d55fc0b

Please sign in to comment.