A handy bit of code to generate patches

Blitz3D Forums/Blitz3D Programming/A handy bit of code to generate patches

Rottbott(Posted 2003) [#1]
I just wrote this, I think it's quite handy. It takes two folders, one of a "new version" and one of an "old version", and creates an output folder with a patch containing all the files which are new or changed between the old and new versions. This allows you to easily create patches for programs without having to remember every little change you made. It also generates a list of all the files in the patch, in a text file. It runs best under BlitzPlus but should work in Blitz3D as well.

; Detects changes between two folders and compiles a directory of files that have changed w/ list

; Settings
Global FO$ = "Another Life Old" ; Folder containing old version
Global FN$ = "Another Life New" ; Folder containing new version
Global Output$ = "Another Life" ; Folder to output patch and files list to

; Go through files/folders recursively and compare to files in old version
ChangeDir FN$
Global FileList = WriteFile(Output$ + "\FilesList.txt")
CheckFolder(".")
CloseFile FileList
Print "Done!"
End

; Checks a folder for changed files compared to old version and adds changes to files list
Function CheckFolder(Folder$)
  Print "Checking: " + Folder$ + "..."
  ; Loop through items
  F = ReadDir(Folder$)
    Item$ = NextFile$(F)
    While Item$ <> ""
      If Item$ <> "." And Item$ <> ".."
        Print "          " + Item$
        ; File - compare
        If FileType(Folder$ + "\" + Item$) = 1
          ; It does exist in old version - check sizes
          If FileType("..\" + FO$ + "\" + Folder$ + "\" + Item$) = 1
            ; Different sizes - list it
            If FileSize(Folder$ + "\" + Item$) <> FileSize("..\" + FO$ + "\" + Folder$ + "\" + Item$)
              ListFile Folder$ + "\" + Item$
            ; Same sizes, do checksum
            Else
              ; Count new checksum
              NewCheck = 0 : OldCheck = 0
              FCheck = ReadFile(Folder$ + "\" + Item$)
                While Eof(FCheck) = False
                  NewCheck = NewCheck + ReadInt(FCheck)
                Wend
              CloseFile FCheck
              FCheck = ReadFile("..\" + FO$ + "\" + Folder$ + "\" + Item$)
                While Eof(FCheck) = False
                  OldCheck = OldCheck + ReadInt(FCheck)
                Wend
              CloseFile FCheck
              ; It changed - list it
              If NewCheck <> OldCheck
                ListFile Folder$ + "\" + Item$
              EndIf
            EndIf
          ; It doesn't exist in old version - list it
          Else
            ListFile Folder$ + "\" + Item$
          EndIf
        ; Folder - write to output and recurse
        ElseIf FileType(Folder$ + "\" + Item$) = 2
          CreateDir "..\" + Output$ + "\" + Folder$ + "\" + Item$
          CheckFolder(Folder$ + "\" + Item$)
        EndIf
      EndIf
      Item$ = NextFile$(F)
    Wend
  CloseDir F
End Function

; Lists a file and copies it to output folder
Function ListFile(Path$)
  WriteLine FileList, Right$(Path$, Len(Path$) - 2)
  CopyFile Path$, "..\" + Output$ + "\" + Path$
End Function


To decide if a file has changed, first it checks if that file existed in the old version. If it did, it checks to see if the file size has changed. If the size is the same, it adds up all the bytes in the file for a sort of checksum, just in case it has changed but remained the same size.


BlitzSupport(Posted 2003) [#2]
Bear in mind that some people will create custom maps for their games, that may well use a fixed file size, eg. storing an absolute 256 x 256 'map' of bytes; if one of those bytes is changed -- possibly changing all instances of a certain tile in a game level -- checking the file size only will detect no change so the new patch folder won't be complete or correct. Same goes for any file where it remains the same after a 'tweak'...

Try calculating a CRC32 checksum for each file and compare the 'possible new' checksum against the old one.

I'd swear I posted CRC32 code ages ago, but it ain't there; however, MrCredo has done the hard part for you... :)

http://www.blitzbasic.com/codearcs/codearcs.php?code=790


Rottbott(Posted 2003) [#3]
James, yep, I am aware of that. My code counts up the values of all the bytes to check if the data has changed. It only does that if the file size is the same though. It's not quite the same as a CRC32 checksum but it works.