<commit_before>; TODO modify the installed redis.conf file to log to a file (instead of stdout).
;      NB we have to use absolute paths in the log file (redis does not play
;         well when we mix the "dir" directive and a relative log file path; it
;         will write the log file under current directory, but after its running,
;         it will write it inside the "dir" setted subdirectory).
; TODO modify the installed redis.conf file to save the database and logs under the "data" subdirectory.
; TODO do not override destiny redis.conf file. instead create a redis.conf.dist
;      with our version, and only override the original if it wasn't modified.
; TODO show a blurb after the install to alert the user to create a dedicated
;      windows account to run redis, change the "data" directory permissions
;      and modify the service startup type to automatic (maybe this should be
;      done automatically?).
; TODO display a redis logo on the left of the setup dialog boxes.
; TODO strip the binaries?

#define AppVersion GetFileVersion(AddBackslash(SourcePath) + "..\src\redis-service.exe")

[Setup]
AppID={{B882ADC5-9DA9-4729-899A-F6728C146D40}
AppName=Redis
AppVersion={#AppVersion}
;AppVerName=Redis {#AppVersion}
AppPublisher=rgl
AppPublisherURL=https://github.com/rgl/redis
AppSupportURL=https://github.com/rgl/redis
AppUpdatesURL=https://github.com/rgl/redis
DefaultDirName={pf}\Redis
DefaultGroupName=Redis
LicenseFile=..\COPYING
InfoBeforeFile=..\README
OutputDir=.
OutputBaseFilename=redis-setup
SetupIconFile=redis.ico
Compression=lzma
SolidCompression=yes

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Files]
Source: "..\src\redis-benchmark.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\redis-check-aof.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\redis-check-dump.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\redis-cli.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\redis-server.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\redis-service.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\redis.conf"; DestDir: "{app}"
Source: "..\README"; DestDir: "{app}"; DestName: "README.txt"
Source: "..\COPYING"; DestDir: "{app}"; DestName: "COPYING.txt"

[Code]
#include "service.pas"

const
  SERVICE_NAME = 'redis';
  SERVICE_DISPLAY_NAME = 'Redis Server';
  SERVICE_DESCRIPTION = 'Persistent key-value database';

function InitializeSetup(): boolean;
begin
  if IsServiceRunning(SERVICE_NAME) then
  begin
    MsgBox('Please stop the ' + SERVICE_NAME + ' service before running this install', mbError, MB_OK);
    Result := false;
  end
  else
    Result := true
end;

function InitializeUninstall(): boolean;
begin
  if IsServiceRunning(SERVICE_NAME) then
  begin
    MsgBox('Please stop the ' + SERVICE_NAME + ' service before running this uninstall', mbError, MB_OK);
    Result := false;
  end
  else
    Result := true
end;

procedure CurStepChanged(CurStep: TSetupStep);
var
  ServicePath: string;
begin
  case CurStep of
    ssPostInstall:
      begin
        if IsServiceInstalled(SERVICE_NAME) then
          Exit;

        ServicePath := ExpandConstant('{app}\redis-service.exe');

        if not InstallService(ServicePath, SERVICE_NAME, SERVICE_DISPLAY_NAME, SERVICE_DESCRIPTION, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START) then
        begin
          MsgBox('Failed to install the ' + SERVICE_NAME + ' service.' #13#13 'You need to install it manually.', mbError, MB_OK)
        end
      end
  end
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  case CurUninstallStep of
    usPostUninstall:
      begin
        if not RemoveService(SERVICE_NAME) then
        begin
          MsgBox('Failed to uninstall the ' + SERVICE_NAME + ' service.' #13#13 'You need to uninstall it manually.', mbError, MB_OK);
        end
      end
  end
end;<commit_msg>Modify the installed configuration to save the databases data into the "data" subdirectory and the logs into the "logs" subdirectory.<commit_after>; TODO show a blurb after the install to alert the user to create a dedicated
;      windows account to run redis, change the "data" directory permissions
;      and modify the service startup type to automatic (maybe this should be
;      done automatically?).
; TODO display a redis logo on the left of the setup dialog boxes.
; TODO strip the binaries?

#define AppVersion GetFileVersion(AddBackslash(SourcePath) + "..\src\redis-service.exe")

[Setup]
AppID={{B882ADC5-9DA9-4729-899A-F6728C146D40}
AppName=Redis
AppVersion={#AppVersion}
;AppVerName=Redis {#AppVersion}
AppPublisher=rgl
AppPublisherURL=https://github.com/rgl/redis
AppSupportURL=https://github.com/rgl/redis
AppUpdatesURL=https://github.com/rgl/redis
DefaultDirName={pf}\Redis
DefaultGroupName=Redis
LicenseFile=..\COPYING
InfoBeforeFile=..\README
OutputDir=.
OutputBaseFilename=redis-setup
SetupIconFile=redis.ico
Compression=lzma
SolidCompression=yes

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Dirs]
Name: "{app}\data";
Name: "{app}\logs";

[Files]
Source: "..\src\redis-benchmark.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\redis-check-aof.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\redis-check-dump.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\redis-cli.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\redis-server.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\redis-service.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\redis.conf"; DestDir: "{app}"; DestName: "redis-dist.conf"; BeforeInstall: BeforeInstallConf; AfterInstall: AfterInstallConf; 
Source: "..\README"; DestDir: "{app}"; DestName: "README.txt"
Source: "..\COPYING"; DestDir: "{app}"; DestName: "COPYING.txt"

[Code]
#include "service.pas"

const
  SERVICE_NAME = 'redis';
  SERVICE_DISPLAY_NAME = 'Redis Server';
  SERVICE_DESCRIPTION = 'Persistent key-value database';

var
  ConfDistFilePath: string;
  ConfFilePath: string;
  ReplaceExistingConfFile: boolean;

function BoolToStr(B: boolean): string;
begin
  if B then Result := 'Yes' else Result := 'No';
end;

function ToForwardSlashes(S: string): string;
begin
  Result := S;
  StringChangeEx(Result, '\', '/', True);
end;

function InitializeSetup(): boolean;
begin
  if IsServiceRunning(SERVICE_NAME) then
  begin
    MsgBox('Please stop the ' + SERVICE_NAME + ' service before running this install', mbError, MB_OK);
    Result := false;
  end
  else
    Result := true
end;

function InitializeUninstall(): boolean;
begin
  if IsServiceRunning(SERVICE_NAME) then
  begin
    MsgBox('Please stop the ' + SERVICE_NAME + ' service before running this uninstall', mbError, MB_OK);
    Result := false;
  end
  else
    Result := true
end;

procedure CurStepChanged(CurStep: TSetupStep);
var
  ServicePath: string;
begin
  case CurStep of
    ssPostInstall:
      begin
        if IsServiceInstalled(SERVICE_NAME) then
          Exit;

        ServicePath := ExpandConstant('{app}\redis-service.exe');

        if not InstallService(ServicePath, SERVICE_NAME, SERVICE_DISPLAY_NAME, SERVICE_DESCRIPTION, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START) then
        begin
          MsgBox('Failed to install the ' + SERVICE_NAME + ' service.' #13#13 'You need to install it manually.', mbError, MB_OK)
        end
      end
  end
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  case CurUninstallStep of
    usPostUninstall:
      begin
        if not RemoveService(SERVICE_NAME) then
        begin
          MsgBox('Failed to uninstall the ' + SERVICE_NAME + ' service.' #13#13 'You need to uninstall it manually.', mbError, MB_OK);
        end
      end
  end
end;

procedure BeforeInstallConf;
var
  ConfDistFileHash: string;
  ConfFileHash: string;
begin
  ConfFilePath := ExpandConstant('{app}\redis.conf');
  ConfDistFilePath := ExpandConstant('{app}\redis-dist.conf');

  if not FileExists(ConfFilePath) then
  begin
    ReplaceExistingConfFile := true;
    Exit;
  end;

  if not FileExists(ConfDistFilePath) then
  begin
    ReplaceExistingConfFile := false;
    Exit;
  end;

  ConfFileHash := GetSHA1OfFile(ConfFilePath);
  ConfDistFileHash := GetSHA1OfFile(ConfDistFilePath);
  ReplaceExistingConfFile := CompareStr(ConfFileHash, ConfDistFileHash) = 0;
end;

procedure AfterInstallConf;
var
  BasePath: string;
  ConfLines: TArrayOfString;
  N: integer;
  Line: string;
begin
  BasePath := RemoveBackslash(ExtractFileDir(ConfDistFilePath));

  if not LoadStringsFromFile(ConfDistFilePath, ConfLines) then
  begin
    MsgBox('Failed to load the ' + ConfDistFilePath + ' configuration file.' #13#13 'This program will not run correctly unless you manually edit the configuration file.', mbError, MB_OK);
    Abort;
  end;

  // NB we need to escape the backslashes in the string arguments on the redis
  //    configuration file. If we are using a file path, we can instead use
  //    forward slashes.

  for N := 0 to GetArrayLength(ConfLines)-1 do
  begin
    Line := Trim(ConfLines[N]);

    if Pos('#', Line) = 1 then
      Continue;

    if Pos('dir ', Line) = 1 then
    begin
      ConfLines[N] := ToForwardSlashes(Format('dir "%s\data"', [BasePath]));
      Continue;
    end;

    if Pos('logfile ', Line) = 1 then
    begin
      ConfLines[N] := ToForwardSlashes(Format('logfile "%s\logs\redis.log"', [BasePath]));
      Continue;
    end;
  end;

  if not SaveStringsToFile(ConfDistFilePath, ConfLines, false) then
  begin
    MsgBox('Failed to save the ' + ConfDistFilePath + ' configuration file.' #13#13 'This program will not run correctly unless you manually edit the configuration file.', mbError, MB_OK);
    Abort;
  end;

  if ReplaceExistingConfFile then
    FileCopy(ConfDistFilePath, ConfFilePath, false);
end;
{'fraction_non_alphanumeric': 0.11228212403729226, 'fraction_numerical': 0.008107012565869477, 'mean_word_length': 4.183298319327731, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3462827', 'n_tokens_mistral': 3204, 'n_tokens_neox': 3059, 'n_words': 921}