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.

554 lines
16 KiB

  1. # ---------------------------------------------------------------------------
  2. # Script: snapbin.pl
  3. #
  4. # (c) 2000 Microsoft Corporation. All rights reserved.
  5. #
  6. # Purpose: Snapshot US binaries tree to INTL.
  7. #
  8. # Version: 1.00 (05/10/2000) : (bensont) Snap the binaries tree
  9. # 1.01 (05/10/2000) : (bensont) Create __BldInfo__usa__ file
  10. #---------------------------------------------------------------------
  11. # Set Package
  12. package SnapBin;
  13. # Set the script name
  14. $ENV{script_name} = 'snapbin.pl';
  15. # Set version
  16. $VERSION = '1.01';
  17. $DEBUG = 0;
  18. # Set required perl version
  19. require 5.003;
  20. # Use section
  21. use lib $ENV{ RazzleToolPath };
  22. use lib "$ENV{ RazzleToolPath }\\PostBuildScripts";
  23. use GetParams;
  24. use LocalEnvEx;
  25. use Logmsg;
  26. use strict;
  27. no strict 'vars';
  28. use HashText;
  29. ($SourceTree, $TargetTree, $SnapList, $machines, $BldInfo, $RoboCopyLog, $BuildNum, %SnapList, @machines, $RoboCopyCmd, $LogRoboCopy)=(
  30. "\\\\ntdev\\release\\main\\usa\\<BuildNum>\\<_BuildArch><_BuildType>\\bin",
  31. "$ENV{_NTTREE}",
  32. "$ENV{RazzleToolPath}\\PostBuildScripts\\SnapList.txt",
  33. "machines.txt",
  34. "$ENV{_NTROOT}\\__BldInfo__usa__",
  35. ".Robocopy"
  36. );
  37. ($Mirror, $OtherOptions, $Incremental)=("/MIR");
  38. ($ROBOCOPY_ERROR, $ROBOCOPY_SERIOS_ERROR)=(8, 16);
  39. # Require section
  40. # Main Function
  41. sub CmdMain {
  42. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  43. # Begin CmdMain code section
  44. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  45. # Return when you want to exit on error
  46. &PrepareRoboCopyCmd || return;
  47. print "$RoboCopyCmd\n";
  48. $DEBUG or &ExecuteRoboCopy;
  49. {
  50. my @stack = ($RoboCopyCmd, $RoboCopyCmd, $SourceTree, $TargetTree);
  51. open (F, "$SnapList");
  52. my $startParse = 0;
  53. my @blist = ();
  54. my $flist = ();
  55. my @a = <F>;
  56. foreach (@a){
  57. next if /^;/;
  58. if (/^Additional *$/){
  59. print "Robocopy: found additional directories to snap\n";
  60. $startParse = 1;
  61. }
  62. $startParse=0 if ($startParse && $_ !~ /\S/);
  63. if ($startParse && /\S/){
  64. my @alist =
  65. split(" ", $_);
  66. if ($#alist>=2){
  67. #
  68. $f_ = undef;
  69. $alist[0] =~ s/(.*)\\([^\\]+)/$1/g and $f_=$2 if $alist[1]=~/F/;
  70. push @flist, $f_;
  71. push @blist, $alist[0];
  72. $DEBUG and print STDERR scalar(@blist),"\n";
  73. }
  74. }
  75. }
  76. close(F);
  77. foreach $cnt (0..$#blist){
  78. $dir = $blist[$cnt];
  79. $file = $flist[$cnt];
  80. $DEBUG and print STDERR "$dir\n";
  81. ($RoboCopyCmd, $RoboCopyLog, $SourceTree, $TargetTree) = @stack;
  82. $RoboCopyCmd =~ s/\\\\.*$//g;
  83. $RoboCopyLog =~ s|^.*(/LOG\+.*)$|$1.ADDED|g;
  84. chomp $RoboCopyLog;
  85. $SourceTree .= "\\$dir";
  86. $TargetTree .= "\\$dir";
  87. print "$SourceTree skipped\n" and next unless -d $SourceTree;
  88. $RoboCopyCmd = join(" ",$RoboCopyCmd, $SourceTree, $TargetTree, $RoboCopyLog, $file);
  89. print "$RoboCopyCmd\n";
  90. $DEBUG or &ExecuteRoboCopy;
  91. }
  92. ($RoboCopyCmd, $RoboCopyLog, $SourceTree, $TargetTree) = @stack;
  93. }
  94. &CreateBldInfo;
  95. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  96. # End CmdMain code section
  97. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  98. }
  99. # PrepareRoboCopyCmd
  100. # Purpose : Reference $SourceTree, $TargetTree and file $SnapList to create Robocopy statement
  101. #
  102. # Input : none
  103. # Output : 0 for fails, 1 for success
  104. #
  105. # Note : The Robocopy statement is stored in $RoboCopyCmd
  106. sub PrepareRoboCopyCmd {
  107. my ($Excludedirs, $Excludefiles, $exclude, $Cmd)=();
  108. -d $TargetTree or qx("md $TargetTree");
  109. HashText::Read_Text_Hash(0, $SnapList, \%snaplist) if ((defined $SnapList) && ($SnapList ne '-'));
  110. # HashText::Read_Text_Hash(1, $machines, \@machines);
  111. # If <var> defined in string, evaluate by the order: global variable, environment variable. Report error if can not evaluate
  112. $SourceTree =~ s/\<(\w+)\>/(eval "defined \$SnapBin::$1")?eval "\$SnapBin::$1":((exists $ENV{$1})?$ENV{$1}:errmsg("Unable to eval $1 in $SourceTree; verify your params and your razzle."))/ge;
  113. $TargetTree =~ s/\<(\w+)\>/(eval "defined \$SnapBin::$1")?eval "\$SnapBin::$1":((exists $ENV{$1})?$ENV{$1}:errmsg("Unable to eval $1 in $TargetTree; verify your params an your razzle."))/ge;
  114. # If source tree not exist
  115. if (!-e $SourceTree) {
  116. errmsg("Source Tree: $SourceTree not found.");
  117. }
  118. # Any above error should stop (Fail)
  119. if ($ENV{errors} > 0) {return 0;}
  120. # Parse the hash-hash table snaplist
  121. for $exclude (keys %snaplist) {
  122. $_ = $snaplist{$exclude}->{Type};
  123. $Excludedirs .= ($exclude=~/\\/)? "$SourceTree\\$exclude ": "$exclude " if /\bD\b/;
  124. $Excludefiles .= "$exclude " if (/\bF\b/);
  125. }
  126. # Check if incremental run.
  127. &ChkBabTree($TargetTree, \%snaplist) and exit;
  128. # Create RoboCopyLogName as %logfile%.RoboCopy
  129. $RoboCopyLog = `uniqfile $ENV{logfile}\.Robocopy`;
  130. if (defined $Incremental) {
  131. $Mirror = ""; # non-Mirror
  132. $OtherOptions = "/XO"; # Exclude Older files
  133. }
  134. # Prepare the robocopy statement
  135. $Cmd = "Robocopy $Mirror /S /E $SourceTree $TargetTree $OtherOptions ";
  136. $Cmd .= "/XD $Excludedirs " if ($Excludedirs ne '');
  137. $Cmd .= "/XF $Excludefiles " if ($Excludefiles ne '');
  138. $RoboCopyCmd = $Cmd . " /LOG+:$RoboCopyLog";
  139. # Success
  140. return 1;
  141. }
  142. # Verify that the snaplist.txt file does not contradict with
  143. # the actual contents of the %_NTTREE%.
  144. # usage:
  145. # &ChkBabTree($TargetTreel, \%SnapList)
  146. sub ChkBabTree{
  147. my $parent = shift;
  148. my $snaplist = shift;
  149. my @children = grep {/\S/} split ("\n", qx ("dir /s/b/ad $parent"));
  150. $DEBUG and print STDERR "checking existing \%_NTTREE% subdirs: ",scalar (@children), "\n";
  151. return 0 unless @children;
  152. print "Robocopy: \"$parent\" is not empty, possibly incremental run\n"
  153. if scalar(@children);
  154. map {$_ =~ s/\Q$parent\E\\//} @children;
  155. my %hashchildren = map {$_=>$_} @children;
  156. $childrenkeys = \%hashchildren;
  157. map {$childrenkeys->{$_} =~ s/^.*\\//} @children;
  158. my @report = ();
  159. foreach $subdir (@children){
  160. my $lastdir = $childrenkeys->{$subdir};
  161. push @report, sprintf("%-30s%-30s",$lastdir,$subdir) # and delete ($snaplist->{$lastdir})
  162. if ($snaplist->{$lastdir}->{Type}=~/\bD\b$/) or () ;
  163. }
  164. foreach $lastdir (keys(%$snaplist)){
  165. next unless $snaplist->{$lastdir}->{Type}=~/\bD\b/ && $lastdir=~/\\/;
  166. my @subdir = grep {/\Q$lastdir\E/} @children;
  167. push @report, sprintf("%-30s%-30s",$lastdir,$subdir[0]) if scalar (@subdir);
  168. }
  169. unshift @report, "snaplist.txt %_NTTREE%\n".
  170. "-----------------------------------------------------"
  171. and print join ("\n", @report ), "\n\n"
  172. if scalar(@report);
  173. scalar(@report);
  174. 0;
  175. }
  176. # ExecuteRoboCopy
  177. # Purpose : Execute Robocopy Command ($RoboCopyCmd)
  178. #
  179. # Input : none
  180. # Output : none
  181. #
  182. # Note : The serious error or fatal error will be logged.
  183. sub ExecuteRoboCopy {
  184. my $r;
  185. logmsg("RoboCopyCmd : $RoboCopyCmd");
  186. logmsg("SOURCE : $SourceTree");
  187. logmsg("TARGET : $TargetTree");
  188. logmsg("RoboCopy LOGFILE : $RoboCopyLog");
  189. $r = system($RoboCopyCmd) / 256;
  190. # Determine the return value
  191. if ($r > $ROBOCOPY_SERIOS_ERROR) {
  192. errmsg("Serious error while running robocopy."); # Robocopy did not copy all files. This is either a usage error or an error due to insufficient access privileges on the source or destination directions.";
  193. } elsif ($r > $ROBOCOPY_ERROR) {
  194. errmsg("Robocopy was not able to copy some files or directories.");
  195. }
  196. }
  197. # ParseLogFile
  198. # Purpose : Parse the log file which from argument and store to $ENV{logfile} with fully path
  199. #
  200. # Input : templogfile
  201. # Output : none
  202. #
  203. # Note : The log file will contain all file get copied and extra files removed.
  204. sub ParseLogFile {
  205. my ($templogfile) = @_;
  206. my ($type, $file, %slots, %fails)=();
  207. local *F;
  208. # Read temp logfile
  209. open(F, $templogfile) || return;
  210. for(<F>) {
  211. next if (/^\s*\-*\s*$/);
  212. if (/^ROBOCOPY/) {(%slots,%fails)=(); next;}
  213. chomp;
  214. # If is error message, add to previous line
  215. if (!/^\s/) {
  216. if ($#{$fails{$type}} eq '-1') {
  217. errmsg($_);
  218. } else {
  219. ${$fails{$type}}[$#{$fails{$type}}] .= "\n$_";
  220. }
  221. next;
  222. }
  223. logmsg($_) if (defined $LogRoboCopy);
  224. # Parse information according the format of robocopy log
  225. if (/^\s+(?:New Dir\s+)?(\d+)\s+([\w\:\\]+)$/) {
  226. $path = $2;
  227. next;
  228. }
  229. if (/^\s+((?:New File)|(?:Newer)|(?:\*EXTRA File)|(?:Older))\s+(\d+)\s+([\w\.]+)/) {
  230. ($type, $file) = ($1, $3);
  231. ((/100\%/)||(/\*EXTRA File/))?push(@{$slots{$type}}, $path . $file):push(@{$fails{$type}}, $path . $file);
  232. }
  233. }
  234. close(F);
  235. # Separate the log to success and fail
  236. logmsg("\n\[Copy Success\]");
  237. for $type (keys %slots) {
  238. logmsg(" \[$type\]");
  239. for $file (@{$slots{$type}}) {
  240. logmsg("\t$file");
  241. }
  242. }
  243. if (scalar(%fails) ne 0) {
  244. errmsg("\n\[Copy Fails\]");
  245. for $type (keys %fails) {
  246. errmsg(" \[$type\]");
  247. for $file (@{$fails{$type}}) {
  248. errmsg("\t$file");
  249. }
  250. }
  251. }
  252. # If Robocopy log include into the logfile, remove the robocopy its logfile
  253. if (defined $LogRoboCopy) {
  254. unlink($templogfile);
  255. } else {
  256. logmsg("See Robocopy's logfile for more details: $templogfile");
  257. }
  258. }
  259. # CreateBldInfo
  260. # Purpose : Create build number and time stamps to $BldInfo
  261. #
  262. # Input : none
  263. # Output : none
  264. #
  265. # Note : The file $BldInfo contain one line: '<Build Number>,<Time Stamp>'
  266. sub CreateBldInfo {
  267. local *F;
  268. my @file;
  269. if ($ENV{errors} > 0) {return 0;}
  270. # Search the matched filename in $SourceTree's parent folder
  271. @file = glob("${SourceTree}\\..\\${BuildNum}.*.bld");
  272. if (defined $file[1]) {
  273. errmsg("non-unique .BLD file exists. " . join(",", @files));
  274. } elsif (!defined $file[0]) {
  275. errmsg(".BLD file not found. Please make sure the US path ${SourceTree}\\..\\${BuildNum}.*.bld exists. ");
  276. }
  277. if ($file[0]!~/$BuildNum\.\w+\.\w+\.([\d|\-]+).bld/i) {
  278. errmsg(".BLD Filename ($file[0]) is incorrect format! It should be as \$BuildNum.\$_BuildArch\$_BuildType.\$_BuildBranch.\$_BuildTimeStamp.BLD");
  279. } else {
  280. open(F, ">$BldInfo");
  281. print F "$BuildNum,$1";
  282. close(F);
  283. }
  284. ###Copy __blddate__ and __bldnum__ from US release server
  285. @file=glob("${SourceTree}\\congeal_scripts\\__bld*__");
  286. for my $theFile ( @file )
  287. {
  288. system( "echo F|xcopy /V /F /R /Y $theFile $ENV{sdxroot}" );
  289. }
  290. }
  291. sub ValidateParams {
  292. #<Add your code for validating the parameters here>
  293. errmsg("Please run under razzle or RazzleToolPath undefined") if (!exists $ENV{RazzleToolPath});
  294. errmsg("Build Number ($BuildNum) contains non-digital or dot character") if ($BuildNum !~ /^[\d\.]+$/);
  295. }
  296. sub Usage {
  297. print <<USAGE;
  298. $0 - Snap Tree from US to INTL
  299. ============================================================================
  300. Usage: $0 -n buildnum [-s SourceTree] [-t TargetTree] [-f SnapList]
  301. [-B bldinfo] [-L] [-i] [-d]
  302. -n Build Number : The Build Number you snapshot
  303. -s Source Tree : Source Tree
  304. -t Target Tree : Target Tree
  305. -f SnapList : A snaplist file contain which files or dirs excluded
  306. -B bldinfo : A bldinfo file should be create after snapshot
  307. -L : Include robocopy log into logfile
  308. -i : Incremental
  309. -d : Debug. Display the robocopy command without running it.
  310. -? Displays usage
  311. Example:
  312. 1. Snapshot US 2121
  313. $0 -n 2121
  314. 2. Snapshot US 2222 with userlst.txt incrementally
  315. $0 -n 2222 -f userlst.txt -i
  316. 3. Snapshot US 2233 from d:\\nt8.binaries.x86fre to f:\\nt9.binaries.x86fre
  317. with userlst.txt and store buildnumber and time stamp to mynote.txt.
  318. $0 -n 2233 -s d:\\nt8.binaries.x86fre -t f:\\nt9.binaries.x86fre -f userlst.txt -B mynote.txt
  319. USAGE
  320. }
  321. sub GetParams {
  322. # Step 1: Call pm getparams with specified arguments
  323. &GetParams::getparams(@_);
  324. # Step 2: Set the language into the enviroment
  325. $ENV{lang}=$lang;
  326. # Step 3: Call the usage if specified by /?
  327. if ($HELP) {
  328. &Usage();
  329. exit 1;
  330. }
  331. }
  332. sub LocalEnvEx {
  333. my ($Option)=(@_);
  334. if ($Option=~/^initalize$/i) {
  335. my $LocalEnvEx=LocalEnvEx->new;
  336. &{$LocalEnvEx->{-Initialize}};
  337. }
  338. if ($Option=~/^end$/i) {
  339. my $LocalEnvEx=LocalEnvEx->new;
  340. &{$LocalEnvEx->{-End}};
  341. }
  342. }
  343. # cmd entry point for script.
  344. if (eval("\$0 =~ /" . __PACKAGE__ . "\\.pl\$/i")) {
  345. @syntax=(
  346. '-n' => 'n:',
  347. '-o' => 's:t:f:Lid',
  348. '-p' => 'BuildNum SourceTree TargetTree SnapList LogRoboCopy Incremental DEBUG'
  349. );
  350. # Step 1: Parse the command line
  351. &GetParams (@syntax, @ARGV);
  352. # Include local environment extensions
  353. &LocalEnvEx('initalize');
  354. # Validate the option given as parameter.
  355. &ValidateParams;
  356. # Step 4: Call the CmdMain function
  357. &CmdMain();
  358. # End local environment extensions.
  359. &LocalEnvEx('end');
  360. }
  361. # -------------------------------------------------------------------------------------------
  362. # Script: snapbin.pl
  363. # Purpose: Snapshot US binaries tree to INTL.
  364. # SD Location: %sdxroot%\tools\postbuildscripts
  365. #
  366. # (1) Code section description:
  367. # CmdMain - Prepare the robocopyCmd, execute and parse its log
  368. # PrepareRoboCopyCmd - Prepare the Robocopy command
  369. # ExecuteRoboCopy - Execute the Robocopy command and test the return value
  370. # ParseLogFile - Parse the logfile, append logfile from temp logfile
  371. #
  372. # (2) Reserved Variables -
  373. # $ENV{HELP} - Flag that specifies usage.
  374. # $ENV{lang} - The specified language. Defaults to USA.
  375. # $ENV{logfile} - The path and filename of the logs file.
  376. # $ENV{logfile_bak} - The path and filename of the logfile.
  377. # $ENV{errfile} - The path and filename of the error file.
  378. # $ENV{tmpfile} - The path and filename of the temp file.
  379. # $ENV{errors} - The scripts errorlevel.
  380. # $ENV{script_name} - The script name.
  381. # $ENV{_NTPostBld} - Abstracts the language from the files path that
  382. # postbuild operates on.
  383. #
  384. # (3) Reserved Subs -
  385. # Usage - Use this sub to discribe the scripts usage.
  386. # ValidateParams - Use this sub to verify the parameters passed to the script.
  387. #
  388. # (4) Call other executables or command scripts by using:
  389. # system "foo.exe";
  390. # Note that the executable/script you're calling with system must return a
  391. # non-zero value on errors to make the error checking mechanism work.
  392. #
  393. # Example
  394. # if (system("perl.exe foo.pl -l $lang")){
  395. # errmsg("perl.exe foo.pl -l $lang failed.");
  396. # # If you need to terminate function's execution on this error
  397. # goto End;
  398. # }
  399. #
  400. # (5) Log non-error information by using:
  401. # logmsg "<log message>";
  402. # and log error information by using:
  403. # errmsg "<error message>";
  404. #
  405. # (6) Have your changes reviewed by a member of the US build team (ntbusa) and
  406. # by a member of the international build team (ntbintl).
  407. #
  408. # -------------------------------------------------------------------------------------------
  409. =head1 NAME
  410. B<SnapBin> - Snapshot US Binaries tree to INTL
  411. =head1 SYNOPSIS
  412. &SnapBin::PrepareRoboCopyCmd;
  413. &SnapBin::ExecuteRoboCopy;
  414. &SnapBin::ParseLogFile;
  415. &SnapBin::CreateBldInfo;
  416. =head1 DESCRIPTION
  417. According SnapList,
  418. PrepareRoboCopyCmd will prepare the command, such as:
  419. Robocopy /MIR /S /E $SourceTree $TargetTree /XD xxxx /XF xxxx /LOG+:$ENV{logfile}.temp
  420. ExecuteRoboCopy execute the command and verify its log.
  421. And, ParseLogFile will append temp logfile to $ENV{logfile} and generate a separate list into log.
  422. Final, create BldInfo file in nt root.
  423. =head1 INSTANCES
  424. =head2 $SourceTree
  425. US Tree, default is \\\\ntdev\\release\\main\\usa\\<BuildNum>\\<_BuildArch><_BuildType>\\bin
  426. =head2 $TargetTree
  427. INTL Tree, default is _NTTREE
  428. =head2 $SnapList
  429. Snap List FileName, default is SnapList.txt
  430. =head2 $BuildNum
  431. Build Number, necessary defined. No default value
  432. =head2 %SnapList
  433. The hash stored by HashText::Read_Text_Hash from file $SnapList.
  434. =head2 $RoboCopyCmd
  435. The command for ExecuteRoboCopy execute
  436. =head1 METHODS
  437. =head2 PrepareRoboCopyCmd
  438. $SnapBin::SourceTree = "f:\\foo";
  439. $SnapBin::TargetTree = "f:\\bar";
  440. $SnapBin::SnapList = "mylist.txt"; # equal to '-' if no exclude list file
  441. &SnapBin::PrepareRoboCopyCmd;
  442. system("$SnapBin::RoboCopyCmd");
  443. =head2 ExecuteRoboCopy
  444. $SnapBin::SourceTree = "f:\\foo";
  445. $SnapBin::TargetTree = "f:\\bar";
  446. $SnapBin::RoboCopyCmd = "Robocopy /S $SnapBin::SourceTree $SnapBin::TargetTree";
  447. &SnapBin::ExecuteRoboCopy;
  448. =head2 ParseLogFile
  449. system("robocopy f:\\temp F:\\tempbak /LOG:abc.log");
  450. &SnapBin::ParseLogFile("abc.log");
  451. =head1 SEE ALSO
  452. HashText.pm
  453. =head1 AUTHOR
  454. Benson Tan <[email protected]>
  455. =cut
  456. 1;