Skip to content

Commit

Permalink
add hpatch_TFileStreamOutput_reopen(); cmdline remove "-o" , no Origi…
Browse files Browse the repository at this point in the history
…nal diff; recode PatchDirlistener; move some code to new files;

update zstd;
  • Loading branch information
sisong committed Mar 13, 2020
1 parent 77c12bb commit a47eb1d
Show file tree
Hide file tree
Showing 61 changed files with 3,202 additions and 2,172 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ full changelog at: https://github.com/sisong/HDiffPatch/commits

## [v3.0.8](https://github.com/sisong/HDiffPatch/tree/v3.0.8) - 2020-01-01
### Added
* patch demo for Android, out lib file libhpatchz.so;
* patch demo for Android, out lib file libhpatchz.so;

## [v3.0.7](https://github.com/sisong/HDiffPatch/tree/v3.0.7) - 2019-12-19
### Fixed
Expand All @@ -19,6 +19,10 @@ full changelog at: https://github.com/sisong/HDiffPatch/commits
### Fixed
* Fix a directory patch bug when changed file's sumSize >=4GB and run as 32bit app;

## [v3.0.4](https://github.com/sisong/HDiffPatch/tree/v3.0.4) - 2019-09-06
### Fixed
* Fix dir_patch can't remove some files bug when patch to same dir on Windows operating system;

## [v3.0.0](https://github.com/sisong/HDiffPatch/tree/v3.0.0) - 2019-03-01
### Added
* hdiffz,hpatchz command line support diff&patch between directories(folder);
Expand Down
23 changes: 14 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
# args
LZMA := 1
DIR_DIFF := 1
MT := 1
LZMA := 1
MD5 := 0
MT := 0


HPATCH_OBJ := \
libHDiffPatch/HPatch/patch.o \
file_for_patch.o \
dirDiffPatch/dir_patch/dir_patch.o
file_for_patch.o

ifeq ($(DIR_DIFF),0)
else
HPATCH_OBJ += \
dirDiffPatch/dir_patch/dir_patch.o \
dirDiffPatch/dir_patch/res_handle_limit.o \
dirDiffPatch/dir_patch/ref_stream.o \
dirDiffPatch/dir_patch/new_stream.o \
dirDiffPatch/dir_patch/dir_patch_tools.o \
dirDiffPatch/dir_patch/new_dir_output.o \
libHDiffPatch/HDiff/private_diff/limit_mem_diff/adler_roll.o
endif

Expand All @@ -33,7 +36,9 @@ HDIFF_OBJ := \
ifeq ($(DIR_DIFF),0)
else
HDIFF_OBJ += \
dirDiffPatch/dir_diff/dir_diff.o
dirDiffPatch/dir_diff/dir_diff.o \
dirDiffPatch/dir_diff/dir_diff_tools.o \
dirDiffPatch/dir_diff/dir_manifest.o
endif
ifeq ($(MT),0)
else
Expand All @@ -45,7 +50,7 @@ endif


DEF_FLAGS := \
-O3 -DNDEBUG -D_FILE_OFFSET_BITS=64 \
-O3 -DNDEBUG -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 \
-D_IS_NEED_ORIGINAL=1 \
-D_IS_NEED_ALL_CompressPlugin=0 \
-D_IS_NEED_DEFAULT_CompressPlugin=0 \
Expand Down Expand Up @@ -115,18 +120,18 @@ ifeq ($(LZMA),0)
LZMA_DEC_OBJ :=
LZMA_OBJ :=
lzmaLib :
else
else
LZMA_DEC_OBJ := 'LzmaDec.o' 'Lzma2Dec.o'
LZMA_OBJ := 'LzFind.o' 'LzmaEnc.o' 'Lzma2Enc.o' $(LZMA_DEC_OBJ)
LZMA_SRC := '../lzma/C/LzFind.c' '../lzma/C/LzmaDec.c' '../lzma/C/LzmaEnc.c' \
'../lzma/C/Lzma2Dec.c' '../lzma/C/Lzma2Enc.c'
ifeq ($(MT),0)
else # download from https://github.com/sisong/lzma/tree/pthread
else
LZMA_OBJ += 'LzFindMt.o' 'MtCoder.o' 'MtDec.o' 'ThreadsP.o'
LZMA_SRC += '../lzma/C/LzFindMt.c' '../lzma/C/MtCoder.c' \
'../lzma/C/MtDec.c' '../lzma/C/ThreadsP.c'
endif
lzmaLib: # https://www.7-zip.org/sdk.html https://github.com/sisong/lzma
lzmaLib: # https://github.com/sisong/lzma
$(CC) -c $(CFLAGS) $(LZMA_SRC)
endif

