pkgglobals.pp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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.2.1';
  31. undef : 'NO_UNIT_ZIPPER'),
  32. (package: 'paszlib';
  33. reqver : '2.2.1';
  34. undef : 'NO_UNIT_ZIPPER'),
  35. (package: 'fcl-process';
  36. reqver : '2.2.1';
  37. undef : 'NO_UNIT_PROCESS'),
  38. (package: 'fpmkunit';
  39. reqver : '2.2.1';
  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. Writeln(stdOut,Prefix,Msg);
  135. end;
  136. Procedure Log(Level:TLogLevel; Fmt:String; const Args:array of const);
  137. begin
  138. Log(Level,Format(Fmt,Args));
  139. end;
  140. procedure Error(Msg: String);
  141. begin
  142. Raise EPackagerError.Create(Msg);
  143. end;
  144. procedure Error(Fmt: String; const Args: array of const);
  145. begin
  146. Raise EPackagerError.CreateFmt(Fmt,Args);
  147. end;
  148. function maybequoted(const s:string):string;
  149. const
  150. {$IFDEF MSWINDOWS}
  151. FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
  152. '{', '}', '''', '`', '~'];
  153. {$ELSE}
  154. FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
  155. '{', '}', '''', ':', '\', '`', '~'];
  156. {$ENDIF}
  157. var
  158. s1 : string;
  159. i : integer;
  160. quoted : boolean;
  161. begin
  162. quoted:=false;
  163. s1:='"';
  164. for i:=1 to length(s) do
  165. begin
  166. case s[i] of
  167. '"' :
  168. begin
  169. quoted:=true;
  170. s1:=s1+'\"';
  171. end;
  172. ' ',
  173. #128..#255 :
  174. begin
  175. quoted:=true;
  176. s1:=s1+s[i];
  177. end;
  178. else begin
  179. if s[i] in FORBIDDEN_CHARS then
  180. quoted:=True;
  181. s1:=s1+s[i];
  182. end;
  183. end;
  184. end;
  185. if quoted then
  186. maybequoted:=s1+'"'
  187. else
  188. maybequoted:=s;
  189. end;
  190. Function FixPath(const S : String) : string;
  191. begin
  192. If (S<>'') then
  193. Result:=IncludeTrailingPathDelimiter(S)
  194. else
  195. Result:='';
  196. end;
  197. Function DirectoryExistsLog(const ADir:string):Boolean;
  198. begin
  199. result:=SysUtils.DirectoryExists(ADir);
  200. if result then
  201. Log(vlDebug,SDbgDirectoryExists,[ADir,SDbgFound])
  202. else
  203. Log(vlDebug,SDbgDirectoryExists,[ADir,SDbgNotFound]);
  204. end;
  205. Function FileExistsLog(const AFileName:string):Boolean;
  206. begin
  207. result:=SysUtils.FileExists(AFileName);
  208. if result then
  209. Log(vlDebug,SDbgFileExists,[AFileName,SDbgFound])
  210. else
  211. Log(vlDebug,SDbgFileExists,[AFileName,SDbgNotFound]);
  212. end;
  213. procedure BackupFile(const AFileName: String);
  214. Var
  215. BFN : String;
  216. begin
  217. BFN:=AFileName+'.bak';
  218. Log(vlDebug,SDbgBackupFile,[BFN]);
  219. If not RenameFile(AFileName,BFN) then
  220. Error(SErrBackupFailed,[AFileName,BFN]);
  221. end;
  222. Procedure DeleteDir(const ADir:string);
  223. var
  224. Info : TSearchRec;
  225. begin
  226. // Prevent accidently deleting all files in current or root dir
  227. if (ADir='') or (ADir=PathDelim) then
  228. exit;
  229. if FindFirst(ADir+PathDelim+AllFiles,faAnyFile, Info)=0 then
  230. try
  231. repeat
  232. if (Info.Attr and faDirectory)=faDirectory then
  233. begin
  234. if (Info.Name<>'.') and (Info.Name<>'..') then
  235. DeleteDir(ADir+PathDelim+Info.Name)
  236. end
  237. else
  238. DeleteFile(ADir+PathDelim+Info.Name);
  239. until FindNext(Info)<>0;
  240. finally
  241. FindClose(Info);
  242. end;
  243. RemoveDir(Adir);
  244. end;
  245. Procedure SearchFiles(SL:TStringList;const APattern:string);
  246. var
  247. Info : TSearchRec;
  248. ADir : string;
  249. begin
  250. ADir:=ExtractFilePath(APattern);
  251. if FindFirst(APattern,faAnyFile, Info)=0 then
  252. try
  253. repeat
  254. if (Info.Attr and faDirectory)=faDirectory then
  255. begin
  256. if (Info.Name<>'.') and (Info.Name<>'..') then
  257. SearchFiles(SL,ADir+Info.Name+PathDelim+ExtractFileName(APattern))
  258. end;
  259. SL.Add(ADir+Info.Name);
  260. until FindNext(Info)<>0;
  261. finally
  262. FindClose(Info);
  263. end;
  264. end;
  265. //
  266. // if use_shell defined uses sysutils.executeprocess else uses 'process'
  267. //
  268. function GetCompilerInfo(const ACompiler,AOptions:string):string;
  269. const
  270. BufSize = 1024;
  271. var
  272. {$IFDEF USE_SHELL}
  273. TmpFileName, ProcIDStr: shortstring;
  274. TmpFile: file;
  275. CmdLine2: string;
  276. {$ELSE USE_SHELL}
  277. S: TProcess;
  278. {$ENDIF USE_SHELL}
  279. Buf: array [0..BufSize - 1] of char;
  280. Count: longint;
  281. begin
  282. {$IFDEF USE_SHELL}
  283. Str (GetProcessID, ProcIDStr);
  284. TmpFileName := GetEnvironmentVariable ('TEMP');
  285. if TmpFileName <> '' then
  286. TmpFileName := TmpFileName + DirectorySeparator + 'fppkgout.' + ProcIDStr
  287. else
  288. TmpfileName := 'fppkgout.' + ProcIDStr;
  289. CmdLine2 := '/C ' + ACompiler + ' ' + AOptions + ' > ' + TmpFileName;
  290. SysUtils.ExecuteProcess (GetEnvironmentVariable ('COMSPEC'), CmdLine2);
  291. Assign (TmpFile, TmpFileName);
  292. Reset (TmpFile, 1);
  293. BlockRead (TmpFile, Buf, BufSize, Count);
  294. Close (TmpFile);
  295. {$ELSE USE_SHELL}
  296. S:=TProcess.Create(Nil);
  297. S.Commandline:=ACompiler+' '+AOptions;
  298. S.Options:=[poUsePipes];
  299. S.execute;
  300. Count:=s.output.read(buf,BufSize);
  301. S.Free;
  302. {$ENDIF USE_SHELL}
  303. SetLength(Result,Count);
  304. Move(Buf,Result[1],Count);
  305. end;
  306. function IsSuperUser:boolean;
  307. begin
  308. {$ifdef unix}
  309. result:=(fpGetUID=0);
  310. {$else unix}
  311. result:=false;
  312. {$endif unix}
  313. end;
  314. initialization
  315. OnGetVendorName:=@FPPkgGetVendorName;
  316. OnGetApplicationName:=@FPPkgGetApplicationName;
  317. end.