pkgglobals.pp 7.8 KB

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