pkgglobals.pp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. {$mode objfpc}
  2. {$h+}
  3. unit pkgglobals;
  4. interface
  5. uses
  6. {$ifdef unix}
  7. baseunix,
  8. {$endif}
  9. SysUtils,
  10. Classes,
  11. fprepos;
  12. Const
  13. {$ifdef unix}
  14. ExeExt = '';
  15. AllFiles='*';
  16. {$else unix}
  17. ExeExt = '.exe';
  18. AllFiles='*.*';
  19. {$endif unix}
  20. Type
  21. TFPMKUnitDep=record
  22. package : string[12];
  23. reqver : string[8];
  24. undef : string[32];
  25. def : string[32];
  26. available: boolean;
  27. end;
  28. Const
  29. CmdLinePackageName='<cmdline>';
  30. CurrentDirPackageName='<currentdir>';
  31. // Dependencies for compiling the fpmkunit unit
  32. FPMKUnitDepDefaultCount=4;
  33. FPMKUnitDepsDefaults : array[0..FPMKUnitDepDefaultCount-1] of TFPMKUnitDep = (
  34. (package: 'hash';
  35. reqver : '2.2.2';
  36. undef : 'NO_UNIT_ZIPPER'),
  37. (package: 'paszlib';
  38. reqver : '2.2.2';
  39. undef : 'NO_UNIT_ZIPPER'),
  40. (package: 'fcl-process';
  41. reqver : '2.2.2';
  42. undef : 'NO_UNIT_PROCESS'),
  43. (package: 'fpmkunit';
  44. reqver : '2.2.2-1';
  45. undef : '')
  46. );
  47. Type
  48. TLogLevel = (vlError,vlWarning,vlInfo,vlCommands,vlDebug);
  49. TLogLevels = Set of TLogLevel;
  50. const
  51. DefaultLogLevels = [vlError,vlWarning];
  52. AllLogLevels = [vlError,vlWarning,vlCommands,vlInfo];
  53. type
  54. EPackagerError = class(Exception);
  55. // Logging
  56. Function StringToLogLevels (S : String) : TLogLevels;
  57. Function LogLevelsToString (V : TLogLevels): String;
  58. Procedure Log(Level: TLogLevel;Msg : String);
  59. Procedure Log(Level: TLogLevel;Fmt : String; const Args : array of const);
  60. Procedure Error(Msg : String);
  61. Procedure Error(Fmt : String; const Args : array of const);
  62. // Utils
  63. function maybequoted(const s:string):string;
  64. Function FixPath(const S : String) : string;
  65. Function DirectoryExistsLog(const ADir:string):Boolean;
  66. Function FileExistsLog(const AFileName:string):Boolean;
  67. procedure BackupFile(const AFileName: String);
  68. Procedure DeleteDir(const ADir:string);
  69. Procedure SearchFiles(SL:TStringList;const APattern:string);
  70. Function GetCompilerInfo(const ACompiler,AOptions:string):string; overload;
  71. Procedure GetCompilerInfo(const ACompiler, AOptions: string; out AVersion: string; out ACPU: TCpu; out aOS:TOS); overload;
  72. function IsSuperUser:boolean;
  73. var
  74. LogLevels : TLogLevels;
  75. FPMKUnitDeps : array of TFPMKUnitDep;
  76. Implementation
  77. // define use_shell to use sysutils.executeprocess
  78. // as alternate to using 'process' in getcompilerinfo
  79. {$IF defined(GO32v2) or defined(WATCOM) or defined(OS2)}
  80. {$DEFINE USE_SHELL}
  81. {$ENDIF GO32v2 or WATCOM or OS2}
  82. uses
  83. typinfo,
  84. {$IFNDEF USE_SHELL}
  85. process,
  86. {$ENDIF USE_SHELL}
  87. contnrs,
  88. uriparser,
  89. pkgmessages;
  90. function FPPkgGetVendorName:string;
  91. begin
  92. {$ifdef unix}
  93. result:='fpc';
  94. {$else}
  95. result:='FreePascal'
  96. {$endif}
  97. end;
  98. function FPPkgGetApplicationName:string;
  99. begin
  100. {$ifdef unix}
  101. result:='fppkg';
  102. {$else}
  103. result:='Packages'
  104. {$endif}
  105. end;
  106. function StringToLogLevels(S: String): TLogLevels;
  107. Var
  108. I : integer;
  109. begin
  110. I:=GetEnumValue(TypeInfo(TLogLevels),'v'+S);
  111. If (I<>-1) then
  112. Result:=TLogLevels(I)
  113. else
  114. Raise EPackagerError.CreateFmt(SErrInvalidLogLevels,[S]);
  115. end;
  116. Function LogLevelsToString (V : TLogLevels): String;
  117. begin
  118. Result:=GetEnumName(TypeInfo(TLogLevels),Integer(V));
  119. Delete(Result,1,1);// Delete 'v'
  120. end;
  121. procedure Log(Level:TLogLevel;Msg: String);
  122. var
  123. Prefix : string;
  124. begin
  125. if not(Level in LogLevels) then
  126. exit;
  127. Prefix:='';
  128. case Level of
  129. vlWarning :
  130. Prefix:=SWarning;
  131. vlError :
  132. Prefix:=SError;
  133. { vlInfo :
  134. Prefix:='I: ';
  135. vlCommands :
  136. Prefix:='C: ';
  137. vlDebug :
  138. Prefix:='D: '; }
  139. end;
  140. Writeln(stdOut,Prefix,Msg);
  141. end;
  142. Procedure Log(Level:TLogLevel; Fmt:String; const Args:array of const);
  143. begin
  144. Log(Level,Format(Fmt,Args));
  145. end;
  146. procedure Error(Msg: String);
  147. begin
  148. Raise EPackagerError.Create(Msg);
  149. end;
  150. procedure Error(Fmt: String; const Args: array of const);
  151. begin
  152. Raise EPackagerError.CreateFmt(Fmt,Args);
  153. end;
  154. function maybequoted(const s:string):string;
  155. const
  156. {$IFDEF MSWINDOWS}
  157. FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
  158. '{', '}', '''', '`', '~'];
  159. {$ELSE}
  160. FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
  161. '{', '}', '''', ':', '\', '`', '~'];
  162. {$ENDIF}
  163. var
  164. s1 : string;
  165. i : integer;
  166. quoted : boolean;
  167. begin
  168. quoted:=false;
  169. s1:='"';
  170. for i:=1 to length(s) do
  171. begin
  172. case s[i] of
  173. '"' :
  174. begin
  175. quoted:=true;
  176. s1:=s1+'\"';
  177. end;
  178. ' ',
  179. #128..#255 :
  180. begin
  181. quoted:=true;
  182. s1:=s1+s[i];
  183. end;
  184. else begin
  185. if s[i] in FORBIDDEN_CHARS then
  186. quoted:=True;
  187. s1:=s1+s[i];
  188. end;
  189. end;
  190. end;
  191. if quoted then
  192. maybequoted:=s1+'"'
  193. else
  194. maybequoted:=s;
  195. end;
  196. Function FixPath(const S : String) : string;
  197. begin
  198. If (S<>'') then
  199. Result:=IncludeTrailingPathDelimiter(S)
  200. else
  201. Result:='';
  202. end;
  203. Function DirectoryExistsLog(const ADir:string):Boolean;
  204. begin
  205. result:=SysUtils.DirectoryExists(ADir);
  206. if result then
  207. Log(vlDebug,SDbgDirectoryExists,[ADir,SDbgFound])
  208. else
  209. Log(vlDebug,SDbgDirectoryExists,[ADir,SDbgNotFound]);
  210. end;
  211. Function FileExistsLog(const AFileName:string):Boolean;
  212. begin
  213. result:=SysUtils.FileExists(AFileName);
  214. if result then
  215. Log(vlDebug,SDbgFileExists,[AFileName,SDbgFound])
  216. else
  217. Log(vlDebug,SDbgFileExists,[AFileName,SDbgNotFound]);
  218. end;
  219. procedure BackupFile(const AFileName: String);
  220. Var
  221. BFN : String;
  222. begin
  223. BFN:=AFileName+'.bak';
  224. Log(vlDebug,SDbgBackupFile,[BFN]);
  225. If not RenameFile(AFileName,BFN) then
  226. Error(SErrBackupFailed,[AFileName,BFN]);
  227. end;
  228. Procedure DeleteDir(const ADir:string);
  229. var
  230. Info : TSearchRec;
  231. begin
  232. // Prevent accidently deleting all files in current or root dir
  233. if (ADir='') or (ADir=PathDelim) then
  234. exit;
  235. if FindFirst(ADir+PathDelim+AllFiles,faAnyFile, Info)=0 then
  236. try
  237. repeat
  238. if (Info.Attr and faDirectory)=faDirectory then
  239. begin
  240. if (Info.Name<>'.') and (Info.Name<>'..') then
  241. DeleteDir(ADir+PathDelim+Info.Name)
  242. end
  243. else
  244. DeleteFile(ADir+PathDelim+Info.Name);
  245. until FindNext(Info)<>0;
  246. finally
  247. FindClose(Info);
  248. end;
  249. RemoveDir(Adir);
  250. end;
  251. Procedure SearchFiles(SL:TStringList;const APattern:string);
  252. var
  253. Info : TSearchRec;
  254. ADir : string;
  255. begin
  256. ADir:=ExtractFilePath(APattern);
  257. if FindFirst(APattern,faAnyFile, Info)=0 then
  258. try
  259. repeat
  260. if (Info.Attr and faDirectory)=faDirectory then
  261. begin
  262. if (Info.Name<>'.') and (Info.Name<>'..') then
  263. SearchFiles(SL,ADir+Info.Name+PathDelim+ExtractFileName(APattern))
  264. end;
  265. SL.Add(ADir+Info.Name);
  266. until FindNext(Info)<>0;
  267. finally
  268. FindClose(Info);
  269. end;
  270. end;
  271. //
  272. // if use_shell defined uses sysutils.executeprocess else uses 'process'
  273. //
  274. function GetCompilerInfo(const ACompiler,AOptions:string):string;
  275. const
  276. BufSize = 1024;
  277. var
  278. {$IFDEF USE_SHELL}
  279. TmpFileName, ProcIDStr: shortstring;
  280. TmpFile: file;
  281. CmdLine2: string;
  282. {$ELSE USE_SHELL}
  283. S: TProcess;
  284. {$ENDIF USE_SHELL}
  285. Buf: array [0..BufSize - 1] of char;
  286. Count: longint;
  287. begin
  288. {$IFDEF USE_SHELL}
  289. Str (GetProcessID, ProcIDStr);
  290. TmpFileName := GetEnvironmentVariable ('TEMP');
  291. if TmpFileName <> '' then
  292. TmpFileName := TmpFileName + DirectorySeparator + 'fppkgout.' + ProcIDStr
  293. else
  294. TmpfileName := 'fppkgout.' + ProcIDStr;
  295. CmdLine2 := '/C ' + ACompiler + ' ' + AOptions + ' > ' + TmpFileName;
  296. SysUtils.ExecuteProcess (GetEnvironmentVariable ('COMSPEC'), CmdLine2);
  297. Assign (TmpFile, TmpFileName);
  298. Reset (TmpFile, 1);
  299. BlockRead (TmpFile, Buf, BufSize, Count);
  300. Close (TmpFile);
  301. {$ELSE USE_SHELL}
  302. S:=TProcess.Create(Nil);
  303. S.Commandline:=ACompiler+' '+AOptions;
  304. S.Options:=[poUsePipes];
  305. S.execute;
  306. Count:=s.output.read(buf,BufSize);
  307. S.Free;
  308. {$ENDIF USE_SHELL}
  309. SetLength(Result,Count);
  310. Move(Buf,Result[1],Count);
  311. end;
  312. Procedure GetCompilerInfo(const ACompiler, AOptions: string; out AVersion: string; out ACPU: TCpu; out aOS:TOS); overload;
  313. var
  314. infosl: TStringList;
  315. begin
  316. infosl:=TStringList.Create;
  317. infosl.Delimiter:=' ';
  318. infosl.DelimitedText:=GetCompilerInfo(ACompiler,AOptions);
  319. if infosl.Count<>3 then
  320. Raise EPackagerError.Create(SErrInvalidFPCInfo);
  321. AVersion:=infosl[0];
  322. ACPU:=StringToCPU(infosl[1]);
  323. AOS:=StringToOS(infosl[2]);
  324. end;
  325. function IsSuperUser:boolean;
  326. begin
  327. {$ifdef unix}
  328. result:=(fpGetUID=0);
  329. {$else unix}
  330. result:=false;
  331. {$endif unix}
  332. end;
  333. initialization
  334. OnGetVendorName:=@FPPkgGetVendorName;
  335. OnGetApplicationName:=@FPPkgGetApplicationName;
  336. end.