Security News
PyPI’s New Archival Feature Closes a Major Security Gap
PyPI now allows maintainers to archive projects, improving security and helping users make informed decisions about their dependencies.
grunt-incrediff
Advanced tools
grunt构建时自动生成文件间增量更新差异数据
chunk
/ chunkLcs
两种差异生成算法,各有使用场景,为了避免算法的不完备性导致差异生成错误,加入强校验,若生成的差异合并失败会使grunt过程fail。通过 npm 安装:
$ npm install grunt-incrediff -g
GruntFiles.js
version: [],
指定要生成差异文件的原始文件的版本号,如["1.0.2","1.0.1","1.0.0"],
chunkSize: 20,
newChunk算法调用时使用的参数,分块大小,建议>=10
isSingleDiff: true,
若 `isSingleDiff` 为 true ,则
生成 v[1]旧版 和 v[0]新版 的差异文件,否则生成 v[1-end] 和 v[0]新版 的所有差异文件
isHashStr: true,
生成差异信息中,是否压缩重复字符串
sourceFormat: '%{CDNURL}/%{OLDVERSION}/%{FILEPATH}',
CDN上原始文件的获取地址,此处的oldversion
当`isSingleDiff===FALSE`时会匹配 version[>=1]的所有元素,
当`isSingleDiff===TRUE`时会匹配 version[1]的元素
format: '%{FILEPATH}\_%{OLDVERSION}\_%{NEWVERSION}.js'
需要生成在build目录的差异文件的路径
dest: 'build'
差异文件生成目录
algorithm: 'chunk'
枚举类型 `chunk` / `chunklcs`/`auto`,两种差分算法
`chunk`: 时间复杂度低,当差异巨大,(如两个完全不同的文件时),此算法速度较快,但差异文件较大
`chunklcs`: 时间复杂度略高,当差异巨大时,速度较慢,300K的文件间比较能跑5s左右,但在差异小时数据量很小,大约是 `chunk` 算法的 80% 左右
`auto`: 自动选择两者之间 数据量小的那个
newsrc: 'build'
新版本文件在之前的grunt构建中的生成目录
cdnUrl: 'http://g.assets.daily.taobao.net/dd/h5/'
CDN存储路径, 会从此地址下拉取 旧版本 资源文件
grunt 配置
grunt.initConfig({
incrediff: {
incre: {
options: {
version: ["1.0.1","1.0.0"],
chunkSize: 20,
isSingleDiff: true,
dest: 'build',
sourceFormat: '%{CDNURL}/%{OLDVERSION}/%{FILEPATH}',
format: '%{FILEPATH}_%{OLDVERSION}_%{NEWVERSION}.js',
newsrc: 'build',
algorithm: 'auto',
cdnUrl: 'http://cdnurl/pathprefix/',
},
files: {
src: ['path/to/css.css', 'path/to/js.js']
}
},
}
});
如果将 version: ["1.0.1","1.0.0"]
变量单独放在其他文件中,请主动修改
本地执行 grunt incrediff
/ 服务端自动 grunt
时会生成到指定目录
增加差异输出强校验,会对差异进行一次合并测试,如果合并测试失败则grunt会fail(如果算法某些点没测试到可能报错)
format: '%{FILEPATH}_%{OLDVERSION}_%{NEWVERSION}.js'
,即生成 path/to/file.ext_1.0.0_1.0.1.js
文件var data = {hash: (Array), diff: (Array), chunkSize: (Number)};
originStr = '1234567u'
targetStr = '12abc567u'
{hash: ['abc'], diff: [ [0,1], [0], [2,2] ], chunkSize: 2}
data.hash
表示 可以把 data.diff
中的重复字符串存到 data.hash
数组中节省空间(可选)data.diff
表示 有3种结构,按以下解释,依次连接起来即能生成 targetStr
[x, y]
: 表示 originStr.substr( x * data.chunkSize, y * data.chunkSize );
[i]
: 表示 data.hash[i]
'string'
: 表示 字符串data.chunkSize
表示 分块大小,chunk
算法默认为20 / chunklcs
算法默认为1var write = JSON.stringify( data ) + '/*"""*/';
fs.writeSync(pathto, write, 'utf8');
/*"""*/
(考虑css和js会被一次combo起来)"
,\
等字符会被转义处理, 因此 分隔符 **/*"""*/
**在理论上并不会在 data的转义序列中出现, 不会出现本地误识别的情况{"hash":[],"diff":[[0,115765],[115796,673],";console.log(\"进入1.3.772 静态渲染方法\");var ",[116470,105278]],"chunkSize":1}/*"""*/
var diff = require('./tasks/lib/newChunk'); var oldS = '1234567890'; var newS = '12345678toString90';
生成差异
var d = diff(oldS, newS, 2, true /是否不压缩字符串/);
合并差异
var m = diff.merge(oldS, null /若d不带chunkSize可以外部输入/, d)
var diff = require('./tasks/lib/chunkLCS'); var oldS = '1234567890'; var newS = '12345678toString90';
生成差异
var d = diff(oldS, newS);
合并差异
var m = diff.merge(oldS, null, d);
其实啊...直接去看代码最好...算法都写在那里...
以下内容为代码实现逻辑,当发现bug/需要修改代码逻辑的时候可以参考一下
chunk
差分算法实现lcs
算法实现,复杂度太高不提供外部调用chunkLcs
两种算法结合,具体实现/* http请求,下载历史版本文件 */
request = require('request')
async = require('async')
/* 显示差异文件大小 */
maxmin = require('maxmin')
chalk = require('chalk')
/* 差异算法库 */
diff = require('./lib/newChunk')
responseHandler
http响应的回调,为了获取dest, done, container, _name, url, cnt, all,而产生的闭包
strFormat
字符串处理格式化,按照指定的 %{XXX} 进行替换
generateDiffData
根据输入新旧数据源计算差异,并存储到指定位置,如果algorithm === 'auto' 则会调用两个方法分别运算选取数据量小的那个
generateFullData
根据输入数据源生成全量数据,并存储到指定位置,(考虑到所有文件,包括CSS和JS能被combo在一起,必须要做一定处理,让本地接收时能够分离成单个文件)
newContent
数组sourceFormat
的格式生成需要下载的旧版本资源文件URL,存入reqQueue
数组async.each(reqQueue, ***)
对所有指定旧版本资源进行下载,把下载后文本存入reqContent
async.each
全部执行done之后,开始生成差异
generateDiffData
生成 版本间差异数据generateFullData
生成 全量更新数据generateOriginBlock
由o原始字符串按照chunkSize分块大小生成对应块的hashmap,用来标记块是否存在
generateOriginBlock
对n按照rsync的思想进行滑动块查询,如果在originHash中查询到了就是未被修改,没查询到就当做新增一个字节然后继续,把生成的差异数据存入diffRecord
可以参照 rsync算法描述
getCorrectHashID
寻找最优分块hashID,由于复杂度原因,不可能做到绝对最优,采用这个O(N)的遍历来寻找一个相对最优的,找一个距离上次正确匹配最相近的匹配块
concatDiffBlock
把相邻的 数组标记块 或者 相邻的字符 连接起来,节省空间
generateOriginBlock
计算源数据分块哈希映射generateDiffBlock
根据源哈希映射 和 新数据 计算差异
getCorrectHashID
计算寻找较优匹配concatDiffBlock
把差异中满足一定条件的相邻块合并lcsDiff
时间、空间复杂度均为O(N^2),在 dp 中存储编辑距离, 在 step 中存储具体路径,然后进行一些处理把差异规则化
buildPaths
由于路径是逆序记录在二维数组中的,需要重新遍历路径才能得到一维的编辑路径
buildDiff
处理之前构造的一维路径数组,把MOD/EUQALL/DEL/ADD,转换成 和newChunk一样的形式
concatDiff
把生成的差异数组中符合一定条件的相邻项进行合并,同newChunk中的concatDiffBlock,合并相邻 数组或相邻字符
lcsDiff
先跑动态规划,把编辑距离路径记录的二维数组跑出来
buildPaths
根据二维路径生成一维最短编辑路径,二维包好了所有编辑路径,不论好坏,生成的一维是最优解buildDiff
把之前的一维路径的结果(MOD/EUQALL/DEL/ADD)处理成仅由 源字符串o.substr 和 新字符串 拼接就能构成的[[0,2], '23']如此的数组形式concatDiff
优化,拼接差异数组中满足某些特定条件的相邻项(数组相邻 或 都是字符串)algoWrap
对外调用做的一个包裹函数,添加了 diff, chunkSize 等通用属性(后来做了点数组优化,增加一个合并小块的过程)
ChunkLCS
递归调用的主函数,进入后,先试用chunk算法分出 最(较大,非绝对最大)大公共字串,及其前缀和后缀,然后对其前缀和后缀字符串递归调用该函数
chunkSplit
对指定的 源数据块o,和 新数据块n,执行最(较)大公共块计算,并返回含有前缀,公共,后缀信息的对象
lcsAdapter
lcs算法适配器,需要适配 preStart的预制数,必须加上,否则会错乱
mergeBlock
由于chunkSplit进行了前中后的拆分,这是重新组装的函数,并且要考虑两个差分数组拼接时连接处是否可以合并的问题
miniLcsBlock
后期发现的一个问题, 本算法能精确到字节级别,那么即chunkSize分块大小===1,所以后期会出现好多[123123,1],这代表了源字符串的一个字符,却要占用10个左右的字节进行表示,对这种情况,直接插入字符,节省差异数据
algoWrap
计算差异
ChunkLCS
,初始化参数 ChunkLCS( 100, 0, o, n )
lcsAdapter
计算差异并返回chunkSplit
寻找 最(较)大公共字符串, 并对其前缀和后缀分别 递归调用 ChunkLCS
计算差异mergeBlock
合并差异miniLcsBlock
进行数据优化合并FAQs
auto-generate tool of difference between two version
The npm package grunt-incrediff receives a total of 14 weekly downloads. As such, grunt-incrediff popularity was classified as not popular.
We found that grunt-incrediff demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now allows maintainers to archive projects, improving security and helping users make informed decisions about their dependencies.
Research
Security News
Malicious npm package postcss-optimizer delivers BeaverTail malware, targeting developer systems; similarities to past campaigns suggest a North Korean connection.
Security News
CISA's KEV data is now on GitHub, offering easier access, API integration, commit history tracking, and automated updates for security teams and researchers.