fs-tree-diff
Advanced tools
Comparing version 0.5.4 to 0.5.5
# master | ||
# v0.5.5 | ||
* add `Entry.fromStat` thanks @trentmwillis | ||
* add `applyPatch` and `calculateAndApplyPatch` thanks @trentmwillis | ||
# v0.5.4 | ||
* Fix remove-before-add bug. Thanks @dfreeman for excellent bug investigation | ||
# v0.5.3 | ||
@@ -4,0 +13,0 @@ |
@@ -6,4 +6,13 @@ 'use strict'; | ||
module.exports = Entry; | ||
function Entry(relativePath, size, mtime) { | ||
var isDirectory = relativePath.charAt(relativePath.length - 1) === '/'; | ||
function Entry(relativePath, size, mtime, mode) { | ||
if (arguments.length < 4) { | ||
var isDirectory = relativePath.charAt(relativePath.length - 1) === '/'; | ||
this.mode = isDirectory ? DIRECTORY_MODE : 0; | ||
} else { | ||
var modeType = typeof mode; | ||
if (modeType !== 'number') { | ||
throw new TypeError('Expected `mode` to be of type `number` but was of type `' + modeType + '` instead.'); | ||
} | ||
this.mode = mode; | ||
} | ||
@@ -14,3 +23,2 @@ // ---------------------------------------------------------------------- | ||
this.relativePath = relativePath; | ||
this.mode = isDirectory ? DIRECTORY_MODE : 0; | ||
this.size = size; | ||
@@ -33,1 +41,6 @@ this.mtime = mtime; | ||
}; | ||
Entry.fromStat = function(relativePath, stat) { | ||
var entry = new Entry(relativePath, stat.size, stat.mtime, stat.mode); | ||
return entry; | ||
}; |
'use strict'; | ||
var fs = require('fs'); | ||
var path = require('path-posix'); | ||
var assign = require('object-assign'); | ||
var symlinkOrCopy = require('symlink-or-copy'); | ||
var Entry = require('./entry'); | ||
@@ -10,3 +14,27 @@ var logger = require('heimdalljs-logger')('fs-tree-diff:'); | ||
var ARBITRARY_START_OF_TIME = 0; | ||
var DEFAULT_DELEGATE = { | ||
unlink: function(inputPath, outputPath, relativePath) { | ||
fs.unlinkSync(outputPath); | ||
}, | ||
rmdir: function(inputPath, outputPath, relativePath) { | ||
fs.rmdirSync(outputPath); | ||
}, | ||
mkdir: function(inputPath, outputPath, relativePath) { | ||
fs.mkdirSync(outputPath); | ||
}, | ||
change: function(inputPath, outputPath, relativePath) { | ||
// We no-op if the platform can symlink, because we assume the output path | ||
// is already linked via a prior create operation. | ||
if (symlinkOrCopy.canSymlink) { | ||
return; | ||
} | ||
fs.unlinkSync(outputPath); | ||
symlinkOrCopy.sync(inputPath, outputPath); | ||
}, | ||
create: function(inputPath, outputPath, relativePath) { | ||
symlinkOrCopy.sync(inputPath, outputPath); | ||
} | ||
}; | ||
module.exports = FSTree; | ||
@@ -166,2 +194,7 @@ | ||
FSTree.prototype.calculateAndApplyPatch = function(otherFSTree, input, output, delegate) { | ||
var patch = this.calculatePatch(otherFSTree); | ||
FSTree.applyPatch(input, output, patch, delegate); | ||
}; | ||
FSTree.defaultIsEqual = function defaultIsEqual(entryA, entryB) { | ||
@@ -184,2 +217,23 @@ if (entryA.isDirectory() && entryB.isDirectory()) { | ||
FSTree.applyPatch = function(input, output, patch, _delegate) { | ||
var delegate = assign({}, DEFAULT_DELEGATE, _delegate); | ||
for (var i = 0; i < patch.length; i++) { | ||
applyOperation(input, output, patch[i], delegate); | ||
} | ||
}; | ||
function applyOperation(input, output, operation, delegate) { | ||
var method = operation[0]; | ||
var relativePath = operation[1]; | ||
var inputPath = path.join(input, relativePath); | ||
var outputPath = path.join(output, relativePath); | ||
var delegateType = typeof delegate[method]; | ||
if (delegateType === 'function') { | ||
delegate[method](inputPath, outputPath, relativePath); | ||
} else { | ||
throw new Error('Unable to apply patch operation: ' + method + '. The value of delegate.' + method + ' is of type ' + delegateType + ', and not a function. Check the `delegate` argument to `FSTree.prototype.applyPatch`.'); | ||
} | ||
} | ||
function addCommand(entry) { | ||
@@ -186,0 +240,0 @@ return [entry.isDirectory() ? 'mkdir' : 'create', entry.relativePath, entry]; |
{ | ||
"name": "fs-tree-diff", | ||
"version": "0.5.4", | ||
"version": "0.5.5", | ||
"description": "Backs out file tree changes", | ||
"main": "lib/index.js", | ||
"files": [ | ||
"lib/" | ||
"lib" | ||
], | ||
@@ -16,5 +16,2 @@ "scripts": { | ||
], | ||
"files": [ | ||
"lib" | ||
], | ||
"author": "Stefan Penner, David J. Hamilton, Chad Hietala", | ||
@@ -24,12 +21,16 @@ "license": "MIT", | ||
"heimdalljs-logger": "^0.1.7", | ||
"fast-ordered-set": "^1.0.2" | ||
"object-assign": "^4.1.0", | ||
"path-posix": "^1.0.0", | ||
"symlink-or-copy": "^1.1.8" | ||
}, | ||
"devDependencies": { | ||
"chai": "^3.3.0", | ||
"mocha": "^2.3.3" | ||
"fs-extra": "^1.0.0", | ||
"mocha": "^2.3.3", | ||
"walk-sync": "^0.3.1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url":"git://github.com/stefanpenner/fs-tree-diff.git" | ||
"url": "git://github.com/stefanpenner/fs-tree-diff.git" | ||
} | ||
} |
@@ -1,3 +0,4 @@ | ||
# fs-tree-diff [![Build Status](https://travis-ci.org/stefanpenner/fs-tree-diff.svg?branch=master)](https://travis-ci.org/stefanpenner/fs-tree-diff) | ||
# fs-tree-diff [![Build Status](https://travis-ci.org/stefanpenner/fs-tree-diff.svg?branch=master)](https://travis-ci.org/stefanpenner/fs-tree-diff) [![Build status](https://ci.appveyor.com/api/projects/status/qmhx48hrquq08fam/branch/master?svg=true)](https://ci.appveyor.com/project/embercli/fs-tree-diff/branch/master) | ||
FSTree provides the means to calculate a patch (set of operations) between one file system tree and another. | ||
@@ -69,3 +70,3 @@ | ||
Now, the above examples do not demonstrate `update` operations. This is because | ||
Now, the above examples do not demonstrate `change` operations. This is because | ||
when providing only paths, we do not have sufficient information to check if | ||
@@ -75,3 +76,3 @@ one entry is merely different from another with the same relativePath. | ||
For this, FSTree supports more complex input structure. To demonstrate, We will | ||
use the [walk-sync](https://github.com/joliss/node-walk-sync) module. | ||
use the [walk-sync](https://github.com/joliss/node-walk-sync) module. | ||
**(note: `walk-sync >= 0.2.7` is required`)** Which provides higher fidelity | ||
@@ -98,3 +99,3 @@ input, allowing FSTree to also detect changes. More on what an | ||
current.calculatePatch(next) === [ | ||
['update', 'foo.js', entryFoo], // mtime + size changed, so this input is stale and needs updating. | ||
['change', 'foo.js', entryFoo], // mtime + size changed, so this input is stale and needs updating. | ||
['create', 'baz.js', entryBaz] // new file, so we should create it | ||
@@ -121,4 +122,9 @@ /* bar stays the same and is left inert*/ | ||
- `mtime` | ||
- `FSTree.applyPatch(inputDir, outputDir, patch, delegate)` applies the given | ||
patch from the input directory to the output directory. You can optionally | ||
provide a delegate object to handle individual types of patch operations. | ||
- `FSTree.prototype.calculatePatch(newTree, isEqual)` calculate a patch against | ||
`newTree`. Optionally specify a custom `isEqual` (see Change Calculation). | ||
- `FSTree.prototype.calculateAndApplyPatch(newTree, inputDir, outputDir, delegate)` | ||
does a `calculatePatch` followed by `applyPatch`. | ||
- `FSTree.prototype.addEntries(entries, options)` adds entries to an | ||
@@ -131,5 +137,13 @@ existing tree. Options are the same as for `FSTree.fromEntries`. | ||
be updated. | ||
- `Entry.fromStat(relativePath, stat)` creates an `Entry` from a given path and | ||
[`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object. It can | ||
then be used with `fromEntries` or `addEntries`. | ||
## Input | ||
The trees returned from `fromPaths` and `fromEntries` are relative to some base | ||
directory. `calculatePatch`, `applyPatch` and `calculateAndApplyPatch` all | ||
assume that the base directory has not changed. | ||
## Input | ||
`FSTree.fromPaths`, `FSTree.fromEntries`, `FSTree.prototype.addPaths`, | ||
@@ -227,1 +241,41 @@ and `FSTree.prototype.addEntries` all validate their inputs. Inputs | ||
## Patch Application | ||
When you want to apply changes from one tree to another easily, you can use the | ||
`FSTree.applyPatch` method. For example, given: | ||
```js | ||
var patch = oldInputTree.calculatePatch(newInputTree); | ||
var inputDir = 'src'; | ||
var outputDir = 'dist'; | ||
FSTree.applyPatch(inputDir, outputDir, patch); | ||
``` | ||
It will apply the patch changes to `dist` while using `src` as a reference for | ||
non-destructive operations (`mkdir`, `create`, `change`). If you want to calculate | ||
and apply a patch without any intermediate operations, you can do: | ||
```js | ||
var inputDir = 'src'; | ||
var outputDir = 'dist'; | ||
oldInputTree.calculateAndApplyPatch(newInputTree, inputDir, outputDir); | ||
``` | ||
You can optionally provide a delegate object to handle applying specific types | ||
of operations: | ||
```js | ||
var createCount = 0; | ||
FSTree.applyPatch(inputDir, outputDir, patch, { | ||
create: function(inputPath, outputPath, relativePath) { | ||
createCount++; | ||
copy(inputPath, outputPath); | ||
} | ||
}); | ||
``` | ||
The available delegate functions are the same as the supported operations: | ||
`unlink`, `rmdir`, `mkdir`, `create`, and `change`. Each delegate function | ||
receives the reference `inputPath`, the `outputPath`, and `relativePath` of the file | ||
or directory for which to apply the operation. | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
21232
334
276
4
4
1
+ Addedobject-assign@^4.1.0
+ Addedpath-posix@^1.0.0
+ Addedsymlink-or-copy@^1.1.8
+ Addedobject-assign@4.1.1(transitive)
+ Addedpath-posix@1.0.0(transitive)
+ Addedsymlink-or-copy@1.3.1(transitive)
- Removedfast-ordered-set@^1.0.2
- Removedblank-object@1.0.2(transitive)
- Removedfast-ordered-set@1.0.3(transitive)