compress project & files.

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
jassing
Addict
Addict
Posts: 1765
Joined: Wed Feb 17, 2010 12:00 am

compress project & files.

Post by jassing »

I needed a simple way to backup all my sources for a given project...
Comple to console, "CompressProject myproject.pbp" (note, i think you have to close your project to get it written to disk)
it's quick&dirty with no frills... mostly x-plat, except for 1 API call to get the full path.
Just found it useful, so I thought I'd share it. (I suppose you could add it as a tool/menu...)

It will grab files from PB project file, and source file XincludeFile, IncludeFile,IncludeBinary, Import.

Code: Select all

; update 2023-04-24 
;    Use readString() instead of Readdata()
;    small windows improvement
;todo grab hard-coded files (like OpenFile(0,"MyFile.exe") or "OpenDatabase()"

UseLZMAPacker()
;- Regex to pull out any file names that are included in project file or source.
CreateRegularExpression(0,"(?i)^[ \t]*(\<(outputfile|file name|inputfile|executable|icon enable)|import|includefile|xincludefile|includebinary).*$",#PB_RegularExpression_MultiLine)

;- If non-windows, you are case-specific, so ignore lcase() calls
;  we windows user can be sloppy with file names & capitilization...
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows
  Macro LCase(a) : a : EndMacro
CompilerEndIf 

CompilerIf #PB_Compiler_Debugger ;- if debuger, don't use console...
  Macro PrintN(a) : Debug a : EndMacro
  Macro OpenConsole() : : EndMacro
  Macro CloseConsole() : : EndMacro
  Macro Input() : : EndMacro
CompilerEndIf

;- use a map to skip duplicate includes
Global NewMap files.s() 

CompilerIf #PB_Compiler_Unicode
  #PATH_MAX = 32767
CompilerElse
  #PATH_MAX = #MAX_PATH
CompilerEndIf

;- gets fullpath from partial or relative paths
Procedure.s getDirectoryEntry( file.s )
  Protected here.s, dir
  
  dir = ExamineDirectory(#PB_Any, GetPathPart(file), GetFilePart(file))
  If dir
    If NextDirectoryEntry(dir)
      here = GetCurrentDirectory()
      SetCurrentDirectory( GetPathPart(file))
      file = GetCurrentDirectory()+DirectoryEntryName(dir)
      SetCurrentDirectory(here)
    EndIf
    FinishDirectory(dir)
  EndIf
  ProcedureReturn file
EndProcedure

;- detect if the console was opened by windows or w/in cmd.exe 

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  Enumeration
    #ParentInfoPID
    #ParentInfoName
  EndEnumeration
  Procedure.s GetParentInfo(GetWhat, MyPid = 0 )
    Protected lppe.PROCESSENTRY32
    Protected hSnap = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS , 0)
    Static ParentPID, ParentName.s
    Protected.s ReturnInfo
    
    If ParentName = ""
      If MyPid = 0 
        MyPid = GetCurrentProcessId_()
      EndIf
      
      If hSnap <> #INVALID_HANDLE_VALUE
        lppe\dwSize = SizeOf(PROCESSENTRY32)
        If Process32First_(hSnap, @lppe)
            Repeat        
                If lppe\th32ProcessID = mypid 
                    ParentPID = lppe\th32ParentProcessID
                    Debug "my parent pid is = " + Str(ParentPID)
                    Break
                EndIf    
            Until Process32Next_(hSnap, @lppe) = 0
        EndIf        
    
        If Process32First_(hSnap, @lppe)
            Repeat        
              If lppe\th32ProcessID = ParentPID    
                ParentName = PeekS(@lppe\szExeFile[0])
                  Debug "and its name is = " + ParentName
                  Break
                EndIf    
            Until Process32Next_(hSnap, @lppe) = 0
        EndIf        
      EndIf
    EndIf
    
    Select GetWhat 
      Case #ParentInfoName
        ReturnInfo = ParentName
      Case #ParentInfoPID
        ReturnInfo = Str(ParentPID)
    EndSelect
    ProcedureReturn ReturnInfo
  EndProcedure
  Macro IsConsole() : Bool(LCase(GetParentInfo(#ParentInfoName)) = "cmd.exe") : EndMacro
CompilerElse ; Sorry, don't have code for linux/mac, so always say "press enter..."
  Macro isConsole() : #False : EndMacro
CompilerEndIf

Procedure.s GetFullPathName( cPath.s, bExact = #False  )
  Protected cFullPath.s, *Buffer, nSize, *FilePart
  *Buffer = AllocateMemory(#PATH_MAX * SizeOf(Character))
  If *Buffer
    nSize = GetFullPathName_(@cPath,#PATH_MAX,*Buffer,@*FilePart)
    If nSize 
      cFullPath = PeekS(*Buffer,nSize)
      ;If *FilePart
      ;  Debug PeekS(*FilePart)
      ;EndIf 
    EndIf
    FreeMemory(*Buffer)
  Else
    Debug "Alloc failure"
  EndIf
  If bExact :   cFullPath = GetDirectoryEntry( cFullPath ) : EndIf 
  ProcedureReturn cFullPath
EndProcedure

;- just read the text file to a string.
Procedure.s ReadToString( file.s )
  Protected fdata.s, s
  Select GetExtensionPart(file)
    Case "pb","pbp","pbi", "pbf"
      If ReadFile(0,file)
        fdata = ReadString(0,#PB_File_IgnoreEOL,Lof(0))
      EndIf
  EndSelect
  ProcedureReturn fdata
EndProcedure

;- Look in each file for additional files & go recursively.
Procedure ScanForIncludes( file.s )
  Define str.s,path.s, lFile.s, libTmp.s
  Dim results.s(0)
  File=GetFullPathName(file,#True) : lfile=file;: lFile=LCase(file)
  If FindMapElement(files(), lFile)=#False 
    str = ReadToString( file )
    files(lFile)=file
    If str<>""
      t = ExtractRegularExpression(0,str,results())
      path=GetPathPart(file)
      While x < t
        results(x)=Trim(results(x))
        If Left(results(x),3)="<ic"
          results(x)=StringField(StringField(results(x),2,">"),1,"<")
        ElseIf FindString(results(x),#DQUOTE$)
          results(x)=StringField(results(x),2,#DQUOTE$)
        EndIf 
        If LCase(GetExtensionPart(results(x)))="lib"
          ;- add the dll & exp components to the list.
          libTmp=Left(results(x),Len(results(x))-3)
          t+2
          ReDim results( t )
          results(t-1) = libtmp+"dll"
          results( t ) = libtmp+"exp"
        EndIf 
        results(x)=path+results(x)
        If FindMapElement( files(), LCase(results(x)) )= #False
          ScanForIncludes(results(x))
        EndIf 
        x+1  
      Wend
    EndIf 
  EndIf 
EndProcedure

OpenConsole()
Define x, param.s, d, archive.s
x = CountProgramParameters()
If x = 0
  PrintN("You must pass at least 1 file to process..(source or project file, wildcads ok)")
Else ;- for each parameter, scan the file ..
  PrintN("Scanning...")
  While x > 0
    x-1
    param = ProgramParameter()
    ;- Load base project or source file.
    d = ExamineDirectory(#PB_Any, GetPathPart(param),GetFilePart(param))
    If d 
      While NextDirectoryEntry(d)
        If DirectoryEntryType(d)=#PB_DirectoryEntry_File
          If archive = ""
            archive = GetFilePart(DirectoryEntryName(d),#PB_FileSystem_NoExtension)
          EndIf
          
          ScanForIncludes(GetPathPart(param)+DirectoryEntryName(d))
        EndIf
      Wend
      FinishDirectory(d)
    EndIf
  Wend
  
  ;- Get current folder to reduce the folder depth in archive to a relative folder.
  Define here.s = GetCurrentDirectory()
  
  ;- Pack name.
  Define packname.s = FormatDate(here+"\backup\"+archive+"-%yyyy%mm%dd%hh%ii%ss.7z",Date())
  PrintN("Archive: "+packname)
  
  ;- Ensure backup folder is there.
  CreateDirectory(here+"\backup")
  
  ;-create the pack
  CreatePack(0,packname,#PB_PackerPlugin_Lzma,9)
  
  CompilerIf #False    ;- sort the file list.
    NewList filesL.s() ;- Move files to a list for sorting
    ForEach files()
      AddElement(filesl()) : filesl() = files()
    Next
    SortList(filesl(),#PB_Sort_Ascending) ;- Sort the actual list.
    ;ClearMap( files() ) : FreeMap(files())
    Macro files() : filesL() : EndMacro ;- macro to make the rest of the code work with sorted list.
  CompilerEndIf 
  
  ;- Scan the file list and add to the pack
  ForEach files()
    If FileSize(files())>=0
      PrintN("Adding "+files()) 
      AddPackFile(0, files(), ReplaceString(ReplaceString( files(),here, "", #PB_String_NoCase) , "\", "/" ) )  
    EndIf 
  Next
  
  ;- Finish up.
  ClosePack(0)
  FreeRegularExpression(0)
  
  If Not IsConsole() ; don't show 'press enter' if started in cmd.exe
    PrintN("Press 'enter' to close")
    Input() 
  EndIf 
  CloseConsole()
  
  CompilerIf #PB_Compiler_Debugger ;- Open pack if run in IDE
    RunProgram(packname, "", here)
  CompilerEndIf
EndIf 

; IDE Options = PureBasic 6.02 beta 2 LTS (Windows - x64)
; ExecutableFormat = Console
; CursorPosition = 46
; FirstLine = 22
; Folding = 869-83-t2
; Optimizer
; EnableThread
; EnableXP
; Executable = CompressProject.exe
; EnablePurifier
; EnableExeConstant
Last edited by jassing on Mon Apr 24, 2023 10:47 am, edited 1 time in total.
User avatar
HeX0R
Addict
Addict
Posts: 992
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: compress project & files.

Post by HeX0R »

PB files are UTF8 not ASCII (not 100% correct, if you have very old source codes, they might be ascii)
jassing
Addict
Addict
Posts: 1765
Joined: Wed Feb 17, 2010 12:00 am

Re: compress project & files.

Post by jassing »

HeX0R wrote: Sun Apr 23, 2023 8:18 pm PB files are UTF8 not ASCII (not 100% correct, if you have very old source codes, they might be ascii)
I tested w/ everything created with pb6.01 x64 (sources & project file)... adjust as needed?
Fred
Administrator
Administrator
Posts: 16664
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: compress project & files.

Post by Fred »

Yes all files are UTF-8 by default since while now. You can also use #PB_File_IgnoreEOL flag for ReadString() instead of readdata()/Peek combo
jassing
Addict
Addict
Posts: 1765
Joined: Wed Feb 17, 2010 12:00 am

Re: compress project & files.

Post by jassing »

Fred wrote: Mon Apr 24, 2023 9:17 am Yes all files are UTF-8 by default since while now. You can also use #PB_File_IgnoreEOL flag for ReadString() instead of readdata()/Peek combo
that will make things a bit cleaner, thank you.
Post Reply