You're Invited: Meet the Socket team at BSidesSF and RSAC - April 27 - May 1.RSVP

phylo

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

phylo - npm Package Compare versions

Comparing version

to
1.0.0-beta.2

{
"name": "phylo",
"version": "1.0.0-beta.1",
"version": "1.0.0-beta.2",
"description": "File operations class",

@@ -5,0 +5,0 @@ "main": "File.js",

@@ -11,3 +11,3 @@ 'use strict';

var re = gg.compile('**/*.txt');
var re = gg.compile('*.{txt,js}[abc]');
console.log(re);

@@ -14,0 +14,0 @@ console.log('match:', re.exec('C:\\Program Files/foo.txt'));

@@ -11,28 +11,31 @@ # phylo

// Starting in cwd, climb up as needed until a directory
// containing "package.json" is found and then load that
// file to return an object.
var root = File.cwd().up('.git');
var pkg = File.cwd().upToFile('package.json').load();
// Starting in cwd, climb up as needed to find the Git
// VCS root directory (not the ".git" folder itself):
var root = File.cwd().up('.git');
If you like infinite loops, try this on Windows:
The `root` value is by looking for a directory with a `'.git'` file or folder in
it, starting at `cwd` and climbing up as necessary. When that location is found,
it is returned as a `File` object. Note, this is not the `'.git'` folder itself,
but the folder that _contains_ the `'.git'` folder (that is, the VCS root).
The `pkg` value is determined in a similar manner but with two differences. The
first is that the location for which we are searching must contain a _file_ (not
a _folder_) with the name `'package.json'`. Secondly, it is the `'package.json'`
file that is returned as a `File` instance, not the location that contained it.
If you like infinite loops, you can try this on Windows:
var path = require('path');
for (var dir = process.cwd(); dir; dir = path.resolve(dir, '..')) {
for (var d = process.cwd(); d; d = path.resolve(d, '..')) {
// climb up...
}
This innocent loops works on Linux/Mac because `path.resolve('/', '..')` returns
a falsey value. On Windows, however, `path.resolve('C:\\', '..')` returns... well
`"C:\\"`.
This innocent loop works on Linux and Mac OS X because `path.resolve('/', '..')`
returns a falsy value. On Windows, however, `path.resolve('C:\\', '..')` returns...
well `'C:\\'`!
Compare to `File`:
Compare the above to the same idea using `File`:
for (var dir = File.cwd(); dir; dir = dir.parent) {
for (var d = File.cwd(); d; d = d.parent) {
// climb up...

@@ -43,6 +46,2 @@ }

It is intended that a `File` instance immutably describes a single path. What is
(or is not) on disk at that location can change of course, but the description is
constant.
The `File` API strives to be purely consistent on these points:

@@ -63,2 +62,21 @@

The conflict between Node.js `path` and `fs` API's is a major reason for these
naming conventions. Consider:
let s = path.join(process.cwd(), 'foo'); // sync
fs.mkdir(s); // async!
Using `File`:
let f = File.cwd().join('foo'); // sync (of course);
f.mkdir(); // also sync
f.asyncMkdir().then(... // async obviously
It is intended that a `File` instance immutably describes a single path. What is
(or is not) on disk at that location can change of course, but the description is
constant.
## Path Manipulation

@@ -75,6 +93,6 @@

- `path` - The path to the file as a `String` (passed to the `constructor`).
- `extent` - The file's type as a `String` (e.g., "json").
- `name` - The file's name as a `String` (e.g., "package.json").
- `extent` - The file's type as a `String` (e.g., `'json'`).
- `name` - The file's name as a `String` (e.g., `'package.json'`).
- `parent` - The `File` for the parent directory (`null` at root).
- `fspath` - The `path` string resolved for "~" (usable by `fs` or `path` modules)
- `fspath` - The `path` string resolved for `'~'` (usable by `fs` or `path` modules)

@@ -123,5 +141,14 @@ ### Methods

Some useful information about a file path:
- `isAbsolute()` - Returns `true` if the file an absolute path (`path.isAbsolute()`)
- `isRelative()` - Returns `true` if the file a relative path (`path.isRelative()`)
You can compare two paths in a few different ways:
- `compare(o)` - Returns -1, 0 or 1 if `this` is less, equal or greater than `o`
- `compare(o,first)` - Returns -1, 0 or 1 if `this` is less-than, equal or
greater-than `o`. By default, directories sort before files (first = `'d'`). To
instead group files before directories, pass `'f'`. To compare only paths, pass
`false`.
in which case files sort before directories.
- `equals(o)` - Returns `true` if `this` is equal to `o` (`compare(o) === 0`)

@@ -132,2 +159,8 @@ - `prefixes(o)` - Returns `true` if `this` is a path prefix of `o`. It is

There are some static sort methods that can be used by `Array.sort()`:
- `File.sorter` - Calls `f1.compare(f2, 'd')` to group directories before files.
- `File.sorterFilesFirst` - Calls `f1.compare(f2, 'df)` to group files first.
- `File.sorterByPath` - Calls `f1.compare(f2, false)` to sort only by path.
File name comparisons are case-insensitive on Windows and Mac OS X, so we have

@@ -143,15 +176,10 @@

Some useful information about a file path:
- `isAbsolute()` - Returns `true` if the file an absolute path (`path.isAbsolute()`)
- `isRelative()` - Returns `true` if the file a relative path (`path.isRelative()`)
## File-System Information
To get information about the file on disk:
To get information about the file on disk (synchronously):
- `access()` - Returns a `File.Access` object. If the file does not exist (or some
other error is encountered), this object will have an `error` property.
- `can(mode)` - Returns `true` if this exists with the desired access (`mode` is "r",
"rw", "rwx", "w", "wx" or "x").
- `can(mode)` - Returns `true` if this exists with the desired access (`mode` is `'r'`,
`'rw'`, `'rwx'`, `'w'`, `'wx'` or `'x'`).
- `exists()` - Returns `true` if the file exists.

@@ -171,4 +199,4 @@ - `has(rel)` - Returns `true` if a file or folder exists at the `rel` path from this file.

The `error` property will be a value like `"ENOENT"` (for file/folder not found), and
`"EACCES"` or `"EPERM"` for permission denied. These codes come directly from the
The `error` property will be a value like `'ENOENT'` (for file/folder not found), and
`'EACCES'` or `'EPERM'` for permission denied. These codes come directly from the
underlying API.

@@ -202,2 +230,11 @@

For example:
if (File.cwd().join('package.json').stat().attrib.H) {
// If the package.json file is hidden... (wat?)
}
Note, if there is no `'package.json'` file, the `stat()` method will return an object
with an `error` property and an empty `attrib` object (it won't have `H` set).
The [`fswin`](https://www.npmjs.com/package/fswin) module is used to retrieve this

@@ -214,5 +251,5 @@ information on Windows. On other platforms, this object contains `false` values for all

`File.Access` objects are succinct descriptions of read, write and execute permission
masks. These replace the use of `fs.constants.R_OK`, `fs.constants.W_OK` and
`fs.constants.X_OK`. For example:
`File.Access` objects are descriptors of read, write and execute permission masks.
These are much simpler to use than the `fs.constants.R_OK`, `fs.constants.W_OK` and
`fs.constants.X_OK` bit-masks. For example:

@@ -273,3 +310,3 @@ try {

- `mask` - The combination of `fs.constants` flags `R_OK`, `W_OK` and/or `X_OK`
- `name` - The string "r", "rw", "rx", "rwx", "w", "wx" or "x"
- `name` - The string `'r'`, `'rw'`, `'rx'`, `'rwx'`, `'w'`, `'wx'` or `'x'`

@@ -318,4 +355,4 @@ ### Classification

- `list(mode)`
- `asyncList(mode)`
- `list(mode, matcher)`
- `asyncList(mode, matcher)`

@@ -330,2 +367,3 @@ The `mode` parameter is a string that consists of the following single letter codes

- `o` - Order the items by `sorter`. (default is `true`)
- `O` - Order the items by `sorterFilesFirst`. (default is `false`)
- `s` - Cache the result of `stat` for each file. (default is `false`)

@@ -358,2 +396,87 @@ - `w` - Indicates that Windows hidden flag alone determines hidden status

The `matcher` can be a function to call for each candidate. This function receives
the arguments `(name, file)`. For example:
dir.list(name => {
return name.endsWith('.txt');
});
dir.list((name, f) => {
return f.extent === 'txt'; // f is a File instance
});
The `matcher` can also be a `RegExp`:
dir.list(/\.txt$/i);
Lastly, `matcher` can be a "glob" (a shell-like wildcard). In this case, since this
is also a string, the `mode` must be passed first:
dir.list('Af', '*.txt');
### Globs
The basic form of globs is a file name and extension pattern (like `'*.txt'`). The `'*'`
character matches only file name characters and not path separators (`'/'` and `'\'` on
Windows).
Internally globs are converted into `RegExp` objects. The conversion of `'*.txt'` is
platform-specific. For Linux, it is:
/^[^/]*\.txt$/
On Windows, it converts to this:
/^[^\\/]*\.txt$/i
This is because Windows uses either `'/'` and `'\'` as path separators and filenames
are case-insensitive.
To match paths, you can use a "glob star" such as `'**/*.txt'`. This glob converts to
this on Linux:
/^(?:[^/]*(?:[/]|$))*[^/]*\.txt$/
Globs also support groups inside `'{'` and `'}'` such as: `'*.{txt,js}'`:
/^[^/]*\.(txt|js)$/
A character set like `'*.{txt,js}[abc]'` converts to:
/^[^/]*\.(txt|js)[abc]$/
### Explicit Glob Conversion
The glob parser has some advanced options via the `File.glob()` method. The `File.glob()`
method converts a glob string into a `RegExp`. This conversion can be customized using
the second argument as the `options`. This string can contain any of these characters:
- `C` - Case-sensitivity is manual (disables auto-detection by platform)
- `G` - Greedy `'*'` expansion changes `'*'` to match path separators (i.e., `'/'`)
- `S` - Simple pattern mode (disables grouping and character sets)
All other characters are passed as the `RegExp` flags (e.g., `'i'` and `'g'`).
The `'S'` options enables "simple" glob mode which disables groups and character sets.
For example:
dir.list(File.glob('*.{txt,js}', 'S'));
== /^[^/]*\.{txt\,js}$/
This would be useful when dealing with files that have `'{'` in their name.
To force case-sensitive comparison (e.g., on Windows):
let re = File.glob('*.txt', 'C');
/^[^\\/]*\.txt$/
To force case-insensitive comparison (e.g., on Linux), you need to use `'C'` to make
this a manual choice, and `'i'` to make the `RegExp` ignore case:
let re = File.glob('*.txt', 'Ci');
/^[^/]*\.txt$/i
## File-System Traversal

@@ -381,3 +504,3 @@

// file is the parent directory that has ".git", not the ".git"
// file is the parent directory that has '.git', not the '.git'
// folder itself. The file may be File.cwd() or some parent.

@@ -387,3 +510,3 @@

// git is the ".git" folder from perhaps File.cwd() or some other
// git is the '.git' folder from perhaps File.cwd() or some other
// parent folder.

@@ -405,4 +528,4 @@

the sub-tree). Uses `walk(mode)` to descend the file-system.
- `walk(mode, before, after)` - Calls `before` for all items that
`list(mode)` generates recursively, then processes those items and
- `walk(mode, matcher, before, after)` - Calls `before` for all items that
`list(mode, matcher)` generates recursively, then processes those items and
lastly calls `after`. Both `before` and `after` are optional but one

@@ -422,7 +545,11 @@ should be provided.

}
The optional `matcher` can be a `String` or a `RegExp` and have the same meaning
as with `list()`. The `matcher` cannot, however, be a function. This is because it
would be ambiguous with `before` and would really offer no advantage over handling
things in the `before` method anyway.
The `state` object has the following members:
- `at` - The current `File` being processed.
- `previous` - The `File` previously passed to the handler.
- `root` - The `File` used to start the descent.

@@ -447,3 +574,3 @@ - `stack` - A `File[]` of instances starting with the `File` used to start things.

- `asyncTips(mode, test)`
- `asyncWalk(mode, before, after)`
- `asyncWalk(mode, matcher, before, after)`

@@ -630,2 +757,29 @@ The `test`, `before` and `after` handlers of the asynchronous methods

## Removing Files and Folders
To remove a file or empty folder, you can use `remove()`:
file.remove();
Internally, `remove()` calls either `fs.unlinkSync()` or `fs.rmdirSync()`.
A folder tree can be removed by passing the `'r'` option:
dir.remove('r');
This will synchronously remove all children of `dir` and then remove `dir` itself.
Internally, this is handled by [`rimraf`](https://www.npmjs.com/package/rimraf).
The asynchronous form of `remove()` is:
dir.asyncRemove().then(() => {
// dir is gone if it was empty
});
Or:
dir.asyncRemove('r').then(() => {
// dir and its children are gone
});
## Static Methods

@@ -646,6 +800,6 @@

string or the `path` property of the `File`). Similar to `from()`, the `path()` method
returns `''` when passed `null`. That value is still "falsey" but won't throw null
returns `''` when passed `null`. That value is still falsy but won't throw null
reference errors if used.
There is also `fspath()` that resolves `"~"` path elements:
There is also `fspath()` that resolves `'~'` path elements:

@@ -655,3 +809,3 @@ var s = File.fspath(file);

If the argument is already a `String` it is simply returned (just like the `path()`
method). If the string may contain `"~"` elements, the safe conversion would be:
method). If the string may contain `'~'` elements, the safe conversion would be:

@@ -726,3 +880,3 @@ var s = File.from(file).fspath;

A common "pseudo" root folder for the user's home folder is `"~"`. One often sees
A common pseudo-root folder for the user's home folder is `'~'`. One often sees
paths like this:

@@ -732,3 +886,3 @@

The `"~"` pseudo-root is recognized throughout `File` methods. It is resolved to the
The `'~'` pseudo-root is recognized throughout `File` methods. It is resolved to the
actual location using `absolutify()` or `canonicalize()` (or their other flavors). In

@@ -739,3 +893,3 @@ other cases the pseudo-root is preserved. For example:

console.log(dir.parent); // just "~"
console.log(dir.parent); // just '~'
console.log(dir.join('foo')); // ~/acme/foo

@@ -747,3 +901,3 @@

In addition there is also the `"~~/"` pseudo-root that maps the the `profile()` directory
In addition there is also the `'~~/'` pseudo-root that maps the the `profile()` directory
instead of the raw homedir.

@@ -750,0 +904,0 @@

Sorry, the diff of this file is too big to display