Source code of Windows XP (NT5)
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.

466 lines
12 KiB

  1. ###
  2. ### File:
  3. ### srcwatch.pl
  4. ###
  5. ### History:
  6. ### 06/17/2000 Jasonsch - Original hacking.
  7. ### 07/21/2000 Jasonsch - Made more general so other groups can use it.
  8. ###
  9. ### Description:
  10. ### Watches a set of directories for changes and e-mails someone about 'em.
  11. ###
  12. use POSIX qw(strftime);
  13. BEGIN {
  14. require "$ENV{'SDXROOT'}\\tools\\sendmsg.pl";
  15. }
  16. ### Constants
  17. my $DEF_CONF_FILE = "srcwatch.txt";
  18. my $NUM_CHANGES = 50;
  19. ### pseudo-globals
  20. my $CDATE = localtime();
  21. my (%config);
  22. my $text = ""; # the body of the message
  23. my $sendmail = 0;
  24. if (!exists($ENV{'SDXROOT'})) {
  25. print "srcwatch.pl must be called from a razzle window!\n";
  26. exit(0);
  27. }
  28. &InitConfig(\%config, @ARGV);
  29. $cnt = keys %{$config{'paths'}};
  30. &InitHtmlText(\%config, $cnt);
  31. foreach (keys %{$config{'paths'}}) {
  32. $sendmail += &GetDepotChanges($_, \%config, $cnt);
  33. }
  34. $text .= << " EOHF";
  35. </table>
  36. </body>
  37. </html>
  38. EOHF
  39. if ($sendmail) {
  40. &sendmsg($config{'from'}, "$config{'groupname'} code changes for $config{'startdate'} to $config{'enddate'}", $text, $config{'targets'}, "content:text/html");
  41. }
  42. ######################### S U B R O U T I N E S ##########################
  43. sub GetTodaysDate()
  44. {
  45. strftime("%Y/%m/%d", localtime(time()));
  46. }
  47. sub GetYesterdaysDate()
  48. {
  49. strftime("%Y/%m/%d", localtime(time() - 60 * 60 * 24));
  50. }
  51. sub GetNewChanges($$$$)
  52. {
  53. my $sdate = shift; # start date
  54. my $edate = shift; # end date
  55. my $config = shift;
  56. my $depot = shift;
  57. my @changes = split(/\n/, `sd changes \@$sdate,$edate -s submitted`);
  58. my ($change, $cnum, $date, $time, $who, $desc, $integration);
  59. my (@new_changes, @files, $file, $lab, $ar);
  60. foreach $change (@changes) {
  61. $change =~ /^Change\s+(\d+)\s+on\s+(.*)\s+(.*)\s+by\s+(.*)\s+'(.*)'$/;
  62. $cnum = $1; $date = $2; $time = $3; $who = $4; $desc = $5;
  63. @files = &GetChangedFiles($cnum, $config, $depot);
  64. next unless(@files);
  65. # @files is an array of array refs ([$file, $lab, $op])
  66. if ($files[0]->[2] eq 'integrate' || $files[0]->[2] eq 'branch') {
  67. if ($files[0]->[1] eq $$config{'lab'}) {
  68. my @md; # array of array refs (meta-data), with the structure:
  69. # ($cnum, $date, $time, $who, $desc, @files)
  70. @md = &GetIntegrationRecords($config, $depot, $desc, @files);
  71. foreach $ar (@md) {
  72. $fileref = pop(@$ar);
  73. @files = &ExtractFiles(@$fileref);
  74. push(@new_changes, [@$ar, $$fileref[0]->[1], [@files]]);
  75. }
  76. } else {
  77. # This is just some other lab integrating files in our depots,
  78. # which we don't care about.
  79. next;
  80. }
  81. } elsif (&InOurView($files[0]->[1], $config, 0)){
  82. my @filelist = &ExtractFiles(@files);
  83. push(@new_changes, [$cnum, $date, $time, $who, $desc, $files[0]->[1], [@filelist]]);
  84. }
  85. }
  86. @new_changes;
  87. }
  88. sub ExtractFiles(@)
  89. {
  90. my @files;
  91. my $file;
  92. foreach $file (@_) {
  93. push(@files, $file->[0]);
  94. }
  95. @files;
  96. }
  97. sub GetChangedFiles($$$)
  98. {
  99. my $change = shift;
  100. my $config = shift;
  101. my $depot = shift;
  102. my @files = split(/\n/, `sd describe -s $change`);
  103. my (@files2, $branch, $op, $file);
  104. foreach (@files) {
  105. if (/^\s*\.\.\.\s+\/\/depot(\/private)?\/(\w+)\/([^\s]+) (\w+)$/) {
  106. $branch = lc($2); $file = $3; $op = $4;
  107. next unless (&CheckPath($file, $config, $depot));
  108. push(@files2, [$file, $branch, $op]);
  109. }
  110. }
  111. @files2;
  112. }
  113. sub GetIntegratedFiles($$$)
  114. {
  115. my $change = shift;
  116. my $config = shift;
  117. my $depot = shift;
  118. my @files = split(/\n/, `sd describe -s $change`);
  119. my (@files2, $branch, $op, $file);
  120. foreach (@files) {
  121. if (/^\s*\.\.\.\s+\/\/depot\/(\w+)\/([^\s]+) (\w+)$/) {
  122. $branch = lc($1); $file = $2; $op = $3;
  123. if (&CheckPath($file, $config, $depot)) {
  124. ### TODO: Should the test below *just* be !InOutView(...)
  125. if (!&InOurView($branch, $config, 1) && $op ne 'integrate' && $op ne 'branch') {
  126. push(@files2, [$file, $branch, $op]);
  127. }
  128. }
  129. }
  130. }
  131. @files2;
  132. }
  133. sub CheckIgnorePath($$$)
  134. {
  135. my $path = shift;
  136. my $config = shift;
  137. my $depot = shift;
  138. my $ret = 0;
  139. my $p;
  140. foreach $p (@{$config->{'ignore_paths'}->{$depot}}) {
  141. if ($path =~ /^$depot\/$p/i) {
  142. $ret = 1; last;
  143. }
  144. }
  145. $ret;
  146. }
  147. sub CheckPath($$$)
  148. {
  149. my $path = shift;
  150. my $config = shift;
  151. my $depot = shift;
  152. my $ret = 0;
  153. my $p;
  154. foreach $p (@{$config->{'paths'}->{$depot}}) {
  155. if ($path =~ /^$depot\/$p/i && !&CheckIgnorePath($path, $config, $depot)) {
  156. $ret = 1; last;
  157. }
  158. }
  159. $ret;
  160. }
  161. sub GetIntegrationRecords($$$)
  162. {
  163. my $config = shift;
  164. my $depot = shift;
  165. my $int_desc = shift;
  166. my ($file, $text, @files, $cnum, $date, $time, $who, $desc, $line, @lines);
  167. my (@changes, $shortlab);
  168. my $originlab = "";
  169. my %cs; # changes we've already seen
  170. $int_desc =~ /lab(\d+)_n/i;
  171. foreach $file (@_) {
  172. $file->[0] =~ s/#\d+$//;
  173. $file->[0] =~ s#^$depot/##i;
  174. foreach $line (@lines = split(/\n/, `sd changes -i $file->[0]`)) {
  175. chomp($line);
  176. $line =~ /^Change\s+(\d+)\s+on\s+(.*)\s+(.*)\s+by\s+(.*)\s+'(.*)'$/;
  177. $cnum = $1; $date = $2; $time = $3; $who = $4; $desc = $5;
  178. last if ($who =~ /ntbuild/i && $originlab && ($desc =~ /$originlab/ || $desc =~ /$shortlab/));
  179. next unless (@files = &GetIntegratedFiles($cnum, $config, $depot));
  180. next if (exists($cs{$cnum}));
  181. if (&HasFile($file->[0], @files)) {
  182. if (!$originlab) {
  183. $originlab = &GetOriginLab($cnum);
  184. $originlab =~ /^lab(\d+)/i;
  185. $shortlab = "lab$1";
  186. }
  187. next unless ($files[0]->[1] eq $originlab);
  188. $cs{$cnum} = 1;
  189. push(@changes, [$cnum, $date, $time, $who, $desc, [@files]]);
  190. }
  191. }
  192. }
  193. @changes;
  194. }
  195. sub GetOriginLab($)
  196. {
  197. my $cnum = shift;
  198. my @lines = `sd describe -s $cnum`;
  199. my $lab = "";
  200. foreach (@lines) {
  201. if (/^\s*\.\.\.\s+\/\/depot\/(\w+)\/[^\s]+\s+\w+$/) {
  202. $lab = lc($1);
  203. last;
  204. }
  205. }
  206. lc($lab);
  207. }
  208. sub HasFile($@)
  209. {
  210. my $file = shift;
  211. my $ret = 0;
  212. foreach (@_) {
  213. if ($_->[0] =~ /$file(#\d+)?$/) {
  214. $ret = 1;
  215. }
  216. }
  217. $ret;
  218. }
  219. sub GetDepotChanges($$)
  220. {
  221. my $depot = shift;
  222. my $config = shift;
  223. my $dc = shift;
  224. my ($domain, $alias, $client, $who, $change, $lab);
  225. my $bChanges = 0;
  226. chdir("$ENV{'SDXROOT'}\\$depot");
  227. my @changes = &GetNewChanges($$config{'startdate'}, $$config{'enddate'}, $config, $depot);
  228. foreach $change (@changes) {
  229. $$change[4] =~ s/</&lt;/g; $$change[4] =~ s/>/&gt;/g;
  230. $$change[3] =~ /^(\w+)\\(.*)\@(.*)$/;
  231. $domain = $1; $alias = $2; $client = $3;
  232. @files = @{$$change[6]};
  233. $lab = $$change[5];
  234. next if ($#files < $[);
  235. if ($lab ne $$config{'lab'}) {
  236. $lab = "<b>$lab</b>";
  237. }
  238. $bChanges = 1;
  239. if(!exists(${$$config{'group'}}{$alias})) {
  240. $alias = "<font color=\"#FF0000\"><b>$alias</b></font>";
  241. }
  242. $dh = "<td>$depot</td>" if ($dc > 1);
  243. $text .= << " EOROW";
  244. <tr align="center">$dh<td>$alias</td><td>$$change[0]</td><td>$$change[1]</td><td>$lab</td><td>$$change[4]</td><td>@files</td>\n
  245. EOROW
  246. }
  247. $bChanges;
  248. }
  249. sub InitConfig($@)
  250. {
  251. my $config = shift;
  252. my @args = @_;
  253. my $configfile = $DEF_CONF_FILE;
  254. my $startdate = "";
  255. my $enddate = "";
  256. my ($arg, $opt);
  257. while (@args) {
  258. $arg = shift(@args);
  259. if ($arg =~ /^-(\w)/) {
  260. $opt = $1;
  261. if ($opt eq 'f') {
  262. $configfile = shift(@args);
  263. } elsif ($opt eq 's') {
  264. $startdate = shift(@args);
  265. } elsif ($opt eq 'e') {
  266. $enddate = shift(@args);
  267. } else {
  268. &PrintUsage();
  269. }
  270. } else {
  271. &PrintUsage();
  272. }
  273. }
  274. if ($startdate) {
  275. # Convert mm/dd/yy to yy/mm/dd
  276. $startdate =~ /^(\d+)\/(\d+)\/(\d+)$/;
  277. $startdate = "$3/$1/$2";
  278. } else {
  279. $startdate = &GetYesterdaysDate();
  280. }
  281. if ($enddate) {
  282. # Convert mm/dd/yy to yy/mm/dd
  283. $enddate =~ /^(\d+)\/(\d+)\/(\d+)$/;
  284. $enddate = "$3/$1/$2";
  285. } else {
  286. $enddate = &GetTodaysDate();
  287. }
  288. $$config{'startdate'} = $startdate;
  289. $$config{'enddate'} = $enddate;
  290. $$config{'premonition'} = 0;
  291. &ReadConfigFile($configfile, $config);
  292. }
  293. sub ReadConfigFile($$)
  294. {
  295. my $file = shift;
  296. my $config = shift;
  297. my ($key, $value, $dir, $depot);
  298. local (*FILE);
  299. # Fill in the config file we're reading from.
  300. $$config{'configfile'} = $file;
  301. if (open(FILE, $file)) {
  302. while (<FILE>) {
  303. /^\s*(\w+)\s*=\s*(.*)$/;
  304. $key = $1; $value = $2;
  305. # Some config options require fixup/processing
  306. $key = lc($key);
  307. if ($key eq "group") {
  308. foreach (split(/\s+|,/, $value)) {
  309. ${$$config{'group'}}{$_} = 1;
  310. }
  311. } elsif ($key eq "paths") {
  312. foreach $dir (split(/\s+|,/, $value)) {
  313. $dir =~ /(\!)?(\w+)\\(.*)$/;
  314. $bang = $1; $depot = $2; $dir = $3;
  315. &PathFixup($dir);
  316. if ($bang) {
  317. push(@{$config->{'ignore_paths'}->{$depot}}, $dir);
  318. } else {
  319. push(@{$config->{'paths'}->{$depot}}, $dir);
  320. }
  321. }
  322. } else {
  323. $$config{$key} = $value;
  324. }
  325. }
  326. close(FILE);
  327. } else {
  328. print "Couldn't open $file for reading: $!\n";
  329. }
  330. }
  331. sub PrintUsage()
  332. {
  333. print << " EOPU";
  334. srcwatch.pl [-f file]
  335. -s mm/dd/yyyy - The start date of the period you want a listing for.
  336. -e mm/dd/yyyy - The end date of the period you want a listing for.
  337. -f file - Use file to read config info. If omitted, srcwatch.txt is assumed.
  338. The config file looks like:
  339. targets = jasonsch
  340. from = jasonsch
  341. paths = core advcore\\duser !core\\ntgdi !core\\cslpk
  342. groupname = NTUSER
  343. group = dwaynen gerardob hiroyama jasonsch jeffbog jstall markfi mhamid msadek
  344. lab = lab06_dev
  345. branches = ntuser
  346. premonition = 1
  347. EOPU
  348. exit(0);
  349. }
  350. sub PathFixup($)
  351. {
  352. $_[0] =~ s#\\#/#g;
  353. }
  354. sub InOurView($$$)
  355. {
  356. my $branch = lc(shift()); # the branch the file was in
  357. my $config = shift;
  358. my $ip = shift; # ignore "premonition" feature
  359. my $fRet = 0;
  360. if (!$ip && $$config{'premonition'}) {
  361. $fRet = 1;
  362. } else {
  363. if($branch ne $$config{'lab'}) {
  364. foreach (split(/\s+/, $$config{'branches'})) {
  365. if ($branch eq lc($_)) {
  366. $fRet = 1;
  367. }
  368. }
  369. } else {
  370. $fRet = 1;
  371. }
  372. }
  373. $fRet;
  374. }
  375. sub InitHtmlText($$)
  376. {
  377. my $config = shift;
  378. my $dc = shift;
  379. my $date = "";
  380. my $dh = ""; # depot column heading, if needed
  381. $dh = "<th>Depot</th>" if ($dc > 1);
  382. $text .= << " EOHTML";
  383. <html>
  384. <head>
  385. <title>srcwatch report</title>
  386. <style>
  387. <!--
  388. p { font-family: Tahoma; font-size: 8pt }
  389. td { font-family: Tahoma; font-size: 8pt }
  390. th { font-family: Tahoma; font-size: 8pt; color: #FFFF00; font-weight: bold; background-color: #000080 }
  391. table { background-color: #DEDFDE }
  392. -->
  393. </style>
  394. </head>
  395. <body bgcolor="#FFFFFF">
  396. <table border>
  397. <tr>$dh<th>Who</th><th>Change #</th><th>Date</th><th>Lab</th><th>Description</th><th>Files</th></tr>
  398. EOHTML
  399. }
  400. __END__