root/trunk/IssBuilderLogic.pas

Revision 158, 36.5 kB (checked in by sagrer, 5 months ago)
  1. Поправлены параметры запуска VerRevUpdater? через IDE
  2. Прикручена локализация в FlistFormat?.pas, IssFormat?.pas, SconfFormat.pas, PascalCodeModifier?.pas
  3. Прикручена локализация к IssBuilder?.
  4. Добавлен перевод на русский для IssBuilder?
  5. Выполнен #34
  • Property svnmailer:content-charset set to cp1251
Line 
1 ///////////////////////////////////////////////////////////
2 //                     GGBuildTools                      //
3 //    Набор утилит для сборки проектов Gipat Group       //
4 //             Copyright (C) 2007 Gipat Group            //
5 //              Распространяется на условиях             //
6 //    Gipat Group's opened EI-editor-utility license     //
7 //                      версии 1.0                       //
8 //                                                       //
9 //                  www.gipatgroup.org                   //
10 ///////////////////////////////////////////////////////////
11
12 //К работе над данным файлом приложили руки, ноги.... короче аффтары:
13 // 1) Sagrer (sagrer@yandex.ru)
14
15 ////////////////////////////////////////////////////////////////////////
16
17 ///////////////////////////////////////////////////////////////
18 //         Класс для логики (т.е. того что не зависит        //
19 //           от интерфейса) софтины вроде IssBuilder         //
20 ///////////////////////////////////////////////////////////////
21
22 //Рассчитано на работу с InnoSetup 5.
23
24 unit IssBuilderLogic;
25
26 {$mode objfpc}{$H+}
27
28 interface
29
30 uses
31   Classes, SysUtils, SconfFormat, IssFormat, VerInfoTxtFormat, ExtraFileUtilsLCL,
32   Registry, FlistFormat, process, forms, FileUtil, ExtraFunctionsLCL, TranslManager;
33  
34 const
35   ISSB_CompilerExecutableName = 'ISCC.exe';
36
37 type
38   FPostExternalMessage = procedure(const TextMessage : AnsiString) of object;    //Тип функции для вызова внешней функции вывода мессаги.
39
40   TIssBuilderLogic = class     //Класс, реально выполняющий работу софтины, по идее независим от интерфейса
41   private
42      Registr : TRegistry;               //Объект класса для работы с вендовым реестром.
43   protected
44     //Защищенные методы.
45    
46   public
47     //Переменные.
48     ErrorMessage : AnsiString;                          //Мессага про ошибку.
49     PostExternalMessage : FPostExternalMessage;         //Функция, воспринимающая сообщения от выполняющегося процесса.
50    
51     //Переменные с "рабочей инфой".
52     SconfFilePath : AnsiString;         //Полный путь к загруженному sconf-файлу.
53     ProjectName : AnsiString;           //Имя проекта.
54     ProjectLocalRoot : AnsiString;      //Локальный путь к проекту.
55     ProjectGlobalRoot : AnsiString;     //Глобальный путь к проекту.
56     ProjectSconf : TSconfFormat;        //Для инфы из sconf проекта.
57     ProjectVit : TVerInfoTxtFormat;     //Для инфы из\для *.vit
58     DefaultIss : TIssFormat;            //Для инфы из дефолтного *.iss
59     CurrentIss : TIssFormat;            //Для текущей iss-ки.
60     CurrentFlist : TFlistFormat;        //Для списка файлов текущей версии.
61     CurrentIssFileName : AnsiString;    //Полный путь к файлу с текущей iss.
62     NoCacheWrite : Boolean;             //Если true - то не будет записывать в кеш вообще ничего. По умолчанию false.
63     ISCC_Path : AnsiString;             //Путь к компилеру InnoSetup.
64     GlobalCachePath : AnsiString;       //Путь к каталогу с кешем (глобальный).
65     GlobalOutputPath : AnsiString;      //Глобальный путь куда будет ложиться собранная инсталляха.
66     GlobalSourcePath : AnsiString;      //Глобальный путь откуда будут браться файлы дистрибутива.
67     LocalOutputPath : AnsiString;       //Локальный (!)относительно кеша(!) путь куда будет ложиться собранная инсталляха.
68     LocalSourcePath : AnsiString;       //Локальный (!)относительно кеша(!) путь откуда будут браться файлы дистрибутива.
69     OldestVerFN : AnsiString;           //Сюда функция AddUpdates сбрасывает самое старое имя версии (в FN-формате) которое было добавлено в iss-ку.
70
71     //Конструкторы-деструкторы...
72     constructor Create; virtual;
73     destructor Destroy; override;
74
75     //Открытые методы...
76     function LoadConfigs() : Boolean;   //Прочитать привязанные к Sconf файлы - *.vit и *.iss. Получить инфу по компилеру Iss. И такой еще момент - в sconf должно быть [Main] ProjectVer=Project, иначе прога не сможет понимать номера версий а без этого не получится собирать iss.
77     procedure NewCurrentIssFromDef();       //Получить CurrentIss на основе DefaultIss
78     procedure AddAppInfo();        //Вбить в iss текущую инфу проги.
79     function AddVersionUpdate(var VitInfo : TVerInfoTxtFormat) : Boolean;    //Вбить в iss апдейт с указанной версии.
80     function AddVersionUpdate(const VerStr : AnsiString) : Boolean;   //Вбить в iss апдейт с указанной версии. Версия в виде строки - 4 цифры разделенные подчеркиванием + буквы статуса - вроде 0.1.0.10rc1
81     function AddUpdates(const UpdVers : AnsiString; const SeparateBuilderMode : Boolean = false) : Boolean;   //По умолчанию - просто добавить апдейты, указанные в строке UpdVers (в формате как в Sconf, например для [IssBuilder].CreateSeparateUpds_UpdVers). В режиме раздельной сборки (SeparateBuilderMode) - сейвит отдельные iss-ки и сразу же билдяет их.
82     function GenFullInstall() : Boolean;   //Сгенерить полную инсталляху по Sconf, который уже должен быть загружен.
83     function GenSeparateUpdates() : Boolean;  //Сгенерить раздельные обновлялки по Sconf, который уже должен быть загружен.
84     function GenCumulateUpdate() : Boolean;  //Сгенерить кумулятивный апдейт по Sconf, который уже должен быть загружен.
85     function ProcessSconf() : Boolean;   //Работать по правилам, описанным в Sconf - он должен быть уже загружен.
86     function BuildIssFile(const FileName : AnsiString) : Boolean;    //Запустить сборку iss консольным компилером InnoSetup.
87
88   end;
89
90 implementation
91
92 /////////////////////////////////////////////
93 //            Внутренние функции           //
94 /////////////////////////////////////////////
95
96 function CompareVersionStrs(List: TStringList; Index1: Integer; Index2: Integer) : Integer;
97 //Функция для кастомной сортировки TStringList с версиями.
98 var
99   Vit1, Vit2 : TVerInfoTxtFormat;
100 begin
101   //Инициализация.
102   Result := 0;
103   Vit1 := TVerInfoTxtFormat.Create;
104   Vit2 := TVerInfoTxtFormat.Create;
105  
106   //Закидываем инфу.
107   Vit1.ReadFromFNString(List.Strings[Index1]);
108   Vit2.ReadFromFNString(List.Strings[Index2]);
109
110   //Сравниваем.
111   if Vit1.IIsNewerThenOldVit(Vit2) = true then begin
112     Result := 1;
113   end
114   else if Vit1.IsSameVersion(Vit2) = false then begin
115     Result := -1;
116   end;
117  
118   //Выкинуть мусор.
119   Vit1.Free;
120   Vit2.Free;
121 end;
122
123 /////////////////////////////////////////////
124 //             TIssBuilderLogic            //
125 /////////////////////////////////////////////
126
127 //-----------------------------------------//
128 //        Конструкторы-деструкторы...      //
129 //-----------------------------------------//
130
131 constructor TIssBuilderLogic.Create;
132 begin
133   //Проставить дефолтные значения...
134
135   //Просто забить инфу в переменные...
136   SconfFilePath := '';
137   ErrorMessage := '';
138   CurrentIssFileName := '';
139   NoCacheWrite := false;
140   ISCC_Path := '';
141   GlobalCachePath := '';
142   GlobalOutputPath := '';
143   GlobalSourcePath := '';
144   LocalOutputPath := '';
145   LocalSourcePath := '';
146   OldestVerFN := '';
147
148   //Создать вложенные объекты классов...
149   ProjectSconf := TSconfFormat.Create;
150   ProjectVit := TVerInfoTxtFormat.Create;
151   DefaultIss := TIssFormat.Create;
152   CurrentIss := TIssFormat.Create;
153   Registr := TRegistry.Create;
154   CurrentFlist := TFlistFormat.Create;
155 end;
156
157 destructor TIssBuilderLogic.Destroy;
158 begin
159   //Выкидываем мусор
160   ProjectSconf.Free;
161   ProjectVit.Free;
162   DefaultIss.Free;
163   CurrentIss.Free;
164   Registr.Free;
165   CurrentFlist.Free;
166
167   //Выполнить унаследованный деструктор
168   inherited;
169 end;
170
171 //------------------------------------------//
172 //           Защищенные методы...           //
173 //------------------------------------------//
174
175 //------------------------------------------//
176 //            Открытые методы...            //
177 //------------------------------------------//
178
179 function TIssBuilderLogic.LoadConfigs() : Boolean;
180 //Прочитать привязанные к Sconf файлы - *.vit и *.iss.
181 //Получить инфу по компилеру Iss.
182 //И такой еще момент - в sconf должно быть [Main] ProjectVer=Project, иначе прога
183 //не сможет понимать номера версий а без этого не получится собирать iss.
184 var
185   TempStr : AnsiString;
186  
187 begin
188   //Инициализация.
189   Result := true;
190  
191   //Для начала.... проверим, удастся ли найти InnoSetup Compuler.
192   //HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 5_is1 - тут в реестре должна по идее валяться
193   //инфа про расположение установленной софтины.
194   Self.Registr.RootKey := HKEY_LOCAL_MACHINE;
195   if Registr.OpenKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 5_is1',false) = true then begin
196     //Есть такой ключик. Он уже вроде как открыт. Смотрим, есть ли там значение с ключегом.
197     if Registr.ValueExists('InstallLocation') = true then begin
198       Self.ISCC_Path := AddLastSlash(Registr.ReadString('InstallLocation'))+ISSB_CompilerExecutableName;
199     end;
200     Registr.CloseKey;
201    
202     //Смотрим - существует ли файл компилера.
203     if FileExists(Self.ISCC_Path) = true then begin
204       //Есть такое дело.
205       Self.PostExternalMessage(_('InnoSetup 5 compiler found at path ')+Self.ISCC_Path);
206     end
207     else begin
208       //Нема компилера.
209       Result := false;
210       Self.ErrorMessage := _('InnoSetup 5 compiler at path ')+Self.ISCC_Path+_(' is not exists!');
211       Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
212     end;
213   end
214   else begin
215     //Нема. Видать не установлен InnoSetup.
216     Result := false;
217     Self.ErrorMessage := _('InnoSetup 5 seems not to be installed.');
218     Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
219   end;
220  
221   //Если компилер найден - то попытаемси прочитать *.vit файл.
222   if Result = true then begin
223     TempStr := AddLastSlash(Self.ProjectGlobalRoot)+Self.ProjectName+'.vit';   //Имя *.vit файла.
224     if FileExists(AddLastSlash(Self.ProjectGlobalRoot)+Self.ProjectName+'.vit') = true then begin
225       //Есть. Читаем.
226       Self.PostExternalMessage(_('Reading file ')+TempStr);
227       if Self.ProjectVit.Load(TempStr) = true then begin
228         //Прочитано.
229         Self.PostExternalMessage(_('Readed.'));
230       end
231       else begin
232         //Хз какая ошибка.
233         Result := false;
234         Self.ErrorMessage := _('VIT format error : ')+Self.ProjectVit.ErrorMessage;
235         Self.PostExternalMessage(Self.ErrorMessage);
236       end;
237     end
238     else begin
239       //Нема такого файла.
240       Result := false;
241       Self.ErrorMessage := _('Can''t find file ')+TempStr;
242       Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
243     end;
244   end;
245  
246   //Аналогично - читаем *.iss. Сначала надо получить абсолютное имя файла.
247   if Result = true then begin
248     TempStr := Self.ProjectSconf.IssBuilderSection.DefaultIssName;
249     //Превращаем локальный путь в глобальный.
250     TempStr := ResolveLocalPath(TempStr,Self.ProjectGlobalRoot);
251     //Теперь собсно если файлег существует - читаем.
252     if FileExists(TempStr) = true then begin
253       //Есть. Читаем.
254       Self.PostExternalMessage(_('Reading file ')+TempStr);
255       if Self.DefaultIss.Load(TempStr) = true then begin
256         //Прочитано.
257         Self.PostExternalMessage(_('Readed.'));
258       end
259       else begin
260         //Хз какая ошибка.
261         Result := false;
262         Self.ErrorMessage := _('VIT format error : ')+Self.DefaultIss.ErrorMessage;
263         Self.PostExternalMessage(Self.ErrorMessage);
264       end;
265     end
266     else begin
267       //Нема такого файла.
268       Result := false;
269       Self.ErrorMessage := _('Can''t find file ')+TempStr;
270       Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
271     end;
272   end;
273  
274 end;
275
276 procedure TIssBuilderLogic.NewCurrentIssFromDef();
277 //Получить CurrentIss на основе DefaultIss
278 begin
279   Self.CurrentIss.MakNewFile();
280   Self.CurrentIss.TextFil1.FileString := Self.DefaultIss.TextFil1.FileString;
281 end;
282
283 procedure TIssBuilderLogic.AddAppInfo();
284 //Вбить в iss текущую инфу проги.
285 //var
286   //TempStr : AnsiString;
287 begin
288   //[Setup]
289   //OutputDir
290   Self.CurrentIss.WriteString('Setup','OutputDir',Self.LocalOutputPath);
291   //SourceDir
292   Self.CurrentIss.WriteString('Setup','SourceDir',Self.LocalSourcePath);
293   //VersionInfoVersion
294   Self.CurrentIss.WriteString('Setup','VersionInfoVersion',Self.ProjectVit.GenerateDotsVersionString());
295   //VersionInfoTextVersion
296   Self.CurrentIss.WriteString('Setup','VersionInfoTextVersion',Self.ProjectName+' '+Self.ProjectVit.GenerateShortVersionString_nosvn());
297   //VersionInfoDescription
298   Self.CurrentIss.WriteString('Setup','VersionInfoDescription',Self.ProjectName+' '+Self.ProjectVit.GenerateShortVersionString_nosvn());
299   //AppVerName
300   Self.CurrentIss.WriteString('Setup','AppVerName',Self.ProjectName+' '+Self.ProjectVit.GenerateShortVersionString_nosvn());
301  
302   //[Code]
303   //AppName
304   Self.CurrentIss.WriteCodeConstValue('AppName',''''+Self.ProjectName+'''');
305   //AppVer
306   Self.CurrentIss.WriteCodeConstValue('AppVer',''''+Self.ProjectVit.GenerateDotsVersionString()+'''');
307  
308 end;
309
310 function TIssBuilderLogic.AddVersionUpdate(var VitInfo : TVerInfoTxtFormat) : Boolean;
311 //Вбить в iss апдейт с указанной версии.
312 var
313   OldIss : TIssFormat;
314   OldFlist : TFlistFormat;
315   ComponName, FuncName, OldFileName, NewFileName : AnsiString;
316  
317 begin
318   //Инициализация.
319   Result := true;
320   OldIss := TIssFormat.Create;
321   OldFlist := TFlistFormat.Create;
322   OldFileName := Self.GlobalCachePath+Self.ProjectName+'_'+VitInfo.GenerateFNVersionString();
323   NewFileName := Self.GlobalCachePath+Self.ProjectName+'_'+Self.ProjectVit.GenerateFNVersionString();
324
325   //Так. Вбить надо следующие везчи - компонент версии, затем разницу с версии, затем файлы разницы версий.
326   //Вбиваем компонент...
327   ComponName := 'UpdFrom_'+VitInfo.GenerateFNVersionString_nostatus()+'_Main';
328   FuncName := 'CheckUpdate_'+VitInfo.GenerateFNVersionString_nostatus();
329   Self.CurrentIss.WriteComponent(ComponName,
330     'Name: '+ComponName+'; Description: Обновление с версии '+VitInfo.GenerateShortVersionString_nosvn()+
331     '; Flags: fixed; Check: '+FuncName+'; Types: StandardInstall');
332    
333   //Вбиваем функцию-проверялку обновления...
334   Self.CurrentIss.WriteCodeFunction(FuncName,'Function '+FuncName+'() : boolean;'+#13+#10+
335     'begin'+#13+#10+'  if (CurrentVer = '''+VitInfo.GenerateDotsVersionString()+''') then Result := true;'+
336     #13+#10+'end;');
337    
338   //Вбиваем разницу между версиями...
339   OldFileName := Self.GlobalCachePath+Self.ProjectName+'_'+VitInfo.GenerateFNVersionString();
340   if FileExists(OldFileName+'.iss') = true then begin
341     Self.CurrentIss.UpdateInfoToVerUpdate(OldFileName+'.iss',ComponName);
342   end
343   else begin
344     Result := false;
345     Self.ErrorMessage := _('Can''t load file ')+OldFileName+'.iss';
346     Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
347   end;
348  
349   //Вбиваем разницу в файлах.
350   if Result = true then begin
351     Result := OldFlist.Load(OldFileName+'.flist');
352     if Result = true then Result := Self.CurrentIss.AddNewFilesFromFlists(OldFlist,Self.CurrentFlist,ComponName);
353     if Result = false then begin
354       Self.ErrorMessage := _('Can''t compare flists ')+OldFileName+_('.flist and ')+NewFileName+'.flist';
355       Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
356     end;
357   end;
358  
359   //Выкинуть мусор.
360   OldIss.Free;
361   OldFlist.Free;
362 end;
363
364 function TIssBuilderLogic.AddVersionUpdate(const VerStr : AnsiString) : Boolean;
365 //Вбить в iss апдейт с указанной версии. Версия в виде строки - 4 цифры разделенные подчеркиванием + буквы статуса - вроде 0.1.0.10rc1
366 var
367   TempVitInfo : TVerInfoTxtFormat;
368  
369 begin
370   //Функция - практически заглушка, все её назначение - перевести версию в формат инфы класса из строки и вызвать реальную функцию.
371   //Инициализация.
372   TempVitInfo := TVerInfoTxtFormat.Create;
373  
374   //Прочитать инфу...
375   Result := TempVitInfo.ReadFromFNString(VerStr);
376   if Result = true then begin
377     //Вызвать реально работающую функцию.
378     Result := Self.AddVersionUpdate(TempVitInfo);
379   end
380   else begin
381     Self.ErrorMessage := TempVitInfo.ErrorMessage;
382     Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
383   end;
384  
385   //Выкинуть мусор.
386   TempVitInfo.Free;
387 end;
388
389 function TIssBuilderLogic.AddUpdates(const UpdVers : AnsiString; const SeparateBuilderMode : Boolean = false) : Boolean;
390 //По умолчанию - просто добавить апдейты, указанные в строке UpdVers (в формате как в
391 //Sconf, например для [IssBuilder].CreateSeparateUpds_UpdVers). В режиме раздельной
392 //сборки (SeparateBuilderMode) - сейвит отдельные iss-ки и сразу же билдяет их.
393 var
394   CurrIssBackUp, FindedName, TempStr, VersionsStr : AnsiString;
395   VersionsList : TStringList;
396   SearchRec : TSearchRec;
397   I, UpdatesNum, J : Integer;
398   TempVit1, TempVit2 : TVerInfoTxtFormat;
399   Finded : Boolean;
400  
401 begin
402   //Инициализация.
403   Result := true;
404   VersionsList := TStringList.Create;
405   UpdatesNum := 0;
406   TempVit1 := TVerInfoTxtFormat.Create;
407   TempVit2 := TVerInfoTxtFormat.Create;
408  
409   //Существует ли каталог с кешем?
410   if DirectoryExists(Self.GlobalCachePath) = false then begin
411     Result := false;
412     Self.ErrorMessage := _('Can''t find directory ')+Self.GlobalCachePath;
413     Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
414   end;
415  
416   //Если нужно - сейвануть текущее состояние iss-ки.
417   if (SeparateBuilderMode = true) and (Result = true) then begin
418     CurrIssBackUp := Self.CurrentIss.TextFil1.FileString;
419   end;
420  
421   //Теперь надо составить список версий из кеша.
422   if Result = true then begin
423     VersionsList.Clear;
424     if FindFirst(AddLastSlash(Self.GlobalCachePath)+Self.ProjectName+'_*.flist', faAnyFile, SearchRec) = 0 then begin
425       //Если поиск успешно начат.
426       repeat
427         //Повторяем поиск пока не закончится то что можно искать %).
428         if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') and (IsDirectory(AddLastSlash(Self.GlobalCachePath)+SearchRec.Name) = false) then begin
429           //Чего-то нашли. Убираем у файла расширение...
430           FindedName := GetFileNameWithoutExtension(SearchRec.Name);
431           //Кромсаем начало строки чтобы осталась только версия.
432           Delete(FindedName,1,Length(Self.ProjectName+'_'));
433           //Проверяем формат версии...
434           if TempVit1.ReadFromFNString(FindedName) = true then begin;
435             //Версия хотя-бы правильного формата... Сравниваем с текущей...
436             if Self.ProjectVit.IIsNewerThenOldVit(TempVit1) = true then begin
437               //Найденная версия старее чем текущая - её можно добавить в список.
438               //Но сначала надо проверить - существует ли *.iss-файлег с тем же именем.
439               if FileExists(AddLastSlash(Self.GlobalCachePath)+GetFileNameWithoutExtension(SearchRec.Name)+'.iss') = true then begin
440                 //Собсно есть такой файлег - можно добавлять.
441                 VersionsList.Add(FindedName);
442               end;
443             end;
444           end;
445         end;
446       until FindNext(SearchRec) <> 0;
447      
448       //Если нужно - отсортировать список.
449       if VersionsList.Count > 1 then begin
450         VersionsList.CustomSort(@CompareVersionStrs);
451       end;
452     end
453     else begin
454       //Это не ошибка - просто в кеше нет ни 1 версии.
455       Self.PostExternalMessage(_('Can''t find any version in directory ')+Self.GlobalCachePath);
456     end;
457   end;
458  
459   //Подсчитать количество апдейтов.
460   UpdatesNum := VersionsList.Count;    //По умолчанию - обрабатываем все.
461   if IsNumericStr(UpdVers) = true then begin
462     //Просто обработать StrToInt(UpdVers) последних версий.
463     if VersionsList.Count > StrToInt(UpdVers) then UpdatesNum := StrToInt(UpdVers);
464   end
465   else begin
466     //Либо All либо From.
467     if LowerCase(UpdVers) = 'all' then begin
468       //All. Просто обрабатываем все что есть.
469       //UpdatesNum := VersionsList.Count;    //Уже присвоено выше.
470     end
471     else begin
472       //Скорее-всего From.
473       if Length(UpdVers) > Length('From:') then begin
474         //гм, вполне вероятно...
475         TempStr := UpdVers;
476         if LowerCase(Parse(TempStr,':')) = 'from' then begin
477           if TempVit1.ReadFromString(TempStr) = true then begin
478             //Если версия прочиталась - то теперь сравниваем её с версиями в списке.
479             UpdatesNum := 0;
480             for I := 0 to VersionsList.Count-1 do begin
481               //Смотрим - не меньше ли субж чем минимальная версия.
482               TempVit2.ReadFromFNString(VersionsList.Strings[I]);
483               if TempVit1.IIsNewerThenOldVit(TempVit2) = false then begin
484                 //Субж больше или равен минимальной версии.
485                 UpdatesNum := UpdatesNum+1;
486               end;;
487             end;
488           end;
489         end;
490       end;
491     end;
492   end;
493   //Подсчитано.
494
495   //Теперь - запускаем добавление нужного количества апдейтов в iss.
496   VersionsStr := '';   //Тут будет список версий для константы кода в *.iss.
497   if SeparateBuilderMode = false then begin
498     //При работе в обычном режиме - сообщить о записи апдейтов.
499     Self.PostExternalMessage(_('Adding updates:'));
500   end;
501   For I := UpdatesNum-1 downto 0 do begin
502     J := (VersionsList.Count-1)-I;   //Текущая добавляемая версия.
503     //Если это самая первая, а значит самая старая добавляемая версия - то запомнить её.
504     if I = UpdatesNum-1 then begin
505       Self.OldestVerFN := VersionsList.Strings[J];
506     end;
507     //Добавляем файлы версии, компонент, прочие различия...
508     TempVit1.ReadFromFNString(VersionsList.Strings[J]);     //Результат функции не проверяется - по алгоритму список уже проверен на правильность.
509     Result := Self.AddVersionUpdate(TempVit1);
510     //В зависимости от механизма работы - либо обновляем список версий, либо собираем iss-ку.
511     if Result = true then begin
512       if SeparateBuilderMode = false then begin
513         //Обычный режим работы. Добавляем версию.
514         if Length(VersionsStr) > 0 then begin
515           //Если в строке уже что-то есть - надо добавить разделитель.
516           VersionsStr := VersionsStr+';';
517         end;
518         VersionsStr := VersionsStr+TempVit1.GenerateDotsVersionString();
519       end
520       else begin
521         //"Раздельный" режим работы.
522         //Вписываем в iss-ку номер апдейтабельной версии...
523         Self.CurrentIss.WriteCodeConstValue('UpdateFrom',''''+TempVit1.GenerateDotsVersionString()+'''');
524         //Генерим имя Iss-ки...
525         Self.CurrentIssFileName := AddLastSlash(Self.GlobalCachePath)+Self.ProjectName+'_'+TempVit1.GenerateFNVersionString()+'_to_'+Self.ProjectVit.GenerateFNVersionString()+'.iss';
526         //Вбиваем имя Output...
527         Self.CurrentIss.WriteString('Setup','OutputBaseFilename',GetFileNameWithoutExtension(Self.CurrentIssFileName));
528         //Сейвим Iss-ку.
529         Result := Self.CurrentIss.Save(Self.CurrentIssFileName);
530         if Result = true then begin
531           Self.PostExternalMessage(_('Saved file ')+Self.CurrentIssFileName);
532           //Запускаем сборку Iss-ки.
533           Result := Self.BuildIssFile(Self.CurrentIssFileName);
534           if Self.NoCacheWrite = true then begin
535             //Если в кеш ничО нельзя писать - убить нафег iss-ку
536             if DeleteFile(Self.CurrentIssFileName) = true then begin
537               Self.PostExternalMessage(_('Deleted file ')+Self.CurrentIssFileName);
538             end
539             else begin
540               Self.PostExternalMessage(_('Achtung!!! Can''t delete file ')+Self.CurrentIssFileName);
541             end;
542           end;
543         end
544         else begin
545           //Облом сохранения.
546           Self.ErrorMessage := _('Can''t save file ')+Self.CurrentIssFileName;
547           Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
548         end;
549         //Засейвлено и скомпилено - восстанавливаем забекапленный текст iss-ки.
550         Self.CurrentIss.TextFil1.FileString := CurrIssBackUp;
551       end;
552     end
553     else begin
554       //Ошибк при добавлении файлов. В принципе о ошибке уже сообщила AddVersionUpdate.
555     end;
556    
557     //Если все ок - и работаем в обычном режиме - оставляем сообщение о добавленной версии.
558     if (Result = true) and (SeparateBuilderMode = false) then begin
559       Self.PostExternalMessage('         '+VersionsList.Strings[J]);
560     end;
561    
562     //В случае ошибки в интерации - остановка.
563     if Result = false then Break;
564   end;
565  
566   if (Result = true) and (SeparateBuilderMode = false) then begin
567     //Если работали в обычном режиме - закинуть список версий в константу.
568     Self.CurrentIss.WriteCodeConstValue('UpdateFrom',''''+VersionsStr+'''');
569     //Сообщаем о успешном завершении записи апдейтов.
570     Self.PostExternalMessage(_('Updates added.'));
571   end;
572  
573   //Выкинуть мусор.
574   VersionsList.Free;
575   TempVit1.Free;
576   TempVit2.Free;
577 end;
578
579 function TIssBuilderLogic.GenFullInstall() : Boolean;
580 //Сгенерить полную инсталляху по Sconf, который уже должен быть загружен.
581 begin
582   //Инициализация.
583   Result := true;
584  
585   //Готовим Iss-ку...
586   Self.NewCurrentIssFromDef();
587   Self.CurrentIssFileName := AddLastSlash(Self.GlobalCachePath)+Self.ProjectName+'_'+Self.ProjectVit.GenerateFNVersionString()+'.iss';
588   Self.AddAppInfo();
589  
590   //Проставляем настройки установки.
591   Self.CurrentIss.WriteCodeConstValue('NoFullInstall','false');
592   Self.CurrentIss.WriteString('Setup','OutputBaseFilename',Self.ProjectName+'_'+Self.ProjectVit.GenerateFNVersionString());
593   if Self.ProjectSconf.IssBuilderSection.CreateFull_AllowUpdate = true then begin
594     //Если разрешено добавление апдейтов - то собсно разрешить и их.
595     Self.CurrentIss.WriteCodeConstValue('NoUpdate','false');
596     //Константу со списком обновлябельных версий пока что обнулить - она будет
597     //заполнена при генерации собсно апдейтов.
598     Self.CurrentIss.WriteCodeConstValue('UpdateFrom','''''');
599   end
600   else begin
601     //Если апдейты не разрешены - проставить запрет.
602     Self.CurrentIss.WriteCodeConstValue('NoUpdate','true');
603   end;
604  
605   //Добавляем полную версию установки.
606   //Добавляем компонент...
607   Self.CurrentIss.WriteComponent('CurrVersion_Main','Name: CurrVersion_Main; Description: Основные файлы полной версии; Flags: fixed; Check: CheckDoNewInstall; Types: StandardInstall');
608   //Добавляем файлы для этого компонента...
609   Self.CurrentIss.AddFilesFromFlist(Self.CurrentFlist,'CurrVersion_Main');
610  
611   //Добавляем апдейты...
612   Self.AddUpdates(Self.ProjectSconf.IssBuilderSection.CreateFull_UpdVers);
613  
614   //Сейвим Iss-ку.
615   Result := Self.CurrentIss.Save(Self.CurrentIssFileName);
616   if Result = true then begin
617     Self.PostExternalMessage(_('Saved file ')+Self.CurrentIssFileName);
618     //Запускаем сборку Iss-ки.
619     Result := Self.BuildIssFile(Self.CurrentIssFileName);
620     if Self.NoCacheWrite = true then begin
621       //Если в кеш ничО нельзя писать - убить нафег iss-ку
622       if DeleteFile(Self.CurrentIssFileName) = true then begin
623         Self.PostExternalMessage(_('Deleted file ')+Self.CurrentIssFileName);
624       end
625       else begin
626         Self.PostExternalMessage(_('Achtung!!! Can''t delete file ')+Self.CurrentIssFileName);
627       end;
628     end;
629   end
630   else begin
631     //Облом сохранения.
632     Self.ErrorMessage := _('Can''t save file ')+Self.CurrentIssFileName;
633     Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
634   end;
635 end;
636
637 function TIssBuilderLogic.GenSeparateUpdates() : Boolean;
638 //Сгенерить раздельные обновлялки по Sconf, который уже должен быть загружен.
639 begin
640   //Инициализация.
641   Result := true;
642
643   //Готовим Iss-ку...
644   Self.NewCurrentIssFromDef();
645
646   Self.AddAppInfo();
647
648   //Проставляем настройки установки.
649   Self.CurrentIss.WriteCodeConstValue('NoFullInstall','true');
650   Self.CurrentIss.WriteCodeConstValue('NoUpdate','false');
651   //Константу со списком обновлябельных версий пока что обнулить - она будет
652   //заполнена при генерации собсно апдейтов.
653   Self.CurrentIss.WriteCodeConstValue('UpdateFrom','''''');
654  
655   //Запускаем добавление апдейтов с одновременной раздельной сборкой.
656   Self.AddUpdates(Self.ProjectSconf.IssBuilderSection.CreateSeparateUpds_UpdVers,true);
657 end;
658
659 function TIssBuilderLogic.GenCumulateUpdate() : Boolean;
660 //Сгенерить кумулятивный апдейт по Sconf, который уже должен быть загружен.
661 begin
662   //Инициализация.
663   Result := true;
664
665   //Готовим Iss-ку...
666   Self.NewCurrentIssFromDef();
667
668   Self.AddAppInfo();
669  
670   //Проставляем настройки установки.
671   Self.CurrentIss.WriteCodeConstValue('NoFullInstall','true');
672   Self.CurrentIss.WriteCodeConstValue('NoUpdate','false');
673   //Константу со списком обновлябельных версий пока что обнулить - она будет
674   //заполнена при генерации собсно апдейтов.
675   Self.CurrentIss.WriteCodeConstValue('UpdateFrom','''''');
676  
677   //Добавляем апдейты...
678   Self.AddUpdates(Self.ProjectSconf.IssBuilderSection.CreateCumulateUpdate_UpdVers);
679  
680   //Смотрим - были ли добавлены какие-либо версии?
681   if Length(Self.CurrentIss.ReadCodeConstValue('UpdateFrom')) > 2 then begin
682     //Реально, какие-то версии были добавлены - значит есть смысл это собирать.
683     //Генерим имена файлов.
684     Self.CurrentIssFileName := AddLastSlash(Self.GlobalCachePath)+Self.ProjectName+'_'+Self.OldestVerFN+'_to_'+Self.ProjectVit.GenerateFNVersionString()+'_CumulateUpdate.iss';
685     Self.CurrentIss.WriteString('Setup','OutputBaseFilename',Self.ProjectName+'_'+Self.OldestVerFN+'_to_'+Self.ProjectVit.GenerateFNVersionString()+'_CumulateUpdate');
686
687     //Сейвим Iss-ку.
688     Result := Self.CurrentIss.Save(Self.CurrentIssFileName);
689     if Result = true then begin
690       Self.PostExternalMessage(_('Saved file ')+Self.CurrentIssFileName);
691       //Запускаем сборку Iss-ки.
692       Result := Self.BuildIssFile(Self.CurrentIssFileName);
693       if Self.NoCacheWrite = true then begin
694         //Если в кеш ничО нельзя писать - убить нафег iss-ку
695         if DeleteFile(Self.CurrentIssFileName) = true then begin
696           Self.PostExternalMessage(_('Deleted file ')+Self.CurrentIssFileName);
697         end
698         else begin
699           Self.PostExternalMessage(_('Achtung!!! Can''t delete file ')+Self.CurrentIssFileName);
700         end;
701       end;
702     end
703     else begin
704       //Облом сохранения.
705       Self.ErrorMessage := _('Can''t save file ')+Self.CurrentIssFileName;
706       Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
707     end;
708   end
709   else begin
710     //Облом - не добавлено ни одной версии - собирать кумулятивный апдейт нет смысла.
711     Self.PostExternalMessage(_('Nothing to update - cumulative update is not needable.'));
712   end;
713
714 end;
715
716 function TIssBuilderLogic.ProcessSconf() : Boolean;
717 //Работать по правилам, описанным в Sconf - он должен быть уже загружен.
718 var
719   TempStr : AnsiString;
720  
721 begin
722   //Инициализация.
723   Result := true;
724  
725   //Получаем имя проекта, глобальный и локальный пути.
726   Self.ProjectName := GetFileNameWithoutExtension(Self.SconfFilePath);
727   Self.ProjectLocalRoot := AddLastSlash(Self.ProjectSconf.MainSection.ProjectRootDir);
728   Self.ProjectGlobalRoot := ResolveLocalPath(Self.ProjectLocalRoot,ExtractFilePath(Self.SconfFilePath));
729  
730   //Подгрузим конфиги.
731   Result := Self.LoadConfigs();
732  
733   //Подгрузилось?
734   if Result = true then begin
735     //Ага, все ок.
736     //Генерим глобальные пути.
737     Self.GlobalCachePath := ResolveLocalPath(Self.ProjectSconf.IssBuilderSection.VersionsCacheDir,Self.ProjectGlobalRoot);
738     Self.GlobalOutputPath := ResolveLocalPath(Self.ProjectSconf.IssBuilderSection.OutputDir,Self.ProjectGlobalRoot);
739     Self.GlobalSourcePath := ResolveLocalPath(Self.ProjectSconf.IssBuilderSection.FilesDir,Self.ProjectGlobalRoot);
740     Self.LocalOutputPath := GetLocalPath(Self.GlobalCachePath,Self.GlobalOutputPath);
741     Self.LocalSourcePath := GetLocalPath(Self.GlobalCachePath,Self.GlobalSourcePath);
742    
743     //Проверить - существует ли пути под output и cache. Если не существуют - создать.
744     if DirectoryExists(Self.GlobalCachePath) = false then begin
745       Result := ForceDirectories(Self.GlobalCachePath);
746       if Result = true then begin
747         //Сообщить о создании директории.
748         Self.PostExternalMessage(_('Created directory ')+Self.GlobalCachePath);
749       end
750       else begin
751         //Сообщить о обломе.
752         Self.ErrorMessage := _('Can''t сreate directory ')+Self.GlobalCachePath;
753         Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
754       end;
755     end;
756     if (DirectoryExists(Self.GlobalOutputPath) = false) and (Result = true) then begin
757       Result := ForceDirectories(Self.GlobalOutputPath);
758       if Result = true then begin
759         //Сообщить о создании директории.
760         Self.PostExternalMessage(_('Created directory ')+Self.GlobalOutputPath);
761       end
762       else begin
763         //Сообщить о обломе.
764         Self.ErrorMessage := _('Can''t сreate directory ')+Self.GlobalOutputPath;
765         Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
766       end;
767     end;
768    
769     //Теперь сгенерить flist-файл для данной версии.
770     if Result = true then begin
771       Self.PostExternalMessage(_('Creating distributive file list...'));
772       Self.CurrentFlist.Clear();
773       Self.CurrentFlist.GlobalRoot := Self.GlobalSourcePath;
774       Self.CurrentFlist.PathsAreAbsolute := false;
775       Self.CurrentFlist.AddSize := true;
776       Self.CurrentFlist.AddCRC32 := true;
777       Result := Self.CurrentFlist.AddRealDirectory(Self.GlobalSourcePath,true);
778       if Result = true then begin
779         if Self.NoCacheWrite = false then begin
780           //Удачно. Сохраняем.
781           TempStr := AddLastSlash(Self.GlobalCachePath)+Self.ProjectName+'_'+Self.ProjectVit.GenerateFNVersionString()+'.flist';
782           Result := Self.CurrentFlist.Save(TempStr);
783           if Result = true then begin
784             //Сохранено.
785             Self.PostExternalMessage(_('Saved file ')+TempStr);
786             //И засавлить директорию с файлами версии если была такая команда.
787             if Self.ProjectSconf.IssBuilderSection.SaveToCache = true then begin
788               //Надо савлить. Предварительно если такая дира была - убить.
789               TempStr := AddLastSlash(Self.GlobalCachePath)+Self.ProjectName+'_'+Self.ProjectVit.GenerateFNVersionString();
790               if DirectoryExists(TempStr) = true then begin
791                 Self.PostExternalMessage(_('Removing old files cache from ')+TempStr);
792                 DeleteDirectory(TempStr,true);
793                 Self.PostExternalMessage(_('Done.'));
794               end;
795               //И копируем.
796               Self.PostExternalMessage(_('Saving files cache to ')+TempStr);
797               CopyDirectory(Self.GlobalSourcePath, TempStr, true, true);
798               Self.PostExternalMessage(_('Done.'));
799             end;
800           end
801           else begin
802             //Облом сохранения.
803             Self.ErrorMessage := _('Can''t save file ')+TempStr;
804             Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
805           end;
806         end;
807       end
808       else begin
809         //Облом создания списка.
810         Self.ErrorMessage := _('Can''t create file list for directory ')+Self.GlobalSourcePath+_('. Error message was: ')+Self.CurrentFlist.ErrorMessage;
811         Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
812       end;
813     end;
814
815     //Теперь - запускаем генерацию тех инсталлях, которые в Sconf указано сгенерить.
816     if Result = true then begin
817       //Полная сборка.
818       if Self.ProjectSconf.IssBuilderSection.CreateFull = true then begin
819         Result := Self.GenFullInstall();
820       end;
821
822       //Отдельный апдейт.
823       if (Self.ProjectSconf.IssBuilderSection.CreateSeparateUpds = true) and (Result = true) then begin
824         Result := Result and Self.GenSeparateUpdates();
825       end;
826
827       //Кумулятивная сборка апдейтов.
828       if (Self.ProjectSconf.IssBuilderSection.CreateCumulateUpdate = true) and (Result = true) then begin
829         Result := Result and Self.GenCumulateUpdate();
830       end;
831     end;
832    
833   end;
834 end;
835
836 function TIssBuilderLogic.BuildIssFile(const FileName : AnsiString) : Boolean;
837 //Запустить сборку iss консольным компилером InnoSetup.
838 var
839   IssCompiler : TProcess;
840  
841 begin
842   //Инициализация.
843   Result := true;
844   IssCompiler := TProcess.Create(Application);
845  
846   if FileExists(FileName) = true then begin
847     Self.PostExternalMessage(_('Compilling file ')+FileName);
848     //Собсно настраиваем...
849     IssCompiler.CommandLine := Self.ISCC_Path+' '+FileName;
850     IssCompiler.CurrentDirectory := Self.GlobalCachePath;
851     IssCompiler.Options := [poNoConsole, poWaitOnExit];
852     //И запускаем.
853     IssCompiler.Execute;
854     if IssCompiler.ExitStatus <> 0 then begin
855       //Ошибк при компилляции.
856       Result := false;
857       Self.ErrorMessage := _('Inno Setup compiler returned ExitStatus=')+IntToStr(IssCompiler.ExitStatus)+_(' - seems that it was any error! Try to compile ')+FileName+_(' manually to check for errors in script.');
858       Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
859     end
860     else begin
861       Self.PostExternalMessage(_('Compilled succesfully!'));
862     end;
863   end
864   else begin
865     //Нечего компилять.
866     Result := false;
867     Self.ErrorMessage := _('File not exists: ')+FileName;
868     Self.PostExternalMessage(_('Error! ')+Self.ErrorMessage);
869   end;;
870  
871   //Выкинуть мусор.
872   IssCompiler.Free;
873 end;
874
875 end.
876
Note: See TracBrowser for help on using the browser.