Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

450 lines
12 KiB

  1. # __________________________________________________________________________________
  2. #
  3. # Purpose:
  4. # PERL Script to emulate SLM's 'log' command
  5. #
  6. # Parameters:
  7. # See Usage below
  8. #
  9. # Output:
  10. # Perforce output manipulated to look like the output from SLM's 'log' command or
  11. # the appropriate error message or usage statement
  12. # __________________________________________________________________________________
  13. #
  14. # Load common SLM wrapper subroutine module
  15. #
  16. use SlmSubs;
  17. #
  18. # Parse command line arguments
  19. #
  20. SlmSubs::ParseArgs(@ARGV);
  21. #
  22. # Call usage and exit if ParseArgs has set the Usage or InvalidFlag flags
  23. #
  24. if ($Usage or $InvalidFlag)
  25. {
  26. print $ErrorMessage;
  27. &Usage;
  28. exit 1;
  29. }
  30. #
  31. # Default maximum number of output lines is 10
  32. #
  33. $MaxOutputLines = 10;
  34. #
  35. # If a different number was passed in on the command line use it for the maximum
  36. #
  37. if ($Number)
  38. {
  39. $MaxOutputLines = $Number;
  40. }
  41. #
  42. # Add Branch Heading if -b specified
  43. #
  44. if ($CrossBranches)
  45. {
  46. $BranchHeading = "branch ";
  47. }
  48. #
  49. # Print out header; suppress if -z is passed in
  50. #
  51. if (!$NoHeaders)
  52. {
  53. print "time user $BranchHeading op file comment\n";
  54. }
  55. #
  56. # Call subroutine that handles recursion and calls the RetrieveLog subroutine that
  57. # pulls 'log' information from @LogCache
  58. #
  59. &SlmSubs::Recurser("main::RetrieveLog");
  60. sub RetrieveLog
  61. # __________________________________________________________________________________
  62. #
  63. # Does all the interaction with the SLM server and reformatting of results to look
  64. # like SLM's 'log' output
  65. #
  66. # Parameters:
  67. # Optional Subdirectory
  68. #
  69. # Output:
  70. # Regular SLM 'log' output
  71. #
  72. # __________________________________________________________________________________
  73. {
  74. if ($_[0])
  75. {
  76. $SubDirectory = $_[0];
  77. #
  78. # Make a chopped version of $SubDirectory to print out
  79. #
  80. $ChoppedSubDirectory = $SubDirectory;
  81. chop $ChoppedSubDirectory;
  82. }
  83. else
  84. {
  85. #
  86. # Initialize string to null
  87. #
  88. $SubDirectory = "";
  89. }
  90. #
  91. # Get the list of changes for either @FileList or every file from Perforce
  92. #
  93. if (@FileList)
  94. {
  95. #
  96. # Append $Subdirectory to every file in $FileList
  97. #
  98. @RelativeFileList = ();
  99. foreach $File (@FileList)
  100. {
  101. push @RelativeFileList, "$SubDirectory$File";
  102. }
  103. @FileSpec = @RelativeFileList;
  104. }
  105. else
  106. {
  107. push @FileSpec, "$SubDirectory\%1";
  108. }
  109. open(FILELOG, qq/$SourceControlClient filelog -m $MaxOutputLines @FileSpec|/);
  110. @FileLog = <FILELOG>;
  111. close(FILELOG);
  112. #
  113. # Make a list of FileLog output
  114. #
  115. foreach $FileLogLine (@FileLog)
  116. {
  117. #
  118. # Figure out which section we're in and manipulate output differently depending
  119. # on which section it is
  120. #
  121. if ( $FileLogLine =~ /^(\/\/.*)$/ )
  122. {
  123. $FileName = $1;
  124. }
  125. else
  126. {
  127. if ( $FileLogLine =~ /^\.\.\. #(\d+) change (\d+) (\S+) on (.*) (.*) by .*@(\S*).*'(.*)'/ )
  128. {
  129. #
  130. # Manipulate filelog output to look like SLM's 'log' output
  131. #
  132. $Version = $1;
  133. $Change = $2;
  134. $Action = $3;
  135. $Time = "$4\@$5";
  136. $Owner = "\U$6";
  137. $Comment = $7;
  138. $Time =~ s/^19//;
  139. $Time =~ s/:[^:]*$//;
  140. $Time =~ s/^(9.)\//19$1\//;
  141. $LogLine = "$Time, $Owner, $Action, $FileName, $Version, $Change, $Comment";
  142. push @LogCache, "$LogLine\n";
  143. }
  144. }
  145. }
  146. if ($CrossBranches)
  147. {
  148. do
  149. {
  150. $FoundBranches = $main::FALSE;
  151. @BranchLogNext = ();
  152. if (not @BranchLog)
  153. {
  154. @BranchLog = @FileLog;
  155. }
  156. #
  157. # Find source of change if not in this branch.
  158. #
  159. foreach $FileBranchLine (@BranchLog)
  160. {
  161. if ( $FileBranchLine =~ /^(\/\/.*)$/ )
  162. {
  163. $FileName = $1;
  164. }
  165. if ( $FileBranchLine =~ /^\.\.\. #(\d+) change (\d+) (\S+) on (.*) (.*) by .*@(\S*).*'(.*)'/ )
  166. {
  167. $ChangeNumber = $1;
  168. }
  169. if ( $FileBranchLine =~ /^\.\.\. \.\.\. .* from ([^#]*#\d+).*\n/ )
  170. {
  171. $FileLogHash{lc("$FileName#$ChangeNumber")} = $1;
  172. push @BranchLogNext, "$1\n";
  173. $FoundBranches = $main::TRUE;
  174. }
  175. }
  176. if (@BranchLogNext)
  177. {
  178. open( TemporaryFileSpec, ">$ENV{tmp}\\TmpBranchSpec");
  179. print TemporaryFileSpec @BranchLogNext;
  180. close (TemporaryFileSpec);
  181. open(BRANCHLOG, qq/type $ENV{tmp}\\TmpBranchSpec | $SourceControlClient -x - filelog -m 1 |/);
  182. @BranchLog = <BRANCHLOG>;
  183. push @FullBranchLog, @BranchLog;
  184. close(BRANCHLOG);
  185. }
  186. } while ($FoundBranches);
  187. unlink "$ENV{tmp}\\TmpBranchSpec";
  188. #
  189. # Make a list of BranchLog output
  190. #
  191. foreach $BranchLogLine (@FullBranchLog)
  192. {
  193. #
  194. # Figure out which section we're in and manipulate output differently depending
  195. # on which section it is
  196. #
  197. if ( $BranchLogLine =~ /^(\/\/.*)$/ )
  198. {
  199. $FileName = $1;
  200. }
  201. else
  202. {
  203. if ( $BranchLogLine =~ /^\.\.\. #(\d+) change (\d+) (\S+) on (.*) (.*) by .*@(\S*).*'(.*)'/ )
  204. {
  205. #
  206. # Manipulate BranchLog output to look like SLM's 'log' output
  207. #
  208. $Version = $1;
  209. $Change = $2;
  210. $Action = $3;
  211. $Time = "$4\@$5";
  212. $Owner = "\U$6";
  213. $Comment = $7;
  214. $Time =~ s/^19//;
  215. $Time =~ s/:[^:]*$//;
  216. $Time =~ s/^(9.)\//19$1\//;
  217. $LogLine = "$Time, $Owner, $Action, $FileName, $Version, $Change, $Comment";
  218. $BranchLogHash{lc("$FileName#$Version")} = "$LogLine\n";
  219. push @BranchLogCache, "$LogLine\n";
  220. }
  221. }
  222. }
  223. }
  224. #
  225. # Print out standard header of 'log' output unless -z switch used
  226. #
  227. if (!$NoHeaders)
  228. {
  229. print "\n";
  230. if ($ChoppedSubDirectory)
  231. {
  232. print "Log for $LocalMap\/$ChoppedSubDirectory:\n";
  233. }
  234. else
  235. {
  236. print "Log for $LocalMap:\n";
  237. }
  238. print "\n";
  239. }
  240. #
  241. # Sort list in case cache was out of order
  242. #
  243. @SortedLogCache = sort @LogCache;
  244. #
  245. # Figure out where to start in @SortedLogCache so that there are no more than $MaxOutputLines outputted
  246. #
  247. $PrintCounter = $#LogCache - $MaxOutputLines;
  248. if ($PrintCounter < 0)
  249. {
  250. $PrintCounter = 0;
  251. }
  252. #
  253. # Print out @SortedLogCache
  254. #
  255. while ($SortedLogCache[$PrintCounter])
  256. {
  257. $LogLine = $SortedLogCache[$PrintCounter++];
  258. $FormattedLine = FormatLine($LogLine);
  259. print "$FormattedLine\n";
  260. if ($CrossBranches)
  261. {
  262. $LogLine =~ /[^,]*, [^,]*, [^,]*, ([^,]*), ([^,]*),.*/;
  263. $FileVer = $FileLogHash{lc("$1#$2")};
  264. @BranchList = ();
  265. while ($FileVer)
  266. {
  267. $FormattedLine = FormatLine(" ($BranchLogHash{lc($FileVer)}");
  268. push @BranchList, "$FormattedLine)\n";
  269. $FileVer = $FileLogHash{lc($FileVer)};
  270. }
  271. print sort @BranchList;
  272. }
  273. }
  274. }
  275. sub FormatLine
  276. # __________________________________________________________________________________
  277. #
  278. # Formats a line from the LogCache to the format specified log.pl parameters
  279. #
  280. # Parameters:
  281. # Line from LogCache
  282. #
  283. # Output:
  284. # Formatted Line
  285. #
  286. # __________________________________________________________________________________
  287. {
  288. $LogCacheLine = $_[0];
  289. $RelativeDepotMap = $DepotMap;
  290. $RelativeDepotMap =~ s/^\/\/depot\/[^\/]+(\/.*)/$1/;
  291. #
  292. # Append the current directory to the root depot map and grep for only those files in the cache that are in this
  293. # subdirectory
  294. #
  295. if ( $LogCacheLine =~ /([^,]*), ([^,]*), ([^,]*), \/\/depot\/([^,]*), ([^,]*), ([^,]*), (.*)\n/i )
  296. {
  297. #
  298. # Format the output to look like SLM's 'log' output
  299. #
  300. $Owner = sprintf "%-12s", "$2";
  301. $Time = sprintf "%-18s", "$1";
  302. $Action = sprintf "%-9s", "$3";
  303. $FileName = $4;
  304. $Version = $5;
  305. $Change = $6;
  306. $Comment = $7;
  307. if ( $FileName =~ /(.*)\Q$RelativeDepotMap$SubDirectory\E([^,]*)/i )
  308. {
  309. $Branch = sprintf "%-9s", "$1";
  310. $FileName = $2;
  311. }
  312. else
  313. {
  314. if ( $FileName =~ /(.*)\/([^,]*)/i )
  315. {
  316. $Branch = sprintf "%-9s", "$1";
  317. $FileName = $2;
  318. }
  319. }
  320. #
  321. # Don't pick up files in subdirectories
  322. #
  323. if (! ($FileName =~ /\//))
  324. {
  325. #
  326. # If $FileList specified, only match files in it
  327. #
  328. if ( (! @FileList) or (SlmSubs::InList($FileName, \@FileList)))
  329. {
  330. #
  331. # Add subdirectory to $FormattedFileName if -z was passed in on command line
  332. #
  333. if ($NoHeaders)
  334. {
  335. $FormattedFileName = sprintf "%-22s", "$SubDirectory$FileName v$Version c$Change";
  336. }
  337. else
  338. {
  339. $FormattedFileName = sprintf "%-22s", "$FileName v$Version c$Change";
  340. }
  341. if ($CrossBranches)
  342. {
  343. $FormattedLogLine = "$Time $Owner $Branch $Action $FormattedFileName $Comment";
  344. }
  345. else
  346. {
  347. $FormattedLogLine = "$Time $Owner $Action $FormattedFileName $Comment";
  348. }
  349. }
  350. }
  351. }
  352. #
  353. # Don't truncate line if in verbose mode
  354. #
  355. if (!$Verbose)
  356. {
  357. $FormattedLogLine = sprintf "%.80s", "$FormattedLogLine";
  358. }
  359. return $FormattedLogLine;
  360. }
  361. sub Usage
  362. # __________________________________________________________________________________
  363. #
  364. # Prints out a usage statement for this script. In this case usurped from SLM's
  365. # 'log' usage statement
  366. #
  367. # Parameters:
  368. # None
  369. #
  370. # Output:
  371. # The usage statement
  372. #
  373. # __________________________________________________________________________________
  374. {
  375. print q/log - prints historical information for a project
  376. Usage: log [-?fhvrzd] [-#] [file1] [file2...]
  377. Arguments:
  378. -h prints out this message.
  379. -v (verbose) Provides a more extensive listing of log information.
  380. -r (recursive) applies the command to a given directory and in every
  381. subdirectory beneath it. Note that a pattern argument is NOT accepted
  382. with this flag for the log command. Use -a or -r, but not both.
  383. -# specifies how many log entries to display, counting back from the
  384. present moment (log -3 displays the 3 most recent events).
  385. -z format the log in a sortable format without headers.
  386. -d include deleted subdirectories in search.
  387. -b apply history across branches.
  388. /;
  389. }