Team Fortress 2 Source Code as on 22/4/2020
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.

660 lines
15 KiB

  1. use strict;
  2. ###################################################
  3. # CONFIG VARS
  4. ###################################################
  5. # FIXME: load these from a separate file so that each user can have their own config without editingthis file.
  6. my $g_P4UserName = "gary";
  7. my $g_LocalBaseDir = "u:\\hl2";
  8. my $g_LocalBranchSubdir = "src5";
  9. my $g_LocalBranchName = "gary_src5";
  10. my $g_LocalBranchClient = "gary_work_src5";
  11. my $g_MainCopyBaseDir = "u:\\hl2";
  12. my $g_LocalBranchMainCopySubdir = "src5_main";
  13. my $g_LocalBranchMainCopyName = "gary_src5_main";
  14. #my $g_LocalBranchMainCopyClient = "gary_work_src5_main";
  15. my $g_MainBaseDir = "u:\\hl2_main";
  16. my $g_MainBranchSubdir = "src_main";
  17. #my $g_MainBranchName = "gary_src_main";
  18. #my $g_MainBranchClient = "gary_work_src_main";
  19. my $g_UseIncredibuildForMain = 1;
  20. # FIXME: need to make this work for those that don't work on HL2.
  21. my $g_LocalBranchHasHL1Port = 0;
  22. my $g_LocalBranchHasCSPort = 0;
  23. my $g_LocalBranchHasTF2 = 0;
  24. my $g_CheckinFileStampTimes = "c:\\checkin_filetimes.txt";
  25. # either use VSS directly via the command-line, or use Tom's tool.
  26. my $g_UseVSS = 0;
  27. ###################################################
  28. # Helper vars made up of config vars
  29. ###################################################
  30. my $g_LocalBranchDir = "$g_LocalBaseDir\\$g_LocalBranchSubdir";
  31. my $g_LocalBranchMainCopyDir = "$g_MainCopyBaseDir\\$g_LocalBranchMainCopySubdir";
  32. my $g_MainBranchDir = "$g_MainBaseDir\\$g_MainBranchSubdir";
  33. ###################################################
  34. my $g_DebugStub = 0;
  35. my $stage = shift;
  36. if( $stage != 1 &&
  37. $stage != 2 &&
  38. $stage != 3 &&
  39. $stage ne "syncmain" &&
  40. $stage ne "syncmainsrc" &&
  41. $stage ne "synclocal" &&
  42. $stage ne "synclocalrelease" &&
  43. $stage ne "synclocaldebug" &&
  44. $stage ne "synclocalsrc" &&
  45. $stage ne "synclocalsrcrelease" &&
  46. $stage ne "sync" &&
  47. $stage ne "syncmaincontent" )
  48. {
  49. print "checkin.pl 1 : to get started with a checkin\n";
  50. print "checkin.pl 2 : second stage of checkin\n";
  51. print "checkin.pl 3 : third stage of checkin\n";
  52. print "checkin.pl syncmain : sync main source and content, then build\n";
  53. print "checkin.pl syncmainsrc : sync main source then build\n";
  54. print "checkin.pl syncmaincontent : sync main content only\n";
  55. print "checkin.pl synclocal : merge personal branch, sync content,\n";
  56. print " then build.\n";
  57. print "checkin.pl synclocalrelease : merge personal branch, sync content,\n";
  58. print " then build (release only).\n";
  59. print "checkin.pl synclocaldebug : merge personal branch, sync content,\n";
  60. print " then build (debug only).\n";
  61. print "checkin.pl synclocalsrc : merge personal branch, then build.\n";
  62. print "checkin.pl synclocalsrcrelease : merge personal branch, then build\n";
  63. print " (release only).\n";
  64. print "checkin.pl sync : merge personal branch, sync main src,\n";
  65. print " sync content for both, and then build\n";
  66. print " the whole thing.\n";
  67. die;
  68. }
  69. sub RunCmd
  70. {
  71. my $cmd = shift;
  72. print $cmd . "\n";
  73. if( !$g_DebugStub )
  74. {
  75. return system $cmd;
  76. }
  77. }
  78. sub CD
  79. {
  80. my $dir = shift;
  81. print "cd $dir\n";
  82. if( !$g_DebugStub )
  83. {
  84. chdir $dir;
  85. }
  86. }
  87. sub SSGet
  88. {
  89. my $vssdir = shift;
  90. my $localdir = shift;
  91. &CD( $localdir );
  92. &RunCmd( "ss WorkFold $vssdir $localdir" );
  93. print "\n";
  94. my $cmd = "ss get $vssdir -R";
  95. local( *SS );
  96. open SS, "$cmd|";
  97. my $workingdir;
  98. while( <SS> )
  99. {
  100. # FIXME: clean up this output.
  101. $_ =~ s/\n//;
  102. if( m/^\$/ )
  103. {
  104. $workingdir = $_;
  105. # print "WORKING DIR: $_\n";
  106. }
  107. elsif( m/^getting/i )
  108. {
  109. print "GETTING: $workingdir $_\n";
  110. }
  111. elsif( m/^replacing local file/i )
  112. {
  113. print "REPLACING: $workingdir $_\n";
  114. }
  115. elsif( m/^File/ )
  116. {
  117. print "ALREADY EXISTS: $workingdir $_\n";
  118. }
  119. else
  120. {
  121. # print "WTF: $_\n";
  122. }
  123. }
  124. close SS;
  125. }
  126. sub FastSSGet
  127. {
  128. my $localdir = shift;
  129. my $option = shift;
  130. &RunCmd( "\\\\hl2vss\\hl2vss\\win32\\syncfrommirror.bat $option $localdir" );
  131. }
  132. sub FileIsWritable
  133. {
  134. my $file = shift;
  135. my @statresult = stat $file;
  136. die if !@statresult;
  137. my $perms = oct( $statresult[2] );
  138. if( $perms & 2 )
  139. {
  140. return 1;
  141. }
  142. else
  143. {
  144. return 0;
  145. }
  146. }
  147. sub CompareDirs
  148. {
  149. my $filesThatHaveChanged = shift;
  150. my $filesThatHaveNotChanged = shift;
  151. my @out = `robocopy $g_MainBaseDir\\checkinbins\\. $g_MainBaseDir\\. /S /L /V`;
  152. my $line;
  153. my $cwd;
  154. foreach $line ( @out )
  155. {
  156. next if( $line =~ /\*EXTRA Dir/ );
  157. next if( $line =~ /\*EXTRA Dir/ );
  158. next if( $line =~ /\*EXTRA File/ );
  159. if( $line =~ m/\s*\d+\s+(\S+\\)/ )
  160. {
  161. $cwd = $1;
  162. next;
  163. }
  164. if( $line =~ m/\s+Older\s+\d+\s+(\S+)/ )
  165. {
  166. my $testfilename = $cwd . $1;
  167. my $filename = $testfilename;
  168. $filename =~ s/\\checkinbins//i;
  169. my $diffresult = system "diff $testfilename $filename > nil";
  170. if( $diffresult != 0 )
  171. {
  172. push @{$filesThatHaveChanged}, $filename;
  173. }
  174. else
  175. {
  176. if( &FileIsWritable( $filename ) )
  177. {
  178. push @{$filesThatHaveNotChanged}, $filename;
  179. }
  180. }
  181. next;
  182. }
  183. elsif( $line =~ m/\s+same\s+\d+\s+(\S+)/ )
  184. {
  185. my $filename = $cwd . $1;
  186. $filename =~ s/\\checkinbins//i;
  187. if( &FileIsWritable( $filename ) )
  188. {
  189. push @{$filesThatHaveNotChanged}, $filename;
  190. }
  191. next;
  192. }
  193. if( $line =~ m/\s+New File\s+\d+\s+(\S+)/ )
  194. {
  195. die "$cwd $1 didn't build!\n";
  196. }
  197. print "DEBUG: unhandled line: $line\n";
  198. }
  199. }
  200. sub CheckoutFile
  201. {
  202. my $file = shift;
  203. print "-----------------\nchecking out $file\n";
  204. if( $file =~ /src_main/i )
  205. {
  206. # need to use p4 to check this one out.
  207. my $dir = $file;
  208. $dir =~ s/\\([^\\]*)$//;
  209. &CD( $dir );
  210. &RunCmd( "p4 edit $1" );
  211. }
  212. else
  213. {
  214. my $dir = $file;
  215. $dir =~ s/\\([^\\]*)$//;
  216. &CD( $dir );
  217. $file =~ s,\\,/,g;
  218. if( $file =~ m/cstrike/i || $file =~ m/hl1/i )
  219. {
  220. $file =~ s,u:/hl2_main/,\$/hl1ports/release/dev/,gi;
  221. &RunCmd( "ss WorkFold \$/hl1ports/release/dev $g_MainBaseDir" );
  222. }
  223. elsif( $file =~ m/\/tf2/i )
  224. {
  225. $file =~ s,u:/hl2_main/,\$/tf2/release/dev/,gi;
  226. &RunCmd( "ss WorkFold \$/tf2/release/dev $g_MainBaseDir" );
  227. }
  228. else
  229. {
  230. $file =~ s,u:/hl2_main/,\$/hl2/release/dev/,gi;
  231. &RunCmd( "ss WorkFold \$/hl2/release/dev $g_MainBaseDir" );
  232. }
  233. print "\n";
  234. &RunCmd( "ss Checkout -G- $file" );
  235. }
  236. }
  237. sub RevertFile
  238. {
  239. my $file = shift;
  240. print "-----------------\nreverting $file\n";
  241. if( $file =~ /src_main/i )
  242. {
  243. # need to use p4 to revert this one
  244. my $dir = $file;
  245. $dir =~ s/\\([^\\]*)$//;
  246. &CD( $dir );
  247. &RunCmd( "p4 sync -f $1" );
  248. }
  249. else
  250. {
  251. my $dir = $file;
  252. $dir =~ s/\\([^\\]*)$//;
  253. &CD( $dir );
  254. $file =~ s,\\,/,g;
  255. my $vssfile = $file;
  256. if( $file =~ m/cstrike/i || $file =~ m/hl1/i )
  257. {
  258. $vssfile =~ s,u:/hl2_main/,\$/hl1ports/release/dev/,gi;
  259. &RunCmd( "ss WorkFold \$/hl1ports/release/dev $g_MainBaseDir" );
  260. }
  261. elsif( $file =~ m/\/tf2/i )
  262. {
  263. $vssfile =~ s,u:/hl2_main/,\$/tf2/release/dev/,gi;
  264. &RunCmd( "ss WorkFold \$/tf2/release/dev $g_MainBaseDir" );
  265. }
  266. else
  267. {
  268. $vssfile =~ s,u:/hl2_main/,\$/hl2/release/dev/,gi;
  269. &RunCmd( "ss WorkFold \$/hl2/release/dev $g_MainBaseDir" );
  270. }
  271. print "\n";
  272. unlink $file;
  273. &RunCmd( "ss Get -I- $vssfile" );
  274. }
  275. }
  276. sub SyncMainSource
  277. {
  278. # SYNC MAIN
  279. &CD( $g_MainBranchDir );
  280. &RunCmd( "p4 sync" );
  281. }
  282. sub SyncMainContent
  283. {
  284. # SYNC VSS
  285. &CD( $g_MainBranchDir );
  286. &RunCmd( "clean.bat" );
  287. if( $g_UseVSS )
  288. {
  289. &SSGet( "\$/hl2/release/dev", $g_MainBaseDir );
  290. &SSGet( "\$/hl1ports/release/dev", $g_MainBaseDir );
  291. # NOTE: only get tf2 bin since we aren't testing tf2 right now
  292. &SSGet( "\$/tf2/release/dev/tf2/bin", "$g_MainBaseDir/tf2/bin" );
  293. }
  294. else
  295. {
  296. &FastSSGet( $g_MainBaseDir, "all" );
  297. }
  298. }
  299. sub BuildMain
  300. {
  301. if( $g_UseIncredibuildForMain )
  302. {
  303. $ENV{"USE_INCREDIBUILD"} = "1";
  304. }
  305. &CD( $g_MainBranchDir );
  306. &RunCmd( "clean.bat" );
  307. &RunCmd( "build_hl2.bat" );
  308. &RunCmd( "build_hl1_game.bat" );
  309. &RunCmd( "build_cs_game.bat" );
  310. &RunCmd( "build_tf2_game.bat" );
  311. if( $g_UseIncredibuildForMain )
  312. {
  313. undef $ENV{"USE_INCREDIBUILD"};
  314. }
  315. }
  316. sub SyncLocalBranchSource
  317. {
  318. &CD( $g_LocalBranchDir );
  319. &RunCmd( "p4mf.bat $g_LocalBranchName $g_LocalBranchClient pause" );
  320. # FIXME: This needs to specify the changelist since p4mf makes a new changelist.
  321. # &RunCmd( "p4 submit" );
  322. }
  323. sub SyncMainCopySource
  324. {
  325. &CD( $g_LocalBranchMainCopyDir );
  326. &RunCmd( "p4 integrate -d -i -b $g_LocalBranchMainCopyName" );
  327. &RunCmd( "p4 resolve -at ..." );
  328. # Update the changelist and submit
  329. &RunCmd( "p4 change -o | sed -e \"s/<enter description here>/Merge from main/g\" | p4 submit -i" );
  330. }
  331. sub SyncLocalBranchContent
  332. {
  333. &CD( $g_LocalBranchDir );
  334. # CLEAN LOCAL BRANCH
  335. &RunCmd( "clean.bat" );
  336. # SYNC VSS
  337. if( $g_UseVSS )
  338. {
  339. &SSGet( "\$/hl2/release/dev", $g_LocalBaseDir );
  340. if( $g_LocalBranchHasHL1Port || $g_LocalBranchHasCSPort )
  341. {
  342. &SSGet( "\$/hl1ports/release/dev", $g_LocalBaseDir );
  343. }
  344. if( $g_LocalBranchHasTF2 )
  345. {
  346. &SSGet( "\$/tf2/release/dev", $g_LocalBaseDir );
  347. }
  348. }
  349. else
  350. {
  351. if( $g_LocalBranchHasHL1Port || $g_LocalBranchHasCSPort )
  352. {
  353. &FastSSGet( $g_LocalBaseDir, "all" );
  354. }
  355. else
  356. {
  357. &FastSSGet( $g_LocalBaseDir, "hl2" );
  358. }
  359. # FIXME: screwed on tf2 here.
  360. }
  361. }
  362. sub BuildLocalBranch
  363. {
  364. &CD( $g_LocalBranchDir );
  365. # BUILD DEBUG if we don't want release only
  366. if( !( $stage =~ /release/i ) )
  367. {
  368. # CLEAN LOCAL BRANCH
  369. &RunCmd( "clean.bat" );
  370. &RunCmd( "build_hl2.bat debug" );
  371. if( $g_LocalBranchHasHL1Port )
  372. {
  373. &RunCmd( "build_hl1_game.bat debug" );
  374. }
  375. if( $g_LocalBranchHasCSPort )
  376. {
  377. &RunCmd( "build_cs_game.bat debug" );
  378. }
  379. if( $g_LocalBranchHasTF2 )
  380. {
  381. &RunCmd( "build_tf2_game.bat debug" );
  382. }
  383. }
  384. if( !( $stage =~ /debug/i ) )
  385. {
  386. # CLEAN LOCAL BRANCH
  387. &RunCmd( "clean.bat" );
  388. # BUILD RELEASE
  389. &RunCmd( "build_hl2.bat" );
  390. if( $g_LocalBranchHasHL1Port )
  391. {
  392. &RunCmd( "build_hl1_game.bat" );
  393. }
  394. if( $g_LocalBranchHasCSPort )
  395. {
  396. &RunCmd( "build_cs_game.bat" );
  397. }
  398. if( $g_LocalBranchHasTF2 )
  399. {
  400. &RunCmd( "build_tf2_game.bat" );
  401. }
  402. }
  403. }
  404. sub GetMainUpToDate
  405. {
  406. &SyncMainSource();
  407. &SyncMainContent();
  408. &BuildMain();
  409. }
  410. sub LockPerforce
  411. {
  412. while( 1 )
  413. {
  414. my $thing = `p4mutex lock main_src 0 $g_P4UserName 207.173.178.12:1666`;
  415. print $thing;
  416. last if $thing =~ /Success/;
  417. sleep 30;
  418. }
  419. }
  420. sub SaveMainTimeStampsBeforeIntegrate
  421. {
  422. &CD( $g_MainBranchDir );
  423. # Get a list of files that are going to be integrated into main so that we can save off their time stamp info.
  424. my @filestointegrate = `p4 integrate -n -r -b $g_LocalBranchName`;
  425. my $file;
  426. local( * TIMESTAMPS );
  427. open TIMESTAMPS, ">$g_CheckinFileStampTimes";
  428. foreach $file ( @filestointegrate )
  429. {
  430. $file =~ s,//ValveGames/main/src/([^#]*)\#.*,$1,gi;
  431. $file =~ s/\n//;
  432. $file =~ s,\\,/,g;
  433. my $localfilename = "$g_MainBranchDir/$file";
  434. my @statinfo = stat $localfilename;
  435. next if !@statinfo;
  436. my $mtime = $statinfo[9];
  437. print TIMESTAMPS $file . "|" . $mtime . "\n";
  438. }
  439. close TIMESTAMPS;
  440. }
  441. sub SetMainTimeStampsOnRevertedFiles
  442. {
  443. &CD( $g_MainBranchDir );
  444. # Get a list of files that we might have to revert times on if they aren't in the changelist.
  445. local( *TIMESTAMPS );
  446. open TIMESTAMPS, "<$g_CheckinFileStampTimes";
  447. my @timestamps = <TIMESTAMPS>;
  448. my %filetotimestamp;
  449. my $i;
  450. for( $i = 0; $i < scalar( @timestamps ); $i++ )
  451. {
  452. $timestamps[$i] =~ s/\n//;
  453. $timestamps[$i] =~ m/^(.*)\|(.*)$/;
  454. $filetotimestamp{$1} = $2;
  455. }
  456. close TIMESTAMPS;
  457. my $key;
  458. foreach $key( keys( %filetotimestamp ) )
  459. {
  460. print "before: \'$key\" \"$filetotimestamp{$key}\"\n";
  461. }
  462. local( *CHANGELIST );
  463. open CHANGELIST, "p4 change -o|";
  464. while( <CHANGELIST> )
  465. {
  466. if( m,//ValveGames/main/src/(.*)\s+\#,i )
  467. {
  468. if( defined $filetotimestamp{$1} )
  469. {
  470. undef $filetotimestamp{$1};
  471. }
  472. }
  473. }
  474. close CHANGELIST;
  475. foreach $key( keys( %filetotimestamp ) )
  476. {
  477. if( defined $filetotimestamp{$key} )
  478. {
  479. my $filename = $g_MainBranchDir . "/" . $key;
  480. $filename =~ s,/,\\,g;
  481. my @statresults;
  482. if( @statresults = stat $filename )
  483. {
  484. my $mode = $statresults[2];
  485. my $atime = $statresults[8];
  486. my $mtime = $statresults[9];
  487. print "reverting timestamp for $filename\n";
  488. chmod 0666, $filename || die $!;
  489. utime $atime, $filetotimestamp{$key}, $filename || die $!;
  490. chmod $mode, $filename || die $!;
  491. }
  492. }
  493. }
  494. }
  495. if( $stage eq "synclocal" || $stage eq "synclocalrelease" || $stage eq "synclocaldebug" || $stage eq "sync" )
  496. {
  497. &SyncLocalBranchSource();
  498. &SyncMainCopySource();
  499. &SyncLocalBranchContent();
  500. &BuildLocalBranch();
  501. }
  502. if( $stage eq "synclocalsrc" || $stage eq "synclocalsrcrelease" )
  503. {
  504. &SyncLocalBranchSource();
  505. &SyncMainCopySource();
  506. &BuildLocalBranch();
  507. }
  508. if( $stage eq "syncmainsrc" )
  509. {
  510. &SyncMainSource();
  511. &BuildMain();
  512. }
  513. if( $stage eq "syncmain" || $stage eq "sync" )
  514. {
  515. &GetMainUpToDate();
  516. }
  517. if( $stage eq "syncmaincontent" )
  518. {
  519. &SyncMainContent();
  520. }
  521. if( $stage == 1 )
  522. {
  523. # lock p4
  524. # &LockPerforce();
  525. &GetMainUpToDate();
  526. # merge main into local branch
  527. &SyncLocalBranchSource();
  528. # TODO: need a way to detect if there are conflicts or not. If there are, pause here.
  529. # Make a copy of targets so that we can tell which ones changed.
  530. &RunCmd( "robocopy $g_MainBaseDir\\ $g_MainBaseDir\\checkinbins\\ /purge" );
  531. &RunCmd( "robocopy $g_MainBaseDir\\bin\\. $g_MainBaseDir\\checkinbins\\bin\\. /mir" );
  532. &RunCmd( "robocopy $g_MainBaseDir\\hl2\\bin\\. $g_MainBaseDir\\checkinbins\\hl2\\bin\\. /mir" );
  533. &RunCmd( "robocopy $g_MainBaseDir\\hl1\\bin\\. $g_MainBaseDir\\checkinbins\\hl1\\bin\\. /mir" );
  534. &RunCmd( "robocopy $g_MainBaseDir\\cstrike\\bin\\. $g_MainBaseDir\\checkinbins\\cstrike\\bin\\. /mir" );
  535. &RunCmd( "robocopy $g_MainBaseDir\\tf2\\bin\\. $g_MainBaseDir\\checkinbins\\tf2\\bin\\. /mir" );
  536. &RunCmd( "robocopy $g_MainBaseDir\\platform\\servers\\. $g_MainBaseDir\\checkinbins\\platform\\servers\\. /mir" );
  537. &RunCmd( "robocopy $g_MainBranchDir\\lib\\. $g_MainBaseDir\\checkinbins\\$g_MainBranchSubdir\\lib\\. /mir" );
  538. # integrate from personal branch into main. . accept theirs.
  539. # TODO: need to check if main has a changelist or not and warn!
  540. &CD( $g_MainBranchDir );
  541. &SaveMainTimeStampsBeforeIntegrate();
  542. &RunCmd( "p4 integrate -r -b $g_LocalBranchName" );
  543. &RunCmd( "p4 resolve -at ..." );
  544. # revert unchanged files.
  545. my @unchanged = `p4 diff -sr`;
  546. my $file;
  547. foreach $file ( @unchanged )
  548. {
  549. &RunCmd( "p4 revert $file" );
  550. }
  551. print "Do \"checkin.pl 2\" when you are done reverting unchanging files and fixing up any other diffs in your main client.\n";
  552. }
  553. elsif( $stage == 2 )
  554. {
  555. &SetMainTimeStampsOnRevertedFiles();
  556. # build main with the new changes
  557. &BuildMain();
  558. # compare what we just built to what we saved off earlier
  559. my @filesToCheckOut;
  560. my @filesThatHaveNotChanged;
  561. &CompareDirs( \@filesToCheckOut, \@filesThatHaveNotChanged );
  562. my $file;
  563. # $g_DebugStub = 1;
  564. foreach $file ( @filesThatHaveNotChanged )
  565. {
  566. &RevertFile( $file );
  567. }
  568. foreach $file ( @filesToCheckOut )
  569. {
  570. &CheckoutFile( $file );
  571. }
  572. print "-----------------\n";
  573. print "Do \"checkin.pl 3\" when you are finished testing to checkin files and release the mutex.\n";
  574. }
  575. elsif( $stage == 3 )
  576. {
  577. my @filesToCheckOut;
  578. my @filesThatHaveNotChanged;
  579. &CompareDirs( \@filesToCheckOut, \@filesThatHaveNotChanged );
  580. # TODO: check stuff in here and unlock p4
  581. # TODO: go ahead and sync src_main to main so that they match
  582. # TODO: merge main into src again so any changes that you made while checking in are propogated
  583. &SyncMainCopySource();
  584. }