Update gitignore (sorry)
This commit is contained in:
parent
a8f8c4d7ad
commit
cca8b02fea
6604 changed files with 1219661 additions and 4 deletions
22
electron/node_modules/dir-compare/LICENSE
generated
vendored
Normal file
22
electron/node_modules/dir-compare/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
Copyright 2014 Liviu Grigorescu (grigoresculiviu@gmail.com)
|
||||
|
||||
This project is free software released under the MIT license:
|
||||
http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
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.
|
||||
374
electron/node_modules/dir-compare/README.md
generated
vendored
Normal file
374
electron/node_modules/dir-compare/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
dir-compare
|
||||
==========
|
||||
Node JS directory compare
|
||||
|
||||
[](https://travis-ci.org/gliviu/dir-compare)
|
||||
[](https://ci.appveyor.com/project/gliviu/dir-compare)
|
||||
[](http://codecov.io/github/gliviu/dir-compare?branch=master)
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Library](#library)
|
||||
* [Use](#use)
|
||||
* [Api](#api)
|
||||
* [Glob patterns](#glob-patterns)
|
||||
* [Custom file content comparators](#custom-file-content-comparators)
|
||||
+ [Ignore line endings and white spaces](#ignore-line-endings-and-white-spaces)
|
||||
* [Custom name comparators](#custom-name-comparators)
|
||||
* [Custom result builder](#custom-result-builder)
|
||||
* [Symbolic links](#symbolic-links)
|
||||
- [Command line](#command-line)
|
||||
- [Changelog](#changelog)
|
||||
|
||||
# Installation
|
||||
```shell
|
||||
$ npm install dir-compare
|
||||
```
|
||||
or
|
||||
```shell
|
||||
$ npm install -g dir-compare
|
||||
```
|
||||
for command line utility.
|
||||
|
||||
# Library
|
||||
|
||||
## Use
|
||||
```javascript
|
||||
const dircompare = require('dir-compare');
|
||||
|
||||
const options = { compareSize: true };
|
||||
// Multiple compare strategy can be used simultaneously - compareSize, compareContent, compareDate, compareSymlink.
|
||||
// If one comparison fails for a pair of files, they are considered distinct.
|
||||
const path1 = '...';
|
||||
const path2 = '...';
|
||||
|
||||
// Synchronous
|
||||
const res = dircompare.compareSync(path1, path2, options)
|
||||
print(res)
|
||||
|
||||
// Asynchronous
|
||||
dircompare.compare(path1, path2, options)
|
||||
.then(res => print(res))
|
||||
.catch(error => console.error(error));
|
||||
|
||||
|
||||
function print(result) {
|
||||
console.log('Directories are %s', result.same ? 'identical' : 'different')
|
||||
|
||||
console.log('Statistics - equal entries: %s, distinct entries: %s, left only entries: %s, right only entries: %s, differences: %s',
|
||||
result.equal, result.distinct, result.left, result.right, result.differences)
|
||||
|
||||
result.diffSet.forEach(dif => console.log('Difference - name1: %s, type1: %s, name2: %s, type2: %s, state: %s',
|
||||
dif.name1, dif.type1, dif.name2, dif.type2, dif.state))
|
||||
}
|
||||
```
|
||||
|
||||
Typescript
|
||||
```typescript
|
||||
import { compare, compareSync, Options, Result } from "dir-compare";
|
||||
const path1 = '...';
|
||||
const path2 = '...';
|
||||
const options: Options = { compareSize: true };
|
||||
|
||||
const res: Result = compareSync(path1, path2, options);
|
||||
console.log(res)
|
||||
|
||||
compare(path1, path2, options)
|
||||
.then(res => console.log(res))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
## Api
|
||||
|
||||
|
||||
Below is a quick recap of the api. For more details check the [reference documentation](https://gliviu.github.io/dc-api/).
|
||||
```typescript
|
||||
compare(path1: string, path2: string, options?: Options): Promise<Result>
|
||||
compareSync(path1: string, path2: string, options?: Options): Result
|
||||
```
|
||||
|
||||
```Options```
|
||||
* **compareSize**: true/false - Compares files by size. Defaults to 'false'.
|
||||
* **compareContent**: true/false - Compares files by content. Defaults to 'false'.
|
||||
* **compareFileSync**, **compareFileAsync**: Callbacks for file comparison. See [Custom file content comparators](#custom-file-content-comparators).
|
||||
* **compareDate**: true/false - Compares files by date of modification (stat.mtime). Defaults to 'false'.
|
||||
* **compareNameHandler**: Callback for name comparison. See [Custom name comparators](#custom-name-comparators).
|
||||
* **dateTolerance**: milliseconds - Two files are considered to have the same date if the difference between their modification dates fits within date tolerance. Defaults to 1000 ms.
|
||||
* **compareSymlink**: true/false - Compares entries by symlink. Defaults to 'false'.
|
||||
* **skipSymlinks**: true/false - Ignore symbolic links. Defaults to 'false'.
|
||||
* **skipSubdirs**: true/false - Skips sub directories. Defaults to 'false'.
|
||||
* **ignoreCase**: true/false - Ignores case when comparing names. Defaults to 'false'.
|
||||
* **noDiffSet**: true/false - Toggles presence of diffSet in output. If true, only statistics are provided. Use this when comparing large number of files to avoid out of memory situations. Defaults to 'false'.
|
||||
* **includeFilter**: File name filter. Comma separated [minimatch](https://www.npmjs.com/package/minimatch) patterns. See [Glob patterns](#glob-patterns) below.
|
||||
* **excludeFilter**: File/directory name exclude filter. Comma separated [minimatch](https://www.npmjs.com/package/minimatch) patterns. See [Glob patterns](#glob-patterns) below.
|
||||
* **resultBuilder**: Callback for constructing result. Called for each compared entry pair. Updates `statistics` and `diffSet`. More details in [Custom result builder](#custom-result-builder).
|
||||
|
||||
```Result```
|
||||
* **same**: true if directories are identical
|
||||
* **distinct**: number of distinct entries
|
||||
* **equal**: number of equal entries
|
||||
* **left**: number of entries only in path1
|
||||
* **right**: number of entries only in path2
|
||||
* **differences**: total number of differences (distinct+left+right)
|
||||
* **total**: total number of entries (differences+equal)
|
||||
* **distinctFiles**: number of distinct files
|
||||
* **equalFiles**: number of equal files
|
||||
* **leftFiles**: number of files only in path1
|
||||
* **rightFiles**: number of files only in path2
|
||||
* **differencesFiles**: total number of different files (distinctFiles+leftFiles+rightFiles)
|
||||
* **totalFiles**: total number of files (differencesFiles+equalFiles)
|
||||
* **distinctDirs**: number of distinct directories
|
||||
* **equalDirs**: number of equal directories
|
||||
* **leftDirs**: number of directories only in path1
|
||||
* **rightDirs**: number of directories only in path2
|
||||
* **differencesDirs**: total number of different directories (distinctDirs+leftDirs+rightDirs)
|
||||
* **totalDirs**: total number of directories (differencesDirs+equalDirs)
|
||||
* **brokenLinks**:
|
||||
* **leftBrokenLinks**: number of broken links only in path1
|
||||
* **rightBrokenLinks**: number of broken links only in path2
|
||||
* **distinctBrokenLinks**: number of broken links with same name appearing in both path1 and path2
|
||||
* **totalBrokenLinks**: total number of broken links (leftBrokenLinks+rightBrokenLinks+distinctBrokenLinks)
|
||||
* **symlinks**: Statistics available if `compareSymlink` options is used
|
||||
* **distinctSymlinks**: number of distinct links
|
||||
* **equalSymlinks**: number of equal links
|
||||
* **leftSymlinks**: number of links only in path1
|
||||
* **rightSymlinks**: number of links only in path2
|
||||
* **differencesSymlinks**: total number of different links (distinctSymlinks+leftSymlinks+rightSymlinks)
|
||||
* **totalSymlinks**: total number of links (differencesSymlinks+equalSymlinks)
|
||||
* **diffSet** - List of changes (present if `options.noDiffSet` is false)
|
||||
* **path1**: path not including file/directory name; can be relative or absolute depending on call to compare(),
|
||||
* **path2**: path not including file/directory name; can be relative or absolute depending on call to compare(),
|
||||
* **relativePath**: path relative to root,
|
||||
* **name1**: file/directory name
|
||||
* **name2**: file/directory name
|
||||
* **state**: one of equal, left, right, distinct,
|
||||
* **type1**: one of missing, file, directory, broken-link
|
||||
* **type2**: one of missing, file, directory, broken-link
|
||||
* **size1**: file size
|
||||
* **size2**: file size
|
||||
* **date1**: modification date (stat.mtime)
|
||||
* **date2**: modification date (stat.mtime)
|
||||
* **level**: depth
|
||||
* **reason**: Provides reason when two identically named entries are distinct.
|
||||
Not available if entries are equal.
|
||||
One of "different-size", "different-date", "different-content", "broken-link", "different-symlink".
|
||||
|
||||
## Glob patterns
|
||||
[Minimatch](https://www.npmjs.com/package/minimatch) patterns are used to include/exclude files to be compared.
|
||||
|
||||
The pattern is matched against the relative path of the entry being compared.
|
||||
|
||||
Following examples assume we are comparing two [dir-compare](https://github.com/gliviu/dir-compare) code bases.
|
||||
|
||||
|
||||
```
|
||||
dircompare -x ".git,node_modules" dir1 dir2') exclude git and node modules directories
|
||||
dircompare -x "expected" dir1 dir2') exclude '/tests/expected' directory
|
||||
dircompare -x "/tests/expected" dir1 dir2') exclude '/tests/expected' directory
|
||||
dircompare -x "**/expected" dir1 dir2') exclude '/tests/expected' directory
|
||||
dircompare -x "**/tests/**/*.js" dir1 dir2') exclude all js files in '/tests' directory and subdirectories
|
||||
dircompare -f "*.js,*.yml" dir1 dir2') include js and yaml files
|
||||
dircompare -f "/tests/**/*.js" dir1 dir2') include all js files in '/tests' directory and subdirectories
|
||||
dircompare -f "**/tests/**/*.ts" dir1 dir2') include all js files in '/tests' directory and subdirectories
|
||||
```
|
||||
|
||||
## Custom file content comparators
|
||||
By default file content is binary compared. As of version 1.5.0 custom file comparison handlers may be specified.
|
||||
|
||||
Custom handlers are specified by `compareFileSync` and `compareFileAsync` options which correspond to `dircompare.compareSync()` or `dircompare.compare()` methods.
|
||||
|
||||
A couple of handlers are included in the library:
|
||||
* binary sync compare - `dircompare.fileCompareHandlers.defaultFileCompare.compareSync`
|
||||
* binary async compare - `dircompare.fileCompareHandlers.defaultFileCompare.compareAsync`
|
||||
* text sync compare - `dircompare.fileCompareHandlers.lineBasedFileCompare.compareSync`
|
||||
* text async compare - `dircompare.fileCompareHandlers.lineBasedFileCompare.compareAsync`
|
||||
|
||||
Use [defaultFileCompare.js](https://github.com/gliviu/dir-compare/blob/master/src/fileCompareHandler/defaultFileCompare.js) as an example to create your own.
|
||||
|
||||
### Ignore line endings and white spaces
|
||||
Line based comparator can be used to ignore line ending and white space differences. This comparator is not available in [CLI](#command-line) mode.
|
||||
```javascript
|
||||
var dircompare = require('dir-compare');
|
||||
|
||||
var options = {
|
||||
compareContent: true,
|
||||
compareFileSync: dircompare.fileCompareHandlers.lineBasedFileCompare.compareSync,
|
||||
compareFileAsync: dircompare.fileCompareHandlers.lineBasedFileCompare.compareAsync,
|
||||
ignoreLineEnding: true,
|
||||
ignoreWhiteSpaces: true
|
||||
};
|
||||
|
||||
var path1 = '...';
|
||||
var path2 = '...';
|
||||
var res = dircompare.compareSync(path1, path2, options);
|
||||
console.log(res)
|
||||
|
||||
dircompare.compare(path1, path2, options)
|
||||
.then(res => console.log(res))
|
||||
```
|
||||
## Custom name comparators
|
||||
If [default](https://github.com/gliviu/dir-compare/blob/master/src/nameCompare/defaultNameCompare.js) name comparison is not enough, custom behavior can be specified with [compareNameHandler](https://gliviu.github.io/dc-api/index.html#comparenamehandler) option.
|
||||
Following example adds the possibility to ignore file extensions.
|
||||
```typescript
|
||||
import { Options, compare } from 'dir-compare'
|
||||
import path from 'path'
|
||||
|
||||
var options: Options = {
|
||||
compareSize: false, // compare only name by disabling size and content criteria
|
||||
compareContent: false,
|
||||
compareNameHandler: customNameCompare, // new name comparator used to ignore extensions
|
||||
ignoreExtension: true, // supported by the custom name compare below
|
||||
};
|
||||
|
||||
function customNameCompare(name1: string, name2: string, options: Options) {
|
||||
if (options.ignoreCase) {
|
||||
name1 = name1.toLowerCase()
|
||||
name2 = name2.toLowerCase()
|
||||
}
|
||||
if (options.ignoreExtension) {
|
||||
name1 = path.basename(name1, path.extname(name1))
|
||||
name2 = path.basename(name2, path.extname(name2))
|
||||
}
|
||||
return ((name1 === name2) ? 0 : ((name1 > name2) ? 1 : -1))
|
||||
}
|
||||
|
||||
var path1 = '/tmp/a';
|
||||
var path2 = '/tmp/b';
|
||||
|
||||
var res = compare(path1, path2, options).then(res => {
|
||||
console.log(`Same: ${res.same}`)
|
||||
if (!res.diffSet) {
|
||||
return
|
||||
}
|
||||
res.diffSet.forEach(dif => console.log(`${dif.name1} ${dif.name2} ${dif.state}`))
|
||||
})
|
||||
|
||||
// Outputs
|
||||
// icon.svg icon.png equal
|
||||
// logo.svg logo.jpg equal
|
||||
```
|
||||
|
||||
## Custom result builder
|
||||
[Result builder](https://gliviu.github.io/dc-api/index.html#resultbuilder) is called for each pair of entries encountered during comparison. Its purpose is to append entries in `diffSet` and eventually update `statistics` object with new stats.
|
||||
|
||||
If needed it can be replaced with custom implementation.
|
||||
|
||||
```javascript
|
||||
var dircompare = require("dircompare")
|
||||
|
||||
var customResultBuilder = function (entry1, entry2, state, level, relativePath, options, statistics, diffSet, reason) {
|
||||
...
|
||||
}
|
||||
|
||||
var options = {
|
||||
compareSize: true,
|
||||
resultBuilder: customResultBuilder
|
||||
}
|
||||
var res = dircompare.compareSync('...', '...', options)
|
||||
|
||||
```
|
||||
|
||||
The [default](https://github.com/gliviu/dir-compare/blob/master/src/resultBuilder/defaultResultBuilderCallback.js) builder can be used as an example.
|
||||
|
||||
## Symbolic links
|
||||
Unless `compareSymlink` option is used, symbolic links are resolved and any comparison is applied to the file/directory they point to.
|
||||
|
||||
Circular loops are handled by breaking the loop as soon as it is detected.
|
||||
|
||||
Version `1.x` treats broken links as `ENOENT: no such file or directory`.
|
||||
Since `2.0` they are treated as a special type of entry - `broken-link` - and are available as stats (`totalBrokenLinks`, `distinctBrokenLinks`, ...).
|
||||
|
||||
Using `compareSymlink` option causes `dircompare` to check symlink values for equality.
|
||||
In this mode two entries with identical name are considered different if
|
||||
* one is symlink, the other is not
|
||||
* both are symlinks but point to different locations
|
||||
|
||||
These rules are applied in addition to the other comparison modes; ie. by content, by size...
|
||||
|
||||
If entries are different because of symlinks, `reason` will be `different-symlink`. Also statistics summarizes differences caused by symbolik links.
|
||||
|
||||
# Command line
|
||||
```
|
||||
Usage: dircompare [options] leftdir rightdir
|
||||
|
||||
Options:
|
||||
|
||||
-h, --help output usage information
|
||||
-V, --version output the version number
|
||||
-c, --compare-content compare files by content
|
||||
-D, --compare-date compare files by date
|
||||
--date-tolerance [type] tolerance to be used in date comparison (milliseconds)
|
||||
--compare-symlink compare files and directories by symlink
|
||||
-f, --filter [type] file name filter
|
||||
-x, --exclude [type] file/directory name exclude filter
|
||||
-S, --skip-subdirs do not recurse into subdirectories
|
||||
-L, --skip-symlinks ignore symlinks
|
||||
-i, --ignore-case ignores case when comparing file names
|
||||
-l, --show-left report - show entries occurring in left dir
|
||||
-r, --show-right report - show entries occurring in right dir
|
||||
-e, --show-equal report - show identic entries occurring in both dirs
|
||||
-d, --show-distinct report - show distinct entries occurring in both dirs
|
||||
-a, --show-all report - show all entries
|
||||
-w, --whole-report report - include directories in detailed report
|
||||
--reason report - show reason when entries are distinct
|
||||
--csv report - print details as csv
|
||||
--nocolors don't use console colors
|
||||
--async Make use of multiple cores
|
||||
|
||||
By default files are compared by size.
|
||||
--date-tolerance defaults to 1000 ms. Two files are considered to have
|
||||
the same date if the difference between their modification dates fits
|
||||
within date tolerance.
|
||||
|
||||
Exit codes:
|
||||
0 - entries are identical
|
||||
1 - entries are different
|
||||
2 - error occurred
|
||||
|
||||
Examples:
|
||||
compare by content dircompare -c dir1 dir2
|
||||
show only different files dircompare -d dir1 dir2
|
||||
|
||||
exclude filter dircompare -x ".git,node_modules" dir1 dir2
|
||||
dircompare -x "/tests/expected" dir1 dir2
|
||||
dircompare -x "**/expected" dir1 dir2
|
||||
dircompare -x "**/tests/**/*.ts" dir1 dir2
|
||||
|
||||
include filter dircompare -f "*.js,*.yml" dir1 dir2
|
||||
dircompare -f "/tests/**/*.js" dir1 dir2
|
||||
dircompare -f "**/tests/**/*.ts" dir1 dir2
|
||||
```
|
||||
|
||||
# Changelog
|
||||
* v2.4.0 New option to customize file/folder name comparison
|
||||
* v2.3.0 Fixes
|
||||
* v2.1.0 Removed [bluebird](https://github.com/petkaantonov/bluebird/#note) dependency
|
||||
* v2.0.0
|
||||
* New option to compare symlinks.
|
||||
* New field indicating reason for two entries being distinct.
|
||||
* Improved command line output format.
|
||||
* Tests are no longer part of published package.
|
||||
* Generated [Api](#api) documentation.
|
||||
|
||||
Breaking changes:
|
||||
* Broken links are no longer treated as errors. As a result there are new statistics (leftBrokenLinks, rightBrokenLinks, distinctBrokenLinks, totalBrokenLinks) and new entry type - broken-link.
|
||||
Details in [Symbolic links](#symbolic-links).
|
||||
* Typescript correction: new interface `Result` replaced `Statistics`.
|
||||
* v1.8.0
|
||||
* globstar patterns
|
||||
* typescript corrections
|
||||
* removed support for node 0.11, 0.12, iojs
|
||||
* v1.7.0 performance improvements
|
||||
* v1.6.0 typescript support
|
||||
* v1.5.0 added option to ignore line endings and white space differences
|
||||
* v1.3.0 added date tolerance option
|
||||
* v1.2.0 added compare by date option
|
||||
* v1.1.0
|
||||
* detect symlink loops
|
||||
* improved color scheme for command line utility
|
||||
* v1.0.0
|
||||
* asynchronous processing
|
||||
* new library options: noDiffSet, resultBuilder
|
||||
* new statistics: distinctFiles, equalFiles, leftFiles, rightFiles, distinctDirs, equalDirs, leftDirs, rightDirs
|
||||
* new --async command line option
|
||||
* Fix for https://github.com/tj/commander.js/issues/125
|
||||
* v0.0.3 Fix fille ordering issue for newer node versions
|
||||
261
electron/node_modules/dir-compare/node_modules/commander/History.md
generated
vendored
Normal file
261
electron/node_modules/dir-compare/node_modules/commander/History.md
generated
vendored
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
|
||||
2.9.0 / 2015-10-13
|
||||
==================
|
||||
|
||||
* Add option `isDefault` to set default subcommand #415 @Qix-
|
||||
* Add callback to allow filtering or post-processing of help text #434 @djulien
|
||||
* Fix `undefined` text in help information close #414 #416 @zhiyelee
|
||||
|
||||
2.8.1 / 2015-04-22
|
||||
==================
|
||||
|
||||
* Back out `support multiline description` Close #396 #397
|
||||
|
||||
2.8.0 / 2015-04-07
|
||||
==================
|
||||
|
||||
* Add `process.execArg` support, execution args like `--harmony` will be passed to sub-commands #387 @DigitalIO @zhiyelee
|
||||
* Fix bug in Git-style sub-commands #372 @zhiyelee
|
||||
* Allow commands to be hidden from help #383 @tonylukasavage
|
||||
* When git-style sub-commands are in use, yet none are called, display help #382 @claylo
|
||||
* Add ability to specify arguments syntax for top-level command #258 @rrthomas
|
||||
* Support multiline descriptions #208 @zxqfox
|
||||
|
||||
2.7.1 / 2015-03-11
|
||||
==================
|
||||
|
||||
* Revert #347 (fix collisions when option and first arg have same name) which causes a bug in #367.
|
||||
|
||||
2.7.0 / 2015-03-09
|
||||
==================
|
||||
|
||||
* Fix git-style bug when installed globally. Close #335 #349 @zhiyelee
|
||||
* Fix collisions when option and first arg have same name. Close #346 #347 @tonylukasavage
|
||||
* Add support for camelCase on `opts()`. Close #353 @nkzawa
|
||||
* Add node.js 0.12 and io.js to travis.yml
|
||||
* Allow RegEx options. #337 @palanik
|
||||
* Fixes exit code when sub-command failing. Close #260 #332 @pirelenito
|
||||
* git-style `bin` files in $PATH make sense. Close #196 #327 @zhiyelee
|
||||
|
||||
2.6.0 / 2014-12-30
|
||||
==================
|
||||
|
||||
* added `Command#allowUnknownOption` method. Close #138 #318 @doozr @zhiyelee
|
||||
* Add application description to the help msg. Close #112 @dalssoft
|
||||
|
||||
2.5.1 / 2014-12-15
|
||||
==================
|
||||
|
||||
* fixed two bugs incurred by variadic arguments. Close #291 @Quentin01 #302 @zhiyelee
|
||||
|
||||
2.5.0 / 2014-10-24
|
||||
==================
|
||||
|
||||
* add support for variadic arguments. Closes #277 @whitlockjc
|
||||
|
||||
2.4.0 / 2014-10-17
|
||||
==================
|
||||
|
||||
* fixed a bug on executing the coercion function of subcommands option. Closes #270
|
||||
* added `Command.prototype.name` to retrieve command name. Closes #264 #266 @tonylukasavage
|
||||
* added `Command.prototype.opts` to retrieve all the options as a simple object of key-value pairs. Closes #262 @tonylukasavage
|
||||
* fixed a bug on subcommand name. Closes #248 @jonathandelgado
|
||||
* fixed function normalize doesn’t honor option terminator. Closes #216 @abbr
|
||||
|
||||
2.3.0 / 2014-07-16
|
||||
==================
|
||||
|
||||
* add command alias'. Closes PR #210
|
||||
* fix: Typos. Closes #99
|
||||
* fix: Unused fs module. Closes #217
|
||||
|
||||
2.2.0 / 2014-03-29
|
||||
==================
|
||||
|
||||
* add passing of previous option value
|
||||
* fix: support subcommands on windows. Closes #142
|
||||
* Now the defaultValue passed as the second argument of the coercion function.
|
||||
|
||||
2.1.0 / 2013-11-21
|
||||
==================
|
||||
|
||||
* add: allow cflag style option params, unit test, fixes #174
|
||||
|
||||
2.0.0 / 2013-07-18
|
||||
==================
|
||||
|
||||
* remove input methods (.prompt, .confirm, etc)
|
||||
|
||||
1.3.2 / 2013-07-18
|
||||
==================
|
||||
|
||||
* add support for sub-commands to co-exist with the original command
|
||||
|
||||
1.3.1 / 2013-07-18
|
||||
==================
|
||||
|
||||
* add quick .runningCommand hack so you can opt-out of other logic when running a sub command
|
||||
|
||||
1.3.0 / 2013-07-09
|
||||
==================
|
||||
|
||||
* add EACCES error handling
|
||||
* fix sub-command --help
|
||||
|
||||
1.2.0 / 2013-06-13
|
||||
==================
|
||||
|
||||
* allow "-" hyphen as an option argument
|
||||
* support for RegExp coercion
|
||||
|
||||
1.1.1 / 2012-11-20
|
||||
==================
|
||||
|
||||
* add more sub-command padding
|
||||
* fix .usage() when args are present. Closes #106
|
||||
|
||||
1.1.0 / 2012-11-16
|
||||
==================
|
||||
|
||||
* add git-style executable subcommand support. Closes #94
|
||||
|
||||
1.0.5 / 2012-10-09
|
||||
==================
|
||||
|
||||
* fix `--name` clobbering. Closes #92
|
||||
* fix examples/help. Closes #89
|
||||
|
||||
1.0.4 / 2012-09-03
|
||||
==================
|
||||
|
||||
* add `outputHelp()` method.
|
||||
|
||||
1.0.3 / 2012-08-30
|
||||
==================
|
||||
|
||||
* remove invalid .version() defaulting
|
||||
|
||||
1.0.2 / 2012-08-24
|
||||
==================
|
||||
|
||||
* add `--foo=bar` support [arv]
|
||||
* fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus]
|
||||
|
||||
1.0.1 / 2012-08-03
|
||||
==================
|
||||
|
||||
* fix issue #56
|
||||
* fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode())
|
||||
|
||||
1.0.0 / 2012-07-05
|
||||
==================
|
||||
|
||||
* add support for optional option descriptions
|
||||
* add defaulting of `.version()` to package.json's version
|
||||
|
||||
0.6.1 / 2012-06-01
|
||||
==================
|
||||
|
||||
* Added: append (yes or no) on confirmation
|
||||
* Added: allow node.js v0.7.x
|
||||
|
||||
0.6.0 / 2012-04-10
|
||||
==================
|
||||
|
||||
* Added `.prompt(obj, callback)` support. Closes #49
|
||||
* Added default support to .choose(). Closes #41
|
||||
* Fixed the choice example
|
||||
|
||||
0.5.1 / 2011-12-20
|
||||
==================
|
||||
|
||||
* Fixed `password()` for recent nodes. Closes #36
|
||||
|
||||
0.5.0 / 2011-12-04
|
||||
==================
|
||||
|
||||
* Added sub-command option support [itay]
|
||||
|
||||
0.4.3 / 2011-12-04
|
||||
==================
|
||||
|
||||
* Fixed custom help ordering. Closes #32
|
||||
|
||||
0.4.2 / 2011-11-24
|
||||
==================
|
||||
|
||||
* Added travis support
|
||||
* Fixed: line-buffered input automatically trimmed. Closes #31
|
||||
|
||||
0.4.1 / 2011-11-18
|
||||
==================
|
||||
|
||||
* Removed listening for "close" on --help
|
||||
|
||||
0.4.0 / 2011-11-15
|
||||
==================
|
||||
|
||||
* Added support for `--`. Closes #24
|
||||
|
||||
0.3.3 / 2011-11-14
|
||||
==================
|
||||
|
||||
* Fixed: wait for close event when writing help info [Jerry Hamlet]
|
||||
|
||||
0.3.2 / 2011-11-01
|
||||
==================
|
||||
|
||||
* Fixed long flag definitions with values [felixge]
|
||||
|
||||
0.3.1 / 2011-10-31
|
||||
==================
|
||||
|
||||
* Changed `--version` short flag to `-V` from `-v`
|
||||
* Changed `.version()` so it's configurable [felixge]
|
||||
|
||||
0.3.0 / 2011-10-31
|
||||
==================
|
||||
|
||||
* Added support for long flags only. Closes #18
|
||||
|
||||
0.2.1 / 2011-10-24
|
||||
==================
|
||||
|
||||
* "node": ">= 0.4.x < 0.7.0". Closes #20
|
||||
|
||||
0.2.0 / 2011-09-26
|
||||
==================
|
||||
|
||||
* Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs]
|
||||
|
||||
0.1.0 / 2011-08-24
|
||||
==================
|
||||
|
||||
* Added support for custom `--help` output
|
||||
|
||||
0.0.5 / 2011-08-18
|
||||
==================
|
||||
|
||||
* Changed: when the user enters nothing prompt for password again
|
||||
* Fixed issue with passwords beginning with numbers [NuckChorris]
|
||||
|
||||
0.0.4 / 2011-08-15
|
||||
==================
|
||||
|
||||
* Fixed `Commander#args`
|
||||
|
||||
0.0.3 / 2011-08-15
|
||||
==================
|
||||
|
||||
* Added default option value support
|
||||
|
||||
0.0.2 / 2011-08-15
|
||||
==================
|
||||
|
||||
* Added mask support to `Command#password(str[, mask], fn)`
|
||||
* Added `Command#password(str, fn)`
|
||||
|
||||
0.0.1 / 2010-01-03
|
||||
==================
|
||||
|
||||
* Initial release
|
||||
22
electron/node_modules/dir-compare/node_modules/commander/LICENSE
generated
vendored
Normal file
22
electron/node_modules/dir-compare/node_modules/commander/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
(The MIT License)
|
||||
|
||||
Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
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.
|
||||
351
electron/node_modules/dir-compare/node_modules/commander/Readme.md
generated
vendored
Normal file
351
electron/node_modules/dir-compare/node_modules/commander/Readme.md
generated
vendored
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
# Commander.js
|
||||
|
||||
|
||||
[](http://travis-ci.org/tj/commander.js)
|
||||
[](https://www.npmjs.org/package/commander)
|
||||
[](https://www.npmjs.org/package/commander)
|
||||
[](https://gitter.im/tj/commander.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/tj/commander).
|
||||
[API documentation](http://tj.github.com/commander.js/)
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
$ npm install commander
|
||||
|
||||
## Option parsing
|
||||
|
||||
Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.
|
||||
|
||||
```js
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var program = require('commander');
|
||||
|
||||
program
|
||||
.version('0.0.1')
|
||||
.option('-p, --peppers', 'Add peppers')
|
||||
.option('-P, --pineapple', 'Add pineapple')
|
||||
.option('-b, --bbq-sauce', 'Add bbq sauce')
|
||||
.option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')
|
||||
.parse(process.argv);
|
||||
|
||||
console.log('you ordered a pizza with:');
|
||||
if (program.peppers) console.log(' - peppers');
|
||||
if (program.pineapple) console.log(' - pineapple');
|
||||
if (program.bbqSauce) console.log(' - bbq');
|
||||
console.log(' - %s cheese', program.cheese);
|
||||
```
|
||||
|
||||
Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc.
|
||||
|
||||
|
||||
## Coercion
|
||||
|
||||
```js
|
||||
function range(val) {
|
||||
return val.split('..').map(Number);
|
||||
}
|
||||
|
||||
function list(val) {
|
||||
return val.split(',');
|
||||
}
|
||||
|
||||
function collect(val, memo) {
|
||||
memo.push(val);
|
||||
return memo;
|
||||
}
|
||||
|
||||
function increaseVerbosity(v, total) {
|
||||
return total + 1;
|
||||
}
|
||||
|
||||
program
|
||||
.version('0.0.1')
|
||||
.usage('[options] <file ...>')
|
||||
.option('-i, --integer <n>', 'An integer argument', parseInt)
|
||||
.option('-f, --float <n>', 'A float argument', parseFloat)
|
||||
.option('-r, --range <a>..<b>', 'A range', range)
|
||||
.option('-l, --list <items>', 'A list', list)
|
||||
.option('-o, --optional [value]', 'An optional value')
|
||||
.option('-c, --collect [value]', 'A repeatable value', collect, [])
|
||||
.option('-v, --verbose', 'A value that can be increased', increaseVerbosity, 0)
|
||||
.parse(process.argv);
|
||||
|
||||
console.log(' int: %j', program.integer);
|
||||
console.log(' float: %j', program.float);
|
||||
console.log(' optional: %j', program.optional);
|
||||
program.range = program.range || [];
|
||||
console.log(' range: %j..%j', program.range[0], program.range[1]);
|
||||
console.log(' list: %j', program.list);
|
||||
console.log(' collect: %j', program.collect);
|
||||
console.log(' verbosity: %j', program.verbose);
|
||||
console.log(' args: %j', program.args);
|
||||
```
|
||||
|
||||
## Regular Expression
|
||||
```js
|
||||
program
|
||||
.version('0.0.1')
|
||||
.option('-s --size <size>', 'Pizza size', /^(large|medium|small)$/i, 'medium')
|
||||
.option('-d --drink [drink]', 'Drink', /^(coke|pepsi|izze)$/i)
|
||||
.parse(process.argv);
|
||||
|
||||
console.log(' size: %j', program.size);
|
||||
console.log(' drink: %j', program.drink);
|
||||
```
|
||||
|
||||
## Variadic arguments
|
||||
|
||||
The last argument of a command can be variadic, and only the last argument. To make an argument variadic you have to
|
||||
append `...` to the argument name. Here is an example:
|
||||
|
||||
```js
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var program = require('commander');
|
||||
|
||||
program
|
||||
.version('0.0.1')
|
||||
.command('rmdir <dir> [otherDirs...]')
|
||||
.action(function (dir, otherDirs) {
|
||||
console.log('rmdir %s', dir);
|
||||
if (otherDirs) {
|
||||
otherDirs.forEach(function (oDir) {
|
||||
console.log('rmdir %s', oDir);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
program.parse(process.argv);
|
||||
```
|
||||
|
||||
An `Array` is used for the value of a variadic argument. This applies to `program.args` as well as the argument passed
|
||||
to your action as demonstrated above.
|
||||
|
||||
## Specify the argument syntax
|
||||
|
||||
```js
|
||||
#!/usr/bin/env node
|
||||
|
||||
var program = require('../');
|
||||
|
||||
program
|
||||
.version('0.0.1')
|
||||
.arguments('<cmd> [env]')
|
||||
.action(function (cmd, env) {
|
||||
cmdValue = cmd;
|
||||
envValue = env;
|
||||
});
|
||||
|
||||
program.parse(process.argv);
|
||||
|
||||
if (typeof cmdValue === 'undefined') {
|
||||
console.error('no command given!');
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('command:', cmdValue);
|
||||
console.log('environment:', envValue || "no environment given");
|
||||
```
|
||||
|
||||
## Git-style sub-commands
|
||||
|
||||
```js
|
||||
// file: ./examples/pm
|
||||
var program = require('..');
|
||||
|
||||
program
|
||||
.version('0.0.1')
|
||||
.command('install [name]', 'install one or more packages')
|
||||
.command('search [query]', 'search with optional query')
|
||||
.command('list', 'list packages installed', {isDefault: true})
|
||||
.parse(process.argv);
|
||||
```
|
||||
|
||||
When `.command()` is invoked with a description argument, no `.action(callback)` should be called to handle sub-commands, otherwise there will be an error. This tells commander that you're going to use separate executables for sub-commands, much like `git(1)` and other popular tools.
|
||||
The commander will try to search the executables in the directory of the entry script (like `./examples/pm`) with the name `program-command`, like `pm-install`, `pm-search`.
|
||||
|
||||
Options can be passed with the call to `.command()`. Specifying `true` for `opts.noHelp` will remove the option from the generated help output. Specifying `true` for `opts.isDefault` will run the subcommand if no other subcommand is specified.
|
||||
|
||||
If the program is designed to be installed globally, make sure the executables have proper modes, like `755`.
|
||||
|
||||
### `--harmony`
|
||||
|
||||
You can enable `--harmony` option in two ways:
|
||||
* Use `#! /usr/bin/env node --harmony` in the sub-commands scripts. Note some os version don’t support this pattern.
|
||||
* Use the `--harmony` option when call the command, like `node --harmony examples/pm publish`. The `--harmony` option will be preserved when spawning sub-command process.
|
||||
|
||||
## Automated --help
|
||||
|
||||
The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:
|
||||
|
||||
```
|
||||
$ ./examples/pizza --help
|
||||
|
||||
Usage: pizza [options]
|
||||
|
||||
An application for pizzas ordering
|
||||
|
||||
Options:
|
||||
|
||||
-h, --help output usage information
|
||||
-V, --version output the version number
|
||||
-p, --peppers Add peppers
|
||||
-P, --pineapple Add pineapple
|
||||
-b, --bbq Add bbq sauce
|
||||
-c, --cheese <type> Add the specified type of cheese [marble]
|
||||
-C, --no-cheese You do not want any cheese
|
||||
|
||||
```
|
||||
|
||||
## Custom help
|
||||
|
||||
You can display arbitrary `-h, --help` information
|
||||
by listening for "--help". Commander will automatically
|
||||
exit once you are done so that the remainder of your program
|
||||
does not execute causing undesired behaviours, for example
|
||||
in the following executable "stuff" will not output when
|
||||
`--help` is used.
|
||||
|
||||
```js
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var program = require('commander');
|
||||
|
||||
program
|
||||
.version('0.0.1')
|
||||
.option('-f, --foo', 'enable some foo')
|
||||
.option('-b, --bar', 'enable some bar')
|
||||
.option('-B, --baz', 'enable some baz');
|
||||
|
||||
// must be before .parse() since
|
||||
// node's emit() is immediate
|
||||
|
||||
program.on('--help', function(){
|
||||
console.log(' Examples:');
|
||||
console.log('');
|
||||
console.log(' $ custom-help --help');
|
||||
console.log(' $ custom-help -h');
|
||||
console.log('');
|
||||
});
|
||||
|
||||
program.parse(process.argv);
|
||||
|
||||
console.log('stuff');
|
||||
```
|
||||
|
||||
Yields the following help output when `node script-name.js -h` or `node script-name.js --help` are run:
|
||||
|
||||
```
|
||||
|
||||
Usage: custom-help [options]
|
||||
|
||||
Options:
|
||||
|
||||
-h, --help output usage information
|
||||
-V, --version output the version number
|
||||
-f, --foo enable some foo
|
||||
-b, --bar enable some bar
|
||||
-B, --baz enable some baz
|
||||
|
||||
Examples:
|
||||
|
||||
$ custom-help --help
|
||||
$ custom-help -h
|
||||
|
||||
```
|
||||
|
||||
## .outputHelp(cb)
|
||||
|
||||
Output help information without exiting.
|
||||
Optional callback cb allows post-processing of help text before it is displayed.
|
||||
|
||||
If you want to display help by default (e.g. if no command was provided), you can use something like:
|
||||
|
||||
```js
|
||||
var program = require('commander');
|
||||
var colors = require('colors');
|
||||
|
||||
program
|
||||
.version('0.0.1')
|
||||
.command('getstream [url]', 'get stream URL')
|
||||
.parse(process.argv);
|
||||
|
||||
if (!process.argv.slice(2).length) {
|
||||
program.outputHelp(make_red);
|
||||
}
|
||||
|
||||
function make_red(txt) {
|
||||
return colors.red(txt); //display the help text in red on the console
|
||||
}
|
||||
```
|
||||
|
||||
## .help(cb)
|
||||
|
||||
Output help information and exit immediately.
|
||||
Optional callback cb allows post-processing of help text before it is displayed.
|
||||
|
||||
## Examples
|
||||
|
||||
```js
|
||||
var program = require('commander');
|
||||
|
||||
program
|
||||
.version('0.0.1')
|
||||
.option('-C, --chdir <path>', 'change the working directory')
|
||||
.option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
|
||||
.option('-T, --no-tests', 'ignore test hook')
|
||||
|
||||
program
|
||||
.command('setup [env]')
|
||||
.description('run setup commands for all envs')
|
||||
.option("-s, --setup_mode [mode]", "Which setup mode to use")
|
||||
.action(function(env, options){
|
||||
var mode = options.setup_mode || "normal";
|
||||
env = env || 'all';
|
||||
console.log('setup for %s env(s) with %s mode', env, mode);
|
||||
});
|
||||
|
||||
program
|
||||
.command('exec <cmd>')
|
||||
.alias('ex')
|
||||
.description('execute the given remote cmd')
|
||||
.option("-e, --exec_mode <mode>", "Which exec mode to use")
|
||||
.action(function(cmd, options){
|
||||
console.log('exec "%s" using %s mode', cmd, options.exec_mode);
|
||||
}).on('--help', function() {
|
||||
console.log(' Examples:');
|
||||
console.log();
|
||||
console.log(' $ deploy exec sequential');
|
||||
console.log(' $ deploy exec async');
|
||||
console.log();
|
||||
});
|
||||
|
||||
program
|
||||
.command('*')
|
||||
.action(function(env){
|
||||
console.log('deploying "%s"', env);
|
||||
});
|
||||
|
||||
program.parse(process.argv);
|
||||
```
|
||||
|
||||
More Demos can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
1110
electron/node_modules/dir-compare/node_modules/commander/index.js
generated
vendored
Normal file
1110
electron/node_modules/dir-compare/node_modules/commander/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
33
electron/node_modules/dir-compare/node_modules/commander/package.json
generated
vendored
Normal file
33
electron/node_modules/dir-compare/node_modules/commander/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "commander",
|
||||
"version": "2.9.0",
|
||||
"description": "the complete solution for node.js command-line programs",
|
||||
"keywords": [
|
||||
"command",
|
||||
"option",
|
||||
"parser"
|
||||
],
|
||||
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tj/commander.js.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"should": ">= 0.0.1",
|
||||
"sinon": ">=1.17.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test"
|
||||
},
|
||||
"main": "index",
|
||||
"engines": {
|
||||
"node": ">= 0.6.x"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"graceful-readlink": ">= 1.0.0"
|
||||
}
|
||||
}
|
||||
15
electron/node_modules/dir-compare/node_modules/minimatch/LICENSE
generated
vendored
Normal file
15
electron/node_modules/dir-compare/node_modules/minimatch/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
209
electron/node_modules/dir-compare/node_modules/minimatch/README.md
generated
vendored
Normal file
209
electron/node_modules/dir-compare/node_modules/minimatch/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
# minimatch
|
||||
|
||||
A minimal matching utility.
|
||||
|
||||
[](http://travis-ci.org/isaacs/minimatch)
|
||||
|
||||
|
||||
This is the matching library used internally by npm.
|
||||
|
||||
It works by converting glob expressions into JavaScript `RegExp`
|
||||
objects.
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var minimatch = require("minimatch")
|
||||
|
||||
minimatch("bar.foo", "*.foo") // true!
|
||||
minimatch("bar.foo", "*.bar") // false!
|
||||
minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy!
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
Supports these glob features:
|
||||
|
||||
* Brace Expansion
|
||||
* Extended glob matching
|
||||
* "Globstar" `**` matching
|
||||
|
||||
See:
|
||||
|
||||
* `man sh`
|
||||
* `man bash`
|
||||
* `man 3 fnmatch`
|
||||
* `man 5 gitignore`
|
||||
|
||||
## Minimatch Class
|
||||
|
||||
Create a minimatch object by instantiating the `minimatch.Minimatch` class.
|
||||
|
||||
```javascript
|
||||
var Minimatch = require("minimatch").Minimatch
|
||||
var mm = new Minimatch(pattern, options)
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
* `pattern` The original pattern the minimatch object represents.
|
||||
* `options` The options supplied to the constructor.
|
||||
* `set` A 2-dimensional array of regexp or string expressions.
|
||||
Each row in the
|
||||
array corresponds to a brace-expanded pattern. Each item in the row
|
||||
corresponds to a single path-part. For example, the pattern
|
||||
`{a,b/c}/d` would expand to a set of patterns like:
|
||||
|
||||
[ [ a, d ]
|
||||
, [ b, c, d ] ]
|
||||
|
||||
If a portion of the pattern doesn't have any "magic" in it
|
||||
(that is, it's something like `"foo"` rather than `fo*o?`), then it
|
||||
will be left as a string rather than converted to a regular
|
||||
expression.
|
||||
|
||||
* `regexp` Created by the `makeRe` method. A single regular expression
|
||||
expressing the entire pattern. This is useful in cases where you wish
|
||||
to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
|
||||
* `negate` True if the pattern is negated.
|
||||
* `comment` True if the pattern is a comment.
|
||||
* `empty` True if the pattern is `""`.
|
||||
|
||||
### Methods
|
||||
|
||||
* `makeRe` Generate the `regexp` member if necessary, and return it.
|
||||
Will return `false` if the pattern is invalid.
|
||||
* `match(fname)` Return true if the filename matches the pattern, or
|
||||
false otherwise.
|
||||
* `matchOne(fileArray, patternArray, partial)` Take a `/`-split
|
||||
filename, and match it against a single row in the `regExpSet`. This
|
||||
method is mainly for internal use, but is exposed so that it can be
|
||||
used by a glob-walker that needs to avoid excessive filesystem calls.
|
||||
|
||||
All other methods are internal, and will be called as necessary.
|
||||
|
||||
### minimatch(path, pattern, options)
|
||||
|
||||
Main export. Tests a path against the pattern using the options.
|
||||
|
||||
```javascript
|
||||
var isJS = minimatch(file, "*.js", { matchBase: true })
|
||||
```
|
||||
|
||||
### minimatch.filter(pattern, options)
|
||||
|
||||
Returns a function that tests its
|
||||
supplied argument, suitable for use with `Array.filter`. Example:
|
||||
|
||||
```javascript
|
||||
var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true}))
|
||||
```
|
||||
|
||||
### minimatch.match(list, pattern, options)
|
||||
|
||||
Match against the list of
|
||||
files, in the style of fnmatch or glob. If nothing is matched, and
|
||||
options.nonull is set, then return a list containing the pattern itself.
|
||||
|
||||
```javascript
|
||||
var javascripts = minimatch.match(fileList, "*.js", {matchBase: true}))
|
||||
```
|
||||
|
||||
### minimatch.makeRe(pattern, options)
|
||||
|
||||
Make a regular expression object from the pattern.
|
||||
|
||||
## Options
|
||||
|
||||
All options are `false` by default.
|
||||
|
||||
### debug
|
||||
|
||||
Dump a ton of stuff to stderr.
|
||||
|
||||
### nobrace
|
||||
|
||||
Do not expand `{a,b}` and `{1..3}` brace sets.
|
||||
|
||||
### noglobstar
|
||||
|
||||
Disable `**` matching against multiple folder names.
|
||||
|
||||
### dot
|
||||
|
||||
Allow patterns to match filenames starting with a period, even if
|
||||
the pattern does not explicitly have a period in that spot.
|
||||
|
||||
Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
|
||||
is set.
|
||||
|
||||
### noext
|
||||
|
||||
Disable "extglob" style patterns like `+(a|b)`.
|
||||
|
||||
### nocase
|
||||
|
||||
Perform a case-insensitive match.
|
||||
|
||||
### nonull
|
||||
|
||||
When a match is not found by `minimatch.match`, return a list containing
|
||||
the pattern itself if this option is set. When not set, an empty list
|
||||
is returned if there are no matches.
|
||||
|
||||
### matchBase
|
||||
|
||||
If set, then patterns without slashes will be matched
|
||||
against the basename of the path if it contains slashes. For example,
|
||||
`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
|
||||
|
||||
### nocomment
|
||||
|
||||
Suppress the behavior of treating `#` at the start of a pattern as a
|
||||
comment.
|
||||
|
||||
### nonegate
|
||||
|
||||
Suppress the behavior of treating a leading `!` character as negation.
|
||||
|
||||
### flipNegate
|
||||
|
||||
Returns from negate expressions the same as if they were not negated.
|
||||
(Ie, true on a hit, false on a miss.)
|
||||
|
||||
|
||||
## Comparisons to other fnmatch/glob implementations
|
||||
|
||||
While strict compliance with the existing standards is a worthwhile
|
||||
goal, some discrepancies exist between minimatch and other
|
||||
implementations, and are intentional.
|
||||
|
||||
If the pattern starts with a `!` character, then it is negated. Set the
|
||||
`nonegate` flag to suppress this behavior, and treat leading `!`
|
||||
characters normally. This is perhaps relevant if you wish to start the
|
||||
pattern with a negative extglob pattern like `!(a|B)`. Multiple `!`
|
||||
characters at the start of a pattern will negate the pattern multiple
|
||||
times.
|
||||
|
||||
If a pattern starts with `#`, then it is treated as a comment, and
|
||||
will not match anything. Use `\#` to match a literal `#` at the
|
||||
start of a line, or set the `nocomment` flag to suppress this behavior.
|
||||
|
||||
The double-star character `**` is supported by default, unless the
|
||||
`noglobstar` flag is set. This is supported in the manner of bsdglob
|
||||
and bash 4.1, where `**` only has special significance if it is the only
|
||||
thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
|
||||
`a/**b` will not.
|
||||
|
||||
If an escaped pattern has no matches, and the `nonull` flag is set,
|
||||
then minimatch.match returns the pattern as-provided, rather than
|
||||
interpreting the character escapes. For example,
|
||||
`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
|
||||
`"*a?"`. This is akin to setting the `nullglob` option in bash, except
|
||||
that it does not resolve escaped pattern characters.
|
||||
|
||||
If brace expansion is not disabled, then it is performed before any
|
||||
other interpretation of the glob pattern. Thus, a pattern like
|
||||
`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
|
||||
**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
|
||||
checked for validity. Since those two are valid, matching proceeds.
|
||||
923
electron/node_modules/dir-compare/node_modules/minimatch/minimatch.js
generated
vendored
Normal file
923
electron/node_modules/dir-compare/node_modules/minimatch/minimatch.js
generated
vendored
Normal file
|
|
@ -0,0 +1,923 @@
|
|||
module.exports = minimatch
|
||||
minimatch.Minimatch = Minimatch
|
||||
|
||||
var path = { sep: '/' }
|
||||
try {
|
||||
path = require('path')
|
||||
} catch (er) {}
|
||||
|
||||
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
|
||||
var expand = require('brace-expansion')
|
||||
|
||||
var plTypes = {
|
||||
'!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
|
||||
'?': { open: '(?:', close: ')?' },
|
||||
'+': { open: '(?:', close: ')+' },
|
||||
'*': { open: '(?:', close: ')*' },
|
||||
'@': { open: '(?:', close: ')' }
|
||||
}
|
||||
|
||||
// any single thing other than /
|
||||
// don't need to escape / when using new RegExp()
|
||||
var qmark = '[^/]'
|
||||
|
||||
// * => any number of characters
|
||||
var star = qmark + '*?'
|
||||
|
||||
// ** when dots are allowed. Anything goes, except .. and .
|
||||
// not (^ or / followed by one or two dots followed by $ or /),
|
||||
// followed by anything, any number of times.
|
||||
var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
|
||||
|
||||
// not a ^ or / followed by a dot,
|
||||
// followed by anything, any number of times.
|
||||
var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
|
||||
|
||||
// characters that need to be escaped in RegExp.
|
||||
var reSpecials = charSet('().*{}+?[]^$\\!')
|
||||
|
||||
// "abc" -> { a:true, b:true, c:true }
|
||||
function charSet (s) {
|
||||
return s.split('').reduce(function (set, c) {
|
||||
set[c] = true
|
||||
return set
|
||||
}, {})
|
||||
}
|
||||
|
||||
// normalizes slashes.
|
||||
var slashSplit = /\/+/
|
||||
|
||||
minimatch.filter = filter
|
||||
function filter (pattern, options) {
|
||||
options = options || {}
|
||||
return function (p, i, list) {
|
||||
return minimatch(p, pattern, options)
|
||||
}
|
||||
}
|
||||
|
||||
function ext (a, b) {
|
||||
a = a || {}
|
||||
b = b || {}
|
||||
var t = {}
|
||||
Object.keys(b).forEach(function (k) {
|
||||
t[k] = b[k]
|
||||
})
|
||||
Object.keys(a).forEach(function (k) {
|
||||
t[k] = a[k]
|
||||
})
|
||||
return t
|
||||
}
|
||||
|
||||
minimatch.defaults = function (def) {
|
||||
if (!def || !Object.keys(def).length) return minimatch
|
||||
|
||||
var orig = minimatch
|
||||
|
||||
var m = function minimatch (p, pattern, options) {
|
||||
return orig.minimatch(p, pattern, ext(def, options))
|
||||
}
|
||||
|
||||
m.Minimatch = function Minimatch (pattern, options) {
|
||||
return new orig.Minimatch(pattern, ext(def, options))
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
Minimatch.defaults = function (def) {
|
||||
if (!def || !Object.keys(def).length) return Minimatch
|
||||
return minimatch.defaults(def).Minimatch
|
||||
}
|
||||
|
||||
function minimatch (p, pattern, options) {
|
||||
if (typeof pattern !== 'string') {
|
||||
throw new TypeError('glob pattern string required')
|
||||
}
|
||||
|
||||
if (!options) options = {}
|
||||
|
||||
// shortcut: comments match nothing.
|
||||
if (!options.nocomment && pattern.charAt(0) === '#') {
|
||||
return false
|
||||
}
|
||||
|
||||
// "" only matches ""
|
||||
if (pattern.trim() === '') return p === ''
|
||||
|
||||
return new Minimatch(pattern, options).match(p)
|
||||
}
|
||||
|
||||
function Minimatch (pattern, options) {
|
||||
if (!(this instanceof Minimatch)) {
|
||||
return new Minimatch(pattern, options)
|
||||
}
|
||||
|
||||
if (typeof pattern !== 'string') {
|
||||
throw new TypeError('glob pattern string required')
|
||||
}
|
||||
|
||||
if (!options) options = {}
|
||||
pattern = pattern.trim()
|
||||
|
||||
// windows support: need to use /, not \
|
||||
if (path.sep !== '/') {
|
||||
pattern = pattern.split(path.sep).join('/')
|
||||
}
|
||||
|
||||
this.options = options
|
||||
this.set = []
|
||||
this.pattern = pattern
|
||||
this.regexp = null
|
||||
this.negate = false
|
||||
this.comment = false
|
||||
this.empty = false
|
||||
|
||||
// make the set of regexps etc.
|
||||
this.make()
|
||||
}
|
||||
|
||||
Minimatch.prototype.debug = function () {}
|
||||
|
||||
Minimatch.prototype.make = make
|
||||
function make () {
|
||||
// don't do it more than once.
|
||||
if (this._made) return
|
||||
|
||||
var pattern = this.pattern
|
||||
var options = this.options
|
||||
|
||||
// empty patterns and comments match nothing.
|
||||
if (!options.nocomment && pattern.charAt(0) === '#') {
|
||||
this.comment = true
|
||||
return
|
||||
}
|
||||
if (!pattern) {
|
||||
this.empty = true
|
||||
return
|
||||
}
|
||||
|
||||
// step 1: figure out negation, etc.
|
||||
this.parseNegate()
|
||||
|
||||
// step 2: expand braces
|
||||
var set = this.globSet = this.braceExpand()
|
||||
|
||||
if (options.debug) this.debug = console.error
|
||||
|
||||
this.debug(this.pattern, set)
|
||||
|
||||
// step 3: now we have a set, so turn each one into a series of path-portion
|
||||
// matching patterns.
|
||||
// These will be regexps, except in the case of "**", which is
|
||||
// set to the GLOBSTAR object for globstar behavior,
|
||||
// and will not contain any / characters
|
||||
set = this.globParts = set.map(function (s) {
|
||||
return s.split(slashSplit)
|
||||
})
|
||||
|
||||
this.debug(this.pattern, set)
|
||||
|
||||
// glob --> regexps
|
||||
set = set.map(function (s, si, set) {
|
||||
return s.map(this.parse, this)
|
||||
}, this)
|
||||
|
||||
this.debug(this.pattern, set)
|
||||
|
||||
// filter out everything that didn't compile properly.
|
||||
set = set.filter(function (s) {
|
||||
return s.indexOf(false) === -1
|
||||
})
|
||||
|
||||
this.debug(this.pattern, set)
|
||||
|
||||
this.set = set
|
||||
}
|
||||
|
||||
Minimatch.prototype.parseNegate = parseNegate
|
||||
function parseNegate () {
|
||||
var pattern = this.pattern
|
||||
var negate = false
|
||||
var options = this.options
|
||||
var negateOffset = 0
|
||||
|
||||
if (options.nonegate) return
|
||||
|
||||
for (var i = 0, l = pattern.length
|
||||
; i < l && pattern.charAt(i) === '!'
|
||||
; i++) {
|
||||
negate = !negate
|
||||
negateOffset++
|
||||
}
|
||||
|
||||
if (negateOffset) this.pattern = pattern.substr(negateOffset)
|
||||
this.negate = negate
|
||||
}
|
||||
|
||||
// Brace expansion:
|
||||
// a{b,c}d -> abd acd
|
||||
// a{b,}c -> abc ac
|
||||
// a{0..3}d -> a0d a1d a2d a3d
|
||||
// a{b,c{d,e}f}g -> abg acdfg acefg
|
||||
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
|
||||
//
|
||||
// Invalid sets are not expanded.
|
||||
// a{2..}b -> a{2..}b
|
||||
// a{b}c -> a{b}c
|
||||
minimatch.braceExpand = function (pattern, options) {
|
||||
return braceExpand(pattern, options)
|
||||
}
|
||||
|
||||
Minimatch.prototype.braceExpand = braceExpand
|
||||
|
||||
function braceExpand (pattern, options) {
|
||||
if (!options) {
|
||||
if (this instanceof Minimatch) {
|
||||
options = this.options
|
||||
} else {
|
||||
options = {}
|
||||
}
|
||||
}
|
||||
|
||||
pattern = typeof pattern === 'undefined'
|
||||
? this.pattern : pattern
|
||||
|
||||
if (typeof pattern === 'undefined') {
|
||||
throw new TypeError('undefined pattern')
|
||||
}
|
||||
|
||||
if (options.nobrace ||
|
||||
!pattern.match(/\{.*\}/)) {
|
||||
// shortcut. no need to expand.
|
||||
return [pattern]
|
||||
}
|
||||
|
||||
return expand(pattern)
|
||||
}
|
||||
|
||||
// parse a component of the expanded set.
|
||||
// At this point, no pattern may contain "/" in it
|
||||
// so we're going to return a 2d array, where each entry is the full
|
||||
// pattern, split on '/', and then turned into a regular expression.
|
||||
// A regexp is made at the end which joins each array with an
|
||||
// escaped /, and another full one which joins each regexp with |.
|
||||
//
|
||||
// Following the lead of Bash 4.1, note that "**" only has special meaning
|
||||
// when it is the *only* thing in a path portion. Otherwise, any series
|
||||
// of * is equivalent to a single *. Globstar behavior is enabled by
|
||||
// default, and can be disabled by setting options.noglobstar.
|
||||
Minimatch.prototype.parse = parse
|
||||
var SUBPARSE = {}
|
||||
function parse (pattern, isSub) {
|
||||
if (pattern.length > 1024 * 64) {
|
||||
throw new TypeError('pattern is too long')
|
||||
}
|
||||
|
||||
var options = this.options
|
||||
|
||||
// shortcuts
|
||||
if (!options.noglobstar && pattern === '**') return GLOBSTAR
|
||||
if (pattern === '') return ''
|
||||
|
||||
var re = ''
|
||||
var hasMagic = !!options.nocase
|
||||
var escaping = false
|
||||
// ? => one single character
|
||||
var patternListStack = []
|
||||
var negativeLists = []
|
||||
var stateChar
|
||||
var inClass = false
|
||||
var reClassStart = -1
|
||||
var classStart = -1
|
||||
// . and .. never match anything that doesn't start with .,
|
||||
// even when options.dot is set.
|
||||
var patternStart = pattern.charAt(0) === '.' ? '' // anything
|
||||
// not (start or / followed by . or .. followed by / or end)
|
||||
: options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
|
||||
: '(?!\\.)'
|
||||
var self = this
|
||||
|
||||
function clearStateChar () {
|
||||
if (stateChar) {
|
||||
// we had some state-tracking character
|
||||
// that wasn't consumed by this pass.
|
||||
switch (stateChar) {
|
||||
case '*':
|
||||
re += star
|
||||
hasMagic = true
|
||||
break
|
||||
case '?':
|
||||
re += qmark
|
||||
hasMagic = true
|
||||
break
|
||||
default:
|
||||
re += '\\' + stateChar
|
||||
break
|
||||
}
|
||||
self.debug('clearStateChar %j %j', stateChar, re)
|
||||
stateChar = false
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0, len = pattern.length, c
|
||||
; (i < len) && (c = pattern.charAt(i))
|
||||
; i++) {
|
||||
this.debug('%s\t%s %s %j', pattern, i, re, c)
|
||||
|
||||
// skip over any that are escaped.
|
||||
if (escaping && reSpecials[c]) {
|
||||
re += '\\' + c
|
||||
escaping = false
|
||||
continue
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case '/':
|
||||
// completely not allowed, even escaped.
|
||||
// Should already be path-split by now.
|
||||
return false
|
||||
|
||||
case '\\':
|
||||
clearStateChar()
|
||||
escaping = true
|
||||
continue
|
||||
|
||||
// the various stateChar values
|
||||
// for the "extglob" stuff.
|
||||
case '?':
|
||||
case '*':
|
||||
case '+':
|
||||
case '@':
|
||||
case '!':
|
||||
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
|
||||
|
||||
// all of those are literals inside a class, except that
|
||||
// the glob [!a] means [^a] in regexp
|
||||
if (inClass) {
|
||||
this.debug(' in class')
|
||||
if (c === '!' && i === classStart + 1) c = '^'
|
||||
re += c
|
||||
continue
|
||||
}
|
||||
|
||||
// if we already have a stateChar, then it means
|
||||
// that there was something like ** or +? in there.
|
||||
// Handle the stateChar, then proceed with this one.
|
||||
self.debug('call clearStateChar %j', stateChar)
|
||||
clearStateChar()
|
||||
stateChar = c
|
||||
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
||||
// just clear the statechar *now*, rather than even diving into
|
||||
// the patternList stuff.
|
||||
if (options.noext) clearStateChar()
|
||||
continue
|
||||
|
||||
case '(':
|
||||
if (inClass) {
|
||||
re += '('
|
||||
continue
|
||||
}
|
||||
|
||||
if (!stateChar) {
|
||||
re += '\\('
|
||||
continue
|
||||
}
|
||||
|
||||
patternListStack.push({
|
||||
type: stateChar,
|
||||
start: i - 1,
|
||||
reStart: re.length,
|
||||
open: plTypes[stateChar].open,
|
||||
close: plTypes[stateChar].close
|
||||
})
|
||||
// negation is (?:(?!js)[^/]*)
|
||||
re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
|
||||
this.debug('plType %j %j', stateChar, re)
|
||||
stateChar = false
|
||||
continue
|
||||
|
||||
case ')':
|
||||
if (inClass || !patternListStack.length) {
|
||||
re += '\\)'
|
||||
continue
|
||||
}
|
||||
|
||||
clearStateChar()
|
||||
hasMagic = true
|
||||
var pl = patternListStack.pop()
|
||||
// negation is (?:(?!js)[^/]*)
|
||||
// The others are (?:<pattern>)<type>
|
||||
re += pl.close
|
||||
if (pl.type === '!') {
|
||||
negativeLists.push(pl)
|
||||
}
|
||||
pl.reEnd = re.length
|
||||
continue
|
||||
|
||||
case '|':
|
||||
if (inClass || !patternListStack.length || escaping) {
|
||||
re += '\\|'
|
||||
escaping = false
|
||||
continue
|
||||
}
|
||||
|
||||
clearStateChar()
|
||||
re += '|'
|
||||
continue
|
||||
|
||||
// these are mostly the same in regexp and glob
|
||||
case '[':
|
||||
// swallow any state-tracking char before the [
|
||||
clearStateChar()
|
||||
|
||||
if (inClass) {
|
||||
re += '\\' + c
|
||||
continue
|
||||
}
|
||||
|
||||
inClass = true
|
||||
classStart = i
|
||||
reClassStart = re.length
|
||||
re += c
|
||||
continue
|
||||
|
||||
case ']':
|
||||
// a right bracket shall lose its special
|
||||
// meaning and represent itself in
|
||||
// a bracket expression if it occurs
|
||||
// first in the list. -- POSIX.2 2.8.3.2
|
||||
if (i === classStart + 1 || !inClass) {
|
||||
re += '\\' + c
|
||||
escaping = false
|
||||
continue
|
||||
}
|
||||
|
||||
// handle the case where we left a class open.
|
||||
// "[z-a]" is valid, equivalent to "\[z-a\]"
|
||||
if (inClass) {
|
||||
// split where the last [ was, make sure we don't have
|
||||
// an invalid re. if so, re-walk the contents of the
|
||||
// would-be class to re-translate any characters that
|
||||
// were passed through as-is
|
||||
// TODO: It would probably be faster to determine this
|
||||
// without a try/catch and a new RegExp, but it's tricky
|
||||
// to do safely. For now, this is safe and works.
|
||||
var cs = pattern.substring(classStart + 1, i)
|
||||
try {
|
||||
RegExp('[' + cs + ']')
|
||||
} catch (er) {
|
||||
// not a valid class!
|
||||
var sp = this.parse(cs, SUBPARSE)
|
||||
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
|
||||
hasMagic = hasMagic || sp[1]
|
||||
inClass = false
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// finish up the class.
|
||||
hasMagic = true
|
||||
inClass = false
|
||||
re += c
|
||||
continue
|
||||
|
||||
default:
|
||||
// swallow any state char that wasn't consumed
|
||||
clearStateChar()
|
||||
|
||||
if (escaping) {
|
||||
// no need
|
||||
escaping = false
|
||||
} else if (reSpecials[c]
|
||||
&& !(c === '^' && inClass)) {
|
||||
re += '\\'
|
||||
}
|
||||
|
||||
re += c
|
||||
|
||||
} // switch
|
||||
} // for
|
||||
|
||||
// handle the case where we left a class open.
|
||||
// "[abc" is valid, equivalent to "\[abc"
|
||||
if (inClass) {
|
||||
// split where the last [ was, and escape it
|
||||
// this is a huge pita. We now have to re-walk
|
||||
// the contents of the would-be class to re-translate
|
||||
// any characters that were passed through as-is
|
||||
cs = pattern.substr(classStart + 1)
|
||||
sp = this.parse(cs, SUBPARSE)
|
||||
re = re.substr(0, reClassStart) + '\\[' + sp[0]
|
||||
hasMagic = hasMagic || sp[1]
|
||||
}
|
||||
|
||||
// handle the case where we had a +( thing at the *end*
|
||||
// of the pattern.
|
||||
// each pattern list stack adds 3 chars, and we need to go through
|
||||
// and escape any | chars that were passed through as-is for the regexp.
|
||||
// Go through and escape them, taking care not to double-escape any
|
||||
// | chars that were already escaped.
|
||||
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
|
||||
var tail = re.slice(pl.reStart + pl.open.length)
|
||||
this.debug('setting tail', re, pl)
|
||||
// maybe some even number of \, then maybe 1 \, followed by a |
|
||||
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
|
||||
if (!$2) {
|
||||
// the | isn't already escaped, so escape it.
|
||||
$2 = '\\'
|
||||
}
|
||||
|
||||
// need to escape all those slashes *again*, without escaping the
|
||||
// one that we need for escaping the | character. As it works out,
|
||||
// escaping an even number of slashes can be done by simply repeating
|
||||
// it exactly after itself. That's why this trick works.
|
||||
//
|
||||
// I am sorry that you have to see this.
|
||||
return $1 + $1 + $2 + '|'
|
||||
})
|
||||
|
||||
this.debug('tail=%j\n %s', tail, tail, pl, re)
|
||||
var t = pl.type === '*' ? star
|
||||
: pl.type === '?' ? qmark
|
||||
: '\\' + pl.type
|
||||
|
||||
hasMagic = true
|
||||
re = re.slice(0, pl.reStart) + t + '\\(' + tail
|
||||
}
|
||||
|
||||
// handle trailing things that only matter at the very end.
|
||||
clearStateChar()
|
||||
if (escaping) {
|
||||
// trailing \\
|
||||
re += '\\\\'
|
||||
}
|
||||
|
||||
// only need to apply the nodot start if the re starts with
|
||||
// something that could conceivably capture a dot
|
||||
var addPatternStart = false
|
||||
switch (re.charAt(0)) {
|
||||
case '.':
|
||||
case '[':
|
||||
case '(': addPatternStart = true
|
||||
}
|
||||
|
||||
// Hack to work around lack of negative lookbehind in JS
|
||||
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
|
||||
// like 'a.xyz.yz' doesn't match. So, the first negative
|
||||
// lookahead, has to look ALL the way ahead, to the end of
|
||||
// the pattern.
|
||||
for (var n = negativeLists.length - 1; n > -1; n--) {
|
||||
var nl = negativeLists[n]
|
||||
|
||||
var nlBefore = re.slice(0, nl.reStart)
|
||||
var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
|
||||
var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)
|
||||
var nlAfter = re.slice(nl.reEnd)
|
||||
|
||||
nlLast += nlAfter
|
||||
|
||||
// Handle nested stuff like *(*.js|!(*.json)), where open parens
|
||||
// mean that we should *not* include the ) in the bit that is considered
|
||||
// "after" the negated section.
|
||||
var openParensBefore = nlBefore.split('(').length - 1
|
||||
var cleanAfter = nlAfter
|
||||
for (i = 0; i < openParensBefore; i++) {
|
||||
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
|
||||
}
|
||||
nlAfter = cleanAfter
|
||||
|
||||
var dollar = ''
|
||||
if (nlAfter === '' && isSub !== SUBPARSE) {
|
||||
dollar = '$'
|
||||
}
|
||||
var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
|
||||
re = newRe
|
||||
}
|
||||
|
||||
// if the re is not "" at this point, then we need to make sure
|
||||
// it doesn't match against an empty path part.
|
||||
// Otherwise a/* will match a/, which it should not.
|
||||
if (re !== '' && hasMagic) {
|
||||
re = '(?=.)' + re
|
||||
}
|
||||
|
||||
if (addPatternStart) {
|
||||
re = patternStart + re
|
||||
}
|
||||
|
||||
// parsing just a piece of a larger pattern.
|
||||
if (isSub === SUBPARSE) {
|
||||
return [re, hasMagic]
|
||||
}
|
||||
|
||||
// skip the regexp for non-magical patterns
|
||||
// unescape anything in it, though, so that it'll be
|
||||
// an exact match against a file etc.
|
||||
if (!hasMagic) {
|
||||
return globUnescape(pattern)
|
||||
}
|
||||
|
||||
var flags = options.nocase ? 'i' : ''
|
||||
try {
|
||||
var regExp = new RegExp('^' + re + '$', flags)
|
||||
} catch (er) {
|
||||
// If it was an invalid regular expression, then it can't match
|
||||
// anything. This trick looks for a character after the end of
|
||||
// the string, which is of course impossible, except in multi-line
|
||||
// mode, but it's not a /m regex.
|
||||
return new RegExp('$.')
|
||||
}
|
||||
|
||||
regExp._glob = pattern
|
||||
regExp._src = re
|
||||
|
||||
return regExp
|
||||
}
|
||||
|
||||
minimatch.makeRe = function (pattern, options) {
|
||||
return new Minimatch(pattern, options || {}).makeRe()
|
||||
}
|
||||
|
||||
Minimatch.prototype.makeRe = makeRe
|
||||
function makeRe () {
|
||||
if (this.regexp || this.regexp === false) return this.regexp
|
||||
|
||||
// at this point, this.set is a 2d array of partial
|
||||
// pattern strings, or "**".
|
||||
//
|
||||
// It's better to use .match(). This function shouldn't
|
||||
// be used, really, but it's pretty convenient sometimes,
|
||||
// when you just want to work with a regex.
|
||||
var set = this.set
|
||||
|
||||
if (!set.length) {
|
||||
this.regexp = false
|
||||
return this.regexp
|
||||
}
|
||||
var options = this.options
|
||||
|
||||
var twoStar = options.noglobstar ? star
|
||||
: options.dot ? twoStarDot
|
||||
: twoStarNoDot
|
||||
var flags = options.nocase ? 'i' : ''
|
||||
|
||||
var re = set.map(function (pattern) {
|
||||
return pattern.map(function (p) {
|
||||
return (p === GLOBSTAR) ? twoStar
|
||||
: (typeof p === 'string') ? regExpEscape(p)
|
||||
: p._src
|
||||
}).join('\\\/')
|
||||
}).join('|')
|
||||
|
||||
// must match entire pattern
|
||||
// ending in a * or ** will make it less strict.
|
||||
re = '^(?:' + re + ')$'
|
||||
|
||||
// can match anything, as long as it's not this.
|
||||
if (this.negate) re = '^(?!' + re + ').*$'
|
||||
|
||||
try {
|
||||
this.regexp = new RegExp(re, flags)
|
||||
} catch (ex) {
|
||||
this.regexp = false
|
||||
}
|
||||
return this.regexp
|
||||
}
|
||||
|
||||
minimatch.match = function (list, pattern, options) {
|
||||
options = options || {}
|
||||
var mm = new Minimatch(pattern, options)
|
||||
list = list.filter(function (f) {
|
||||
return mm.match(f)
|
||||
})
|
||||
if (mm.options.nonull && !list.length) {
|
||||
list.push(pattern)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
Minimatch.prototype.match = match
|
||||
function match (f, partial) {
|
||||
this.debug('match', f, this.pattern)
|
||||
// short-circuit in the case of busted things.
|
||||
// comments, etc.
|
||||
if (this.comment) return false
|
||||
if (this.empty) return f === ''
|
||||
|
||||
if (f === '/' && partial) return true
|
||||
|
||||
var options = this.options
|
||||
|
||||
// windows: need to use /, not \
|
||||
if (path.sep !== '/') {
|
||||
f = f.split(path.sep).join('/')
|
||||
}
|
||||
|
||||
// treat the test path as a set of pathparts.
|
||||
f = f.split(slashSplit)
|
||||
this.debug(this.pattern, 'split', f)
|
||||
|
||||
// just ONE of the pattern sets in this.set needs to match
|
||||
// in order for it to be valid. If negating, then just one
|
||||
// match means that we have failed.
|
||||
// Either way, return on the first hit.
|
||||
|
||||
var set = this.set
|
||||
this.debug(this.pattern, 'set', set)
|
||||
|
||||
// Find the basename of the path by looking for the last non-empty segment
|
||||
var filename
|
||||
var i
|
||||
for (i = f.length - 1; i >= 0; i--) {
|
||||
filename = f[i]
|
||||
if (filename) break
|
||||
}
|
||||
|
||||
for (i = 0; i < set.length; i++) {
|
||||
var pattern = set[i]
|
||||
var file = f
|
||||
if (options.matchBase && pattern.length === 1) {
|
||||
file = [filename]
|
||||
}
|
||||
var hit = this.matchOne(file, pattern, partial)
|
||||
if (hit) {
|
||||
if (options.flipNegate) return true
|
||||
return !this.negate
|
||||
}
|
||||
}
|
||||
|
||||
// didn't get any hits. this is success if it's a negative
|
||||
// pattern, failure otherwise.
|
||||
if (options.flipNegate) return false
|
||||
return this.negate
|
||||
}
|
||||
|
||||
// set partial to true to test if, for example,
|
||||
// "/a/b" matches the start of "/*/b/*/d"
|
||||
// Partial means, if you run out of file before you run
|
||||
// out of pattern, then that's fine, as long as all
|
||||
// the parts match.
|
||||
Minimatch.prototype.matchOne = function (file, pattern, partial) {
|
||||
var options = this.options
|
||||
|
||||
this.debug('matchOne',
|
||||
{ 'this': this, file: file, pattern: pattern })
|
||||
|
||||
this.debug('matchOne', file.length, pattern.length)
|
||||
|
||||
for (var fi = 0,
|
||||
pi = 0,
|
||||
fl = file.length,
|
||||
pl = pattern.length
|
||||
; (fi < fl) && (pi < pl)
|
||||
; fi++, pi++) {
|
||||
this.debug('matchOne loop')
|
||||
var p = pattern[pi]
|
||||
var f = file[fi]
|
||||
|
||||
this.debug(pattern, p, f)
|
||||
|
||||
// should be impossible.
|
||||
// some invalid regexp stuff in the set.
|
||||
if (p === false) return false
|
||||
|
||||
if (p === GLOBSTAR) {
|
||||
this.debug('GLOBSTAR', [pattern, p, f])
|
||||
|
||||
// "**"
|
||||
// a/**/b/**/c would match the following:
|
||||
// a/b/x/y/z/c
|
||||
// a/x/y/z/b/c
|
||||
// a/b/x/b/x/c
|
||||
// a/b/c
|
||||
// To do this, take the rest of the pattern after
|
||||
// the **, and see if it would match the file remainder.
|
||||
// If so, return success.
|
||||
// If not, the ** "swallows" a segment, and try again.
|
||||
// This is recursively awful.
|
||||
//
|
||||
// a/**/b/**/c matching a/b/x/y/z/c
|
||||
// - a matches a
|
||||
// - doublestar
|
||||
// - matchOne(b/x/y/z/c, b/**/c)
|
||||
// - b matches b
|
||||
// - doublestar
|
||||
// - matchOne(x/y/z/c, c) -> no
|
||||
// - matchOne(y/z/c, c) -> no
|
||||
// - matchOne(z/c, c) -> no
|
||||
// - matchOne(c, c) yes, hit
|
||||
var fr = fi
|
||||
var pr = pi + 1
|
||||
if (pr === pl) {
|
||||
this.debug('** at the end')
|
||||
// a ** at the end will just swallow the rest.
|
||||
// We have found a match.
|
||||
// however, it will not swallow /.x, unless
|
||||
// options.dot is set.
|
||||
// . and .. are *never* matched by **, for explosively
|
||||
// exponential reasons.
|
||||
for (; fi < fl; fi++) {
|
||||
if (file[fi] === '.' || file[fi] === '..' ||
|
||||
(!options.dot && file[fi].charAt(0) === '.')) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ok, let's see if we can swallow whatever we can.
|
||||
while (fr < fl) {
|
||||
var swallowee = file[fr]
|
||||
|
||||
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
|
||||
|
||||
// XXX remove this slice. Just pass the start index.
|
||||
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
|
||||
this.debug('globstar found match!', fr, fl, swallowee)
|
||||
// found a match.
|
||||
return true
|
||||
} else {
|
||||
// can't swallow "." or ".." ever.
|
||||
// can only swallow ".foo" when explicitly asked.
|
||||
if (swallowee === '.' || swallowee === '..' ||
|
||||
(!options.dot && swallowee.charAt(0) === '.')) {
|
||||
this.debug('dot detected!', file, fr, pattern, pr)
|
||||
break
|
||||
}
|
||||
|
||||
// ** swallows a segment, and continue.
|
||||
this.debug('globstar swallow a segment, and continue')
|
||||
fr++
|
||||
}
|
||||
}
|
||||
|
||||
// no match was found.
|
||||
// However, in partial mode, we can't say this is necessarily over.
|
||||
// If there's more *pattern* left, then
|
||||
if (partial) {
|
||||
// ran out of file
|
||||
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
|
||||
if (fr === fl) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// something other than **
|
||||
// non-magic patterns just have to match exactly
|
||||
// patterns with magic have been turned into regexps.
|
||||
var hit
|
||||
if (typeof p === 'string') {
|
||||
if (options.nocase) {
|
||||
hit = f.toLowerCase() === p.toLowerCase()
|
||||
} else {
|
||||
hit = f === p
|
||||
}
|
||||
this.debug('string match', p, f, hit)
|
||||
} else {
|
||||
hit = f.match(p)
|
||||
this.debug('pattern match', p, f, hit)
|
||||
}
|
||||
|
||||
if (!hit) return false
|
||||
}
|
||||
|
||||
// Note: ending in / means that we'll get a final ""
|
||||
// at the end of the pattern. This can only match a
|
||||
// corresponding "" at the end of the file.
|
||||
// If the file ends in /, then it can only match a
|
||||
// a pattern that ends in /, unless the pattern just
|
||||
// doesn't have any more for it. But, a/b/ should *not*
|
||||
// match "a/b/*", even though "" matches against the
|
||||
// [^/]*? pattern, except in partial mode, where it might
|
||||
// simply not be reached yet.
|
||||
// However, a/b/ should still satisfy a/*
|
||||
|
||||
// now either we fell off the end of the pattern, or we're done.
|
||||
if (fi === fl && pi === pl) {
|
||||
// ran out of pattern and filename at the same time.
|
||||
// an exact hit!
|
||||
return true
|
||||
} else if (fi === fl) {
|
||||
// ran out of file, but still had pattern left.
|
||||
// this is ok if we're doing the match as part of
|
||||
// a glob fs traversal.
|
||||
return partial
|
||||
} else if (pi === pl) {
|
||||
// ran out of pattern, still have file left.
|
||||
// this is only acceptable if we're on the very last
|
||||
// empty segment of a file with a trailing slash.
|
||||
// a/* should match a/b/
|
||||
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
|
||||
return emptyFileEnd
|
||||
}
|
||||
|
||||
// should be unreachable.
|
||||
throw new Error('wtf?')
|
||||
}
|
||||
|
||||
// replace stuff like \* with *
|
||||
function globUnescape (s) {
|
||||
return s.replace(/\\(.)/g, '$1')
|
||||
}
|
||||
|
||||
function regExpEscape (s) {
|
||||
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
|
||||
}
|
||||
30
electron/node_modules/dir-compare/node_modules/minimatch/package.json
generated
vendored
Normal file
30
electron/node_modules/dir-compare/node_modules/minimatch/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
|
||||
"name": "minimatch",
|
||||
"description": "a glob matcher in javascript",
|
||||
"version": "3.0.4",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/isaacs/minimatch.git"
|
||||
},
|
||||
"main": "minimatch.js",
|
||||
"scripts": {
|
||||
"test": "tap test/*.js --cov",
|
||||
"preversion": "npm test",
|
||||
"postversion": "npm publish",
|
||||
"postpublish": "git push origin --all; git push origin --tags"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tap": "^10.3.2"
|
||||
},
|
||||
"license": "ISC",
|
||||
"files": [
|
||||
"minimatch.js"
|
||||
]
|
||||
}
|
||||
59
electron/node_modules/dir-compare/package.json
generated
vendored
Normal file
59
electron/node_modules/dir-compare/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"name": "dir-compare",
|
||||
"version": "2.4.0",
|
||||
"description": "Node JS directory compare",
|
||||
"main": "src/index.js",
|
||||
"types": "src/index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/gliviu/dir-compare"
|
||||
},
|
||||
"keywords": [
|
||||
"compare",
|
||||
"directory",
|
||||
"folder"
|
||||
],
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rm -rf build && rm -rf .nyc_output && rm -rf coverage",
|
||||
"copydeps": "copyfiles \"test/expected/**\" test/testdir.tar \"test/extended/res/**\" package.json build",
|
||||
"build": "tsc && npm run copydeps",
|
||||
"lint": "tslint -p tsconfig.json",
|
||||
"pretest": "npm install && npm run build",
|
||||
"test": "node build/test/runTests.js",
|
||||
"extest": "npm run pretest && ./test/extended/init.sh && test/extended/runall.sh",
|
||||
"coverage": "npx nyc --exclude \"build/test/**\" --reporter=lcov npm test && npx nyc report",
|
||||
"toc": "npx markdown-toc README.md; echo \n",
|
||||
"docs": "typedoc --includeVersion --includeDeclarations --excludeExternals --theme minimal --mode file --readme none --gitRevision master --toc compare,compareSync,fileCompareHandlers,Options,Result --out docs ./src/index.d.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"buffer-equal": "1.0.0",
|
||||
"colors": "1.0.3",
|
||||
"commander": "2.9.0",
|
||||
"minimatch": "3.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.11.7",
|
||||
"copyfiles": "^1.2.0",
|
||||
"memory-streams": "0.1.0",
|
||||
"semver": "5.6.0",
|
||||
"shelljs": "0.3.0",
|
||||
"tar-fs": "2.1.1",
|
||||
"temp": "0.9.0",
|
||||
"ts-node": "^8.5.4",
|
||||
"tslint": "^5.20.0",
|
||||
"tslint-config-prettier": "^1.13.0",
|
||||
"typedoc": "0.19.2",
|
||||
"typescript": "^3.7.4"
|
||||
},
|
||||
"bin": {
|
||||
"dircompare": "src/cli/dircompare.js"
|
||||
},
|
||||
"author": "Liviu Grigorescu",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/gliviu/dir-compare/issues"
|
||||
}
|
||||
}
|
||||
147
electron/node_modules/dir-compare/src/cli/dircompare.js
generated
vendored
Executable file
147
electron/node_modules/dir-compare/src/cli/dircompare.js
generated
vendored
Executable file
|
|
@ -0,0 +1,147 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var program = require('commander')
|
||||
var dircompare = require('../index')
|
||||
var fs = require('fs')
|
||||
var util = require('util')
|
||||
var print = require('./print')
|
||||
var pjson = require('../../package.json')
|
||||
|
||||
program
|
||||
.version(pjson.version)
|
||||
.usage('[options] leftdir rightdir')
|
||||
.option('-c, --compare-content', 'compare files by content')
|
||||
.option('-D, --compare-date', 'compare files by date')
|
||||
.option('--date-tolerance [type]', 'tolerance to be used in date comparison (milliseconds)')
|
||||
.option('--compare-symlink', 'compare files and directories by symlink')
|
||||
.option('-f, --filter [type]', 'file name filter', undefined)
|
||||
.option('-x, --exclude [type]', 'file/directory name exclude filter', undefined)
|
||||
.option('-S, --skip-subdirs', 'do not recurse into subdirectories')
|
||||
.option('-L, --skip-symlinks', 'ignore symlinks')
|
||||
.option('-i, --ignore-case', 'ignores case when comparing file names')
|
||||
.option('-l, --show-left', 'report - show entries occurring in left dir')
|
||||
.option('-r, --show-right', 'report - show entries occurring in right dir')
|
||||
.option('-e, --show-equal', 'report - show identic entries occurring in both dirs')
|
||||
.option('-d, --show-distinct', 'report - show distinct entries occurring in both dirs')
|
||||
.option('-a, --show-all', 'report - show all entries')
|
||||
.option('-w, --whole-report', 'report - include directories in detailed report')
|
||||
.option('--reason', 'report - show reason when entries are distinct')
|
||||
.option('--csv', 'report - print details as csv')
|
||||
.option('--nocolors', 'don\'t use console colors')
|
||||
.option('--async', 'Make use of multiple cores')
|
||||
|
||||
|
||||
program.on('--help', function () {
|
||||
console.log(' By default files are compared by size.')
|
||||
console.log(' --date-tolerance defaults to 1000 ms. Two files are considered to have')
|
||||
console.log(' the same date if the difference between their modification dates fits')
|
||||
console.log(' within date tolerance.')
|
||||
console.log()
|
||||
console.log(' Exit codes:')
|
||||
console.log(' 0 - entries are identical')
|
||||
console.log(' 1 - entries are different')
|
||||
console.log(' 2 - error occurred')
|
||||
console.log()
|
||||
console.log(' Examples:')
|
||||
console.log(' compare by content dircompare -c dir1 dir2')
|
||||
console.log(' show only different files dircompare -d dir1 dir2')
|
||||
console.log()
|
||||
console.log(' exclude filter dircompare -x ".git,node_modules" dir1 dir2')
|
||||
console.log(' dircompare -x "/tests/expected" dir1 dir2')
|
||||
console.log(' dircompare -x "**/expected" dir1 dir2')
|
||||
console.log(' dircompare -x "**/tests/**/*.ts" dir1 dir2')
|
||||
console.log()
|
||||
console.log(' include filter dircompare -f "*.js,*.yml" dir1 dir2')
|
||||
console.log(' dircompare -f "/tests/**/*.js" dir1 dir2')
|
||||
console.log(' dircompare -f "**/tests/**/*.ts" dir1 dir2')
|
||||
})
|
||||
|
||||
// Fix for https://github.com/tj/commander.js/issues/125
|
||||
program.allowUnknownOption()
|
||||
program.parse(process.argv)
|
||||
var parsed = program.parseOptions(program.normalize(process.argv.slice(2)))
|
||||
if (parsed.unknown.length > 0) {
|
||||
console.error('Unknown options: ' + parsed.unknown)
|
||||
process.exit(2)
|
||||
}
|
||||
|
||||
var run = function () {
|
||||
try {
|
||||
if (program.args.length !== 2) {
|
||||
program.outputHelp()
|
||||
process.exit(2)
|
||||
} else {
|
||||
var options = {}
|
||||
|
||||
|
||||
options.compareContent = program.compareContent
|
||||
options.compareDate = program.compareDate
|
||||
options.compareSymlink = program.compareSymlink
|
||||
options.compareSize = true
|
||||
options.skipSubdirs = program.skipSubdirs
|
||||
options.skipSymlinks = program.skipSymlinks
|
||||
options.ignoreCase = program.ignoreCase
|
||||
options.includeFilter = program.filter
|
||||
options.excludeFilter = program.exclude
|
||||
options.noDiffSet = !(program.showAll || program.showEqual || program.showLeft || program.showRight || program.showDistinct)
|
||||
options.dateTolerance = program.dateTolerance || 1000
|
||||
|
||||
var async = program.async
|
||||
|
||||
var path1 = program.args[0]
|
||||
var path2 = program.args[1]
|
||||
var abort = false
|
||||
if (!isNumeric(options.dateTolerance)) {
|
||||
console.error("Numeric value expected for --date-tolerance")
|
||||
abort = true
|
||||
}
|
||||
if (!fs.existsSync(path1)) {
|
||||
console.error(util.format("Path '%s' missing"), path1)
|
||||
abort = true
|
||||
}
|
||||
if (!fs.existsSync(path2)) {
|
||||
console.error(util.format("Path '%s' missing"), path2)
|
||||
abort = true
|
||||
}
|
||||
if (!abort) {
|
||||
// compare
|
||||
var comparePromise
|
||||
if (async) {
|
||||
comparePromise = dircompare.compare(path1, path2, options)
|
||||
} else {
|
||||
comparePromise = new Promise(function (resolve, reject) {
|
||||
resolve(dircompare.compareSync(path1, path2, options))
|
||||
})
|
||||
}
|
||||
|
||||
comparePromise.then(
|
||||
function (res) {
|
||||
// PRINT DETAILS
|
||||
print(res, process.stdout, program)
|
||||
if (res.same) {
|
||||
process.exit(0)
|
||||
} else {
|
||||
process.exit(1)
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
console.error('Error occurred: ' + (error instanceof Error ? error.stack : error))
|
||||
process.exit(2)
|
||||
})
|
||||
} else {
|
||||
process.exit(2)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e.stack)
|
||||
process.exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
function isNumeric(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n)
|
||||
}
|
||||
|
||||
|
||||
|
||||
run()
|
||||
192
electron/node_modules/dir-compare/src/cli/print.js
generated
vendored
Normal file
192
electron/node_modules/dir-compare/src/cli/print.js
generated
vendored
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
var colors = require('colors')
|
||||
var util = require('util')
|
||||
var pathUtils = require('path')
|
||||
|
||||
var PATH_SEP = pathUtils.sep
|
||||
|
||||
// Prints dir compare results.
|
||||
// 'program' represents display options and correspond to dircompare command line parameters.
|
||||
// Example: 'dircompare --show-all --exclude *.js dir1 dir2' translates into
|
||||
// program: {showAll: true, exclude: '*.js'}
|
||||
//
|
||||
var print = function (res, writer, program) {
|
||||
var noColor = function (str) { return str }
|
||||
var colorEqual = program.nocolors ? noColor : colors.green
|
||||
var colorDistinct = program.nocolors ? noColor : colors.red
|
||||
var colorLeft = noColor
|
||||
var colorRight = noColor
|
||||
var colorDir = noColor
|
||||
var colorBrokenLinks = noColor
|
||||
var colorMissing = program.nocolors ? noColor : colors.yellow
|
||||
|
||||
// calculate relative path length for pretty print
|
||||
var relativePathMaxLength = 0, fileNameMaxLength = 0
|
||||
if (!program.csv && res.diffSet) {
|
||||
res.diffSet.forEach(function (diff) {
|
||||
if (diff.relativePath.length > relativePathMaxLength) {
|
||||
relativePathMaxLength = diff.relativePath.length
|
||||
}
|
||||
var len = getCompareFile(diff, '??', colorMissing).length
|
||||
if (len > fileNameMaxLength) {
|
||||
fileNameMaxLength = len
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// csv header
|
||||
if (program.csv) {
|
||||
writer.write('path,name,state,type,size1,size2,date1,date2,reason\n')
|
||||
}
|
||||
if (res.diffSet) {
|
||||
for (var i = 0; i < res.diffSet.length; i++) {
|
||||
var detail = res.diffSet[i]
|
||||
var color, show = true
|
||||
|
||||
if (!program.wholeReport) {
|
||||
// show only files or broken links
|
||||
var type = detail.type1 !== 'missing' ? detail.type1 : detail.type2
|
||||
if (type !== 'file' && type !== 'broken-link') {
|
||||
show = false
|
||||
}
|
||||
}
|
||||
if (show) {
|
||||
switch (detail.state) {
|
||||
case 'equal':
|
||||
color = colorEqual
|
||||
show = program.showAll || program.showEqual ? true : false
|
||||
break
|
||||
case 'left':
|
||||
color = colorLeft
|
||||
show = program.showAll || program.showLeft ? true : false
|
||||
break
|
||||
case 'right':
|
||||
color = colorRight
|
||||
show = program.showAll || program.showRight ? true : false
|
||||
break
|
||||
case 'distinct':
|
||||
color = colorDistinct
|
||||
show = program.showAll || program.showDistinct ? true : false
|
||||
break
|
||||
default:
|
||||
show = true
|
||||
color = colors.gray
|
||||
}
|
||||
if (show) {
|
||||
if (program.csv) {
|
||||
printCsv(writer, detail, color)
|
||||
} else {
|
||||
printPretty(writer, program, detail, color, colorDir, colorMissing, relativePathMaxLength, fileNameMaxLength)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PRINT STATISTICS
|
||||
var statTotal, statEqual, statLeft, statRight, statDistinct
|
||||
if (program.wholeReport) {
|
||||
statTotal = res.total
|
||||
statEqual = res.equal
|
||||
statLeft = res.left
|
||||
statRight = res.right
|
||||
statDistinct = res.distinct
|
||||
} else {
|
||||
var brokenLInksStats = res.brokenLinks
|
||||
statTotal = res.totalFiles + brokenLInksStats.totalBrokenLinks
|
||||
statEqual = res.equalFiles
|
||||
statLeft = res.leftFiles + brokenLInksStats.leftBrokenLinks
|
||||
statRight = res.rightFiles + brokenLInksStats.rightBrokenLinks
|
||||
statDistinct = res.distinctFiles + brokenLInksStats.distinctBrokenLinks
|
||||
}
|
||||
if (!program.noDiffIndicator) {
|
||||
writer.write(res.same ? colorEqual('Entries are identical\n') : colorDistinct('Entries are different\n'))
|
||||
}
|
||||
var stats = util.format('total: %s, equal: %s, distinct: %s, only left: %s, only right: %s',
|
||||
statTotal,
|
||||
colorEqual(statEqual),
|
||||
colorDistinct(statDistinct),
|
||||
colorLeft(statLeft),
|
||||
colorRight(statRight)
|
||||
)
|
||||
if (res.brokenLinks.totalBrokenLinks > 0) {
|
||||
stats += util.format(', broken links: %s', colorBrokenLinks(res.brokenLinks.totalBrokenLinks))
|
||||
}
|
||||
stats += '\n'
|
||||
writer.write(stats)
|
||||
}
|
||||
|
||||
/**
|
||||
* Print details for default view mode
|
||||
*/
|
||||
var printPretty = function (writer, program, detail, color, dirColor, missingColor, relativePathMaxLength, fileNameMaxLength) {
|
||||
var path = detail.relativePath === '' ? PATH_SEP : detail.relativePath
|
||||
|
||||
var state
|
||||
switch (detail.state) {
|
||||
case 'equal':
|
||||
state = '=='
|
||||
break
|
||||
case 'left':
|
||||
state = '->'
|
||||
break
|
||||
case 'right':
|
||||
state = '<-'
|
||||
break
|
||||
case 'distinct':
|
||||
state = '<>'
|
||||
break
|
||||
default:
|
||||
state = '?'
|
||||
}
|
||||
var type = ''
|
||||
type = detail.type1 !== 'missing' ? detail.type1 : detail.type2
|
||||
if (type === 'directory') {
|
||||
type = dirColor(type)
|
||||
}
|
||||
var cmpEntry = getCompareFile(detail, color(state), missingColor)
|
||||
var reason = ''
|
||||
if (program.reason && detail.reason) {
|
||||
reason = util.format(' <%s>', detail.reason)
|
||||
}
|
||||
if (program.wholeReport || type === 'broken-link') {
|
||||
writer.write(util.format('[%s] %s (%s)%s\n', path, cmpEntry, type, reason))
|
||||
} else {
|
||||
writer.write(util.format('[%s] %s%s\n', path, cmpEntry, reason))
|
||||
}
|
||||
}
|
||||
|
||||
var getCompareFile = function (detail, state, missingcolor) {
|
||||
p1 = detail.name1 ? detail.name1 : ''
|
||||
p2 = detail.name2 ? detail.name2 : ''
|
||||
var missing1 = detail.type1 === 'missing' ? missingcolor('missing') : ''
|
||||
var missing2 = detail.type2 === 'missing' ? missingcolor('missing') : ''
|
||||
return util.format('%s%s %s %s%s', missing1, p1, state, missing2, p2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Print csv details.
|
||||
*/
|
||||
var printCsv = function (writer, detail, color) {
|
||||
var size1 = '', size2 = ''
|
||||
if (detail.type1 === 'file') {
|
||||
size1 = detail.size1 !== undefined ? detail.size1 : ''
|
||||
}
|
||||
if (detail.type2 === 'file') {
|
||||
size2 = detail.size2 !== undefined ? detail.size2 : ''
|
||||
}
|
||||
|
||||
var date1 = '', date2 = ''
|
||||
date1 = detail.date1 !== undefined ? detail.date1.toISOString() : ''
|
||||
date2 = detail.date2 !== undefined ? detail.date2.toISOString() : ''
|
||||
|
||||
var type = ''
|
||||
type = detail.type1 !== 'missing' ? detail.type1 : detail.type2
|
||||
|
||||
var path = detail.relativePath ? detail.relativePath : PATH_SEP
|
||||
var name = (detail.name1 ? detail.name1 : detail.name2)
|
||||
var reason = detail.reason || ''
|
||||
|
||||
writer.write(util.format('%s,%s,%s,%s,%s,%s,%s,%s,%s\n', path, name, color(detail.state), type, size1, size2, date1, date2, reason))
|
||||
}
|
||||
|
||||
module.exports = print
|
||||
141
electron/node_modules/dir-compare/src/compareAsync.js
generated
vendored
Normal file
141
electron/node_modules/dir-compare/src/compareAsync.js
generated
vendored
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
var fs = require('fs')
|
||||
var entryBuilder = require('./entry/entryBuilder')
|
||||
var entryEquality = require('./entry/entryEquality')
|
||||
var stats = require('./statistics/statisticsUpdate')
|
||||
var pathUtils = require('path')
|
||||
var fsPromise = require('./fs/fsPromise')
|
||||
var loopDetector = require('./symlink/loopDetector')
|
||||
var entryComparator = require('./entry/entryComparator')
|
||||
var entryType = require('./entry/entryType')
|
||||
|
||||
/**
|
||||
* Returns the sorted list of entries in a directory.
|
||||
*/
|
||||
var getEntries = function (rootEntry, relativePath, loopDetected, options) {
|
||||
if (!rootEntry || loopDetected) {
|
||||
return Promise.resolve([])
|
||||
}
|
||||
if (rootEntry.isDirectory) {
|
||||
return fsPromise.readdir(rootEntry.absolutePath)
|
||||
.then(function (entries) {
|
||||
return entryBuilder.buildDirEntries(rootEntry, entries, relativePath, options)
|
||||
})
|
||||
}
|
||||
return Promise.resolve([rootEntry])
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two directories asynchronously.
|
||||
*/
|
||||
var compare = function (rootEntry1, rootEntry2, level, relativePath, options, statistics, diffSet, symlinkCache) {
|
||||
var loopDetected1 = loopDetector.detectLoop(rootEntry1, symlinkCache.dir1)
|
||||
var loopDetected2 = loopDetector.detectLoop(rootEntry2, symlinkCache.dir2)
|
||||
loopDetector.updateSymlinkCache(symlinkCache, rootEntry1, rootEntry2, loopDetected1, loopDetected2)
|
||||
|
||||
return Promise.all([getEntries(rootEntry1, relativePath, loopDetected1, options), getEntries(rootEntry2, relativePath, loopDetected2, options)]).then(
|
||||
function (entriesResult) {
|
||||
var entries1 = entriesResult[0]
|
||||
var entries2 = entriesResult[1]
|
||||
var i1 = 0, i2 = 0
|
||||
var comparePromises = []
|
||||
var compareFilePromises = []
|
||||
var subDiffSet
|
||||
|
||||
while (i1 < entries1.length || i2 < entries2.length) {
|
||||
var entry1 = entries1[i1]
|
||||
var entry2 = entries2[i2]
|
||||
var type1, type2
|
||||
|
||||
// compare entry name (-1, 0, 1)
|
||||
var cmp
|
||||
if (i1 < entries1.length && i2 < entries2.length) {
|
||||
cmp = entryComparator.compareEntry(entry1, entry2, options)
|
||||
type1 = entryType.getType(entry1)
|
||||
type2 = entryType.getType(entry2)
|
||||
} else if (i1 < entries1.length) {
|
||||
type1 = entryType.getType(entry1)
|
||||
type2 = entryType.getType(undefined)
|
||||
cmp = -1
|
||||
} else {
|
||||
type1 = entryType.getType(undefined)
|
||||
type2 = entryType.getType(entry2)
|
||||
cmp = 1
|
||||
}
|
||||
|
||||
// process entry
|
||||
if (cmp === 0) {
|
||||
// Both left/right exist and have the same name and type
|
||||
var compareAsyncRes = entryEquality.isEntryEqualAsync(entry1, entry2, type1, diffSet, options)
|
||||
var samePromise = compareAsyncRes.samePromise
|
||||
var same = compareAsyncRes.same
|
||||
if (same !== undefined) {
|
||||
options.resultBuilder(entry1, entry2,
|
||||
same ? 'equal' : 'distinct',
|
||||
level, relativePath, options, statistics, diffSet,
|
||||
compareAsyncRes.reason)
|
||||
stats.updateStatisticsBoth(entry1, entry2, compareAsyncRes.same, compareAsyncRes.reason, type1, statistics, options)
|
||||
} else {
|
||||
compareFilePromises.push(samePromise)
|
||||
}
|
||||
|
||||
i1++
|
||||
i2++
|
||||
if (!options.skipSubdirs && type1 === 'directory') {
|
||||
if (!options.noDiffSet) {
|
||||
subDiffSet = []
|
||||
diffSet.push(subDiffSet)
|
||||
}
|
||||
comparePromises.push(compare(entry1, entry2, level + 1,
|
||||
pathUtils.join(relativePath, entry1.name),
|
||||
options, statistics, subDiffSet, loopDetector.cloneSymlinkCache(symlinkCache)))
|
||||
}
|
||||
} else if (cmp < 0) {
|
||||
// Right missing
|
||||
options.resultBuilder(entry1, undefined, 'left', level, relativePath, options, statistics, diffSet)
|
||||
stats.updateStatisticsLeft(entry1, type1, statistics, options)
|
||||
i1++
|
||||
if (type1 === 'directory' && !options.skipSubdirs) {
|
||||
if (!options.noDiffSet) {
|
||||
subDiffSet = []
|
||||
diffSet.push(subDiffSet)
|
||||
}
|
||||
comparePromises.push(compare(entry1, undefined,
|
||||
level + 1,
|
||||
pathUtils.join(relativePath, entry1.name), options, statistics, subDiffSet, loopDetector.cloneSymlinkCache(symlinkCache)))
|
||||
}
|
||||
} else {
|
||||
// Left missing
|
||||
options.resultBuilder(undefined, entry2, 'right', level, relativePath, options, statistics, diffSet)
|
||||
stats.updateStatisticsRight(entry2, type2, statistics, options)
|
||||
i2++
|
||||
if (type2 === 'directory' && !options.skipSubdirs) {
|
||||
if (!options.noDiffSet) {
|
||||
subDiffSet = []
|
||||
diffSet.push(subDiffSet)
|
||||
}
|
||||
comparePromises.push(compare(undefined, entry2,
|
||||
level + 1,
|
||||
pathUtils.join(relativePath, entry2.name), options, statistics, subDiffSet, loopDetector.cloneSymlinkCache(symlinkCache)))
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.all(comparePromises).then(function () {
|
||||
return Promise.all(compareFilePromises).then(function (sameResults) {
|
||||
for (var i = 0; i < sameResults.length; i++) {
|
||||
var sameResult = sameResults[i]
|
||||
if (sameResult.error) {
|
||||
return Promise.reject(sameResult.error)
|
||||
} else {
|
||||
options.resultBuilder(sameResult.entry1, sameResult.entry2,
|
||||
sameResult.same ? 'equal' : 'distinct',
|
||||
level, relativePath, options, statistics, sameResult.diffSet,
|
||||
sameResult.reason)
|
||||
stats.updateStatisticsBoth(sameResult.entries1, sameResult.entries2, sameResult.same, sameResult.reason, sameResult.type1, statistics, options)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = compare
|
||||
90
electron/node_modules/dir-compare/src/compareSync.js
generated
vendored
Normal file
90
electron/node_modules/dir-compare/src/compareSync.js
generated
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
var fs = require('fs')
|
||||
var pathUtils = require('path')
|
||||
var entryBuilder = require('./entry/entryBuilder')
|
||||
var entryEquality = require('./entry/entryEquality')
|
||||
var stats = require('./statistics/statisticsUpdate')
|
||||
var loopDetector = require('./symlink/loopDetector')
|
||||
var entryComparator = require('./entry/entryComparator')
|
||||
var entryType = require('./entry/entryType')
|
||||
|
||||
/**
|
||||
* Returns the sorted list of entries in a directory.
|
||||
*/
|
||||
var getEntries = function (rootEntry, relativePath, loopDetected, options) {
|
||||
if (!rootEntry || loopDetected) {
|
||||
return []
|
||||
}
|
||||
if (rootEntry.isDirectory) {
|
||||
var entries = fs.readdirSync(rootEntry.absolutePath)
|
||||
return entryBuilder.buildDirEntries(rootEntry, entries, relativePath, options)
|
||||
}
|
||||
return [rootEntry]
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two directories synchronously.
|
||||
*/
|
||||
var compare = function (rootEntry1, rootEntry2, level, relativePath, options, statistics, diffSet, symlinkCache) {
|
||||
var loopDetected1 = loopDetector.detectLoop(rootEntry1, symlinkCache.dir1)
|
||||
var loopDetected2 = loopDetector.detectLoop(rootEntry2, symlinkCache.dir2)
|
||||
loopDetector.updateSymlinkCache(symlinkCache, rootEntry1, rootEntry2, loopDetected1, loopDetected2)
|
||||
|
||||
var entries1 = getEntries(rootEntry1, relativePath, loopDetected1, options)
|
||||
var entries2 = getEntries(rootEntry2, relativePath, loopDetected2, options)
|
||||
var i1 = 0, i2 = 0
|
||||
while (i1 < entries1.length || i2 < entries2.length) {
|
||||
var entry1 = entries1[i1]
|
||||
var entry2 = entries2[i2]
|
||||
var type1, type2
|
||||
|
||||
// compare entry name (-1, 0, 1)
|
||||
var cmp
|
||||
if (i1 < entries1.length && i2 < entries2.length) {
|
||||
cmp = entryComparator.compareEntry(entry1, entry2, options)
|
||||
type1 = entryType.getType(entry1)
|
||||
type2 = entryType.getType(entry2)
|
||||
} else if (i1 < entries1.length) {
|
||||
type1 = entryType.getType(entry1)
|
||||
type2 = entryType.getType(undefined)
|
||||
cmp = -1
|
||||
} else {
|
||||
type1 = entryType.getType(undefined)
|
||||
type2 = entryType.getType(entry2)
|
||||
cmp = 1
|
||||
}
|
||||
|
||||
// process entry
|
||||
if (cmp === 0) {
|
||||
// Both left/right exist and have the same name and type
|
||||
var compareEntryRes = entryEquality.isEntryEqualSync(entry1, entry2, type1, options)
|
||||
options.resultBuilder(entry1, entry2,
|
||||
compareEntryRes.same ? 'equal' : 'distinct',
|
||||
level, relativePath, options, statistics, diffSet,
|
||||
compareEntryRes.reason)
|
||||
stats.updateStatisticsBoth(entry1, entry2, compareEntryRes.same, compareEntryRes.reason, type1, statistics, options)
|
||||
i1++
|
||||
i2++
|
||||
if (!options.skipSubdirs && type1 === 'directory') {
|
||||
compare(entry1, entry2, level + 1, pathUtils.join(relativePath, entry1.name), options, statistics, diffSet, loopDetector.cloneSymlinkCache(symlinkCache))
|
||||
}
|
||||
} else if (cmp < 0) {
|
||||
// Right missing
|
||||
options.resultBuilder(entry1, undefined, 'left', level, relativePath, options, statistics, diffSet)
|
||||
stats.updateStatisticsLeft(entry1, type1, statistics, options)
|
||||
i1++
|
||||
if (type1 === 'directory' && !options.skipSubdirs) {
|
||||
compare(entry1, undefined, level + 1, pathUtils.join(relativePath, entry1.name), options, statistics, diffSet, loopDetector.cloneSymlinkCache(symlinkCache))
|
||||
}
|
||||
} else {
|
||||
// Left missing
|
||||
options.resultBuilder(undefined, entry2, 'right', level, relativePath, options, statistics, diffSet)
|
||||
stats.updateStatisticsRight(entry2, type2, statistics, options)
|
||||
i2++
|
||||
if (type2 === 'directory' && !options.skipSubdirs) {
|
||||
compare(undefined, entry2, level + 1, pathUtils.join(relativePath, entry2.name), options, statistics, diffSet, loopDetector.cloneSymlinkCache(symlinkCache))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = compare
|
||||
102
electron/node_modules/dir-compare/src/entry/entryBuilder.js
generated
vendored
Normal file
102
electron/node_modules/dir-compare/src/entry/entryBuilder.js
generated
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
var fs = require('fs')
|
||||
var minimatch = require('minimatch')
|
||||
var pathUtils = require('path')
|
||||
var entryComparator = require('./entryComparator')
|
||||
|
||||
var PATH_SEP = pathUtils.sep
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Returns the sorted list of entries in a directory.
|
||||
*/
|
||||
buildDirEntries: function (rootEntry, dirEntries, relativePath, options) {
|
||||
var res = []
|
||||
for (var i = 0; i < dirEntries.length; i++) {
|
||||
var entryName = dirEntries[i]
|
||||
var entryAbsolutePath = rootEntry.absolutePath + PATH_SEP + entryName
|
||||
var entryPath = rootEntry.path + PATH_SEP + entryName
|
||||
|
||||
var entry = this.buildEntry(entryAbsolutePath, entryPath, entryName)
|
||||
if (options.skipSymlinks && entry.isSymlink) {
|
||||
entry.stat = undefined
|
||||
}
|
||||
|
||||
if (filterEntry(entry, relativePath, options)) {
|
||||
res.push(entry)
|
||||
}
|
||||
}
|
||||
return res.sort((a, b) => entryComparator.compareEntry(a, b, options))
|
||||
},
|
||||
|
||||
buildEntry: function (absolutePath, path, name) {
|
||||
var stats = getStatIgnoreBrokenLink(absolutePath)
|
||||
|
||||
return {
|
||||
name: name,
|
||||
absolutePath: absolutePath,
|
||||
path: path,
|
||||
stat: stats.stat,
|
||||
lstat: stats.lstat,
|
||||
isSymlink: stats.lstat.isSymbolicLink(),
|
||||
isBrokenLink: stats.isBrokenLink,
|
||||
isDirectory: stats.stat.isDirectory()
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getStatIgnoreBrokenLink(absolutePath) {
|
||||
var lstat = fs.lstatSync(absolutePath)
|
||||
try {
|
||||
return {
|
||||
stat: fs.statSync(absolutePath),
|
||||
lstat: lstat,
|
||||
isBrokenLink: false
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
return {
|
||||
stat: lstat,
|
||||
lstat: lstat,
|
||||
isBrokenLink: true
|
||||
}
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter entries by file name. Returns true if the file is to be processed.
|
||||
*/
|
||||
function filterEntry(entry, relativePath, options) {
|
||||
if (entry.isSymlink && options.skipSymlinks) {
|
||||
return false
|
||||
}
|
||||
var path = pathUtils.join(relativePath, entry.name)
|
||||
|
||||
if ((entry.stat.isFile() && options.includeFilter) && (!match(path, options.includeFilter))) {
|
||||
return false
|
||||
}
|
||||
|
||||
if ((options.excludeFilter) && (match(path, options.excludeFilter))) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches path by pattern.
|
||||
*/
|
||||
function match(path, pattern) {
|
||||
var patternArray = pattern.split(',')
|
||||
for (var i = 0; i < patternArray.length; i++) {
|
||||
var pat = patternArray[i]
|
||||
if (minimatch(path, pat, { dot: true, matchBase: true })) { //nocase
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
20
electron/node_modules/dir-compare/src/entry/entryComparator.js
generated
vendored
Normal file
20
electron/node_modules/dir-compare/src/entry/entryComparator.js
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Determines order criteria for sorting entries in a directory.
|
||||
*/
|
||||
module.exports = {
|
||||
compareEntry: function (a, b, options) {
|
||||
if (a.isBrokenLink && b.isBrokenLink) {
|
||||
return options.compareNameHandler(a.name, b.name, options)
|
||||
} else if (a.isBrokenLink) {
|
||||
return -1
|
||||
} else if (b.isBrokenLink) {
|
||||
return 1
|
||||
} else if (a.stat.isDirectory() && b.stat.isFile()) {
|
||||
return -1
|
||||
} else if (a.stat.isFile() && b.stat.isDirectory()) {
|
||||
return 1
|
||||
} else {
|
||||
return options.compareNameHandler(a.name, b.name, options)
|
||||
}
|
||||
}
|
||||
}
|
||||
135
electron/node_modules/dir-compare/src/entry/entryEquality.js
generated
vendored
Normal file
135
electron/node_modules/dir-compare/src/entry/entryEquality.js
generated
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
var fs = require('fs')
|
||||
/**
|
||||
* Compares two entries with identical name and type.
|
||||
*/
|
||||
module.exports = {
|
||||
isEntryEqualSync: function (entry1, entry2, type, options) {
|
||||
if (type === 'file') {
|
||||
return isFileEqualSync(entry1, entry2, options)
|
||||
}
|
||||
if (type === 'directory') {
|
||||
return isDirectoryEqual(entry1, entry2, options)
|
||||
}
|
||||
if (type === 'broken-link') {
|
||||
return isBrokenLinkEqual()
|
||||
}
|
||||
throw new Error('Unexpected type ' + type)
|
||||
},
|
||||
|
||||
isEntryEqualAsync: function (entry1, entry2, type, diffSet, options) {
|
||||
if (type === 'file') {
|
||||
return isFileEqualAsync(entry1, entry2, type, diffSet, options)
|
||||
}
|
||||
if (type === 'directory') {
|
||||
return isDirectoryEqual(entry1, entry2, options)
|
||||
}
|
||||
if (type === 'broken-link') {
|
||||
return isBrokenLinkEqual()
|
||||
}
|
||||
throw new Error('Unexpected type ' + type)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function isFileEqualSync(entry1, entry2, options) {
|
||||
var p1 = entry1 ? entry1.absolutePath : undefined
|
||||
var p2 = entry2 ? entry2.absolutePath : undefined
|
||||
if (options.compareSymlink && !isSymlinkEqual(entry1, entry2)) {
|
||||
return { same: false, reason: 'different-symlink' }
|
||||
}
|
||||
if (options.compareSize && entry1.stat.size !== entry2.stat.size) {
|
||||
return { same: false, reason: 'different-size' }
|
||||
}
|
||||
if (options.compareDate && !isDateEqual(entry1.stat.mtime, entry2.stat.mtime, options.dateTolerance)) {
|
||||
return { same: false, reason: 'different-date' }
|
||||
}
|
||||
if (options.compareContent && !options.compareFileSync(p1, entry1.stat, p2, entry2.stat, options)) {
|
||||
return { same: false, reason: 'different-content' }
|
||||
}
|
||||
return { same: true }
|
||||
}
|
||||
|
||||
function isFileEqualAsync(entry1, entry2, type, diffSet, options) {
|
||||
var p1 = entry1 ? entry1.absolutePath : undefined
|
||||
var p2 = entry2 ? entry2.absolutePath : undefined
|
||||
if (options.compareSymlink && !isSymlinkEqual(entry1, entry2)) {
|
||||
return { same: false, reason: 'different-symlink' }
|
||||
}
|
||||
if (options.compareSize && entry1.stat.size !== entry2.stat.size) {
|
||||
return { same: false, samePromise: undefined, reason: 'different-size' }
|
||||
}
|
||||
|
||||
if (options.compareDate && !isDateEqual(entry1.stat.mtime, entry2.stat.mtime, options.dateTolerance)) {
|
||||
return { same: false, samePromise: undefined, reason: 'different-date' }
|
||||
}
|
||||
|
||||
if (options.compareContent) {
|
||||
var samePromise = undefined
|
||||
var subDiffSet
|
||||
if (!options.noDiffSet) {
|
||||
subDiffSet = []
|
||||
diffSet.push(subDiffSet)
|
||||
}
|
||||
samePromise = options.compareFileAsync(p1, entry1.stat, p2, entry2.stat, options)
|
||||
.then(function (comparisonResult) {
|
||||
var same, error
|
||||
if (typeof (comparisonResult) === "boolean") {
|
||||
same = comparisonResult
|
||||
} else {
|
||||
error = comparisonResult
|
||||
}
|
||||
|
||||
return {
|
||||
entry1: entry1, entry2: entry2, same: same,
|
||||
error: error, type1: type, type2: type,
|
||||
diffSet: subDiffSet,
|
||||
reason: same ? undefined : 'different-content'
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
return {
|
||||
error: error
|
||||
}
|
||||
})
|
||||
|
||||
return { same: undefined, samePromise: samePromise }
|
||||
}
|
||||
|
||||
return { same: true, samePromise: undefined }
|
||||
}
|
||||
|
||||
function isDirectoryEqual(entry1, entry2, options) {
|
||||
if (options.compareSymlink && !isSymlinkEqual(entry1, entry2)) {
|
||||
return { same: false, reason: 'different-symlink' }
|
||||
}
|
||||
return { same: true }
|
||||
}
|
||||
|
||||
function isBrokenLinkEqual() {
|
||||
return { same: false, reason: 'broken-link' } // broken links are never considered equal
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two dates and returns true/false depending on tolerance (milliseconds).
|
||||
* Two dates are considered equal if the difference in milliseconds between them is less or equal than tolerance.
|
||||
*/
|
||||
function isDateEqual(date1, date2, tolerance) {
|
||||
return Math.abs(date1.getTime() - date2.getTime()) <= tolerance ? true : false
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two entries for symlink equality.
|
||||
*/
|
||||
function isSymlinkEqual(entry1, entry2) {
|
||||
if (!entry1.isSymlink && !entry2.isSymlink) {
|
||||
return true
|
||||
}
|
||||
if (entry1.isSymlink && entry2.isSymlink && hasIdenticalLink(entry1.absolutePath, entry2.absolutePath)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function hasIdenticalLink(path1, path2) {
|
||||
return fs.readlinkSync(path1) === fs.readlinkSync(path2)
|
||||
}
|
||||
18
electron/node_modules/dir-compare/src/entry/entryType.js
generated
vendored
Normal file
18
electron/node_modules/dir-compare/src/entry/entryType.js
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
module.exports = {
|
||||
/**
|
||||
* One of 'missing','file','directory','broken-link'
|
||||
*/
|
||||
getType: function (entry) {
|
||||
if (!entry) {
|
||||
return 'missing'
|
||||
}
|
||||
if (entry.isBrokenLink) {
|
||||
return 'broken-link'
|
||||
}
|
||||
if (entry.isDirectory) {
|
||||
return 'directory'
|
||||
}
|
||||
return 'file'
|
||||
}
|
||||
}
|
||||
28
electron/node_modules/dir-compare/src/fileCompareHandler/closeFile.js
generated
vendored
Normal file
28
electron/node_modules/dir-compare/src/fileCompareHandler/closeFile.js
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
var fs = require('fs')
|
||||
|
||||
var closeFilesSync = function (fd1, fd2) {
|
||||
if (fd1) {
|
||||
fs.closeSync(fd1)
|
||||
}
|
||||
if (fd2) {
|
||||
fs.closeSync(fd2)
|
||||
}
|
||||
}
|
||||
|
||||
var closeFilesAsync = function (fd1, fd2, fdQueue) {
|
||||
if (fd1 && fd2) {
|
||||
return fdQueue.promises.close(fd1).then(() => fdQueue.promises.close(fd2))
|
||||
}
|
||||
if (fd1) {
|
||||
return fdQueue.promises.close(fd1)
|
||||
}
|
||||
if (fd2) {
|
||||
return fdQueue.promises.close(fd2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
closeFilesSync: closeFilesSync,
|
||||
closeFilesAsync: closeFilesAsync
|
||||
}
|
||||
113
electron/node_modules/dir-compare/src/fileCompareHandler/defaultFileCompare.js
generated
vendored
Normal file
113
electron/node_modules/dir-compare/src/fileCompareHandler/defaultFileCompare.js
generated
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
var fs = require('fs')
|
||||
var bufferEqual = require('buffer-equal')
|
||||
var FileDescriptorQueue = require('../fs/FileDescriptorQueue')
|
||||
var closeFilesSync = require('./closeFile').closeFilesSync
|
||||
var closeFilesAsync = require('./closeFile').closeFilesAsync
|
||||
var fsPromise = require('../fs/fsPromise')
|
||||
var BufferPool = require('../fs/BufferPool')
|
||||
|
||||
var MAX_CONCURRENT_FILE_COMPARE = 8
|
||||
var BUF_SIZE = 100000
|
||||
var fdQueue = new FileDescriptorQueue(MAX_CONCURRENT_FILE_COMPARE * 2)
|
||||
var bufferPool = new BufferPool(BUF_SIZE, MAX_CONCURRENT_FILE_COMPARE); // fdQueue guarantees there will be no more than MAX_CONCURRENT_FILE_COMPARE async processes accessing the buffers concurrently
|
||||
|
||||
|
||||
/**
|
||||
* Compares two partial buffers.
|
||||
*/
|
||||
var compareBuffers = function (buf1, buf2, contentSize) {
|
||||
return bufferEqual(buf1.slice(0, contentSize), buf2.slice(0, contentSize))
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two files by content.
|
||||
*/
|
||||
var compareSync = function (path1, stat1, path2, stat2, options) {
|
||||
var fd1, fd2
|
||||
if (stat1.size !== stat2.size) {
|
||||
return false
|
||||
}
|
||||
var bufferPair = bufferPool.allocateBuffers()
|
||||
try {
|
||||
fd1 = fs.openSync(path1, 'r')
|
||||
fd2 = fs.openSync(path2, 'r')
|
||||
var buf1 = bufferPair.buf1
|
||||
var buf2 = bufferPair.buf2
|
||||
var progress = 0
|
||||
while (true) {
|
||||
var size1 = fs.readSync(fd1, buf1, 0, BUF_SIZE, null)
|
||||
var size2 = fs.readSync(fd2, buf2, 0, BUF_SIZE, null)
|
||||
if (size1 !== size2) {
|
||||
return false
|
||||
} else if (size1 === 0) {
|
||||
// End of file reached
|
||||
return true
|
||||
} else if (!compareBuffers(buf1, buf2, size1)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
closeFilesSync(fd1, fd2)
|
||||
bufferPool.freeBuffers(bufferPair)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two files by content
|
||||
*/
|
||||
var compareAsync = function (path1, stat1, path2, stat2, options) {
|
||||
var fd1, fd2
|
||||
var bufferPair
|
||||
if (stat1.size !== stat2.size) {
|
||||
return Promise.resolve(false)
|
||||
}
|
||||
return Promise.all([fdQueue.promises.open(path1, 'r'), fdQueue.promises.open(path2, 'r')])
|
||||
.then(function (fds) {
|
||||
bufferPair = bufferPool.allocateBuffers()
|
||||
fd1 = fds[0]
|
||||
fd2 = fds[1]
|
||||
var buf1 = bufferPair.buf1
|
||||
var buf2 = bufferPair.buf2
|
||||
var progress = 0
|
||||
var compareAsyncInternal = function () {
|
||||
return Promise.all([
|
||||
fsPromise.read(fd1, buf1, 0, BUF_SIZE, null),
|
||||
fsPromise.read(fd2, buf2, 0, BUF_SIZE, null)
|
||||
]).then(function (bufferSizes) {
|
||||
var size1 = bufferSizes[0]
|
||||
var size2 = bufferSizes[1]
|
||||
if (size1 !== size2) {
|
||||
return false
|
||||
} else if (size1 === 0) {
|
||||
// End of file reached
|
||||
return true
|
||||
} else if (!compareBuffers(buf1, buf2, size1)) {
|
||||
return false
|
||||
} else {
|
||||
return compareAsyncInternal()
|
||||
}
|
||||
})
|
||||
}
|
||||
return compareAsyncInternal()
|
||||
})
|
||||
.then(
|
||||
// 'finally' polyfill for node 8 and below
|
||||
function (res) {
|
||||
return finalizeAsync(fd1, fd2, bufferPair).then(() => res)
|
||||
},
|
||||
function (err) {
|
||||
return finalizeAsync(fd1, fd2, bufferPair).then(() => { throw err; })
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function finalizeAsync(fd1, fd2, bufferPair) {
|
||||
bufferPool.freeBuffers(bufferPair)
|
||||
return closeFilesAsync(fd1, fd2, fdQueue)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
compareSync: compareSync,
|
||||
compareAsync: compareAsync
|
||||
}
|
||||
196
electron/node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js
generated
vendored
Normal file
196
electron/node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js
generated
vendored
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/**
|
||||
* Compare files line by line with options to ignore
|
||||
* line endings and white space differencies.
|
||||
*/
|
||||
var fs = require('fs')
|
||||
var FileDescriptorQueue = require('../fs/FileDescriptorQueue')
|
||||
var closeFilesSync = require('./closeFile').closeFilesSync
|
||||
var closeFilesAsync = require('./closeFile').closeFilesAsync
|
||||
var fsPromise = require('../fs/fsPromise')
|
||||
var BufferPool = require('../fs/BufferPool')
|
||||
|
||||
const LINE_TOKENIZER_REGEXP = /[^\n]+\n?|\n/g
|
||||
const TRIM_LINE_ENDING_REGEXP = /\r\n$/g
|
||||
const SPLIT_CONTENT_AND_LINE_ENDING_REGEXP = /([^\r\n]*)([\r\n]*)/
|
||||
const TRIM_WHITE_SPACES_REGEXP = /^[ \f\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+|[ \f\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+$/g
|
||||
|
||||
var MAX_CONCURRENT_FILE_COMPARE = 8
|
||||
var BUF_SIZE = 100000
|
||||
var fdQueue = new FileDescriptorQueue(MAX_CONCURRENT_FILE_COMPARE * 2)
|
||||
var bufferPool = new BufferPool(BUF_SIZE, MAX_CONCURRENT_FILE_COMPARE); // fdQueue guarantees there will be no more than MAX_CONCURRENT_FILE_COMPARE async processes accessing the buffers concurrently
|
||||
|
||||
function compareSync(path1, stat1, path2, stat2, options) {
|
||||
var fd1, fd2
|
||||
var bufferPair = bufferPool.allocateBuffers()
|
||||
var bufferSize = options.lineBasedHandlerBufferSize || BUF_SIZE
|
||||
try {
|
||||
fd1 = fs.openSync(path1, 'r')
|
||||
fd2 = fs.openSync(path2, 'r')
|
||||
var buf1 = bufferPair.buf1
|
||||
var buf2 = bufferPair.buf2
|
||||
var nextPosition1 = 0, nextPosition2 = 0
|
||||
while (true) {
|
||||
var lines1 = readLinesSync(fd1, buf1, bufferSize, nextPosition1)
|
||||
var lines2 = readLinesSync(fd2, buf2, bufferSize, nextPosition2)
|
||||
if (lines1.length === 0 && lines2.length === 0) {
|
||||
// End of file reached
|
||||
return true
|
||||
}
|
||||
var equalLines = compareLines(lines1, lines2, options)
|
||||
if (equalLines === 0) {
|
||||
return false
|
||||
}
|
||||
nextPosition1 += calculateSize(lines1, equalLines)
|
||||
nextPosition2 += calculateSize(lines2, equalLines)
|
||||
}
|
||||
} finally {
|
||||
closeFilesSync(fd1, fd2)
|
||||
bufferPool.freeBuffers(bufferPair)
|
||||
}
|
||||
}
|
||||
|
||||
async function compareAsync(path1, stat1, path2, stat2, options) {
|
||||
var fd1, fd2
|
||||
var bufferSize = options.lineBasedHandlerBufferSize || BUF_SIZE
|
||||
var bufferPair
|
||||
try {
|
||||
var fds = await Promise.all([fdQueue.promises.open(path1, 'r'), fdQueue.promises.open(path2, 'r')])
|
||||
bufferPair = bufferPool.allocateBuffers()
|
||||
fd1 = fds[0]
|
||||
fd2 = fds[1]
|
||||
var buf1 = bufferPair.buf1
|
||||
var buf2 = bufferPair.buf2
|
||||
var nextPosition1 = 0, nextPosition2 = 0
|
||||
while (true) {
|
||||
var lines1 = await readLinesAsync(fd1, buf1, bufferSize, nextPosition1)
|
||||
var lines2 = await readLinesAsync(fd2, buf2, bufferSize, nextPosition2)
|
||||
if (lines1.length === 0 && lines2.length === 0) {
|
||||
// End of file reached
|
||||
return true
|
||||
}
|
||||
var equalLines = compareLines(lines1, lines2, options)
|
||||
if (equalLines === 0) {
|
||||
return false
|
||||
}
|
||||
nextPosition1 += calculateSize(lines1, equalLines)
|
||||
nextPosition2 += calculateSize(lines2, equalLines)
|
||||
}
|
||||
} finally {
|
||||
bufferPool.freeBuffers(bufferPair)
|
||||
await closeFilesAsync(fd1, fd2, fdQueue)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read lines from file starting with nextPosition.
|
||||
* Returns 0 lines if eof is reached, otherwise returns at least one complete line.
|
||||
*/
|
||||
function readLinesSync(fd, buf, bufferSize, nextPosition) {
|
||||
var lines = []
|
||||
var chunk = ""
|
||||
while (true) {
|
||||
var size = fs.readSync(fd, buf, 0, bufferSize, nextPosition)
|
||||
if (size === 0) {
|
||||
// end of file
|
||||
normalizeLastFileLine(lines)
|
||||
return lines
|
||||
}
|
||||
chunk += buf.toString('utf8', 0, size)
|
||||
lines = chunk.match(LINE_TOKENIZER_REGEXP)
|
||||
if (lines.length > 1) {
|
||||
return removeLastIncompleteLine(lines)
|
||||
}
|
||||
nextPosition += size
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read lines from file starting with nextPosition.
|
||||
* Returns 0 lines if eof is reached, otherwise returns at least one complete line.
|
||||
*/
|
||||
async function readLinesAsync(fd, buf, bufferSize, nextPosition) {
|
||||
var lines = []
|
||||
var chunk = ""
|
||||
while (true) {
|
||||
var size = await fsPromise.read(fd, buf, 0, bufferSize, nextPosition)
|
||||
if (size === 0) {
|
||||
// end of file
|
||||
normalizeLastFileLine(lines)
|
||||
return lines
|
||||
}
|
||||
chunk += buf.toString('utf8', 0, size)
|
||||
lines = chunk.match(LINE_TOKENIZER_REGEXP)
|
||||
if (lines.length > 1) {
|
||||
return removeLastIncompleteLine(lines)
|
||||
}
|
||||
nextPosition += size
|
||||
}
|
||||
}
|
||||
|
||||
function removeLastIncompleteLine(lines) {
|
||||
const lastLine = lines[lines.length - 1]
|
||||
if (!lastLine.endsWith('\n')) {
|
||||
return lines.slice(0, lines.length - 1)
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
function normalizeLastFileLine(lines) {
|
||||
if (lines.length === 0) {
|
||||
return
|
||||
}
|
||||
const lastLine = lines[lines.length - 1]
|
||||
if (!lastLine.endsWith('\n')) {
|
||||
lines[lines.length - 1] = lastLine + '\n'
|
||||
}
|
||||
}
|
||||
|
||||
function calculateSize(lines, numberOfLines) {
|
||||
var size = 0
|
||||
for (var i = 0; i < numberOfLines; i++) {
|
||||
var line = lines[i]
|
||||
size += line.length
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
function compareLines(lines1, lines2, options) {
|
||||
var equalLines = 0
|
||||
var len = lines1.length < lines2.length ? lines1.length : lines2.length
|
||||
for (var i = 0; i < len; i++) {
|
||||
var line1 = lines1[i]
|
||||
var line2 = lines2[i]
|
||||
if (options.ignoreLineEnding) {
|
||||
line1 = trimLineEnding(line1)
|
||||
line2 = trimLineEnding(line2)
|
||||
}
|
||||
if (options.ignoreWhiteSpaces) {
|
||||
line1 = trimSpaces(line1)
|
||||
line2 = trimSpaces(line2)
|
||||
}
|
||||
if (line1 !== line2) {
|
||||
return equalLines
|
||||
}
|
||||
equalLines++
|
||||
}
|
||||
return equalLines
|
||||
}
|
||||
|
||||
// Trims string like ' abc \n' into 'abc\n'
|
||||
function trimSpaces(s) {
|
||||
var matchResult = s.match(SPLIT_CONTENT_AND_LINE_ENDING_REGEXP);
|
||||
var content = matchResult[1]
|
||||
var lineEnding = matchResult[2]
|
||||
var trimmed = content.replace(TRIM_WHITE_SPACES_REGEXP, '')
|
||||
return trimmed + lineEnding
|
||||
}
|
||||
|
||||
// Trims string like 'abc\r\n' into 'abc\n'
|
||||
function trimLineEnding(s) {
|
||||
return s.replace(TRIM_LINE_ENDING_REGEXP, '\n')
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
compareSync: compareSync,
|
||||
compareAsync: compareAsync
|
||||
}
|
||||
46
electron/node_modules/dir-compare/src/fs/BufferPool.js
generated
vendored
Normal file
46
electron/node_modules/dir-compare/src/fs/BufferPool.js
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* Collection of buffers to be shared between async processes.
|
||||
* Avoids allocating buffers each time async process starts.
|
||||
* bufSize - size of each buffer
|
||||
* bufNo - number of buffers
|
||||
* Caller has to make sure no more than bufNo async processes run simultaneously.
|
||||
*/
|
||||
function BufferPool(bufSize, bufNo) {
|
||||
var bufferPool = []
|
||||
for (var i = 0; i < bufNo; i++) {
|
||||
bufferPool.push({
|
||||
buf1: alloc(bufSize),
|
||||
buf2: alloc(bufSize),
|
||||
busy: false
|
||||
})
|
||||
}
|
||||
|
||||
var allocateBuffers = function () {
|
||||
for (var j = 0; j < bufNo; j++) {
|
||||
var bufferPair = bufferPool[j]
|
||||
if (!bufferPair.busy) {
|
||||
bufferPair.busy = true
|
||||
return bufferPair
|
||||
}
|
||||
}
|
||||
throw new Error('Async buffer limit reached')
|
||||
}
|
||||
|
||||
return {
|
||||
allocateBuffers: allocateBuffers,
|
||||
freeBuffers: freeBuffers
|
||||
}
|
||||
|
||||
function freeBuffers(bufferPair) {
|
||||
bufferPair.busy = false
|
||||
}
|
||||
}
|
||||
|
||||
function alloc(bufSize) {
|
||||
if (Buffer.alloc) {
|
||||
return Buffer.alloc(bufSize)
|
||||
}
|
||||
return new Buffer(bufSize)
|
||||
}
|
||||
|
||||
module.exports = BufferPool
|
||||
78
electron/node_modules/dir-compare/src/fs/FileDescriptorQueue.js
generated
vendored
Normal file
78
electron/node_modules/dir-compare/src/fs/FileDescriptorQueue.js
generated
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
'use strict'
|
||||
|
||||
var fs = require('fs')
|
||||
var Queue = require('./Queue')
|
||||
/**
|
||||
* Limits the number of concurrent file handlers.
|
||||
* Use it as a wrapper over fs.open() and fs.close().
|
||||
* Example:
|
||||
* var fdQueue = new FileDescriptorQueue(8)
|
||||
* fdQueue.open(path, flags, (err, fd) =>{
|
||||
* ...
|
||||
* fdQueue.close(fd, (err) =>{
|
||||
* ...
|
||||
* })
|
||||
* })
|
||||
* As of node v7, calling fd.close without a callback is deprecated.
|
||||
*/
|
||||
var FileDescriptorQueue = function (maxFilesNo) {
|
||||
var pendingJobs = new Queue()
|
||||
var activeCount = 0
|
||||
|
||||
var open = function (path, flags, callback) {
|
||||
pendingJobs.enqueue({
|
||||
path: path,
|
||||
flags: flags,
|
||||
callback: callback
|
||||
})
|
||||
process()
|
||||
}
|
||||
|
||||
var process = function () {
|
||||
if (pendingJobs.getLength() > 0 && activeCount < maxFilesNo) {
|
||||
var job = pendingJobs.dequeue()
|
||||
activeCount++
|
||||
fs.open(job.path, job.flags, job.callback)
|
||||
}
|
||||
}
|
||||
|
||||
var close = function (fd, callback) {
|
||||
activeCount--
|
||||
fs.close(fd, callback)
|
||||
process()
|
||||
}
|
||||
|
||||
var promises = {
|
||||
open: function (path, flags) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
open(path, flags, function (err, fd) {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(fd)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
close: function (fd) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
close(fd, function (err) {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
open: open,
|
||||
close: close,
|
||||
promises: promises
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FileDescriptorQueue
|
||||
63
electron/node_modules/dir-compare/src/fs/Queue.js
generated
vendored
Normal file
63
electron/node_modules/dir-compare/src/fs/Queue.js
generated
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
|
||||
Queue.js
|
||||
|
||||
A function to represent a queue
|
||||
|
||||
Created by Kate Morley - http://code.iamkate.com/ - and released under the terms
|
||||
of the CC0 1.0 Universal legal code:
|
||||
|
||||
http://creativecommons.org/publicdomain/zero/1.0/legalcode
|
||||
|
||||
*/
|
||||
|
||||
var MAX_UNUSED_ARRAY_SIZE = 10000
|
||||
|
||||
/* Creates a new queue. A queue is a first-in-first-out (FIFO) data structure -
|
||||
* items are added to the end of the queue and removed from the front.
|
||||
*/
|
||||
function Queue() {
|
||||
|
||||
// initialise the queue and offset
|
||||
var queue = []
|
||||
var offset = 0
|
||||
|
||||
// Returns the length of the queue.
|
||||
this.getLength = function () {
|
||||
return (queue.length - offset)
|
||||
}
|
||||
|
||||
/* Enqueues the specified item. The parameter is:
|
||||
*
|
||||
* item - the item to enqueue
|
||||
*/
|
||||
this.enqueue = function (item) {
|
||||
queue.push(item)
|
||||
}
|
||||
|
||||
/* Dequeues an item and returns it. If the queue is empty, the value
|
||||
* 'undefined' is returned.
|
||||
*/
|
||||
this.dequeue = function () {
|
||||
|
||||
// if the queue is empty, return immediately
|
||||
if (queue.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
// store the item at the front of the queue
|
||||
var item = queue[offset]
|
||||
|
||||
// increment the offset and remove the free space if necessary
|
||||
if (++offset > MAX_UNUSED_ARRAY_SIZE) {
|
||||
queue = queue.slice(offset)
|
||||
offset = 0
|
||||
}
|
||||
|
||||
// return the dequeued item
|
||||
return item
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Queue
|
||||
26
electron/node_modules/dir-compare/src/fs/fsPromise.js
generated
vendored
Normal file
26
electron/node_modules/dir-compare/src/fs/fsPromise.js
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
var fs = require('fs')
|
||||
|
||||
module.exports = {
|
||||
readdir: function (path) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.readdir(path, function (err, files) {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(files)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
read: function (fd, buffer, offset, length, position) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.read(fd, buffer, offset, length, position, function(err, bytesRead) {
|
||||
if(err){
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(bytesRead)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
476
electron/node_modules/dir-compare/src/index.d.ts
generated
vendored
Normal file
476
electron/node_modules/dir-compare/src/index.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,476 @@
|
|||
/// <reference types="node" />
|
||||
|
||||
import * as fs from "fs"
|
||||
|
||||
/**
|
||||
* Synchronously compares given paths.
|
||||
* @param path1 Left file or directory to be compared.
|
||||
* @param path2 Right file or directory to be compared.
|
||||
* @param options Comparison options.
|
||||
*/
|
||||
export function compareSync(path1: string, path2: string, options?: Options): Result
|
||||
|
||||
/**
|
||||
* Asynchronously compares given paths.
|
||||
* @param path1 Left file or directory to be compared.
|
||||
* @param path2 Right file or directory to be compared.
|
||||
* @param options Comparison options.
|
||||
*/
|
||||
export function compare(path1: string, path2: string, options?: Options): Promise<Result>
|
||||
|
||||
/**
|
||||
* Comparison options.
|
||||
*/
|
||||
export interface Options {
|
||||
/**
|
||||
* Properties to be used in various extension points ie. result builder.
|
||||
*/
|
||||
[key: string]: any
|
||||
|
||||
/**
|
||||
* Compares files by size. Defaults to 'false'.
|
||||
*/
|
||||
compareSize?: boolean
|
||||
|
||||
/**
|
||||
* Compares files by date of modification (stat.mtime). Defaults to 'false'.
|
||||
*/
|
||||
compareDate?: boolean
|
||||
|
||||
/**
|
||||
* Two files are considered to have the same date if the difference between their modification dates fits within date tolerance. Defaults to 1000 ms.
|
||||
*/
|
||||
dateTolerance?: number
|
||||
|
||||
/**
|
||||
* Compares files by content. Defaults to 'false'.
|
||||
*/
|
||||
compareContent?: boolean
|
||||
|
||||
/**
|
||||
* Compares entries by symlink. Defaults to 'false'.
|
||||
*/
|
||||
compareSymlink?: boolean
|
||||
|
||||
/**
|
||||
* Skips sub directories. Defaults to 'false'.
|
||||
*/
|
||||
skipSubdirs?: boolean
|
||||
|
||||
/**
|
||||
* Ignore symbolic links. Defaults to 'false'.
|
||||
*/
|
||||
skipSymlinks?: boolean
|
||||
|
||||
/**
|
||||
* Ignores case when comparing names. Defaults to 'false'.
|
||||
*/
|
||||
ignoreCase?: boolean
|
||||
|
||||
/**
|
||||
* Toggles presence of diffSet in output. If true, only statistics are provided. Use this when comparing large number of files to avoid out of memory situations. Defaults to 'false'.
|
||||
*/
|
||||
noDiffSet?: boolean
|
||||
|
||||
/**
|
||||
* File name filter. Comma separated minimatch patterns. See [Glob patterns](https://github.com/gliviu/dir-compare#glob-patterns).
|
||||
*/
|
||||
includeFilter?: string
|
||||
|
||||
/**
|
||||
* File/directory name exclude filter. Comma separated minimatch patterns. See [Glob patterns](https://github.com/gliviu/dir-compare#glob-patterns)
|
||||
*/
|
||||
excludeFilter?: string
|
||||
|
||||
/**
|
||||
* Callback for constructing result. Called for each compared entry pair.
|
||||
*
|
||||
* Updates 'statistics' and 'diffSet'.
|
||||
*
|
||||
* See [Custom result builder](https://github.com/gliviu/dir-compare#custom-result-builder).
|
||||
*/
|
||||
resultBuilder?: ResultBuilder
|
||||
|
||||
/**
|
||||
* File comparison handler. See [Custom file comparators](https://github.com/gliviu/dir-compare#custom-file-content-comparators).
|
||||
*/
|
||||
compareFileSync?: CompareFileSync
|
||||
|
||||
/**
|
||||
* File comparison handler. See [Custom file comparators](https://github.com/gliviu/dir-compare#custom-file-content-comparators).
|
||||
*/
|
||||
compareFileAsync?: CompareFileAsync
|
||||
|
||||
/**
|
||||
* Entry name comparison handler. See [Custom name comparators](https://github.com/gliviu/dir-compare#custom-name-comparators).
|
||||
*/
|
||||
compareNameHandler?: CompareNameHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for constructing result. Called for each compared entry pair.
|
||||
*
|
||||
* Updates 'statistics' and 'diffSet'.
|
||||
*/
|
||||
export type ResultBuilder =
|
||||
/**
|
||||
* @param entry1 Left entry.
|
||||
* @param entry2 Right entry.
|
||||
* @param state See [[DifferenceState]].
|
||||
* @param level Depth level relative to root dir.
|
||||
* @param relativePath Path relative to root dir.
|
||||
* @param statistics Statistics to be updated.
|
||||
* @param diffSet Status per each entry to be appended.
|
||||
* Do not append if [[Options.noDiffSet]] is false.
|
||||
* @param reason See [[Reason]]. Not available if entries are equal.
|
||||
*/
|
||||
(
|
||||
entry1: Entry | undefined,
|
||||
entry2: Entry | undefined,
|
||||
state: DifferenceState,
|
||||
level: number,
|
||||
relativePath: string,
|
||||
options: Options,
|
||||
statistics: Statistics,
|
||||
diffSet: Array<Difference> | undefined,
|
||||
reason: Reason | undefined
|
||||
) => void
|
||||
|
||||
export interface Entry {
|
||||
name: string
|
||||
absolutePath: string
|
||||
path: string
|
||||
stat: fs.Stats
|
||||
lstat: fs.Stats
|
||||
symlink: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparison result.
|
||||
*/
|
||||
export interface Result extends Statistics {
|
||||
/**
|
||||
* List of changes (present if [[Options.noDiffSet]] is false).
|
||||
*/
|
||||
diffSet?: Array<Difference>
|
||||
}
|
||||
|
||||
export interface Statistics {
|
||||
/**
|
||||
* Any property is allowed if default result builder is not used.
|
||||
*/
|
||||
[key: string]: any
|
||||
|
||||
/**
|
||||
* True if directories are identical.
|
||||
*/
|
||||
same: boolean
|
||||
|
||||
/**
|
||||
* Number of distinct entries.
|
||||
*/
|
||||
distinct: number
|
||||
|
||||
/**
|
||||
* Number of equal entries.
|
||||
*/
|
||||
equal: number
|
||||
|
||||
/**
|
||||
* Number of entries only in path1.
|
||||
*/
|
||||
left: number
|
||||
|
||||
/**
|
||||
* Number of entries only in path2.
|
||||
*/
|
||||
right: number
|
||||
|
||||
/**
|
||||
* Total number of differences (distinct+left+right).
|
||||
*/
|
||||
differences: number
|
||||
|
||||
/**
|
||||
* Total number of entries (differences+equal).
|
||||
*/
|
||||
total: number
|
||||
|
||||
/**
|
||||
* Number of distinct files.
|
||||
*/
|
||||
distinctFiles: number
|
||||
|
||||
/**
|
||||
* Number of equal files.
|
||||
*/
|
||||
equalFiles: number
|
||||
|
||||
/**
|
||||
* Number of files only in path1.
|
||||
*/
|
||||
leftFiles: number
|
||||
|
||||
/**
|
||||
* Number of files only in path2
|
||||
*/
|
||||
rightFiles: number
|
||||
|
||||
/**
|
||||
* Total number of different files (distinctFiles+leftFiles+rightFiles).
|
||||
*/
|
||||
differencesFiles: number
|
||||
|
||||
/**
|
||||
* Total number of files (differencesFiles+equalFiles).
|
||||
*/
|
||||
totalFiles: number
|
||||
|
||||
/**
|
||||
* Number of distinct directories.
|
||||
*/
|
||||
distinctDirs: number
|
||||
|
||||
/**
|
||||
* Number of equal directories.
|
||||
*/
|
||||
equalDirs: number
|
||||
|
||||
/**
|
||||
* Number of directories only in path1.
|
||||
*/
|
||||
leftDirs: number
|
||||
|
||||
/**
|
||||
* Number of directories only in path2.
|
||||
*/
|
||||
rightDirs: number
|
||||
|
||||
/**
|
||||
* Total number of different directories (distinctDirs+leftDirs+rightDirs).
|
||||
*/
|
||||
differencesDirs: number
|
||||
|
||||
/**
|
||||
* Total number of directories (differencesDirs+equalDirs).
|
||||
*/
|
||||
totalDirs: number
|
||||
|
||||
/**
|
||||
* Stats about broken links.
|
||||
*/
|
||||
brokenLinks: BrokenLinksStatistics
|
||||
|
||||
/**
|
||||
* Statistics available if 'compareSymlink' options is used.
|
||||
*/
|
||||
symlinks?: SymlinkStatistics
|
||||
}
|
||||
|
||||
export interface BrokenLinksStatistics {
|
||||
/**
|
||||
* Number of broken links only in path1
|
||||
*/
|
||||
leftBrokenLinks: number
|
||||
|
||||
/**
|
||||
* Number of broken links only in path2
|
||||
*/
|
||||
rightBrokenLinks: number
|
||||
|
||||
/**
|
||||
* Number of broken links with same name appearing in both path1 and path2 (leftBrokenLinks+rightBrokenLinks+distinctBrokenLinks)
|
||||
*/
|
||||
distinctBrokenLinks: number
|
||||
|
||||
/**
|
||||
* Total number of broken links
|
||||
*/
|
||||
totalBrokenLinks: number
|
||||
|
||||
}
|
||||
|
||||
export interface SymlinkStatistics {
|
||||
/**
|
||||
* Number of distinct links.
|
||||
*/
|
||||
distinctSymlinks: number
|
||||
|
||||
/**
|
||||
* Number of equal links.
|
||||
*/
|
||||
equalSymlinks: number
|
||||
|
||||
/**
|
||||
* Number of links only in path1.
|
||||
*/
|
||||
leftSymlinks: number
|
||||
|
||||
/**
|
||||
* Number of links only in path2
|
||||
*/
|
||||
rightSymlinks: number
|
||||
|
||||
/**
|
||||
* Total number of different links (distinctSymlinks+leftSymlinks+rightSymlinks).
|
||||
*/
|
||||
differencesSymlinks: number
|
||||
|
||||
/**
|
||||
* Total number of links (differencesSymlinks+equalSymlinks).
|
||||
*/
|
||||
totalSymlinks: number
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* State of left/right entries relative to each other.
|
||||
*/
|
||||
export type DifferenceState = "equal" | "left" | "right" | "distinct"
|
||||
|
||||
/**
|
||||
* Type of entry.
|
||||
*/
|
||||
export type DifferenceType = "missing" | "file" | "directory" | "broken-link"
|
||||
|
||||
/**
|
||||
* Provides reason when two identically named entries are distinct.
|
||||
*/
|
||||
export type Reason = "different-size" | "different-date" | "different-content" | "broken-link" | 'different-symlink'
|
||||
|
||||
export interface Difference {
|
||||
/**
|
||||
* Any property is allowed if default result builder is not used.
|
||||
*/
|
||||
[key: string]: any
|
||||
|
||||
/**
|
||||
* Path not including file/directory name; can be relative or absolute depending on call to compare().
|
||||
*/
|
||||
path1?: string
|
||||
|
||||
/**
|
||||
* Path not including file/directory name; can be relative or absolute depending on call to compare().
|
||||
*/
|
||||
path2?: string
|
||||
|
||||
/**
|
||||
* Path relative to root dir.
|
||||
*/
|
||||
relativePath: string
|
||||
|
||||
/**
|
||||
* Left file/directory name.
|
||||
*/
|
||||
name1?: string
|
||||
|
||||
/**
|
||||
* Right file/directory name.
|
||||
*/
|
||||
name2?: string
|
||||
|
||||
/**
|
||||
* See [[DifferenceState]]
|
||||
*/
|
||||
state: DifferenceState
|
||||
|
||||
/**
|
||||
* Type of left entry.
|
||||
*/
|
||||
type1: DifferenceType
|
||||
|
||||
/**
|
||||
* Type of right entry.
|
||||
*/
|
||||
type2: DifferenceType
|
||||
|
||||
/**
|
||||
* Left file size.
|
||||
*/
|
||||
size1?: number
|
||||
|
||||
/**
|
||||
* Right file size.
|
||||
*/
|
||||
size2?: number
|
||||
|
||||
/**
|
||||
* Left entry modification date (stat.mtime).
|
||||
*/
|
||||
date1?: number
|
||||
|
||||
/**
|
||||
* Right entry modification date (stat.mtime).
|
||||
*/
|
||||
date2?: number
|
||||
|
||||
/**
|
||||
* Depth level relative to root dir.
|
||||
*/
|
||||
level: number
|
||||
|
||||
/**
|
||||
* See [[Reason]].
|
||||
* Not available if entries are equal.
|
||||
*/
|
||||
reason?: Reason
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronous file content comparison handler.
|
||||
*/
|
||||
export type CompareFileSync = (
|
||||
path1: string,
|
||||
stat1: fs.Stats,
|
||||
path2: string,
|
||||
stat2: fs.Stats,
|
||||
options: Options
|
||||
) => boolean
|
||||
|
||||
/**
|
||||
* Asynchronous file content comparison handler.
|
||||
*/
|
||||
export type CompareFileAsync = (
|
||||
path1: string,
|
||||
stat1: fs.Stats,
|
||||
path2: string,
|
||||
stat2: fs.Stats,
|
||||
options: Options
|
||||
) => Promise<boolean>
|
||||
|
||||
export interface CompareFileHandler {
|
||||
compareSync: CompareFileSync,
|
||||
compareAsync: CompareFileAsync
|
||||
}
|
||||
|
||||
/**
|
||||
* Available file content comparison handlers.
|
||||
* These handlers are used when [[Options.compareContent]] is set.
|
||||
*/
|
||||
export const fileCompareHandlers: {
|
||||
/**
|
||||
* Default file content comparison handlers, used if [[Options.compareFileAsync]] or [[Options.compareFileSync]] are not specified.
|
||||
*
|
||||
* Performs binary comparison.
|
||||
*/
|
||||
defaultFileCompare: CompareFileHandler,
|
||||
/**
|
||||
* Compares files line by line.
|
||||
*
|
||||
* Options:
|
||||
* * ignoreLineEnding - tru/false (default: false)
|
||||
* * ignoreWhiteSpaces - tru/false (default: false)
|
||||
*/
|
||||
lineBasedFileCompare: CompareFileHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the names of two entries.
|
||||
* The comparison should be dependent on received options (ie. case sensitive, ...).
|
||||
* Returns 0 if names are identical, -1 if name1<name2, 1 if name1>name2.
|
||||
*/
|
||||
export type CompareNameHandler = (
|
||||
name1: string,
|
||||
name2: string,
|
||||
options: Options
|
||||
) => 0 | 1 | -1
|
||||
204
electron/node_modules/dir-compare/src/index.js
generated
vendored
Normal file
204
electron/node_modules/dir-compare/src/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
var util = require('util')
|
||||
var pathUtils = require('path')
|
||||
var fs = require('fs')
|
||||
var compareSyncInternal = require('./compareSync')
|
||||
var compareAsyncInternal = require('./compareAsync')
|
||||
var defaultResultBuilderCallback = require('./resultBuilder/defaultResultBuilderCallback')
|
||||
var defaultFileCompare = require('./fileCompareHandler/defaultFileCompare')
|
||||
var lineBasedFileCompare = require('./fileCompareHandler/lineBasedFileCompare')
|
||||
var defaultNameCompare = require('./nameCompare/defaultNameCompare')
|
||||
var entryBuilder = require('./entry/entryBuilder')
|
||||
var statsLifecycle = require('./statistics/statisticsLifecycle')
|
||||
var loopDetector = require('./symlink/loopDetector')
|
||||
|
||||
var ROOT_PATH = pathUtils.sep
|
||||
|
||||
var compareSync = function (path1, path2, options) {
|
||||
'use strict'
|
||||
// realpathSync() is necessary for loop detection to work properly
|
||||
var absolutePath1 = pathUtils.normalize(pathUtils.resolve(fs.realpathSync(path1)))
|
||||
var absolutePath2 = pathUtils.normalize(pathUtils.resolve(fs.realpathSync(path2)))
|
||||
var diffSet
|
||||
options = prepareOptions(options)
|
||||
if (!options.noDiffSet) {
|
||||
diffSet = []
|
||||
}
|
||||
var statistics = statsLifecycle.initStats(options)
|
||||
compareSyncInternal(
|
||||
entryBuilder.buildEntry(absolutePath1, path1, pathUtils.basename(absolutePath1)),
|
||||
entryBuilder.buildEntry(absolutePath2, path2, pathUtils.basename(absolutePath2)),
|
||||
0, ROOT_PATH, options, statistics, diffSet, loopDetector.initSymlinkCache())
|
||||
statsLifecycle.completeStatistics(statistics, options)
|
||||
statistics.diffSet = diffSet
|
||||
|
||||
return statistics
|
||||
}
|
||||
|
||||
var wrapper = {
|
||||
realPath: function(path, options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.realpath(path, options, function(err, resolvedPath) {
|
||||
if(err){
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(resolvedPath)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var compareAsync = function (path1, path2, options) {
|
||||
'use strict'
|
||||
var absolutePath1, absolutePath2
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return Promise.all([wrapper.realPath(path1), wrapper.realPath(path2)])
|
||||
})
|
||||
.then(function (realPaths) {
|
||||
var realPath1 = realPaths[0]
|
||||
var realPath2 = realPaths[1]
|
||||
// realpath() is necessary for loop detection to work properly
|
||||
absolutePath1 = pathUtils.normalize(pathUtils.resolve(realPath1))
|
||||
absolutePath2 = pathUtils.normalize(pathUtils.resolve(realPath2))
|
||||
})
|
||||
.then(function () {
|
||||
options = prepareOptions(options)
|
||||
var asyncDiffSet
|
||||
if (!options.noDiffSet) {
|
||||
asyncDiffSet = []
|
||||
}
|
||||
var statistics = statsLifecycle.initStats(options)
|
||||
return compareAsyncInternal(
|
||||
entryBuilder.buildEntry(absolutePath1, path1, pathUtils.basename(path1)),
|
||||
entryBuilder.buildEntry(absolutePath2, path2, pathUtils.basename(path2)),
|
||||
0, ROOT_PATH, options, statistics, asyncDiffSet, loopDetector.initSymlinkCache()).then(
|
||||
function () {
|
||||
statsLifecycle.completeStatistics(statistics, options)
|
||||
if (!options.noDiffSet) {
|
||||
var diffSet = []
|
||||
rebuildAsyncDiffSet(statistics, asyncDiffSet, diffSet)
|
||||
statistics.diffSet = diffSet
|
||||
}
|
||||
return statistics
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
var prepareOptions = function (options) {
|
||||
options = options || {}
|
||||
var clone = JSON.parse(JSON.stringify(options))
|
||||
clone.resultBuilder = options.resultBuilder
|
||||
clone.compareFileSync = options.compareFileSync
|
||||
clone.compareFileAsync = options.compareFileAsync
|
||||
clone.compareNameHandler = options.compareNameHandler
|
||||
if (!clone.resultBuilder) {
|
||||
clone.resultBuilder = defaultResultBuilderCallback
|
||||
}
|
||||
if (!clone.compareFileSync) {
|
||||
clone.compareFileSync = defaultFileCompare.compareSync
|
||||
}
|
||||
if (!clone.compareFileAsync) {
|
||||
clone.compareFileAsync = defaultFileCompare.compareAsync
|
||||
}
|
||||
if(!clone.compareNameHandler) {
|
||||
clone.compareNameHandler = defaultNameCompare
|
||||
}
|
||||
clone.dateTolerance = clone.dateTolerance || 1000
|
||||
clone.dateTolerance = Number(clone.dateTolerance)
|
||||
if (isNaN(clone.dateTolerance)) {
|
||||
throw new Error('Date tolerance is not a number')
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
|
||||
// Async diffsets are kept into recursive structures.
|
||||
// This method transforms them into one dimensional arrays.
|
||||
var rebuildAsyncDiffSet = function (statistics, asyncDiffSet, diffSet) {
|
||||
asyncDiffSet.forEach(function (rawDiff) {
|
||||
if (!Array.isArray(rawDiff)) {
|
||||
diffSet.push(rawDiff)
|
||||
} else {
|
||||
rebuildAsyncDiffSet(statistics, rawDiff, diffSet)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Options:
|
||||
* compareSize: true/false - Compares files by size. Defaults to 'false'.
|
||||
* compareDate: true/false - Compares files by date of modification (stat.mtime). Defaults to 'false'.
|
||||
* dateTolerance: milliseconds - Two files are considered to have the same date if the difference between their modification dates fits within date tolerance. Defaults to 1000 ms.
|
||||
* compareContent: true/false - Compares files by content. Defaults to 'false'.
|
||||
* compareSymlink: true/false - Compares entries by symlink. Defaults to 'false'.
|
||||
* skipSubdirs: true/false - Skips sub directories. Defaults to 'false'.
|
||||
* skipSymlinks: true/false - Skips symbolic links. Defaults to 'false'.
|
||||
* ignoreCase: true/false - Ignores case when comparing names. Defaults to 'false'.
|
||||
* noDiffSet: true/false - Toggles presence of diffSet in output. If true, only statistics are provided. Use this when comparing large number of files to avoid out of memory situations. Defaults to 'false'.
|
||||
* includeFilter: File name filter. Comma separated [minimatch](https://www.npmjs.com/package/minimatch) patterns.
|
||||
* excludeFilter: File/directory name exclude filter. Comma separated [minimatch](https://www.npmjs.com/package/minimatch) patterns.
|
||||
* resultBuilder: Callback for constructing result.
|
||||
* function (entry1, entry2, state, level, relativePath, options, statistics, diffSet). Called for each compared entry pair. Updates 'statistics' and 'diffSet'.
|
||||
* compareFileSync, compareFileAsync: Callbacks for file comparison.
|
||||
* compareNameHandler: Callback for name comparison
|
||||
*
|
||||
* Result:
|
||||
* same: true if directories are identical
|
||||
* distinct: number of distinct entries
|
||||
* equal: number of equal entries
|
||||
* left: number of entries only in path1
|
||||
* right: number of entries only in path2
|
||||
* differences: total number of differences (distinct+left+right)
|
||||
* total: total number of entries (differences+equal)
|
||||
* distinctFiles: number of distinct files
|
||||
* equalFiles: number of equal files
|
||||
* leftFiles: number of files only in path1
|
||||
* rightFiles: number of files only in path2
|
||||
* differencesFiles: total number of different files (distinctFiles+leftFiles+rightFiles)
|
||||
* totalFiles: total number of files (differencesFiles+equalFiles)
|
||||
* distinctDirs: number of distinct directories
|
||||
* equalDirs: number of equal directories
|
||||
* leftDirs: number of directories only in path1
|
||||
* rightDirs: number of directories only in path2
|
||||
* differencesDirs: total number of different directories (distinctDirs+leftDirs+rightDirs)
|
||||
* totalDirs: total number of directories (differencesDirs+equalDirs)
|
||||
* brokenLinks:
|
||||
* leftBrokenLinks: number of broken links only in path1
|
||||
* rightBrokenLinks: number of broken links only in path2
|
||||
* distinctBrokenLinks: number of broken links with same name appearing in both path1 and path2
|
||||
* totalBrokenLinks: total number of broken links (leftBrokenLinks+rightBrokenLinks+distinctBrokenLinks)
|
||||
* symlinks: Statistics available if 'compareSymlink' options is used
|
||||
* distinctSymlinks: number of distinct links
|
||||
* equalSymlinks: number of equal links
|
||||
* leftSymlinks: number of links only in path1
|
||||
* rightSymlinks: number of links only in path2
|
||||
* differencesSymlinks: total number of different links (distinctSymlinks+leftSymlinks+rightSymlinks)
|
||||
* totalSymlinks: total number of links (differencesSymlinks+equalSymlinks)
|
||||
* diffSet - List of changes (present if Options.noDiffSet is false)
|
||||
* path1: absolute path not including file/directory name,
|
||||
* path2: absolute path not including file/directory name,
|
||||
* relativePath: common path relative to root,
|
||||
* name1: file/directory name
|
||||
* name2: file/directory name
|
||||
* state: one of equal, left, right, distinct,
|
||||
* type1: one of missing, file, directory, broken-link
|
||||
* type2: one of missing, file, directory, broken-link
|
||||
* size1: file size
|
||||
* size2: file size
|
||||
* date1: modification date (stat.mtime)
|
||||
* date2: modification date (stat.mtime)
|
||||
* level: depth
|
||||
* reason: Provides reason when two identically named entries are distinct
|
||||
* Not available if entries are equal
|
||||
* One of "different-size", "different-date", "different-content", "broken-link", "different-symlink"
|
||||
*/
|
||||
module.exports = {
|
||||
compareSync: compareSync,
|
||||
compare: compareAsync,
|
||||
fileCompareHandlers: {
|
||||
defaultFileCompare: defaultFileCompare,
|
||||
lineBasedFileCompare: lineBasedFileCompare
|
||||
}
|
||||
}
|
||||
12
electron/node_modules/dir-compare/src/nameCompare/defaultNameCompare.js
generated
vendored
Normal file
12
electron/node_modules/dir-compare/src/nameCompare/defaultNameCompare.js
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
module.exports = function compareName(name1, name2, options) {
|
||||
if (options.ignoreCase) {
|
||||
name1 = name1.toLowerCase()
|
||||
name2 = name2.toLowerCase()
|
||||
}
|
||||
return strcmp(name1, name2)
|
||||
}
|
||||
|
||||
function strcmp(str1, str2) {
|
||||
return ((str1 === str2) ? 0 : ((str1 > str2) ? 1 : -1))
|
||||
}
|
||||
27
electron/node_modules/dir-compare/src/resultBuilder/defaultResultBuilderCallback.js
generated
vendored
Normal file
27
electron/node_modules/dir-compare/src/resultBuilder/defaultResultBuilderCallback.js
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
'use strict'
|
||||
|
||||
var pathUtils = require('path')
|
||||
var common = require('../entry/entryBuilder')
|
||||
var entryType = require('../entry/entryType')
|
||||
|
||||
module.exports = function (entry1, entry2, state, level, relativePath, options, statistics, diffSet, reason) {
|
||||
if (options.noDiffSet) {
|
||||
return
|
||||
}
|
||||
diffSet.push({
|
||||
path1: entry1 ? pathUtils.dirname(entry1.path) : undefined,
|
||||
path2: entry2 ? pathUtils.dirname(entry2.path) : undefined,
|
||||
relativePath: relativePath,
|
||||
name1: entry1 ? entry1.name : undefined,
|
||||
name2: entry2 ? entry2.name : undefined,
|
||||
state: state,
|
||||
type1: entryType.getType(entry1),
|
||||
type2: entryType.getType(entry2),
|
||||
level: level,
|
||||
size1: entry1 ? entry1.stat.size : undefined,
|
||||
size2: entry2 ? entry2.stat.size : undefined,
|
||||
date1: entry1 ? entry1.stat.mtime : undefined,
|
||||
date2: entry2 ? entry2.stat.mtime : undefined,
|
||||
reason: reason
|
||||
})
|
||||
}
|
||||
59
electron/node_modules/dir-compare/src/statistics/statisticsLifecycle.js
generated
vendored
Normal file
59
electron/node_modules/dir-compare/src/statistics/statisticsLifecycle.js
generated
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Controls creation/completion of global statistics object.
|
||||
*/
|
||||
module.exports = {
|
||||
initStats(options) {
|
||||
var symlinkStatistics = undefined
|
||||
if (options.compareSymlink) {
|
||||
symlinkStatistics = {
|
||||
distinctSymlinks: 0,
|
||||
equalSymlinks: 0,
|
||||
leftSymlinks: 0,
|
||||
rightSymlinks: 0,
|
||||
differencesSymlinks: 0,
|
||||
totalSymlinks: 0,
|
||||
}
|
||||
}
|
||||
var brokenLinksStatistics = {
|
||||
leftBrokenLinks: 0,
|
||||
rightBrokenLinks: 0,
|
||||
distinctBrokenLinks: 0,
|
||||
}
|
||||
return {
|
||||
distinct: 0,
|
||||
equal: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
distinctFiles: 0,
|
||||
equalFiles: 0,
|
||||
leftFiles: 0,
|
||||
rightFiles: 0,
|
||||
distinctDirs: 0,
|
||||
equalDirs: 0,
|
||||
leftDirs: 0,
|
||||
rightDirs: 0,
|
||||
brokenLinks: brokenLinksStatistics,
|
||||
symlinks: symlinkStatistics,
|
||||
same: undefined
|
||||
}
|
||||
},
|
||||
|
||||
completeStatistics(statistics, options) {
|
||||
statistics.differences = statistics.distinct + statistics.left + statistics.right
|
||||
statistics.differencesFiles = statistics.distinctFiles + statistics.leftFiles + statistics.rightFiles
|
||||
statistics.differencesDirs = statistics.distinctDirs + statistics.leftDirs + statistics.rightDirs
|
||||
statistics.total = statistics.equal + statistics.differences
|
||||
statistics.totalFiles = statistics.equalFiles + statistics.differencesFiles
|
||||
statistics.totalDirs = statistics.equalDirs + statistics.differencesDirs
|
||||
var brokenLInksStats = statistics.brokenLinks
|
||||
brokenLInksStats.totalBrokenLinks = brokenLInksStats.leftBrokenLinks + brokenLInksStats.rightBrokenLinks + brokenLInksStats.distinctBrokenLinks
|
||||
statistics.same = statistics.differences ? false : true
|
||||
|
||||
if (options.compareSymlink) {
|
||||
statistics.symlinks.differencesSymlinks = statistics.symlinks.distinctSymlinks +
|
||||
statistics.symlinks.leftSymlinks + statistics.symlinks.rightSymlinks
|
||||
statistics.symlinks.totalSymlinks = statistics.symlinks.differencesSymlinks + statistics.symlinks.equalSymlinks
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
62
electron/node_modules/dir-compare/src/statistics/statisticsUpdate.js
generated
vendored
Normal file
62
electron/node_modules/dir-compare/src/statistics/statisticsUpdate.js
generated
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Calculates comparison statistics.
|
||||
*/
|
||||
module.exports = {
|
||||
updateStatisticsBoth: function (entry1, entry2, same, reason, type, statistics, options) {
|
||||
same ? statistics.equal++ : statistics.distinct++
|
||||
if (type === 'file') {
|
||||
same ? statistics.equalFiles++ : statistics.distinctFiles++
|
||||
} else if (type === 'directory') {
|
||||
same ? statistics.equalDirs++ : statistics.distinctDirs++
|
||||
} else if (type === 'broken-link') {
|
||||
statistics.brokenLinks.distinctBrokenLinks++
|
||||
} else {
|
||||
throw new Error('Unexpected type ' + type)
|
||||
}
|
||||
|
||||
var isSymlink1 = entry1 ? entry1.isSymlink : false
|
||||
var isSymlink2 = entry2 ? entry2.isSymlink : false
|
||||
var isSymlink = isSymlink1 || isSymlink2
|
||||
if (options.compareSymlink && isSymlink) {
|
||||
var symlinks = statistics.symlinks
|
||||
if (reason === 'different-symlink') {
|
||||
symlinks.distinctSymlinks++
|
||||
} else {
|
||||
symlinks.equalSymlinks++
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
updateStatisticsLeft: function (entry1, type, statistics, options) {
|
||||
statistics.left++
|
||||
if (type === 'file') {
|
||||
statistics.leftFiles++
|
||||
} else if (type === 'directory') {
|
||||
statistics.leftDirs++
|
||||
} else if (type === 'broken-link') {
|
||||
statistics.brokenLinks.leftBrokenLinks++
|
||||
} else {
|
||||
throw new Error('Unexpected type ' + type)
|
||||
}
|
||||
|
||||
if (options.compareSymlink && entry1.isSymlink) {
|
||||
statistics.symlinks.leftSymlinks++
|
||||
}
|
||||
},
|
||||
updateStatisticsRight: function (entry2, type, statistics, options) {
|
||||
statistics.right++
|
||||
if (type === 'file') {
|
||||
statistics.rightFiles++
|
||||
} else if (type === 'directory') {
|
||||
statistics.rightDirs++
|
||||
} else if (type === 'broken-link') {
|
||||
statistics.brokenLinks.rightBrokenLinks++
|
||||
} else {
|
||||
throw new Error('Unexpected type ' + type)
|
||||
}
|
||||
|
||||
if (options.compareSymlink && entry2.isSymlink) {
|
||||
statistics.symlinks.rightSymlinks++
|
||||
}
|
||||
},
|
||||
}
|
||||
51
electron/node_modules/dir-compare/src/symlink/loopDetector.js
generated
vendored
Normal file
51
electron/node_modules/dir-compare/src/symlink/loopDetector.js
generated
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
var fs = require('fs')
|
||||
|
||||
/**
|
||||
* Provides symlink loop detection to directory traversal algorithm.
|
||||
*/
|
||||
module.exports = {
|
||||
detectLoop: function (entry, symlinkCache) {
|
||||
if (entry && entry.isSymlink) {
|
||||
var realPath = fs.realpathSync(entry.absolutePath)
|
||||
if (symlinkCache[realPath]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
|
||||
initSymlinkCache: function() {
|
||||
return {
|
||||
dir1: {},
|
||||
dir2: {}
|
||||
}
|
||||
},
|
||||
|
||||
updateSymlinkCache: function(symlinkCache, rootEntry1, rootEntry2, loopDetected1, loopDetected2) {
|
||||
var symlinkCachePath1, symlinkCachePath2
|
||||
if (rootEntry1 && !loopDetected1) {
|
||||
symlinkCachePath1 = rootEntry1.isSymlink ? fs.realpathSync(rootEntry1.absolutePath) : rootEntry1.absolutePath
|
||||
symlinkCache.dir1[symlinkCachePath1] = true
|
||||
}
|
||||
if (rootEntry2 && !loopDetected2) {
|
||||
symlinkCachePath2 = rootEntry2.isSymlink ? fs.realpathSync(rootEntry2.absolutePath) : rootEntry2.absolutePath
|
||||
symlinkCache.dir2[symlinkCachePath2] = true
|
||||
}
|
||||
},
|
||||
|
||||
cloneSymlinkCache: function (symlinkCache) {
|
||||
return {
|
||||
dir1: shallowClone(symlinkCache.dir1),
|
||||
dir2: shallowClone(symlinkCache.dir2)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
function shallowClone(obj) {
|
||||
var cloned = {}
|
||||
Object.keys(obj).forEach(function (key) {
|
||||
cloned[key] = obj[key]
|
||||
})
|
||||
return cloned
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue