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