Expand Down
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@
[![Build Status](https://travis-ci.org/sisong/HDiffPatch.svg?branch=master)](https://travis-ci.org/sisong/HDiffPatch)
[![Build status](https://ci.appveyor.com/api/projects/status/t9ow8dft8lt898cv/branch/master?svg=true)](https://ci.appveyor.com/project/sisong/hdiffpatch/branch/master)

a C\C++ library and command-line tools for binary data Diff & Patch; fast and create small delta/differential; support large files and directory(folder) and limit memory requires both diff & patch.
a C\C++ library and command-line tools for Diff & Patch between binary files or directories(folder); cross-platform; fast and create small delta/differential; support large files and limit memory requires when diff & patch.

( update Android Apk? Jar or Zip file diff & patch? try [ApkDiffPatch](https://github.com/sisong/ApkDiffPatch)! )
( NOTE: This library does not deal with file metadata, such as file last wirte time, permissions, link file, etc... To this library, a file is just as a stream of bytes; You can extend this library or use other tools. )

---
## Releases/Binaries
[Download from last release](https://github.com/sisong/HDiffPatch/releases) : Command line app for Windows , Linux , MacOS; and .so .java for Android.
[Download from latest release](https://github.com/sisong/HDiffPatch/releases) : Command line app for Windows, Linux, MacOS; and .so patch lib for Android.

## diff command line usage:
diff usage: **hdiffz** [options] **oldPath newPath outDiffFile**
diff usage: **hdiffz** [options] **oldPath newPath outDiffFile**
compress usage: **hdiffz** [-c-...] **"" newPath outDiffFile**
test usage: **hdiffz** -t **oldPath newPath testDiffFile**
resave usage: **hdiffz** [-c-...] **diffFile outDiffFile**
get manifest: **hdiffz** [-g#...] [-C-checksumType] **inputPath -M#outManifestTxtFile**
Expand Down Expand Up @@ -110,11 +111,11 @@ special options:

## patch command line usage:
patch usage: **hpatchz** [options] **oldPath diffFile outNewPath**
uncompress usage: **hpatchz** [options] **"" diffFile outNewPath**
create SFX: **hpatchz** [-X-exe#selfExecuteFile] **diffFile -X#outSelfExtractArchive**
run SFX: **selfExtractArchive** [options] **oldPath -X outNewPath**
extract SFX: **selfExtractArchive** (same as: selfExtractArchive -f "" -X "./")
extract SFX: **selfExtractArchive** (same as: selfExtractArchive -f "" -X "./")
```
( if oldPath is empty input parameter "" )
memory options:
-m oldPath all loaded into Memory;
requires (oldFileSize+ 4*decompress stream size)+O(1) bytes of memory.
Expand Down Expand Up @@ -222,6 +223,8 @@ Average 100% 28.9% 100% 71.5% 100% 52.3% 29.9% 21.3% 1
```

## HDiffPatch vs xdelta:
system: macOS10.12.6, compiler: xcode8.3.3 x64, CPU: i7 2.5G(turbo3.7G,6MB L3 cache),SSD Disk,Memroy:8G*2 DDR3 1600MHz
(purge file cache before every test)
```
HDiffPatch2.4 hdiffz run by: -s-128 -c-bzip2-9 oldFile newFile outDiffFile
        hpatchz run by: -s-4m oldFile diffFile outNewFile
Expand Down
191 changes: 191 additions & 0 deletions _dir_ignore.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
// _dir_ignore.h
// hdiffz
// Created by housisong on 2019-09-30.
//
/*
The MIT License (MIT)
Copyright (c) 2012-2019 HouSisong
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 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.
*/
#ifndef _dir_ignore_h
#define _dir_ignore_h
#include <vector>
#include <string>
#include <algorithm>
#include "dirDiffPatch/dir_patch/dir_patch.h"

#if (_IS_NEED_DIR_DIFF_PATCH)
static void formatIgnorePathName(std::string& path_utf8){
for (size_t i=0;i<path_utf8.size();++i) {
char c=path_utf8[i];
if ((c=='\\')||(c=='/'))
path_utf8[i]=kPatch_dirSeparator;
#ifdef _WIN32
else if (isascii(c))
path_utf8[i]=(char)tolower(c);
#endif
}
}

#ifdef _WIN32
static const char _private_kIgnoreMagicChar = '?'; //a char not used in path name on WIN32
#else
static const char _private_kIgnoreMagicChar = ':'; //a char not used in path name
#endif
static void _formatIgnorePathSet(std::string& path_utf8){
formatIgnorePathName(path_utf8);
size_t insert=0;
size_t i=0;
while (i<path_utf8.size()) {
char c=path_utf8[i];
if (c=='*'){
if ((i+1<path_utf8.size())&&(path_utf8[i+1]==':')){ // *: as *
path_utf8[insert++]=c; i+=2; //skip *:
}else{
path_utf8[insert++]=_private_kIgnoreMagicChar; ++i; //skip *
}
}else{
path_utf8[insert++]=c; ++i; //skip c
}
}
path_utf8.resize(insert);
}

static hpatch_BOOL _getIgnorePathSetList(std::vector<std::string>& out_pathList,const char* plist){
std::string cur;
while (true) {
char c=*plist;
if ((c=='#')&&(plist[1]==':')){ // #: as #
cur.push_back(c); plist+=2; //skip #:
}else if ((c=='*')&&(plist[1]==':')){ // *: as *:
cur.push_back(c); cur.push_back(':'); plist+=2; //skip *:
}else if ((c=='\0')||((c=='#')&&(plist[1]!=':'))){
if (cur.empty()) return hpatch_FALSE;// can't empty
if (std::string::npos!=cur.find("**")) return hpatch_FALSE;// can't **
_formatIgnorePathSet(cur);
out_pathList.push_back(cur);
if (c=='\0') return hpatch_TRUE;
cur.clear(); ++plist; //skip #
}else if (c==_private_kIgnoreMagicChar){
return hpatch_FALSE; //error path char
}else{
cur.push_back(c); ++plist; //skip c
}
}
}

static bool _matchIgnore(const char* beginS,const char* endS,
const std::vector<const char*>& matchs,size_t mi,
const char* ignoreBegin,const char* ignoreEnd){
//O(n*n) !
const char* match =matchs[mi];
const char* matchEnd=matchs[mi+1];
const char* curS=beginS;
while (curS<endS){
const char* found=std::search(curS,endS,match,matchEnd);
if (found==endS) return false;
bool isMatched=true;
//check front
if (beginS<found){
if (mi>0){ //[front match]*[cur match]
for (const char* it=beginS;it<found; ++it) {
if ((*it)==kPatch_dirSeparator) { isMatched=false; break; }
}
}else{ // ?[first match]
if ((match==ignoreBegin)&&(match[0]!=kPatch_dirSeparator)&&(found[-1]!=kPatch_dirSeparator))
isMatched=false;
}
}
const char* foundEnd=found+(matchEnd-match);
//check back
if (isMatched && (mi+2>=matchs.size()) && (foundEnd<endS)){ //[last match]
if ((matchEnd==ignoreEnd)&&(matchEnd[-1]!=kPatch_dirSeparator)&&(foundEnd[0]!=kPatch_dirSeparator))
isMatched=false;
}
if (isMatched && (mi+2<matchs.size())
&& (!_matchIgnore(foundEnd,endS,matchs,mi+2,ignoreBegin,ignoreEnd)))
isMatched=false;
if (isMatched) return true;
curS=found+1;//continue
}
return false;
}

static bool isMatchIgnore(const std::string& subPath,const std::string& ignore){
assert(!ignore.empty());
std::vector<const char*> matchs;
const char* beginI=ignore.c_str();
const char* endI=beginI+ignore.size();
const char* curI=beginI;
while (curI<endI) {
const char* clip=std::find(curI,endI,_private_kIgnoreMagicChar);
if (curI<clip){
matchs.push_back(curI);
matchs.push_back(clip);
}
curI=clip+1;
}
if (matchs.empty()) return true; // WARNING : match any path
const char* beginS=subPath.c_str();
const char* endS=beginS+subPath.size();
return _matchIgnore(beginS,endS,matchs,0,beginI,endI);
}

static inline bool isMatchIgnoreList(const std::string& subPath,const std::vector<std::string>& ignoreList){
for (size_t i=0; i<ignoreList.size(); ++i) {
if (isMatchIgnore(subPath,ignoreList[i])) return true;
}
return false;
}

struct CDirPathIgnore{
CDirPathIgnore(const std::vector<std::string>& ignorePathListBase,
const std::vector<std::string>& ignorePathList,bool isPrintIgnore)
:_ignorePathListBase(ignorePathListBase),_ignorePathList(ignorePathList),
_isPrintIgnore(isPrintIgnore),_ignoreCount(0){ }
CDirPathIgnore(const std::vector<std::string>& ignorePathList,bool isPrintIgnore)
:_ignorePathListBase(ignorePathList),_ignorePathList(ignorePathList),
_isPrintIgnore(isPrintIgnore),_ignoreCount(0){ }
bool isNeedIgnore(const std::string& path,size_t rootPathNameLen){
std::string subPath(path.begin()+rootPathNameLen,path.end());
formatIgnorePathName(subPath);
bool result= isMatchIgnoreList(subPath,_ignorePathListBase);
if ((!result)&&(&_ignorePathListBase!=&_ignorePathList))
result=isMatchIgnoreList(subPath,_ignorePathList);
if (result) ++_ignoreCount;
if (result&&_isPrintIgnore){ //printf
printf(" ignore file : \"");
hpatch_printPath_utf8(path.c_str()); printf("\"\n");
}
return result;
}
inline size_t ignoreCount()const{ return _ignoreCount; }
private:
const std::vector<std::string>& _ignorePathListBase;
const std::vector<std::string>& _ignorePathList;
const bool _isPrintIgnore;
size_t _ignoreCount;
};
#endif

#endif // dir_ignore_h
6 changes: 3 additions & 3 deletions builds/android_ndk_jni_mk/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ LZMA := 1
ifeq ($(LZMA),0)
Lzma_Files :=
else
# http://www.7-zip.org/sdk.html https://github.com/sisong/lzma
# https://github.com/sisong/lzma
LZMA_PATH := $(LOCAL_PATH)/../../../lzma/C/
Lzma_Files := $(LZMA_PATH)/LzmaDec.c \
$(LZMA_PATH)/Lzma2Dec.c
Expand All @@ -22,8 +22,8 @@ Hdp_Files := $(HDP_PATH)/file_for_patch.c \
Src_Files := $(LOCAL_PATH)/hpatch_jni.c \
$(LOCAL_PATH)/hpatch.c

DEF_LIBS := -lz
DEF_FLAGS := -D_CompressPlugin_zlib
DEF_LIBS := -lz
DEF_FLAGS := -Os -D_CompressPlugin_zlib -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
ifeq ($(LZMA),0)
else
DEF_FLAGS += -D_7ZIP_ST -D_CompressPlugin_lzma -D_CompressPlugin_lzma2 \
Expand Down
2 changes: 1 addition & 1 deletion builds/android_ndk_jni_mk/hpatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
int hpatchz(const char *oldFileName,const char *diffFileName,
const char *outNewFileName, size_t cacheMemory){
return hpatch(oldFileName,diffFileName,outNewFileName,
hpatch_FALSE,hpatch_FALSE,cacheMemory,0,0);
hpatch_FALSE,cacheMemory,0,0);
}
Loading

0 comments on commit a47eb1d

Please sign in to comment.