Author: Copyright (c) 2020, Marketeer
Miscellaneous
Uses files from the file systemIt reads information from a file
0 Views
0 Downloads
0 Favorites
mql5pack
//+------------------------------------------------------------------+
//|                                                     mql5pack.mq5 |
//|                                    Copyright (c) 2020, Marketeer |
//|                          https://www.mql5.com/en/users/marketeer |
//|                               https://www.mql5.com/en/code/27955 |
//+------------------------------------------------------------------+
#property copyright "Copyright (c) 2020, Marketeer"
#property link "https://www.mql5.com/en/users/marketeer"
#property version "1.1"
#property description "This is MQL5 project packer: assemble all source and resource files from dependencies into a single ZIP."

#property script_show_inputs


// NB: first level folder name is assumed to be created virtual root (real-MQL5 container)
input string VirtualRootFolder = "MQL5";
// by default this script will pack itself with all dependencies
input string MainSourceFile = "Scripts/mql5pack.mq5";
// by default (if PackedFile is empty) zip-filename will be source-file-name.mq*.zip
input string PackedFile = "";
// optionally specify a text file with elements to exclude from process (1 element per line)
input string ExceptionListFilename = "mql5pack.txt";

      string IncludesFolder; // must include trailing slash
      string SourceFile = NULL;
const bool LoadIncludes = true;

// Basic support for icons
// Please load this file from the page https://www.mql5.com/en/code/27955
// Strangely, the codebase does not support ico/png files uploading
// #property icon "mql5pack.png"

// Basic support for Images and Sounds (uncomment for demonstration purpose only)
// #resource "\\Images\\euro.bmp";
// #resource "\\Images\\dollar.bmp";

// this is shell command to create symlink to terminal's data folder with
// all source and resource folders inside MQL5/Files/[pseudo-MQL5-link]
// rename this txt-file to makelink.bat (bat-files can not be added as resources!)
#resource "\\Files\\makelink.txt" as string __cmd1Folder

// example with exception list (standard included files)
#resource "\\Files\\mql5pack.txt" as string __exceptionListExample


// #define UNICODE_WARNING
#include <mql5/FileReader.mqh>
#include <Zip/Zip.mqh>


CZip Zip;      // Create empty zip archive.

bool ProcessTarget(const string name, string &result[])
{
  Preprocessor loader(name, IncludesFolder, LoadIncludes);
  if(!loader.run())
  {
    Print("Loader failed for ", name);
    return false;
  }
  
  Print("Files processed: ", loader.scannedFilesCount());
  Print("Source length: ", loader.totalCharactersCount());
  
  const uint n = loader.scannedFilesCount();
  ArrayResize(result, n);
  
  for(uint i = 0; i < n; i++)
  {
    result[i] = loader.scannedFilename(i);
  }
  return true;
}

string TimeStamp(const datetime now = 0)
{
  string result = TimeToString(now == 0 ? TimeLocal() : now, TIME_DATE|TIME_MINUTES|TIME_SECONDS);
  StringReplace(result, ".", "");
  StringReplace(result, ":", "");
  StringReplace(result, " ", "");
  return result;
}

void OnStart()
{
  Print("\n");

  IncludesFolder = VirtualRootFolder + "/Include/";

  string exceptions[];
  int ex = 0;
  
  if(StringLen(ExceptionListFilename) > 0)
  {
    int h = FileOpen(ExceptionListFilename, FILE_READ | FILE_TXT | FILE_ANSI | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CP_UTF8);
    if(h == INVALID_HANDLE)
    {
      Print("Can't open ", ExceptionListFilename, " ", GetLastError());
    }
    else
    {
      while(!FileIsEnding(h))
      {
        string line = FileReadString(h);
        if(StringLen(line) > 0)
        {
          StringToLower(line);
          ArrayResize(exceptions, ex + 1);
          exceptions[ex++] = line;
        }
      }
      FileClose(h);
    }
  }
  

  Print("Scanning...");

  string targets[];
  string all[];
  int duplicates = 0;
  int processed = 0;
  const int m = StringSplit(MainSourceFile, ';', targets);
  for(int i = 0; i < m; i++)
  {
    if(StringLen(targets[i]) == 0) continue;

    if(SourceFile == NULL) SourceFile = VirtualRootFolder + "/" + targets[i];

    string result[];
    if(ProcessTarget(VirtualRootFolder + "/" + targets[i], result))
    {
      processed++;

      const int p = ArraySize(all);
      ArrayCopy(all, result, p);
      
      // check for duplicates
      for(int j = p; j < ArraySize(all); j++) // candidates
      {
        for(int k = 0; k < p; k++)            // existing
        {
          if(StringCompare(all[j], all[k]) == 0)
          {
            all[j] = NULL;
            duplicates++;
            break;
          }
        }
      }
    }
  }
  
  if(processed > 1)
  {
    Print("Multiple targets: ", processed);
  }

  if(duplicates > 0)
  {
    Print("Shared files count: ", duplicates);
  }
  

  string root = VirtualRootFolder;
  StringToLower(root);

  int added = 0, j;
  const uint n = ArraySize(all);
  string listing = "";

  if(n > 0)
  {
    Print("Packing...");
  }
  
  for(uint i = 0; i < n; i++)
  {
    string name = all[i];
    
    if(name == NULL) continue;
    
    for(j = 0; j < ex; j++)
    {
      string _name = name;
      StringToLower(_name);
      if(StringFind(_name, root + "/" + exceptions[j]) == 0)
      {
        Print(" - ", name);
        listing += " - " + name + "\n";
        break;
      }
    }
    
    if(j < ex) continue;
    
    Print(" + ", name);
    listing += " + " + name + "\n";
    CZipFile *file = new CZipFile();
    if(!file.AddFile(name)
    || !Zip.AddFile(file))
    {
      delete file;
    }
    else
    {
     added++;
    }
  }
  
  if(added > 0)
  {
    string target = processed > 1 ? "Multi_Target_Archive_" + TimeStamp() : SourceFile;
    string dirfile = target + ".log";
    StringReplace(dirfile, "/", "_");
    uchar array[];
    StringToCharArray(listing, array, 0, WHOLE_ARRAY, CP_UTF8);
    CZipFile *dir = new CZipFile(dirfile, array);
    Zip.AddFile(dir);
    
    const string archive = (PackedFile != "" ? PackedFile : target) + ".zip";
    if(Zip.SaveZipToFile(archive))
    {
      Print("Packed file saved: ", archive);
    }
  }
  else
  {
    Print("No files added.");
    Print("Make sure to create pseudo-MQL5-link in the real MQL5/Files folder by running makelink.bat:");
    Print(__cmd1Folder);
  }
}

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---